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
作者:无脑仔的小明 出处:http://www.cnblogs.com/wunaozai/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果文中有什么错误,欢迎指出。以免更多的人被误导。有需要沟通的,可以站内私信,文章留言,或者关注“无脑仔的小明”公众号私信我。一定尽力回答。 |