-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
qinyujie3
committed
May 12, 2023
1 parent
622f98f
commit f2aab04
Showing
12 changed files
with
242 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
src/main/java/com/feiniaojin/gracefulresponse/advice/ValidationExceptionAdvice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package com.feiniaojin.gracefulresponse.advice; | ||
|
||
import com.feiniaojin.gracefulresponse.GracefulResponseProperties; | ||
import com.feiniaojin.gracefulresponse.api.ResponseFactory; | ||
import com.feiniaojin.gracefulresponse.api.ResponseStatusFactory; | ||
import com.feiniaojin.gracefulresponse.api.ValidationStatusCode; | ||
import com.feiniaojin.gracefulresponse.data.Response; | ||
import com.feiniaojin.gracefulresponse.data.ResponseStatus; | ||
import org.springframework.core.annotation.Order; | ||
import org.springframework.validation.BindException; | ||
import org.springframework.validation.FieldError; | ||
import org.springframework.validation.ObjectError; | ||
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.ResponseBody; | ||
import org.springframework.web.context.request.RequestAttributes; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
import org.springframework.web.method.HandlerMethod; | ||
import org.springframework.web.servlet.HandlerExecutionChain; | ||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||
|
||
import javax.annotation.Resource; | ||
import javax.validation.ConstraintViolation; | ||
import javax.validation.ConstraintViolationException; | ||
import javax.validation.ValidationException; | ||
import java.lang.reflect.Field; | ||
import java.lang.reflect.Method; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
@ControllerAdvice | ||
@Order(100) | ||
public class ValidationExceptionAdvice { | ||
|
||
@Resource | ||
private RequestMappingHandlerMapping mapping; | ||
|
||
@Resource | ||
private ResponseStatusFactory responseStatusFactory; | ||
|
||
@Resource | ||
private ResponseFactory responseFactory; | ||
|
||
@Resource | ||
private GracefulResponseProperties gracefulResponseProperties; | ||
|
||
@ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class}) | ||
@ResponseBody | ||
public Response exceptionHandler(Exception e) throws Exception { | ||
|
||
if (e instanceof BindException) { | ||
ResponseStatus responseStatus = this.fromBindException(e); | ||
return responseFactory.newInstance(responseStatus); | ||
} | ||
|
||
if (e instanceof MethodArgumentNotValidException) { | ||
ResponseStatus responseStatus = this.fromMethodArgumentNotValidException(e); | ||
return responseFactory.newInstance(responseStatus); | ||
} | ||
|
||
if (e instanceof ConstraintViolationException) { | ||
ResponseStatus responseStatus = this.fromConstraintViolationException(e); | ||
return responseFactory.newInstance(responseStatus); | ||
} | ||
|
||
return responseFactory.newFailInstance(); | ||
} | ||
|
||
private ResponseStatus fromMethodArgumentNotValidException(Exception e) throws Exception { | ||
MethodArgumentNotValidException me = (MethodArgumentNotValidException) e; | ||
List<ObjectError> allErrors = me.getBindingResult().getAllErrors(); | ||
String msg = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining(";")); | ||
String code = this.determineErrorCode(); | ||
return responseStatusFactory.newInstance(code, msg); | ||
} | ||
|
||
private String determineErrorCode() throws Exception { | ||
Method method = this.currentControllerMethod(); | ||
ValidationStatusCode validateStatusCode = method.getAnnotation(ValidationStatusCode.class); | ||
if (validateStatusCode == null) { | ||
validateStatusCode = method.getDeclaringClass().getAnnotation(ValidationStatusCode.class); | ||
} | ||
if (validateStatusCode != null) { | ||
return validateStatusCode.code(); | ||
} | ||
return gracefulResponseProperties.getDefaultValidateErrorCode(); | ||
} | ||
|
||
private Method currentControllerMethod() throws Exception { | ||
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); | ||
ServletRequestAttributes sra = (ServletRequestAttributes) requestAttributes; | ||
HandlerExecutionChain handlerChain = mapping.getHandler(sra.getRequest()); | ||
HandlerMethod handler = (HandlerMethod) handlerChain.getHandler(); | ||
Method method = handler.getMethod(); | ||
return method; | ||
} | ||
|
||
private ResponseStatus fromConstraintViolationException(Exception e) throws Exception { | ||
|
||
ConstraintViolationException exception = (ConstraintViolationException) e; | ||
Set<ConstraintViolation<?>> violationSet = exception.getConstraintViolations(); | ||
String msg = violationSet.stream().map(s -> s.getConstraintDescriptor().getMessageTemplate()).collect(Collectors.joining(";")); | ||
String code = this.determineErrorCode(); | ||
return responseStatusFactory.newInstance(code, msg); | ||
} | ||
|
||
private ResponseStatus fromBindException(Exception e) throws NoSuchFieldException { | ||
|
||
String code; | ||
|
||
BindException bindException = (BindException) e; | ||
FieldError fieldError = bindException.getFieldError(); | ||
String fieldName = fieldError.getField(); | ||
Object target = bindException.getTarget(); | ||
Field declaredField = target.getClass().getDeclaredField(fieldName); | ||
declaredField.setAccessible(true); | ||
ValidationStatusCode annotation = declaredField.getAnnotation(ValidationStatusCode.class); | ||
declaredField.setAccessible(false); | ||
|
||
//属性上找不到注解,尝试获取类上的注解 | ||
if (annotation == null) { | ||
annotation = target.getClass().getAnnotation(ValidationStatusCode.class); | ||
} | ||
|
||
if (annotation != null) { | ||
code = annotation.code(); | ||
} else { | ||
code = gracefulResponseProperties.getDefaultValidateErrorCode(); | ||
} | ||
|
||
String msg = bindException.getAllErrors() | ||
.stream().map(s -> s.getDefaultMessage()) | ||
.collect(Collectors.joining(";")); | ||
|
||
return responseStatusFactory.newInstance(code, msg); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
src/main/java/com/feiniaojin/gracefulresponse/api/ValidationStatusCode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.feiniaojin.gracefulresponse.api; | ||
|
||
import com.feiniaojin.gracefulresponse.defaults.DefaultConstants; | ||
|
||
import java.lang.annotation.*; | ||
|
||
/** | ||
* 指定参数校验的异常码 | ||
*/ | ||
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Inherited | ||
public @interface ValidationStatusCode { | ||
|
||
/** | ||
* 异常对应的错误码. | ||
* | ||
* @return 异常对应的错误码 | ||
*/ | ||
String code() default DefaultConstants.DEFAULT_ERROR_CODE; | ||
} |
28 changes: 28 additions & 0 deletions
28
src/main/java/com/feiniaojin/gracefulresponse/defaults/DefaultConstants.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.feiniaojin.gracefulresponse.defaults; | ||
|
||
/** | ||
* 默认的响应码和提示信息 | ||
*/ | ||
public class DefaultConstants { | ||
|
||
/** | ||
* 默认的成功响应码 | ||
*/ | ||
public static final String DEFAULT_SUCCESS_CODE = "0"; | ||
|
||
/** | ||
* 默认的成功提示信息 | ||
*/ | ||
public static final String DEFAULT_SUCCESS_MSG = "ok"; | ||
|
||
/** | ||
* 默认的错误码 | ||
*/ | ||
public static final String DEFAULT_ERROR_CODE = "1"; | ||
|
||
/** | ||
* 默认的错误提示 | ||
*/ | ||
public static final String DEFAULT_ERROR_MSG = "error"; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.