不废话,直接上代码
1.配置参数校验
pom中引入参数校验器
org.springframework.boot
spring-boot-starter-validation
增加手动验证类
/**
* 对象验证器
* @Author hl1314
* @Date 11:04 2019-08-19
**/
public class BeanValidator {
/**
* 验证某个bean的参数
* @Author hl1314
* @Date 11:04 2019-08-19
* @Param [object]
* @return void
**/
public static void validate(T object,Class>... var) {
//获得验证器
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
//执行验证
Set> constraintViolations = validator.validate(object,var);
//如果有验证信息,则取出来包装成异常返回
if (CollectionUtils.isEmpty(constraintViolations)) {
return;
}
throw new ValidationException(convertErrorMsg(constraintViolations));
}
/**
* 验证bean list
* @Author hl1314
* @Date 11:44 2019-08-19
* @Param [objectList, var]
* @return void
**/
public static void validate(List objectList, Class>... var) {
for(T t : objectList){
validate(t,var);
}
}
/**
* 拼接异常信息
* @Author hl1314
* @Date 11:31 2019-08-19
* @Param [set]
* @return java.lang.String
**/
private static String convertErrorMsg(Set> set) {
Map errorMap = new HashMap<>(4);
String property;
for (ConstraintViolation cv : set) {
//循环获取错误信息
property = cv.getPropertyPath().toString();
if (errorMap.get(property) != null) {
errorMap.get(property).append("," + cv.getMessage());
} else {
StringBuilder sb = new StringBuilder();
sb.append(cv.getMessage());
errorMap.put(property, sb);
}
}
return errorMap.toString();
}
}
定义校验分组,分组没有实际意义,只是区分每次验证那一组
/**
* @author : hl1314
* @description: delete分组
* @data : 2019-08-19 11:20
*/
public interface Delete {
}
/**
* @author : hl1314
* @description: insert分组
* @data : 2019-08-19 10:18
*/
public interface Insert {
}
/**
* @author : hl1314
* @description: select分组
* @data : 2019-08-19 11:35
*/
public interface Select {
}
/**
* @author : hl1314
* @description: update分组
* @data : 2019-08-19 10:19
*/
public interface Update {
}
在bean类中使用注解,验证参数
@Data
public class QueryDataDTO {
@NotNull(message = "不能为空", groups = {Insert.class, Update.class})
@Range(min = 1L, message = "最小为1", groups = {Insert.class,Update.class})
private Long taskId;
@NotNull(message = "不能为空", groups = {Insert.class,Update.class})
@Range(min = 1L, message = "最小为1", groups = {Insert.class,Update.class})
private Long queryId;
@Range(min = 0,max = 9,message = "类型异常,超出范围", groups = {Insert.class,Update.class})
@NotNull(message = "不能为空", groups = {Insert.class,Update.class})
private Integer geoType;
@NotBlank(message = "不能为空", groups = {Insert.class})
private String wkt;
@Range(min = 0,max = 50,message = "超出范围", groups = {Insert.class,Update.class})
@NotNull(message = "查询地址列不能为空", groups = {Insert.class,Update.class})
private Integer addressColumn;
@Pattern(regexp="^[0-9]*$",message = "必须是数字", groups = {Insert.class,Update.class})
@NotNull(message = "不能为空", groups = {Insert.class,Update.class})
private String selectType;
}
在controller中手动验证,两个方法的验证错误都将错误抛出了,所以,需要加全局异常处理
/**
* 校验对象,手动触发校验
*
* @Author hl1314
* @Date 17:50 2019-07-16
* @Param [importDataDTO]
**/
@RequestMapping(value = "/importData", method = {RequestMethod.POST})
@ResponseBody
public ShortResponseVO importData(@RequestBody QueryDataDTO dto) throws Exception {
//只校验Insert分组
BeanValidator.validate(dto, Insert.class);
dataAnalysisService.importDataAnalysisTemp(importDataDTO);
return ShortResponseVO.success(null);
}
/**
* 在参数上使用校验,需要在controller类上加,@Validated注解
*
* @Author hl1314
* @Date 17:51 2019-07-16
**/
@RequestMapping(value = "/triggerDataAnalysis", method = {RequestMethod.GET})
@ResponseBody
public ShortResponseVO triggerDataAnalysis(@NotNull(message = "taskId不能为空") @Range(min = 1, message = "taskId最小为1") @RequestParam("taskId") Long taskId,
@NotNull(message = "isDelayed不能为空") @Range(min = 0, max = 3, message = "isDelayed取值范围为0-3") @RequestParam("isDelayed") Integer isDelayed) throws Exception {
dataAnalysisService.triggerDataReserveAnalysis(taskId, isDelayed);
return ShortResponseVO.success(null);
}
2.添加全局异常处理
首先增加自定义异常
/**
* @author : hl1314
* @description: 通用异常
* @data : 2019-07-16 17:22
*/
public class CommonException extends RuntimeException {
private Integer code;
public Integer getCode() {
return code;
}
public CommonException(String msg){
super(msg);
}
public CommonException(String msg,Throwable cause){
super(msg,cause);
}
public CommonException(String msg,Integer code,Throwable cause){
super(msg,cause);
this.code = code;
}
public CommonException(String msg,Integer code){
super(msg);
this.code = code;
}
}
定义返回对象
/**
* @author : hl1314
* @description: 返回对象
* @data : 2019-07-16 17:08
*/
@Data
@JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL)
public class ShortResponseVO {
private Integer code;
private String message;
private Object data;
public ShortResponseVO(){
}
public ShortResponseVO(Integer code,String message){
this.code = code;
this.message = message;
}
public ShortResponseVO(Integer code,String message,Object data){
this.code = code;
this.message = message;
this.data = data;
}
public static ShortResponseVO success(Object data){
return new ShortResponseVO(ResponseCodeEnum.SUCCESS.getCode(),ResponseCodeEnum.SUCCESS.getMsg(),data);
}
public static ShortResponseVO err(){
return new ShortResponseVO(ResponseCodeEnum.SYSTEM_ERROR.getCode(),ResponseCodeEnum.SYSTEM_ERROR.getMsg(),null);
}
}
定义返回编码
/**
* 返回编码
* @Author hl1314
* @Date 17:13 2019-07-16
**/
public enum ResponseCodeEnum {
SUCCESS(0,"OK"),
SYSTEM_ERROR(1,"系统错误"),
PARAM_IS_EMPTY(10001,"必填参数为空"),
DATA_SIZE_TRANSFINITE(10002,"数据超限限制"),
PARAM_IS_ERROR(10003,"参数填写错误"),
PATH_ERROR(10004,"路径错误")
;
/**
* 获取msg
* @Author hl1314
* @Date 11:26 2019-07-17
* @Param [code]
* @return java.lang.String
**/
public static String getMsg(Integer code){
for(ResponseCodeEnum enum : ResponseCodeEnum.values()){
if(enum.code.equals(code)){
return enum.msg;
}
}
return null;
}
ResponseCodeEnum(Integer code,String msg){
this.code = code;
this.msg = msg;
}
private Integer code;
private String msg;
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
全局异常拦截(需要拦截的异常可以再添加)
/**
* 异常注解处理
*
* @Author hl1314
* @Date 17:04 2019-08-17
**/
@RestControllerAdvice
public class BadRequestExceptionHandler {
private Logger logger = LoggerFactory.getLogger(BadRequestExceptionHandler.class);
/**
* validated类验证错误
* @Author hl1314
* @Date 17:50 2019-08-17
* @Param [e]
**/
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO validatedForClassExceptionHandler(ConstraintViolationException e) {
Iterator> iterator = e.getConstraintViolations().iterator();
StringBuffer msg = new StringBuffer();
while (iterator.hasNext()) {
ConstraintViolation> next = iterator.next();
msg.append(next.getMessage());
msg.append(";");
}
logger.error("validatedForClassExceptionHandler -> e={}", e.getLocalizedMessage());
return new ShortResponseVO(ResponseCodeEnum.PARAM_IS_ERROR.getCode(), msg.toString());
}
/**
* validated模型验证错误
* @Author hl1314
* @Date 10:59 2019-08-17
* @Param [e]
**/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO validatedForModleExceptionHandler(MethodArgumentNotValidException e) {
List fieldErrors = e.getBindingResult().getFieldErrors();
StringBuffer msg = new StringBuffer();
for (FieldError fieldError : fieldErrors) {
msg.append(fieldError.getDefaultMessage());
msg.append(";");
}
logger.error("validatedForModleExceptionHandler -> e={}", e.getLocalizedMessage());
return new ShortResponseVO(ResponseCodeEnum.PARAM_IS_ERROR.getCode(), msg.toString());
}
/**
* validated手动验证错误
* @Author hl1314
* @Date 12:50 2019-08-18
* @Param [e]
**/
@ExceptionHandler(ValidationException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO validatedExceptionHandler(ValidationException e) {
logger.error("validatedExceptionHandler -> e={}", e.getLocalizedMessage());
return new ShortResponseVO(ResponseCodeEnum.PARAM_IS_ERROR.getCode(), e.getLocalizedMessage());
}
/**
* 参数为空错误
* @Author hl1314
* @Date 11:40 2019-08-18
* @Param [e]
**/
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException e) {
logger.error("missingServletRequestParameterExceptionHandler -> e={}", e.getLocalizedMessage(), e);
return new ShortResponseVO(ResponseCodeEnum.PARAM_IS_EMPTY.getCode(), ResponseCodeEnum.PARAM_IS_EMPTY.getMsg() + ":" + e.getLocalizedMessage());
}
/**
* 路径错误
* @Author hl1314
* @Date 10:00 2019-08-20
* @Param [e]
**/
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO noHandlerFoundExceptionHandler(NoHandlerFoundException e) {
logger.error("noHandlerFoundExceptionHandler -> e={}", e.getLocalizedMessage(), e);
return new ShortResponseVO(ResponseCodeEnum.PATH_ERROR.getCode(), ResponseCodeEnum.PATH_ERROR.getMsg() + ":" + e.getLocalizedMessage());
}
/**
* 自定义异常
* @Author hl1314
* @Date 10:45 2019-08-20
* @Param [e]
**/
@ExceptionHandler(CommonException.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO commonExceptionHandler(CommonException e) {
logger.error("commonExceptionHandler -> e={}", e.getLocalizedMessage());
return new ShortResponseVO(e.getCode(), e.getMessage());
}
/**
* http参数异常
* @Author hl1314
* @Date 14:50 2019-08-19
* @Param [e]
**/
@ExceptionHandler({HttpMessageNotReadableException.class, MethodArgumentTypeMismatchException.class, TypeMismatchException.class})
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO httpParamExceptionHandler(Exception e) {
logger.error("httpParamExceptionHandler -> e={}", e.getLocalizedMessage(), e);
return new ShortResponseVO(ResponseCodeEnum.PARAM_IS_ERROR.getCode(), ResponseCodeEnum.PARAM_IS_ERROR.getMsg() + ":" + e.getLocalizedMessage());
}
/**
* 异常处理
*
* @Author hl1314
* @Date 18:09 2019-08-17
* @Param [e]
**/
@ExceptionHandler(Exception.class)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ShortResponseVO runtimeExceptionHandler(Exception e) {
logger.error("runtimeExceptionHandler -> e={}", e.getLocalizedMessage(), e);
return new ShortResponseVO(ResponseCodeEnum.SYSTEM_ERROR.getCode(),ResponseCodeEnum.SYSTEM_ERROR.getMsg() + ":" + e.getLocalizedMessage());
}
}
如果要校验路径等错误,需要在配置文件中添加
spring:
mvc:
throw-exception-if-no-handler-found: true
resources:
add-mappings: false
全部添加完毕,测试下