使用 @ControllerAdvice 和 实现ResponseBodyAdvice接口, 拦截Controller方法默认返回参数,统一处理返回值/响应体

直接上代码

package com.XX.edu.advice;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.XX.edu.annotation.NotControllerResponseAdvice;
import com.XX.edu.common.bean.ResultTO;
import com.XX.edu.exception.APIException;
import com.XX.edu.exception.AppCode;
import org.springframework.core.MethodParameter;
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.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @description:对返回进行封装(response是ResultTO类型,或者注释了NotControllerResponseAdvice都不进行包装) 使用 @ControllerAdvice 和 实现ResponseBodyAdvice接口, 拦截Controller方法默认返回参数,统一处理返回值/响应体
 * @author:
 * @date: 2022/7/15 15:23
 * @param: null
 * @return:
 **/
@RestControllerAdvice(basePackages = {"com.XX.edu"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {
    //supports对你需要进行拦截的response进行判断筛选,返回true则进行拦截反之放行
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        // response是ResultTO类型,或者注释了NotControllerResponseAdvice都不进行包装
        return !(methodParameter.getParameterType().isAssignableFrom(ResultTO.class) || methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class));
    }

    //beforeBodyWrite对supports进行拦截的response进行处理,封装你需要的类型参数,加密等等
    @Override
    public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {
        // String类型不能直接包装
        if (returnType.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在ResultTO里后转换为json串进行返回
                return objectMapper.writeValueAsString(ResultTO.OK(data));
            } catch (JsonProcessingException e) {
                throw new APIException(AppCode.VALIDATE_ERROR, e.getMessage());
            }
        }
        // 否则直接包装成ResultVo返回
        return ResultTO.OK(data);
    }
}

对于不想封装的返回如何处理??

自定义注解:

package com.XX.edu.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotControllerResponseAdvice {
}
ControllerResponseAdvice实现ResponseBodyAdvice<Object>接口

在supports方法中处理,凡是有注解的都跳过封装,不进入beforeBodyWrite方法。

完成收工~~!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果使用@ControllerAdvice注解拦截接口时,没有拦截到手动抛出的异常,可能是以下原因: 1. 异常类型不匹配:@ControllerAdvice通常是根据异常类型来拦截异常的,如果手动抛出的异常类型与拦截的异常类型不匹配,就不会被拦截。可以尝试在@ControllerAdvice注解中添加拦截的异常类型,例如: ``` @ControllerAdvice(Exception.class) public class GlobalExceptionHandler { // ... } ``` 2. 异常未被捕获:如果手动抛出异常时,没有被try-catch语句捕获,而是直接抛出到调用栈上,就不会被@ControllerAdvice拦截。可以尝试在抛出异常的方法上添加throws声明,或者在调用该方法使用try-catch语句捕获异常。 3. 拦截器顺序问题:如果项目中使用了多个拦截器,可能存在拦截器顺序问题,导致@ControllerAdvice无法拦截异常。可以尝试在拦截器中调整拦截器的顺序,或者在@ControllerAdvice注解中添加优先级,例如: ``` @ControllerAdvice(priority = 1) public class GlobalExceptionHandler { // ... } ``` 4. 拦截器未激活:如果没有激活拦截器,@ControllerAdvice也无法拦截异常。可以尝试在配置文件中激活拦截器,例如: ``` spring.mvc.throw-exception-if-no-handler-found=true spring.resources.add-mappings=false ``` 总之,如果使用@ControllerAdvice注解拦截接口时,没有拦截到手动抛出的异常,可以从异常类型、异常捕获、拦截器顺序和拦截器激活等方面进行排查。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值