上一节讲到SpringBoot的异常处理机制,但异常处理忽略了参数校验。下面我们将开始讲解参数校验机制。
要实现参数校验机制,我们需要了解SpringBoot是如何接收参数;如何进行验证参数;如何把错误信息抛出。
参数的传输可分为:
1、Url参数传参,类似于GET。这种传参又存在两种方式
- url传参,如:www.fcors.com/type/a
- 查询传参,如:www.fcors.com/index.php?a=b
2、RequestBody请求,例如post请求
菜单
demo1:url传参的方式
传参url: http://192.168.8.10:8081/api/sample/v1/test/testnew/33/fcors
使用@PathVariable [类型] [变量]
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.exception.ForbiddenException;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ISkill iskill;
@GetMapping("/testnew/{id}/{xtype}")
public String test2(
@PathVariable Integer id,@PathVariable String xtype
) throws RuntimeException {
iskill.q();
throw new ForbiddenException(10000);
// return "Hello Fox is testing~";
}
}
如果url参数与接收的变量不一致的时候
使用@PathVariable(name=”xxx”) [类型] [变量]
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.exception.ForbiddenException;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.websocket.server.PathParam;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ISkill iskill;
@GetMapping("/testnew/id/{idx}/type/{xtypex}")
public String test2(
@PathVariable(name="idx") Integer id, @PathVariable(name="xtypex") String xtype
) throws RuntimeException {
iskill.q();
throw new ForbiddenException(10000);
// return "Hello Fox is testing~";
}
}
demo2: url查询参数
url: http://192.168.8.10:8081/api/sample/v1/test/testnew/id/2?xtype=1&xcate=2
@RequestParam(name=”XXXX”) [类型] [变量]
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.exception.ForbiddenException;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
import javax.websocket.server.PathParam;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ISkill iskill;
@GetMapping("/testnew/id/{idx}")
public String test2(
@PathVariable(name="idx") Integer id,
@RequestParam(name="xtype") String type,
@RequestParam(name="xcate") String cate
) throws RuntimeException {
iskill.q();
throw new ForbiddenException(10000);
// return "Hello Fox is testing~";
}
}
demo3: Requestbody请求
url: http://192.168.8.10:8081/api/sample/v1/test/testnew/id/2
databody
{
"name":"fcros",
"sex":"box",
"age":18
}
使用@Requestbody
方法一:偷懒方法,定义一个Map接收
定义个Map接收参数,缺点:无法进行序列化
@Requestbody Map<String,Object> person
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.exception.ForbiddenException;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
import javax.websocket.server.PathParam;
import java.util.Map;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ISkill iskill;
@PostMapping("/testnew/id/{idx}")
public String test2(
@PathVariable(name="idx") Integer id,
@RequestBody Map<String,Object> person
) throws RuntimeException {
iskill.q();
throw new ForbiddenException(10000);
// return "Hello Fox is testing~";
}
}
方法二:定义一个 PersonDTO类接收
在项目下创建一个package,命名为dto,并创建一个类PersonDTO
定义成员变量:name、sex、age,并genrate生成setter和getter方法。
package com.fcors.fcors.dto;
public class PersonDTO {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
private String name;
private String sex;
private Integer age;
}
代码执行层,设置引用接收的这个类
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.dto.PersonDTO;
import com.fcors.fcors.exception.ForbiddenException;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;
import javax.websocket.server.PathParam;
import java.util.Map;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ISkill iskill;
@PostMapping("/testnew/id/{idx}")
public String test2(
@PathVariable(name="idx") Integer id,
@RequestBody PersonDTO person
) throws RuntimeException {
iskill.q();
throw new ForbiddenException(10000);
// return "Hello Fox is testing~";
}
}
上述的例子,如果我们接收的变量又多而且存在变动的情况,对代码的维护工作量也挺大的。下面引入一个工具: lombok。使用它,就可以解决此类问题
先来一个简单的demo,基于demo3的修改
demo4-1:lombok的使用
4.1.1、SpringBoot引入lombok
在pom.xml文件中,添加引用
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
添加后,在项目处右键,Maven>>>Reload project
4.1.2、使用lombok的注解
@Getter 编译的时候会自动创建getter
@Setter 编译时会自动创建setter
@Data 编译时除了会创建Getter和Setter,还会创建equals、hashCode、toString
扩展学习:
如果成员变量是final private String at=””; 那么不会创建Setter,只会创建Getter
demo4-2: lombok的构造函数
4.2.1、不使用lombok的全参数构造函数
右键“generate”>>>”Constructor”
package com.fcors.fcors.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class PersonDTO {
private String name;
private String sex;
private Integer age;
public PersonDTO(String name, String sex, Integer age) {
this.name = name;
this.sex = sex;
this.age = age;
}
final private String at="";
}
PersonDTO personnew = new PersonDTO("fcors","boy",18);
上述代码通过Lombok生成全参的构造函数
添加@AllArgsConstructor
4.2.2、如何实现实例化时,不一定传参呢?
@AllArgsConstructor:所有参数的构造函数
@NoArgsConstructor: 无参构造函数
两个参数一同使用,实例化的时候就不一定传参
4.2.3、如何实现实例化时,某些参数必填呢?
添加注解:@RequiredArgsConstructor 在参数前添加 @NonNull
package com.fcors.fcors.dto;
import lombok.*;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@RequiredArgsConstructor
public class PersonDTO {
@NonNull
private String name;
@NonNull
private String sex;
private Integer age;
final private String at="";
}
demo4-3: lombok的build方法
lombok提供一个build方法,用这个方法可以不用定义@setter。
实例化的时候可以传参
package com.fcors.fcors.dto;
import lombok.*;
@Getter
@Builder
public class PersonDTO {
// @NonNull
private String name;
// @NonNull
private String sex;
private Integer age;
final private String at="";
}
PersonDTO dotnew = PersonDTO.builder()
.sex("boy")
.name("fcors")
.build();
demo4-4: lombok的build 和setter同时可用
加入注解:@NoArgsConstructor和@Setter
package com.fcors.fcors.dto;
import lombok.*;
@Getter
@Builder
@NoArgsConstructor
@Setter
public class PersonDTO {
// @NonNull
private String name;
// @NonNull
private String sex;
private Integer age;
final private String at="";
}
实例化类
PersonDTO dotnew = PersonDTO.builder()
.sex("boy")
.build();
dotnew.setName("fcros");
demo4-5: lombok的build 和 Getter 同时可用
@Builder 默认的情况是不能序列化返回到前端
如果我们把DTO的@Getter屏蔽后,返回是会报错。
解决办法:引入@Getter注解
demo5: 基础注解的参数校验
在类的前面添加@Validated;在参数处加入注解
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.dto.PersonDTO;
import com.fcors.fcors.exception.ForbiddenException;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.Max;
import javax.websocket.server.PathParam;
import java.util.Map;
@RestController
@RequestMapping("/test")
@Validated
public class TestController {
@Autowired
private ISkill xing;
@PostMapping("/testnew/id/{idx}")
public String test2(
@PathVariable(name="idx") @Max(value=10,message="不能大于10") Integer id,
@RequestBody PersonDTO person
) throws RuntimeException {
throw new ForbiddenException(10000);
// return "Hello Fox is testing~";
}
}
下面提供一些基础的参数校验注解:
- @Null 被注释的元素必须为 null
- @NotNull 被注释的元素必须不为 null
- @AssertTrue 被注释的元素必须为 true
- @AssertFalse 被注释的元素必须为 false
- @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @Range(min=,max=) 被注释必须是一个数字,且满足范围
- @Length 被注释的长度必须满足范围
- @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @Size(max=, min=) 被注释的元素的大小必须在指定的范围内
- @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
- @Past 被注释的元素必须是一个过去的日期
- @Future 被注释的元素必须是一个将来的日期
- @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达
泛式builder
-----
@Data
@Builder
public class ResponseResultVO<T> {
private long code;
private String msg;
private T data;
}
------
ResponseResultVO<SysUsers> vo = ResponseResultVO.<SysUsers>builder()
.code(1)
.data(sysUsers)
.build();
SysUsers sysUsers1 = vo.getData();
demo6: 自定义的类如何实现基础注解
6.1、在类的成员变量前添加参数校验基础注解
package com.fcors.fcors.dto;
import lombok.*;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
//@Getter
@Builder
//@NoArgsConstructor
//@Setter
public class PersonDTO {
// @NonNull
@Length(min=2,max=10,message = "字符转字节不在2~10范围")
private String name;
// @NonNull
private String sex;
private Integer age;
final private String at="";
}
6.2、在接收变量前添加@Validated
package com.fcors.fcors.api.sample.v1;
import com.fcors.fcors.dto.PersonDTO;
import com.fcors.fcors.exception.ForbiddenException;
import com.fcors.fcors.exception.NotFoundException;
import com.fcors.fcors.sample.IConnect;
import com.fcors.fcors.sample.ISkill;
import com.fcors.fcors.sample.database.MySql;
import com.fcors.fcors.sample.hero.Diana;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.Max;
import javax.websocket.server.PathParam;
import java.util.Map;
@RestController
@RequestMapping("/test")
@Validated
public class TestController {
@Autowired
private ISkill xing;
@PostMapping("/testnew/id/{idx}")
public String test2(
@PathVariable(name="idx") @Max(value=10,message="不能大于10") Integer id,
@RequestBody @Validated PersonDTO person
) throws RuntimeException {
throw new ForbiddenException(10000);
// return "Hello Fox is testing~";
}
}
demo7: 级联参数校验
例如上述的PersonDTO存在一个成员变量是一个类,如何对这个子类进行参数校验呢?
7.1、首先在dto下面创建一个类 SchoolDTO
package com.fcors.fcors.dto;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
@Getter
@Setter
public class SchoolDTO {
@Length(min=2,message = "schoolName 字符串必须大于2位")
private String schoolName;
}
7.2、修改PersonDTO
新增成员变量private SchoolDTO schoolDTO;
在成员变量 的前面加 @Valid
package com.fcors.fcors.dto;
import lombok.*;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
//@Getter
@Builder
//@NoArgsConstructor
//@Setter
public class PersonDTO {
// @NonNull
@Length(min=2,max=10,message = "字符转字节不在2~10范围")
private String name;
// @NonNull
private String sex;
private Integer age;
final private String at="";
@Valid
private SchoolDTO schoolDTO;
}
demo8:自定义校验方法
下面通过一个例子来演示如何自定义校验方法。检测两次密码是否一致
首先在PersonDTO添加两个成员变量private String Password1; private String Password2;
8.1创建一个 PasswordValidator 的类
在项目中创建package,并命名为validators,并创建一个 PasswordValidator 的Annotation
注解解析
@Target:说明 Annotation 所修饰对象范围,可用作package、types[类、接口、枚举和 Annotation 类型等]、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(循环变量、catch参数)
- TYPE **用于描述类、接口(包括注解类型)或enum声明Class
- FIELD **用于描述域
- METHOD **用于描述方法 Method declaration
- PARAMETER **用于描述参数
- CONSTRUCTOR **用于描述构造器
- LOCAL_VARIABLE **用于描述局部变量
- PACKAGE 用于描述包
package com.fcors.fcors.validators;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE,ElementType.FIELD})
/*{ElementType.TYPE} 注解可打在类上
* {ElementType.FIELD} 注解可打在成员变量上
* */
@Constraint(validatedBy = PasswordValidator.class)
public @interface PasswordEqual {
String message() default "password are not equal";
/* groups && payload 是一定要写上的 不然不生效 */
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
8.2、创建一个 PasswordEqual 的 Annotation
在 validators 创建一个 PasswordEqual 的 Annotation,并 implements ConstraintValidator<@value1,@value2>
@value1:自定义注解的命名
@value2:被该自定义注解修饰的目标类
例如下面的例子:
自定义的注解是@PasswordEqual,这个就是@value1
在PersonDTO上被使用到,所以@value2= PersonDTO
public class PasswordValidator implements ConstraintValidator<PasswordEqual, PersonDTO> {
}
右键“ genrate “>>>”Override”>>>”isValid”
完善代码
package com.fcors.fcors.validators;
import com.fcors.fcors.dto.PersonDTO;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PasswordValidator implements ConstraintValidator<PasswordEqual, PersonDTO> {
@Override
public boolean isValid(PersonDTO personDTO, ConstraintValidatorContext constraintValidatorContext) {
String password1 = personDTO.getPassword1();
String password2 = personDTO.getPassword2();
boolean match = password1.equals(password2);
return match;
}
}
如果我们需要自定义校验中使用参数,例如定义最大值和最小值。
设置一个min参数key和max的参数key
package com.fcors.fcors.dto.validators;
import lombok.Setter;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
/*{ElementType.TYPE} 注解可打在类上
* {ElementType.FIELD} 注解可打在成员变量上
* */
@Constraint(validatedBy = PasswordValidator.class )
public @interface PasswordEqual {
int min() default 4;
int max() default 6;
String message() default "passwords are not equal";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
//关联类 编程模式
}
PersonDTO在使用自定义的参数:min和max
package com.fcors.fcors.dto;
import com.fcors.fcors.validators.PasswordEqual;
import lombok.*;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
@Getter
@Builder
//@NoArgsConstructor
//@Setter
@PasswordEqual(min=2)
public class PersonDTO {
// @NonNull
@Length(min=2,max=10,message = "字符转字节不在2~10范围")
private String name;
// @NonNull
private String sex;
private Integer age;
final private String at="";
private String Password1;
private String Password2;
@Valid
private SchoolDTO schoolDTO;
}
PasswordValidator接收参数,处理逻辑(未完待续,参数并没有修改)
/**
* @作者 7七月
* @微信公号 林间有风
* @开源项目 $ http://7yue.pro
* @免费专栏 $ http://course.7yue.pro
* @我的课程 $ http://imooc.com/t/4294850
* @创建时间 2020-01-21 15:34
*/
package com.fcors.fcors.dto.validators;
import com.fcors.fcors.dto.PersonDTO;
import com.fcors.fcors.dto.validators.PasswordEqual;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PasswordValidator implements ConstraintValidator<PasswordEqual, PersonDTO> {
private int min;
private int max;
@Override
public void initialize(PasswordEqual constraintAnnotation) {
this.min = constraintAnnotation.min();
this.max = constraintAnnotation.max();
}
@Override
public boolean isValid(PersonDTO personDTO, ConstraintValidatorContext constraintValidatorContext) {
String password1 = personDTO.getPassword1();
String password2 = personDTO.getPassword2();
Boolean match = false;
if (true == password1.equals(password2)) {
match = true;
}
if (true == password1.length() < min) {
Fox_error(constraintValidatorContext,"password1字节小于" + min);
match = false;
}
if (true == password1.length() > max) {
Fox_error(constraintValidatorContext,"password1字节大于" + max);
match = false;
}
if (true == password2.length() < min) {
Fox_error(constraintValidatorContext,"password2字节小于" + min);
match = false;
}
if (true == password2.length() > max) {
Fox_error(constraintValidatorContext,"password2字节大于" + max);
match = false;
}
return match;
}
private static void Fox_error(ConstraintValidatorContext context, String message) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
}
//第二个:自定义注解修饰的目标的类型
}
=======扩展学习=======
如果在PasswordEqual的@Target添加上ElementType.FIELD,则注解可以使用在变量上
此时我们应该如何接收参数呢?因为修饰的是String,因此@value2=String
demo10:修改报错信息
url: http://192.168.8.10:8081/api/sample/v1/test/testnew/id/89
RequestBody:
{
"name":"fcors",
"sex":"box",
"age":18,
"Password1":"1",
"Password2":"111",
"schoolDTO":{
"schoolName":"hello"
}
}
通过报错可以看到两种错误类型:MethodArgumentNotValidException和ConstraintViolationException
下面通过全局异常机制,重新定义返回信息。修改core/GolbalExceptionAdvice
package com.fcors.fcors.core;
import com.fcors.fcors.core.configuration.ExceptionCodeConfiguration;
import com.fcors.fcors.exception.HttpException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.bind.annotation.ResponseStatus;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;
@ControllerAdvice
public class GolbalExceptionAdvice {
@Autowired
private ExceptionCodeConfiguration codeConfiguration;
@ExceptionHandler(value=Exception.class)
@ResponseBody
@ResponseStatus(code= HttpStatus.INTERNAL_SERVER_ERROR)
public UnifyResponse handleException(HttpServletRequest req, Exception e){
System.out.println("全局异常报错处理");
UnifyResponse message = new UnifyResponse(999,"全局异常测试错误","url");
return message;
}
@ExceptionHandler(value=HttpException.class)
public ResponseEntity handelHttpException(HttpServletRequest req, HttpException e){
String requestUrl = req.getRequestURI();
String method = req.getMethod();
UnifyResponse message = new UnifyResponse(e.getCode(),codeConfiguration.getMessage(e.getCode()),method+" "+requestUrl);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
ResponseEntity<UnifyResponse> r = new ResponseEntity<>(message,headers,httpStatus);
System.out.println("专用HttpException异常报错处理");
return r;
}
/* 定义MethodArgumentNotValidException专属 */
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public UnifyResponse handleBeanValidation(HttpServletRequest req, MethodArgumentNotValidException e) {
String requestUrl = req.getRequestURI();
String method = req.getMethod();
List<ObjectError> errors = e.getBindingResult().getAllErrors();
String message = this.formatAllErrorMessages(errors);
return new UnifyResponse(10001, message,method + " " + requestUrl);
}
/* 定义ConstraintViolationException专属 */
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(code= HttpStatus.BAD_REQUEST)
@ResponseBody
public UnifyResponse handleConstraintException(HttpServletRequest req, ConstraintViolationException e){
String requestUrl = req.getRequestURI();
String method = req.getMethod();
String message = e.getMessage();
return new UnifyResponse(10001, message, method + " " + requestUrl);
}
private String formatAllErrorMessages(List<ObjectError> errors) {
StringBuffer errorMsg = new StringBuffer();
errors.forEach(error ->
errorMsg.append(error.getDefaultMessage()).append(';')
);
return errorMsg.toString();
}
}
下面我们讲解一下,如何创建目录路由