舒适提示:本文使用的spring boot版本为2.1.8.RELEASE。html
全局异常处理你们应该都接触过,也不是什么难事,网上一搜一大堆,可是写的对不对只能本身测试了,运气好的话找了一个能用的,运气很差的可能会烦到你怀疑人生。java
我就是那个运气很差的人,也是由于碰到了一些问题,因此才会有这篇文章吧。web
全局异常处理主要的好处:spring
通常的方案都是基于@ControllerAdvice
和@ExceptionHandler
作的。apache
@ControllerAdvice
至关于controller的切面,主要用于@ExceptionHandler
, @InitBinder
和@ModelAttribute
,使注解标注的方法对每个controller都起做用。默认对全部controller都起做用,固然也能够经过@ControllerAdvice
注解中的一些属性选定符合条件的controller。@ExceptionHandler
用于异常处理的注解,能够经过value指定处理哪一种类型的异常还能够与@ResponseStatus
搭配使用,处理特定的http错误。标记的方法入参与返回值都有很大的灵活性,具体能够看注释也能够后边的深度探究。其实有上面两个已经够了,还能够继承ResponseEntityExceptionHandler
json
读一下这个类的注释就知道它是干啥的了微信
大概意思就是这个类是为了方便统一异常处理的基类,可是要注意返回的是ResponseEntity
,若是不须要往响应体中写内容或者返回一个视图,可使用DefaultHandlerExceptionResolver
。session
能够看一下这个类的实现mvc
/** * Provides handling for standard Spring MVC exceptions. * @param ex the target exception * @param request the current request */ @ExceptionHandler({ HttpRequestMethodNotSupportedException.class, HttpMediaTypeNotSupportedException.class, HttpMediaTypeNotAcceptableException.class, MissingPathVariableException.class, MissingServletRequestParameterException.class, ServletRequestBindingException.class, ConversionNotSupportedException.class, TypeMismatchException.class, HttpMessageNotReadableException.class, HttpMessageNotWritableException.class, MethodArgumentNotValidException.class, MissingServletRequestPartException.class, BindException.class, NoHandlerFoundException.class, AsyncRequestTimeoutException.class }) @Nullable public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception { HttpHeaders headers = new HttpHeaders(); if (ex instanceof HttpRequestMethodNotSupportedException) { HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED; return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request); } else if (ex instanceof HttpMediaTypeNotSupportedException) { HttpStatus status = HttpStatus.UNSUPPORTED_MEDIA_TYPE; return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, headers, status, request); } else if (ex instanceof HttpMediaTypeNotAcceptableException) { HttpStatus status = HttpStatus.NOT_ACCEPTABLE; return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, headers, status, request); } else if (ex instanceof MissingPathVariableException) { HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; return handleMissingPathVariable((MissingPathVariableException) ex, headers, status, request); } else if (ex instanceof MissingServletRequestParameterException) { HttpStatus status = HttpStatus.BAD_REQUEST; return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, headers, status, request); } else if (ex instanceof ServletRequestBindingException) { HttpStatus status = HttpStatus.BAD_REQUEST; return handleServletRequestBindingException((ServletRequestBindingException) ex, headers, status, request); } else if (ex instanceof ConversionNotSupportedException) { HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; return handleConversionNotSupported((ConversionNotSupportedException) ex, headers, status, request); } else if (ex instanceof TypeMismatchException) { HttpStatus status = HttpStatus.BAD_REQUEST; return handleTypeMismatch((TypeMismatchException) ex, headers, status, request); } else if (ex instanceof HttpMessageNotReadableException) { HttpStatus status = HttpStatus.BAD_REQUEST; return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, headers, status, request); } else if (ex instanceof HttpMessageNotWritableException) { HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, headers, status, request); } else if (ex instanceof MethodArgumentNotValidException) { HttpStatus status = HttpStatus.BAD_REQUEST; return handleMethodArgumentNotValid((MethodArgumentNotValidException) ex, headers, status, request); } else if (ex instanceof MissingServletRequestPartException) { HttpStatus status = HttpStatus.BAD_REQUEST; return handleMissingServletRequestPart((MissingServletRequestPartException) ex, headers, status, request); } else if (ex instanceof BindException) { HttpStatus status = HttpStatus.BAD_REQUEST; return handleBindException((BindException) ex, headers, status, request); } else if (ex instanceof NoHandlerFoundException) { HttpStatus status = HttpStatus.NOT_FOUND; return handleNoHandlerFoundException((NoHandlerFoundException) ex, headers, status, request); } else if (ex instanceof AsyncRequestTimeoutException) { HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE; return handleAsyncRequestTimeoutException((AsyncRequestTimeoutException) ex, headers, status, request); } else { // Unknown exception, typically a wrapper with a common MVC exception as cause // (since @ExceptionHandler type declarations also match first-level causes): // We only deal with top-level MVC exceptions here, so let's rethrow the given // exception for further processing through the HandlerExceptionResolver chain. throw ex; } }
对于每一种异常,能够重写相应的方法。同时每一个异常的具体处理方法最后又调用了同一个方法app
/** * A single place to customize the response body of all exception types. * <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE} * request attribute and creates a {@link ResponseEntity} from the given * body, headers, and status. * @param ex the exception * @param body the body for the response * @param headers the headers for the response * @param status the response status * @param request the current request */ protected ResponseEntity<Object> handleExceptionInternal( Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST); } return new ResponseEntity<>(body, headers, status); }
通用的处理能够在这个方法中实现,返回结果中能够自定义body、header、以及http status。好比对于一些异常,可能并不但愿http status code为500,而是返回200,用body里的code再去判断是成功仍是失败,用这种方法就很是容易实现。
使用这种方案,咱们本身写的类就应该相似这种
package com.zworks.aircraft.web.advice; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @ControllerAdvice public class AirCraftExceptionHandler extends ResponseEntityExceptionHandler { }
能够去Spring Initializr去初始化工程
依赖只须要web就能够了,为了方即可以添加lombok
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.zworks</groupId> <artifactId>aircraft</artifactId> <version>0.0.1-SNAPSHOT</version> <name>aircraft</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
定义一个通用返回结果
package com.zworks.aircraft.model; import lombok.Data; @Data public class RespMsg<T> { private int code = 200; private String msg; private T data; public RespMsg() { } public RespMsg(int code, String msg) { this.code = code; this.msg = msg; } public RespMsg(T data) { this.data = data; } public static <T> RespMsg<T> success() { return new RespMsg(); } public static <T> RespMsg<T> success(T data) { return new RespMsg(data); } public static RespMsg failed(int code, String msg) { return new RespMsg(code, msg); } }
定义用户实体类,在字段上加上校验,方便演示错误的请求
package com.zworks.aircraft.model; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data public class User { @NotNull(message = "id不能为空") private Long id; @NotBlank(message = "名称不能为空") private String name; }
定义一个Controller,什么都不用干,只须要验证参数的合法性,而后返回正确便可。
package com.zworks.aircraft.web.controller; import com.zworks.aircraft.model.RespMsg; import com.zworks.aircraft.model.User; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController public class UserController { @PostMapping(value = "user") public RespMsg user(@Valid @RequestBody User user) { return RespMsg.success(); } }
若是参数正确,返回以下
{ "code": 200, "msg": null, "data": null }
但若是参数错误,好比不传入name,则会返回
{ "timestamp": "2019-09-07T14:04:54.440+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "NotBlank.user.name", "NotBlank.name", "NotBlank.java.lang.String", "NotBlank" ], "arguments": [ { "codes": [ "user.name", "name" ], "arguments": null, "defaultMessage": "name", "code": "name" } ], "defaultMessage": "名称不能为空", "objectName": "user", "field": "name", "rejectedValue": null, "bindingFailure": false, "code": "NotBlank" } ], "message": "Validation failed for object='user'. Error count: 1", "path": "/user" }
这确定不是咱们想要的结果。
按照刚才的方案,实现一个全局异常处理。
package com.zworks.aircraft.web.advice; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @ControllerAdvice public class AirCraftExceptionHandler extends ResponseEntityExceptionHandler { }
这个时候其实已经生效了,只是默认的什么数据都没有返回,能够重写handleExceptionInternal
方法
package com.zworks.aircraft.web.advice; import com.zworks.aircraft.model.RespMsg; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import org.springframework.web.util.WebUtils; @ControllerAdvice public class AirCraftExceptionHandler extends ResponseEntityExceptionHandler { protected ResponseEntity<Object> handleExceptionInternal( Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST); } logger.error(ex.getMessage(), ex);//打印异常信息 RespMsg respMsg = RespMsg.failed(status.value(), ex.getMessage());//使用http状态码做为返回体的code,同时把异常信息返回 return new ResponseEntity<>(respMsg, headers, status); } }
这时返回的信息以下
{ "code": 400, "msg": "Validation failed for argument [0] in public com.zworks.aircraft.model.RespMsg com.zworks.aircraft.web.controller.UserController.user(com.zworks.aircraft.model.User): [Field error in object 'user' on field 'name': rejected value [null]; codes [NotBlank.user.name,NotBlank.name,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.name,name]; arguments []; default message [name]]; default message [不能为空]] ", "data": null }
虽然已是咱们想要的格式了,可是返回的内容不太已读。
刚才打印了日志,能够看到报错为MethodArgumentNotValidException
,能够经过重写handleMethodArgumentNotValid
方法改变异常信息
package com.zworks.aircraft.web.advice; import com.zworks.aircraft.model.RespMsg; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import org.springframework.web.util.WebUtils; @ControllerAdvice public class AirCraftExceptionHandler extends ResponseEntityExceptionHandler { protected ResponseEntity<Object> handleExceptionInternal( Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST); } logger.error(ex.getMessage(), ex);//打印异常信息 RespMsg respMsg = RespMsg.failed(status.value(), ex.getMessage());//使用http状态码做为返回体的code,同时把异常信息返回 return new ResponseEntity<>(respMsg, headers, status); } protected ResponseEntity<Object> handleMethodArgumentNotValid( MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { StringBuffer sb = new StringBuffer(); ex.getBindingResult().getAllErrors().forEach(error -> { sb.append(error.getDefaultMessage()).append(";"); }); RespMsg respMsg = RespMsg.failed(status.value(), sb.toString()); return new ResponseEntity<>(respMsg, headers, HttpStatus.OK);//这里能够根据具体状况改变状态码 } }
返回以下
{ "code": 400, "msg": "名称不能为空;", "data": null }
同时须要注意的是,因为我修改了返回码,此次请求返回的是http status code是200而不是以前的400。
在最开始没有自定义全局异常处理的时候,也返回了错误信息,那这个是谁处理的呢。
默认spring boot 会提供一个/error映射处理全部的异常。并且会根据请求的不一样返回一个页面或是json。
在ErrorMvcAutoConfiguration
类中能够看到
@Bean @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT) public DefaultErrorAttributes errorAttributes() { return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException()); } @Bean @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT) public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) { return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers); }
均可以经过本身定义相应的类进行定制化。
以前因为被网上文章误导,使用前面那种方式没成功,为了记录异常,我还写了个切面。
package com.zworks.aircraft.config; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Aspect @Component @Slf4j public class ErrorControllerAspect { @Before("execution(public * org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.*(..))") public void before(JoinPoint joinPoint) { Object arg = joinPoint.getArgs()[0]; if (arg instanceof HttpServletRequest) { HttpServletRequest request = (HttpServletRequest) arg; log.error((String) request.getAttribute("javax.servlet.error.message"), (Throwable) request.getAttribute("javax.servlet.error.exception")); } } }
我被坑主要是由于看了一篇文章,Validation in Spring Boot,我不能说必定是文章的问题,至少我按他的没作对。
异常处理是这么写的
package com.zworks.aircraft.web.advice; import org.springframework.http.HttpStatus; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import java.util.HashMap; import java.util.Map; @ControllerAdvice public class AirCraftExceptionHandler { @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return errors; } }
注意这里返回的是Map类型
返回和没加是同样的
{ "timestamp": "2019-09-07T14:30:21.688+0000", "status": 500, "error": "Internal Server Error", "errors": [ { "codes": [ "NotBlank.user.name", "NotBlank.name", "NotBlank.java.lang.String", "NotBlank" ], "arguments": [ { "codes": [ "user.name", "name" ], "arguments": null, "defaultMessage": "name", "code": "name" } ], "defaultMessage": "名称不能为空", "objectName": "user", "field": "name", "rejectedValue": null, "bindingFailure": false, "code": "NotBlank" } ], "message": "Validation failed for object='user'. Error count: 1", "path": "/user" }
而后我在那个方法上打了断点,发现代码竟然执行了
而后我就跟代码,也对比了两种实现的执行状况,发如今HandlerMethodReturnValueHandlerComposite
的selectHandler
方法中会根据返回的类型决定使用那个handler进行处理
@Nullable private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } if (handler.supportsReturnType(returnType)) { return handler; } } return null; }
如今的handler是MapMethodProcessor
而若是咱们将返回值格式改一下
package com.zworks.aircraft.web.advice; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import java.util.HashMap; import java.util.Map; @ControllerAdvice public class AirCraftExceptionHandler { @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleValidationExceptions(MethodArgumentNotValidException ex) { Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return new ResponseEntity<>(errors, new HttpHeaders(), HttpStatus.OK);//这里能够根据具体状况改变状态码 } }
会发现handler变成了HttpEntityMethodProcessor
返回值也没问题了
{ "name": "名称不能为空" }
大部分人从网上查到了信息,都不会考虑请求参数该传那些,顺序有没有影响吧,受前面返回类型的影响,我也看了下请求参数相关的。
能够在本身的方法中打个断点,而后不断找上层调用。
在InvocableHandlerMethod
的invokeForRequest
方法中能够看到
@Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } return doInvoke(args); }
会获取参数,而后调用咱们的方法
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { // Leave stack trace for later, exception may actually be resolved and handled... if (logger.isDebugEnabled()) { String exMsg = ex.getMessage(); if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, exMsg)); } } throw ex; } } return args; }
在findProvidedArgument
中会根据类型找参数
@Nullable protected static Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) { if (!ObjectUtils.isEmpty(providedArgs)) { for (Object providedArg : providedArgs) { if (parameter.getParameterType().isInstance(providedArg)) { return providedArg; } } } return null; }
providedArgs
中有两个类型,一个是org.springframework.web.bind.MethodArgumentNotValidException
类型,也就是异常,另外一个是org.springframework.web.method.HandlerMethod
。因此若是单写一个异常是没问题的。
若是经过providedArgs
没取到,会从resolvers
里去取。
只要这些resolvers
能支持的参数,均可以取到。
好比看到了上面有ServletRequestMethodArgumentResolver
类,能够看到支持HttpSession
@Override public boolean supportsParameter(MethodParameter parameter) { Class<?> paramType = parameter.getParameterType(); return (WebRequest.class.isAssignableFrom(paramType) || ServletRequest.class.isAssignableFrom(paramType) || MultipartRequest.class.isAssignableFrom(paramType) || HttpSession.class.isAssignableFrom(paramType) || (pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) || Principal.class.isAssignableFrom(paramType) || InputStream.class.isAssignableFrom(paramType) || Reader.class.isAssignableFrom(paramType) || HttpMethod.class == paramType || Locale.class == paramType || TimeZone.class == paramType || ZoneId.class == paramType); }
咱们测试下,在参数里添加一个HttpSession
package com.zworks.aircraft.web.advice; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.context.request.WebRequest; import javax.servlet.http.HttpSession; import java.util.HashMap; import java.util.Map; @Slf4j @ControllerAdvice public class AirCraftExceptionHandler { @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleValidationExceptions(WebRequest request, MethodArgumentNotValidException ex, HttpSession httpSession) { log.info("sessionId:{}", httpSession.getId()); Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return new ResponseEntity<>(errors, new HttpHeaders(), HttpStatus.OK);//这里能够根据具体状况改变状态码 } }
能够看到已经输出了sessionId
2019-09-07 23:15:43.257 INFO 25692 --- [nio-8080-exec-1] c.z.a.w.advice.AirCraftExceptionHandler : sessionId:B9C6E5BA4156BBBC5931FFE9B259E5ED
请求参数的处理方式和返回类型的处理方式是否很类似呢
全局异常处理我也处理过不少次了,大部分也都是网上找一篇,虽然每次不会花不少时间,可是作了这么多遍也只是有个大概印象,并无很深刻的去探究过。整理一下,知识才会变成本身的。
看到了这里必定是真爱了,关注微信公众号【憨憨的春天】第一时间获取更新