SpringBoot--全局响应处理--方法/实例

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

简介

说明

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

方案简述

         全局响应处理(处理返回值):@ControllerAdvice+ 实现ResponseBodyAdvice接口。

        @ControllerAdvice所在类的beforBodyWrite方法将会在Controller方法执行之后执行。

系列文章

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博客

实例

代码

 @ControllerAdvice类

package com.example.common;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 
@RestControllerAdvice
// 也可以:类上加@ControllerAdvice + 方法上加@ResponseBody
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {
 
    @Override
    public boolean supports(MethodParameter returnType,
                            Class<? extends HttpMessageConverter<?>> converterType) {
        // 若接口返回的类型本身就是ResultWrapper,则无需操作,返回false
        // return !returnType.getParameterType().equals(ResultWrapper.class);
        System.out.println("GlobalResponseBodyAdvice#supports");
        return true;
    }
 
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        System.out.println("GlobalResponseBodyAdvice#beforeBodyWrite");
        if (body instanceof String) {
            // 若返回值为String类型,需要包装为String类型返回。否则会报错
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                Result<Object> result = new Result<>().data(body);
                return objectMapper.writeValueAsString(result);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("序列化String错误");
            }
        } else if (body instanceof Result) {
            return body;
        } else if (isKnife4jUrl(request.getURI().getPath())) {
            // 如果是接口文档uri,直接跳过
            return body;
        }
        return new Result<>().data(body);
    }
 
    private boolean isKnife4jUrl(String uri) {
        // AntPathMatcher pathMatcher = new AntPathMatcher();
        // for (String s : WhiteList.KNIFE4J) {
        //     if (pathMatcher.match(s, uri)) {
        //         return true;
        //     }
        // }
        return false;
    }
}

controller

package com.example.business.controller;

import com.example.business.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

    @GetMapping("/getUser")
    public User getUser() {
        return new User(1L, "Tony", 23);
    }

}

测试

postman访问:http://localhost:8080/user/getUser

postman结果

后端结果

猜你喜欢

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