java项目中的一些通用处理

一、全局异常处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 * 统一异常处理、数据预处理等
 */
@ControllerAdvice
public class ControllerExceptionHandler {
    private static final Logger LOG = LoggerFactory.getLogger(ControllerExceptionHandler.class);
    /**
     * 所有异常统一处理,出现这个情况很可能有bug
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    //状态码自定义,出现这个状态码大概率就有未处理异常或者bug
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) 
    public CommonResp exceptionHandler(Exception e) {
        CommonResp commonResp = new CommonResp();
        LOG.error("系统异常:", e);
        commonResp.setSuccess(false);
        commonResp.setMessage("系统出现异常,请联系管理员");
        return commonResp;
    }
    /**
     * 所有自定义异常统一处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public CommonResp businessExceptionHandler(BusinessException e) {
        CommonResp commonResp = new CommonResp();
        LOG.error("业务异常:", e);
        commonResp.setSuccess(false);
        commonResp.setMessage(e.getMessage());
        return commonResp;
    }
    /**
     * 校验异常统一处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public CommonResp validExceptionHandler(BindException e) {
        CommonResp commonResp = new CommonResp();
        LOG.warn("参数校验失败:{}", e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
        commonResp.setSuccess(false);
        commonResp.setMessage(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
        return commonResp;
    }
}
//自定义异常
public class BusinessException extends RuntimeException {
    private BusinessExceptionEnum exceptionEnum;
    public BusinessException(BusinessExceptionEnum exceptionEnum) {
        super(exceptionEnum.getMessage());
        this.exceptionEnum = exceptionEnum;
    }
    public BusinessExceptionEnum getExceptionEnum() {
        return exceptionEnum;
    }
    public void setExceptionEnum(BusinessExceptionEnum exceptionEnum) {
        this.exceptionEnum = exceptionEnum;
    }
    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}

二、全局返回值处理

实现返回值处理接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class ApiResponseHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
    private final HandlerMethodReturnValueHandler handler;
    private static final HashSet<String> URL_SET = new HashSet<>() {{
        add("/alipay/pay");
        add("/wechat/pay");
    }};
    public ApiResponseHandlerMethodReturnValueHandler(HandlerMethodReturnValueHandler handler) {
        this.handler = handler;
    }
    @Override
    public boolean supportsReturnType(MethodParameter methodParameter) {
        return this.handler.supportsReturnType(methodParameter);
    }
    @Override
    public void handleReturnValue(Object returnValue,
                                  MethodParameter methodParameter,
                                  ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest) throws Exception {
        String servletPath = nativeWebRequest.getNativeRequest(HttpServletRequest.class).getServletPath();
        // 这里根据请求路径做一些处理,比如支付宝、微信支付等接口,对返回值有明确要求的接口路径。保持原返回格式
        //todo: 所有的支付接口,都需要
        if (URL_SET.contains(servletPath)) {
            this.handler.handleReturnValue(returnValue, methodParameter, modelAndViewContainer, nativeWebRequest);
            return;
        }
        // 已经被包装过的CommonResp返回值,直接返回
        if (returnValue instanceof CommonResp<?> value) {
            this.handler.handleReturnValue(returnValue, methodParameter, modelAndViewContainer, nativeWebRequest);
            return;
        }
        // 其他接口返回值,包装成CommonResp返回值
        this.handleReturnValue(CommonResp.success(returnValue), methodParameter, modelAndViewContainer, nativeWebRequest);
    }
}

替换原有的返回值处理器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Configuration
public class WebMvcConfiguration {
    @Autowired
    public void resetRequestMappingHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        var oldReturnValueHandlers = requestMappingHandlerAdapter.getReturnValueHandlers();
        assert oldReturnValueHandlers != null;
        List<HandlerMethodReturnValueHandler> list = new ArrayList<>(oldReturnValueHandlers.size());
        for (HandlerMethodReturnValueHandler returnValueHandler : oldReturnValueHandlers) {
            // 替换原有的返回值处理器
            if (returnValueHandler instanceof RequestResponseBodyMethodProcessor) {
                list.add(new ApiResponseHandlerMethodReturnValueHandler(returnValueHandler));
            } else {
                list.add(returnValueHandler);
            }
        }
        requestMappingHandlerAdapter.setReturnValueHandlers(list);
    }
}

3、序列化替换jackson为fastjson2

  1. 添加Fastjson2依赖: 首先,在你的pom.xml文件中添加Fastjson2的依赖。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson2</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <artifactId>fastjson2-extension-spring6</artifactId>
        <groupId>com.alibaba.fastjson2</groupId>
        <version>2.0.2</version>
    </dependency>
    
  2. 配置Fastjson2为默认的序列化工具

    创建一个配置类,用于替换Spring Boot默认的Jackson为Fastjson2。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    import com.alibaba.fastjson2.support.config.FastJsonConfig;
    import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
    import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.HttpMessageConverter;
    
    @Configuration
    public class FastJsonConfiguration {
        @Bean
        public HttpMessageConverters fastJsonHttpMessageConverters() {
            // 1. 需要定义一个convert转换消息的对象;
            FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
            // 2. 添加fastJson的配置信息,比如:是否要格式化返回的json数据;
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
            fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
            fastConverter.setFastJsonConfig(fastJsonConfig);
            // 3. 在convert中添加配置信息;
            return new HttpMessageConverters(fastConverter);
        }
    }
    
  3. 移除Jackson依赖(可选): 如果你不希望Spring Boot项目中包含Jackson依赖,防止用到了默认的jackson后与预期的序列化不一致,可以在pom.xml中排除Jackson依赖。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    

通过以上步骤,你就可以将Spring Boot默认的Jackson序列化工具替换为Fastjson2。这样,Spring Boot应用在处理HTTP请求和响应时,将使用Fastjson2进行序列化和反序列化。

Talk is cheap, show me the bug/code.
使用 Hugo 构建
主题 StackJimmy 设计