Controller 的方法上面加注解@Validated不能校验泛型参数,直接进入到方法中,需要进行手动校验
使用aop来拦截Controller方法,不符合校验的请求参数直接抛出异常
@Data
public class BaseRequest<T> implements Serializable {
private T params;
}
public class TTRequest<T> extends BaseRequest<T> {
/**
* 公共的参数Id
*/
private String id;
}
/**
@Validated 加上不起作用,不支持泛型参数
**/
@PostMapping(value = "/test")
public BaseResponse<> test( @RequestBody TTRequest<xxx> request) {
return BaseResponse.ok();
}
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.List;
import java.util.Set;
@Aspect
@Component
@Slf4j
public class InterceptControllerAspect {
private static final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
@Before(value = "execution(* xxxx.xxxController.*(..))&& args(request,..)")
public void interceptTenantRequest(JoinPoint joinPoint, TTRequest<?> request) {
if (request != null) {
String id = request.getId();
if (StringUtils.isBlank(id)) {
throw new BizException("请求参数异常");
}
String methodName = joinPoint.getSignature().getName();
log.info("methodName {}:Intercepted Tenant Request with Id:{} ", methodName, id);
validate(request.getParams());
}
}
public static <T> void validate(T t) {
if (t instanceof List) {
if (((List<?>) t).size() == 0) {
throw new BizException("请求参数异常");
}
}
if (t instanceof Set) {
if (((Set<?>) t).size() == 0) {
throw new BizException("请求参数异常");
}
}
Validator validator = factory.getValidator();
Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
for (ConstraintViolation<T> constraintViolation : constraintViolations) {
//这里循环获取错误信息,可以自定义格式
String property = constraintViolation.getPropertyPath().toString();
String msg = constraintViolation.getMessage();
throw new BizException(property + msg);
}
}
}
接收到异常后,进行全局捕获,统一异常处理
@Slf4j
@ControllerAdvice
public class ControllerHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public BaseResponse exceptionHandler(MethodArgumentNotValidException e) {
BindingResult result = e.getBindingResult();
String msg=ApiErrorCode.INVALID_PARAM.getMsg();
if (result.hasErrors()) {
List<ObjectError> errors = result.getAllErrors();
if (CollectionUtils.isNotEmpty(errors)) {
msg =msg+":"+ errors.stream().map(c -> c.getDefaultMessage()).collect(Collectors.joining(","));
}
}
log.info("param exception>>>>>>>>>>>>>>>>>>>>>>>>>>" + e.getMessage(), e);
return BaseResponse.fail(msg);
}
@ExceptionHandler(BizException.class)
@ResponseBody
public BaseResponse exceptionHandler(BizException e) {
log.info("business exception>>>>>>>>>>>>>>>>>>>>>>>>>>code:{}||message:{}", e.getCode(), e.getMsg());
return BaseResponse.fail(e.getMsg());
}
@ExceptionHandler(Exception.class)
@ResponseBody
public BaseResponse exceptionHandler(Exception e) {
log.error("system exception>>>>>>>>>>>>>>>>>>>>>>>>>>message:" + e.getMessage(), e);
return BaseResponse.fail("服务器开小差,请稍后重试");
}
}