0. 前言
最近搞微服务的全家桶,用到的Spring Cloud Gateway 这个组件。需要对这个网关抛出的异常进行自定义。网关的异常处理跟单体SpringBoot的全局异常处理还有点不一样。
单体全局异常处理,是采用@RestControllerAdvice 这个注解来实现的。微服务Gateway是采用另外的方式来实现的。
1. 单体自定义异常返回
CustomException.java
1 package com.wunaozai.config.advice;
2
3 /**
4 * 自定义异常类(运行时异常)
5 * @author wunaozai
6 * @date 2018-06-27
7 */
8 public class CustomException extends RuntimeException {
9
10 private static final long serialVersionUID = 6304501072268270030L;
11
12 public CustomException(String msg) {
13 this(500, msg);
14 }
15 public CustomException(int code, String msg) {
16 this(code, msg, null);
17 }
18 public CustomException(String msg, Object data) {
19 this(500, msg, data);
20 }
21 public CustomException(int code, String msg, Object data) {
22 super(msg);
23 this.code = code;
24 this.msg = msg;
25 this.data = data;
26 }
27
28
29 /**
30 * 异常代码
31 */
32 private int code;
33 /**
34 * 异常信息
35 */
36 private String msg;
37 /**
38 * 异常调试信息
39 */
40 private Object data;
41
42 /**
43 * 异常代码
44 * @return code
45 */
46 public int getCode() {
47 return code;
48 }
49 /**
50 * 异常代码
51 * @param code 异常代码
52 */
53 public void setCode(int code) {
54 this.code = code;
55 }
56 /**
57 * 异常信息
58 * @return msg
59 */
60 public String getMsg() {
61 return msg;
62 }
63 /**
64 * 异常信息
65 * @param msg 异常信息
66 */
67 public void setMsg(String msg) {
68 this.msg = msg;
69 }
70 /**
71 * 异常调试信息
72 * @return data
73 */
74 public Object getData() {
75 return data;
76 }
77 /**
78 * 异常调试信息
79 * @param data 异常调试信息
80 */
81 public void setData(Object data) {
82 this.data = data;
83 }
84 }
CustomControllerAdvice.java
1 package com.wunaozai.config.advice;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.springframework.ui.Model;
7 import org.springframework.web.bind.WebDataBinder;
8 import org.springframework.web.bind.annotation.ExceptionHandler;
9 import org.springframework.web.bind.annotation.InitBinder;
10 import org.springframework.web.bind.annotation.ModelAttribute;
11 import org.springframework.web.bind.annotation.RestControllerAdvice;
12
13 import com.baomidou.mybatisplus.extension.api.R;
14
15 /**
16 * 控制器Controller异常处理
17 * @author wunaozai
18 * @Date 2020-03-05
19 */
20 @RestControllerAdvice
21 public class CustomControllerAdvice {
22
23 /**
24 * 应用到所有@RequestMapper 注解方法,在其执行之前初始化数据绑定器
25 * @param binder
26 */
27 @InitBinder
28 public void initBinder(WebDataBinder binder) {
29
30 }
31
32 /**
33 * 把值绑定到Model中,使全局@RequestMapper可以获取到该值
34 * @param model
35 */
36 @ModelAttribute
37 public void addAttributes(Model model) {
38 model.addAttribute("Server", "Wunaozai");
39 }
40
41 @ExceptionHandler(value= {Exception.class, CustomException.class})
42 public R errorHandler(Exception ex){
43 Map map = new HashMap<>();
44 map.put("code", 500);
45 map.put("msg", ex.getMessage());
46 System.out.println("异常Handler.");
47 ex.printStackTrace();
48 //System.out.println(resuserService.count());
49 return R.failed(ex.getMessage());
50 }
51 }
2. 微服务Gateway自定义异常返回
JsonExceptionHandler.java
1 package com.wunaozai.config.exception;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.springframework.boot.autoconfigure.web.ErrorProperties;
7 import org.springframework.boot.autoconfigure.web.ResourceProperties;
8 import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
9 import org.springframework.boot.web.reactive.error.ErrorAttributes;
10 import org.springframework.cloud.gateway.support.NotFoundException;
11 import org.springframework.context.ApplicationContext;
12 import org.springframework.http.HttpStatus;
13 import org.springframework.web.reactive.function.server.RequestPredicates;
14 import org.springframework.web.reactive.function.server.RouterFunction;
15 import org.springframework.web.reactive.function.server.RouterFunctions;
16 import org.springframework.web.reactive.function.server.ServerRequest;
17 import org.springframework.web.reactive.function.server.ServerResponse;
18
19 import lombok.extern.slf4j.Slf4j;
20
21 /**
22 * 序列化
23 * @author wunaozai
24 * @Date 2020-06-04
25 */
26 @Slf4j
27 public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {
28
29 public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
30 ErrorProperties errorProperties, ApplicationContext applicationContext) {
31 super(errorAttributes, resourceProperties, errorProperties, applicationContext);
32 }
33
34 @Override
35 protected Map getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
36 int code = HttpStatus.INTERNAL_SERVER_ERROR.value();
37 Throwable error = super.getError(request);
38 // if(error instanceof NotFoundException) {
39 // code = HttpStatus.NOT_FOUND.value();
40 // }
41 return response(code, this.buildMessage(request, error));
42 }
43
44 /**
45 * 指定响应处理方法为JSON处理的方法
46 * @param errorAttributes
47 */
48 @Override
49 protected RouterFunction getRoutingFunction(ErrorAttributes errorAttributes) {
50 return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
51 }
52
53
54 /**
55 * 根据code获取对应的HttpStatus
56 * @param errorAttributes
57 */
58 @Override
59 protected int getHttpStatus(Map errorAttributes) {
60 int statusCode = (int) errorAttributes.get("code");
61 return statusCode;
62 }
63
64 /**
65 * 构建异常信息
66 * @param request
67 * @param ex
68 * @return
69 */
70 private String buildMessage(ServerRequest request, Throwable ex) {
71 StringBuilder message = new StringBuilder("Failed to handle request [");
72 message.append(request.methodName());
73 message.append(" ");
74 message.append(request.uri());
75 message.append("]");
76 if (ex != null) {
77 message.append(": ");
78 message.append(ex.getMessage());
79 }
80 return message.toString();
81 }
82
83 /**
84 * 构建返回的JSON数据格式
85 * @param status 状态码
86 * @param errorMessage 异常信息
87 * @return
88 */
89 public static Map response(int status, String errorMessage) {
90 Map map = new HashMap<>();
91 map.put("code", status);
92 map.put("message", errorMessage);
93 map.put("data", null);
94 log.error(map.toString());
95 return map;
96 }
97 }
ExceptionHandlerConfiguration.java
1 package com.wunaozai.config.exception;
2
3 import java.util.Collections;
4 import java.util.List;
5
6 import org.springframework.beans.factory.ObjectProvider;
7 import org.springframework.boot.autoconfigure.web.ResourceProperties;
8 import org.springframework.boot.autoconfigure.web.ServerProperties;
9 import org.springframework.boot.context.properties.EnableConfigurationProperties;
10 import org.springframework.boot.web.reactive.error.ErrorAttributes;
11 import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
12 import org.springframework.context.ApplicationContext;
13 import org.springframework.context.annotation.Bean;
14 import org.springframework.context.annotation.Configuration;
15 import org.springframework.core.Ordered;
16 import org.springframework.core.annotation.Order;
17 import org.springframework.http.codec.ServerCodecConfigurer;
18 import org.springframework.web.reactive.result.view.ViewResolver;
19
20 /**
21 * 自定义异常处理
22 * https://www.cnblogs.com/viaiu/p/10403557.html
23 * @author wunaozai
24 * @Date 2020-06-04
25 */
26 @Configuration
27 @EnableConfigurationProperties({ ServerProperties.class, ResourceProperties.class })
28 public class ExceptionHandlerConfiguration {
29
30 private final ServerProperties serverProperties;
31
32 private final ApplicationContext applicationContext;
33
34 private final ResourceProperties resourceProperties;
35
36 private final List viewResolvers;
37
38 private final ServerCodecConfigurer serverCodecConfigurer;
39
40 public ExceptionHandlerConfiguration(ServerProperties serverProperties, ResourceProperties resourceProperties,
41 ObjectProvider> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer,
42 ApplicationContext applicationContext) {
43 this.serverProperties = serverProperties;
44 this.applicationContext = applicationContext;
45 this.resourceProperties = resourceProperties;
46 this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
47 this.serverCodecConfigurer = serverCodecConfigurer;
48 }
49
50 @Bean
51 @Order(Ordered.HIGHEST_PRECEDENCE)
52 public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
53 JsonExceptionHandler exceptionHandler = new JsonExceptionHandler(errorAttributes, this.resourceProperties,
54 this.serverProperties.getError(), this.applicationContext);
55 exceptionHandler.setViewResolvers(this.viewResolvers);
56 exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
57 exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
58 return exceptionHandler;
59 }
60 }
处理前异常返回
自定义后异常返回
参考资料: https://www.cnblogs.com/viaiu/p/10403557.html
本文地址: https://www.cnblogs.com/wunaozai/p/13043979.html
Original: https://www.cnblogs.com/wunaozai/p/13043979.html
Author: 无脑仔的小明
Title: Spring Cloud Gateway配置自定义异常返回
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/540649/
转载文章受原作者版权保护。转载请注明原作者出处!