Spring Cloud Gateway配置自定义异常返回

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<String> errorHandler(Exception ex){
43         Map<String, Object> 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<String, Object> 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<ServerResponse> 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<String, Object> 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<String, Object> response(int status, String errorMessage) {
90         Map<String, Object> 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  * 自定义异常处理<br>
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<ViewResolver> viewResolvers;
37 
38     private final ServerCodecConfigurer serverCodecConfigurer;
39 
40     public ExceptionHandlerConfiguration(ServerProperties serverProperties, ResourceProperties resourceProperties,
41             ObjectProvider<List<ViewResolver>> 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

 

posted @ 2020-06-09 16:57  无脑仔的小明  阅读(7752)  评论(0编辑  收藏  举报