Skip to content

Commit

Permalink
3.5.2
Browse files Browse the repository at this point in the history
修复JSON入参中列表元素参数校验问题
  • Loading branch information
feiniaojin committed Feb 27, 2024
1 parent aef852f commit 63be8cb
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 33 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.feiniaojin</groupId>
<artifactId>graceful-response</artifactId>
<version>3.5.1-boot3</version>
<version>3.5.2-boot3</version>
<name>Graceful Response for Boot3</name>
<description>Help Spring Boot web application responses gracefully!</description>
<url>https://github.com/feiniaojin/graceful-response.git</url>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.annotation.Order;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
Expand Down Expand Up @@ -53,6 +57,9 @@ public class ValidationExceptionAdvice {
@Resource
private GracefulResponseProperties gracefulResponseProperties;

private static ExpressionParser parser = new SpelExpressionParser();


@ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
@ResponseBody
public Response exceptionHandler(Exception e) throws Exception {
Expand All @@ -72,48 +79,54 @@ public Response exceptionHandler(Exception e) throws Exception {
}

//Controller方法的参数校验码
//Controller方法>Controller类>DTO入参属性>DTO入参类>配置文件默认参数码>默认错误码
//Controller方法>Controller类>DTO入参属性>DTO入参属性所在类>DTO入参根类>配置文件默认参数码>默认错误码
//这个取值顺序的逻辑是按照个性化程度由高到底排序的
private ResponseStatus handleBindException(BindException e) throws Exception {
List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
BindingResult bindingResult = e.getBindingResult();
List<ObjectError> allErrors = bindingResult.getAllErrors();
String msg = allErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";"));
String code;
//Controller方法上的注解
//Controller方法和类上的注解
ValidationStatusCode validateStatusCode = this.findValidationStatusCodeInController();
if (validateStatusCode != null) {
code = validateStatusCode.code();
return responseStatusFactory.newInstance(code, msg);
}
//属性校验上的注解,只会取第一个属性上的注解,因此要配置
//hibernate.validator.fail_fast=true

//DTO入参属性
List<FieldError> fieldErrors = e.getFieldErrors();
if (!CollectionUtils.isEmpty(fieldErrors)) {
FieldError fieldError = fieldErrors.get(0);
String fieldName = fieldError.getField();
Object target = e.getTarget();
Field field = null;
Class<?> clazz = null;
Object obj = target;
if (fieldName.contains(".")) {
String[] strings = fieldName.split("\\.");
for (String fName : strings) {
clazz = obj.getClass();
field = obj.getClass().getDeclaredField(fName);
field.setAccessible(true);
obj = field.get(obj);
}
} else {
clazz = target.getClass();
field = target.getClass().getDeclaredField(fieldName);
}
FieldError fieldError = fieldErrors.get(0);
String fieldName = fieldError.getField();
Field field = null;
Class<?> clazz = null;
Object target = bindingResult.getTarget();
//不包含.,说明直接是根路径
if (!fieldName.contains(".")) {
clazz = target.getClass();
} else {
String fieldParentPath = fieldParentPath(fieldName);
fieldName = fieldSimpleName(fieldName);
Expression expression = parser.parseExpression(fieldParentPath);
clazz = expression.getValue(target).getClass();
}
field = clazz.getDeclaredField(fieldName);

ValidationStatusCode annotation = field.getAnnotation(ValidationStatusCode.class);
//属性上找到注解
if (annotation != null) {
code = annotation.code();
return responseStatusFactory.newInstance(code, msg);
}
//类上面找到注解
annotation = clazz.getAnnotation(ValidationStatusCode.class);
ValidationStatusCode annotation = field.getAnnotation(ValidationStatusCode.class);
//属性上找到注解
if (annotation != null) {
code = annotation.code();
return responseStatusFactory.newInstance(code, msg);
}
//属性所在类上面找到注解
annotation = clazz.getAnnotation(ValidationStatusCode.class);
if (annotation != null) {
code = annotation.code();
return responseStatusFactory.newInstance(code, msg);
}

//根类上找注解
if (target.getClass() != clazz) {
annotation = target.getClass().getAnnotation(ValidationStatusCode.class);
if (annotation != null) {
code = annotation.code();
return responseStatusFactory.newInstance(code, msg);
Expand All @@ -129,6 +142,68 @@ private ResponseStatus handleBindException(BindException e) throws Exception {
return responseStatusFactory.newInstance(code, msg);
}

private String fieldSimpleName(String fieldName) {
int lastIndex = fieldName.lastIndexOf(".");
StringBuilder stringBuilder = new StringBuilder();
int length = fieldName.length();
for (int i = lastIndex + 1; i < length; i++) {
stringBuilder.append(fieldName.charAt(i));
}
return stringBuilder.toString();
}

/**
* 属性父类路径
*
* @param fieldName
* @return
*/
private String fieldParentPath(String fieldName) {
int lastIndex = fieldName.lastIndexOf(".");
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < lastIndex; i++) {
stringBuilder.append(fieldName.charAt(i));
}
return stringBuilder.toString();
}

private String leafPropertyFieldName(String fieldName) {
int lastIndexOf = fieldName.lastIndexOf('.');
if (lastIndexOf == -1) {
return fieldName;
}
StringBuilder stringBuilder = new StringBuilder();
int len = fieldName.length();
for (int i = lastIndexOf + 1; i < len; i++) {
stringBuilder.append(fieldName.charAt(i));
}
return stringBuilder.toString();
}

/**
* 适配数组属性,包括数组、集合
*
* @param fieldName
* @return
*/
private String adapterArrayProperty(String fieldName) {
//最后一个字符不是],则不是数组属性
if (fieldName.lastIndexOf(']') == -1) {
return fieldName;
}
StringBuilder stringBuilder = new StringBuilder();
int len = fieldName.length();
char c;
for (int i = 0; i < len; i++) {
c = fieldName.charAt(i);
if (c == '[') {
break;
}
stringBuilder.append(c);
}
return stringBuilder.toString();
}

/**
* 当前Controller方法
*
Expand Down

0 comments on commit 63be8cb

Please sign in to comment.