SpringBoot--全局格式处理--方法/实例

原文网址: SpringBoot--全局格式处理--方法/实例_IT利刃出鞘的博客-CSDN博客

简介

说明

       本文用实例介绍SpringBoot如何进行全局格式处理。

方案简介

        全局格式处理有很多方案,见:此文。本文介绍这种方案:@ControllerAdvice+@InitBinder

        Spring MVC中提供了一个注解@InitBinder,它的作用是在执行控制器方法前,处理器会先执行@InitBinder标注的方法。这时可以将WebDataBinder对象作为参数传递到方法中,通过这层关系得到WebDataBinder对象。

        可以进行的操作:设置时间格式、自定义参数。

        在Controller下直接使用@InitBinder只对当前Controller生效。想全局生效,可用@ControllerAdvice或者WebBindingInitializer。

系列文章

SpringBoot全局处理我写了一个系列:

  1. SpringBoot--全局异常处理--方法/实例_IT利刃出鞘的博客-CSDN博客
  2. SpringBoot--全局响应处理--方法/实例_IT利刃出鞘的博客-CSDN博客
  3. SpringBoot--全局请求处理--方法/实例_IT利刃出鞘的博客-CSDN博客
  4. SpringBoot--全局格式处理--方法/实例_IT利刃出鞘的博客-CSDN博客

@ControllerAdvice介绍

说明

        @ControllerAdvice里边有@Component,用于类,可包含@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。(因此是全局的处理方法)。

        可以在多个类上使用@ControllerAdvice,可通过@Order来控制顺序。不能通过实现Order接口来控制顺序,因为这部分源码里只支持@Order这种方式。见:调整多个ControllerAdvice的执行顺序_felixu的博客-CSDN博客

        在Spring4及之后, @ControllerAdvice支持配置控制器的子集,可通过annotations(), basePackageClasses(), basePackages()方法选择控制器子集。

官网网址

springmvc 注解总结 - SpringMVC中文官网

使用场景

  1. @ControllerAdvice+@ExceptionHandler:全局异常处理
    1. 捕获Controller中抛出的指定类型异常,可对不同类型的异常区别处理
  2. @ControllerAdvice+ 实现ResponseBodyAdvice接口:全局响应处理(处理返回值)
    1. 其标注的方法将会在目标Controller方法执行之后执行。
  3. @ControllerAdvice+@ModelAttribute:全局请求处理
    1. 其标注的方法将会在目标Controller方法执行之前执行。
    2. 使用场景示例:鉴权/授权、全局处理格式
  4. @ControllerAdvice+@InitBinder:全局请求处理
    1. 其标注的方法将会在目标Controller方法执行之前执行。
    2. request中自定义参数解析方式进行注册
    3. 使用场景示例:全局处理格式
      SpringBoot--LocalDateTime--全局格式转换/前后端/前端入参/响应给前端_IT利刃出鞘的博客-CSDN博客

实例1:全局处理

代码

全局格式处理

package com.example.common.advice;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;

import java.beans.PropertyEditorSupport;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

@ControllerAdvice
public class GlobalRequestFormatAdvice {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        });

        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        });

        binder.registerCustomEditor(LocalTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalTime.parse(text, DateTimeFormatter.ofPattern("HH:mm:ss")));
            }
        });
    }
}

Controller

package com.example.business.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;

@RestController
@RequestMapping("user")
public class UserController {

    @GetMapping("/initBinder")
    public Object localDateTimeTest(LocalDateTime localDateTime) {
        System.out.println(localDateTime);
        return localDateTime;
    }
}

测试

postman访问:http://localhost:8080/user/initBinder?localDateTime=2020-08-20 12:12:34

postman结果

后端结果

实例:单个Controller写法

代码

设置时间参数 

package com.example.controller;

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.beans.PropertyEditorSupport;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

@RestController
@RequestMapper("user")
public class UserController {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        });

        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        });

        binder.registerCustomEditor(LocalTime.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                setValue(LocalTime.parse(text, DateTimeFormatter.ofPattern("HH:mm:ss")));
            }
        });
    }

    @RequestMapping(value = "/initBinder")
    public Object localDateTimeTest(LocalDateTime localDateTime) {
        System.out.println(localDateTime);
        return localDateTime;
    }
}

value属性(全局、单独Controller都适用)

若指定了value值,那么只有方法参数名(或者模型名)匹配上了此注解方法才会执行(若不指定,都执行)。

package com.example.controller;

import com.example.entity.User;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

@RestController
public class HelloController {
    @InitBinder({"param", "user"})
    public void initBinder(WebDataBinder binder, HttpServletRequest request) {
        System.out.println("当前key:" + binder.getObjectName());
    }

    @ResponseBody
    @RequestMapping("/initbinder")
    public Object testInitBinder(String param, String date,
                                 @ModelAttribute("user") User user) {
        System.out.println(user.getName());
        return param + ":" + date;
    }
}

测试 

浏览器访问:http://localhost:8080/initbinder?param=abc&date=2019&user.name=demoUser

后端输出

当前key:param
当前key:user
null

前端输出

abc:2019

虽然此处有key是user.name,但是User对象可是不会封装到此值的(因为request.getParameter('user')没这个key。

解决方法:

法1:加前缀

package com.example.controller;

import com.example.entity.User;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

@RestController
public class HelloController {
    @InitBinder({"param"})
    public void initBinderParam(WebDataBinder binder) {
        System.out.println("当前key:" + binder.getObjectName());
    }

    @InitBinder({"user"})
    public void initBinderUser(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("user.");
        System.out.println("当前key:" + binder.getObjectName());
    }

    @ResponseBody
    @RequestMapping("/initbinder")
    public Object testInitBinder(String param, String date,
                                 @ModelAttribute("user") User user) {
        System.out.println(user.getName());
        return param + ":" + date;
    }
}

后端输出

当前key:param
当前key:user
demoUser

前端输出

abc:2019

猜你喜欢

转载自blog.csdn.net/feiying0canglang/article/details/125231920