其实JSR303没啥介绍的,大家知道是做校验的就可以了。简书里面是这样说的:SR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
一切尽在代码中:
快捷创建一个springboot项目
![369c693b7fb69fa69ab0faa81faf258e.png](https://i-blog.csdnimg.cn/blog_migrate/2c4746b232e0c436ff25b3d854e724eb.jpeg)
1,pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>4.0.0org.springframework.boot spring-boot-starter-parent 2.1.8.RELEASEcom.dwsoft.test test-jsr303 0.0.1-SNAPSHOTtest-jsr303Demo project for Spring Boot11org.apache.httpcomponents httpcore 4.4.13org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test testorg.junit.vintage junit-vintage-engine org.projectlombok lombok 1.18.8org.springframework.boot spring-boot-maven-plugin
我用的springboot版本是:2.1.8.RELEASE,如果使用其他版本也可以,但是一定要确保引入了校验包:
![4899b660d34711f0839f243fe079b0a8.png](https://i-blog.csdnimg.cn/blog_migrate/11cc13a96d68cdf431d6097328c3669e.jpeg)
2,创建主类,实体类,控制器
主类:
@SpringBootApplicationpublic class TestJsr303Application { public static void main(String[] args) { SpringApplication.run(TestJsr303Application.class, args); }}
控制类:
/** * @author tlk * @date 2020/8/4-18:36 */@RestControllerpublic class TestController { }
实体类:
package com.dwsoft.test.testjsr303.entity;import lombok.Data;import java.io.Serializable;/** * @author tlk * @date 2020/8/4 */@Datapublic class Brand implements Serializable { private static final long serialVersionUID = 6249214818970952452L; /** * 品牌id */ private Long brandId; /** * 品牌名 */ private String name; /** * 品牌logo地址 */ private String logo; /** * 介绍 */ private String descript; /** * 显示状态[0-不显示;1-显示] */ private Integer showStatus; /** * 检索首字母 */ private String firstLetter; /** * 排序 */ private Integer sort;}
用的是注解@Data,需要安装插件lombok;你也可以不用这个注解,直接写get,set等方法。
统一格式响应封装类:
package com.dwsoft.test.testjsr303.utils;import org.apache.http.HttpStatus;import java.util.HashMap;import java.util.Map;/** * 返回数据 * * @author tlk */public class R extends HashMap { private static final long serialVersionUID = 1L; public R() { put("code", 0); put("msg", "success"); } public static R error() { return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员"); } public static R error(String msg) { return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg); } public static R error(int code, String msg) { R r = new R(); r.put("code", code); r.put("msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put("msg", msg); return r; } public static R ok(Map map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } public R put(String key, Object value) { super.put(key, value); return this; }}
开始校验:
1》简简单单的校验
给bean添加校验注解:
![c58f96460dc8ae34760531741f82cef9.png](https://i-blog.csdnimg.cn/blog_migrate/150bddce1dab4ee04ea8ff43df85e02b.jpeg)
开启校验功能@Valid
![4ac589cf139da77e58b16e1e8e150067.png](https://i-blog.csdnimg.cn/blog_migrate/ea62c05e6b7a83f6137ea02d8c95bf51.jpeg)
用postman测试(入参给的是一个空的json串):
![761a13a3f05ac19a2b21cf761f9c6aa9.png](https://i-blog.csdnimg.cn/blog_migrate/97987cdf0e41ea9832a811c72dca7e26.jpeg)
这是原始响应,我们可以封装统一格式,并且自定义message
改动如下:
![f5faa1dd19e4e842cfb3bccdd36511cc.png](https://i-blog.csdnimg.cn/blog_migrate/f840fc0839d938c96c90ec3bdb028960.jpeg)
控制器中引入 BindingResult
package com.dwsoft.test.testjsr303.controller;import com.dwsoft.test.testjsr303.entity.Brand;import com.dwsoft.test.testjsr303.utils.R;import org.apache.http.HttpStatus;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;import java.util.HashMap;import java.util.List;import java.util.Map;/** * @author tlk * @date 2020/8/4 */@RestControllerpublic class TestController { @RequestMapping("/test/jsr303") public R testJsr303(@Valid @RequestBody Brand brand, BindingResult bindingResult) { if(bindingResult.hasErrors()){ Mapmap=new HashMap<>(); List fieldErrors = bindingResult.getFieldErrors(); fieldErrors.forEach((item) ->{ String field = item.getField(); String defaultMessage = item.getDefaultMessage(); map.put(field,defaultMessage); }); return R.error(HttpStatus.SC_BAD_REQUEST,"入参不合法").put("data",map); } //业务处理 return R.ok(); }}
再次测试:
![18bbd13f1f34a124fc448f0c4e0c1d46.png](https://i-blog.csdnimg.cn/blog_migrate/9658635d47b2de91e09425e09b4ce5b0.jpeg)
完美!
2》分组校验主要用于表单的添加或者修改进行区分
添加两个接口:
package com.dwsoft.test.testjsr303.valid;/** * @author tlk * @date 2020/8/4-11:08 */public interface UpdateGroup {}
package com.dwsoft.test.testjsr303.valid;/** * @author tlk * @date 2020/8/4-11:08 */public interface AddGroup {}
如果想在添加的时候生效,如下:
![cf1b294160158bc2239db75b09a7c473.png](https://i-blog.csdnimg.cn/blog_migrate/a45c9dc19a6bdbf54855225943823e8b.jpeg)
![0312963ab229c8824defbbd2f873edc4.png](https://i-blog.csdnimg.cn/blog_migrate/bf14c650852532edac6c0a47f60fa952.jpeg)
测试:
![451f74bb77b04844d268cfd94be139c1.png](https://i-blog.csdnimg.cn/blog_migrate/fc5b4c160fa9ef09dbce50d25b57de1a.jpeg)
如果只是把bean改成:
![15208938d1f8dc86dffdec43453ee69e.png](https://i-blog.csdnimg.cn/blog_migrate/b2c1c1872ac6a05eb71187fb60876536.jpeg)
测试:
![2c964033b81af67b1a8b9030f59d5fa8.png](https://i-blog.csdnimg.cn/blog_migrate/7dc545179580f1128809b565aebb39d7.jpeg)
校验没有起作用。
也可这样配置:
![a22ab3ee6410c72a6c3f730ccc16ca80.png](https://i-blog.csdnimg.cn/blog_migrate/b70ddd5d754caa6de5c1a7530674c8cd.jpeg)
![ba112260e11856401fbb343721d8ec36.png](https://i-blog.csdnimg.cn/blog_migrate/646622eb3e38111af48ae75add54fdc5.jpeg)
正常逻辑添加修改分开写,控制器对应方法只会配置一个分组
只要满足校验规则,就起作用。
注意:如果采用分组校验的形式,对应bean中的属性必须标注采用哪个校验组,不然不起任何校验作用
比如:
![21315951d94ebd66a52ee0c878581bae.png](https://i-blog.csdnimg.cn/blog_migrate/9407fa615a40a07647cdbedb90a1ea7c.jpeg)
![ba112260e11856401fbb343721d8ec36.png](https://i-blog.csdnimg.cn/blog_migrate/646622eb3e38111af48ae75add54fdc5.jpeg)
正常逻辑添加修改分开写,控制器对应方法只会配置一个分组
测试:
![e621e3d6df5e2f9f233bc643d030bafd.png](https://i-blog.csdnimg.cn/blog_migrate/210f43e1a2b0280c78597590fbafcd82.jpeg)
加上分组:
![cf515a2ea17a99b8ffb901e22ac62e0d.png](https://i-blog.csdnimg.cn/blog_migrate/bc3f7199cf9ad2a3f28eae9f5940d944.jpeg)
测试:
![200a9aebc2e76e2a169a3445c7a762f5.png](https://i-blog.csdnimg.cn/blog_migrate/928a642a2de99a08d3b6dc2c7c4533e6.jpeg)
完美!分组主要看自己的分配逻辑,我这边只是做一个引导!
3》自定义校验:
如显示状态,我们要求在指定的数据中选择
![2a7f98cda67b4fbec305abdeebe279b5.png](https://i-blog.csdnimg.cn/blog_migrate/0d6e06514606753ad28735582f555bb2.jpeg)
该怎么操作?
a》编写一个自定义的校验注解(可以参照@NotBlank等注解格式)
package com.dwsoft.test.testjsr303.valid;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.*;/** * @author tlk * @date 2020/8/4-14:15 */@Documented@Constraint( validatedBy = {})@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})@Retention(RetentionPolicy.RUNTIME)@Repeatable(Checkvalue.List.class)public @interface Checkvalue { String message() default "{com.dwsoft.test.testjsr303.valid.Checkvalue.message}"; Class>[] groups() default {}; Class extends Payload>[] payload() default {}; int[] value() default {}; @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface List { Checkvalue[] value(); }}
![20c6ba1208d32400bd046cd42b69e5c5.png](https://i-blog.csdnimg.cn/blog_migrate/4b9c209f14dc98a5f9e91a25dd842977.jpeg)
这个地方可以创建自己的消息文件(位置:resources/),ValidationMessages.properties,文件名一定要是这个
com.dwsoft.test.testjsr303.valid.Checkvalue.message = "请使用指定值"
b》编写一个自定义的校验器
package com.dwsoft.test.testjsr303.valid;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.util.HashSet;import java.util.Set;/** * @author tlk * @date 2020/8/4-14:29 */public class CheckValueConstraintValidator implements ConstraintValidator { private Set set=new HashSet<>(); @Override public void initialize(Checkvalue constraintAnnotation) { int[] value = constraintAnnotation.value(); if(value!=null && value.length>1){ for (Integer integer : set) { set.add(integer); } } } @Override public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) { if(set.contains(integer)) return true; return false; }}
c》关联自定义的校验器和自定义的校验注解
![ba68359a83b284984d8acbb14915e5de.png](https://i-blog.csdnimg.cn/blog_migrate/49339f7bf9bc8b88c9b2476cee5fa538.jpeg)
测试:
先修改控制器:
![90e824bd2a0aff30cf60084482e19ef6.png](https://i-blog.csdnimg.cn/blog_migrate/fa95cf4f310b1231e7bfea706df657ee.jpeg)
修改bean:
![35d39c91de3b5c5f34355efb327aa74c.png](https://i-blog.csdnimg.cn/blog_migrate/9cea956fbd9469dcafe6e6f8ce17e645.jpeg)
postman:
![17a08251a98d09b3fbf0bd6cbd61c914.png](https://i-blog.csdnimg.cn/blog_migrate/64bdad0736d064fc27bc38eae11ee7f7.jpeg)
成功!
![474181d399b8b677cfeebf340a848f9d.png](https://i-blog.csdnimg.cn/blog_migrate/40a729f1f9b3e8f4f834b42301ec6cd5.jpeg)
这个是配置文件的提示,咱们也可以在bean上再自定义
![e8912323c8fa0395656503f3b0e707e1.png](https://i-blog.csdnimg.cn/blog_migrate/c0f46d718423024563d51298e6a46d03.jpeg)
测试:
![8a8540defe3a62e715e07c9d9735e8b4.png](https://i-blog.csdnimg.cn/blog_migrate/833c045d062477cf4e157cb338c1b12e.jpeg)
校验这一块结束!!!!!!
补充一下全局异常处理:
a》编写异常处理类,使用@ControllerAdvice,使用@ExceptionHandler标注方法可以处理的异常。
package com.dwsoft.test.testjsr303.expection;import com.dwsoft.test.testjsr303.utils.R;import lombok.extern.slf4j.Slf4j;import org.apache.http.HttpStatus;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.HashMap;import java.util.List;import java.util.Map;/** * @author tlk * @date 2020/8/4-15:31 *///@ResponseBody//@ControllerAdvice 合二为一@RestControllerAdvicepublic class MyControllerAdvice { @ExceptionHandler(value = MethodArgumentNotValidException.class) public R handleValidExpection(MethodArgumentNotValidException e){ Mapmap=new HashMap<>(); BindingResult bindingResult = e.getBindingResult(); List fieldErrors = bindingResult.getFieldErrors(); fieldErrors.forEach((one)->{ String field = one.getField(); String defaultMessage = one.getDefaultMessage(); map.put(field,defaultMessage); }); return R.error(HttpStatus.SC_BAD_REQUEST,"入参不合法").put("data",map); } //其他异常 @ExceptionHandler(value = Throwable.class) public R handleOtherExpection(Throwable throwable){ return R.error(); }}
控制器注释掉之前的处理:
package com.dwsoft.test.testjsr303.controller;import com.dwsoft.test.testjsr303.entity.Brand;import com.dwsoft.test.testjsr303.utils.R;import com.dwsoft.test.testjsr303.valid.AddGroup;import com.dwsoft.test.testjsr303.valid.UpdateGroup;import org.apache.http.HttpStatus;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.validation.annotation.Validated;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;import java.security.acl.Group;import java.util.HashMap;import java.util.List;import java.util.Map;/** * @author tlk * @date 2020/8/4 */@RestControllerpublic class TestController { @RequestMapping("/test/jsr303") public R testJsr303(@Validated(value = {AddGroup.class}) @RequestBody Brand brand// , BindingResult bindingResult ) {// if(bindingResult.hasErrors()){// Mapmap=new HashMap<>();// List fieldErrors = bindingResult.getFieldErrors();// fieldErrors.forEach((item) ->{// String field = item.getField();// String defaultMessage = item.getDefaultMessage();// map.put(field,defaultMessage);// });// return R.error(HttpStatus.SC_BAD_REQUEST,"入参不合法").put("data",map);// } //业务处理 return R.ok(); }}
测试:
![2402dfcef75f8f320953804c0954f0ff.png](https://i-blog.csdnimg.cn/blog_migrate/fa224a5c087bbc3745651f48516cee76.jpeg)
大功告成!!!!!!!!!!!