先说应用场景,比如说前台传来一个参数,我们肯定得在后台判断一下,比如id不能为空了,电话号码不能少于11位了等等。如果在service层一个一个判断岂不是要累死个人。代码也不简洁,这时候我们肯定会想到用注解啊。javax包提供了参数验证的功能。足够满足我们的需要。在对象上加上注解还没有完,还有验证,比如说我给对象加上注解了,我们没有验证还是没一点用,验证方法肯定是我们自己定义了,如果报错,我们这边写一个方法获取这些报错信息要么写入日志,要么返回前端。
首先我们需要这些类的依赖
<!-- 注解validator --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.4.Final</version> </dependency> <!--工具包 tools --> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.2</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency>
写一个验证的工具类(这个工具类可以直接拿起来用,不用管他里面是如何实现的)
package com.mmall.util; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.mmall.exception.ParamException; import org.apache.commons.collections.MapUtils; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; public class BeanValidator { private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); //检查一个object对象 public static <T> Map<String, String> validate(T t, Class... groups) { Validator validator = validatorFactory.getValidator(); Set validateResult = validator.validate(t, groups); if (validateResult.isEmpty()) { return Collections.emptyMap(); } else { LinkedHashMap errors = Maps.newLinkedHashMap(); Iterator iterator = validateResult.iterator(); while (iterator.hasNext()) { ConstraintViolation violation = (ConstraintViolation)iterator.next(); errors.put(violation.getPropertyPath().toString(), violation.getMessage()); } return errors; } } //检查一个list对象 public static Map<String, String> validateList(Collection<?> collection) { Preconditions.checkNotNull(collection); Iterator iterator = collection.iterator(); Map errors; do { if (!iterator.hasNext()) { return Collections.emptyMap(); } Object object = iterator.next(); errors = validate(object, new Class[0]); } while (errors.isEmpty()); return errors; } //用一个方法来封装上面的两个方法。我们可以选择用这个方法,然后到map,把map的错误信息记录到日志,再抛异常 public static Map<String, String> validateObject(Object first, Object... objects) { if (objects != null && objects.length > 0) { return validateList(Lists.asList(first, objects)); } else { return validate(first, new Class[0]); } } //我们也可以选择用这个方法,直接抛异常 public static void check(Object param) throws ParamException { Map<String, String> map = BeanValidator.validateObject(param); if (MapUtils.isNotEmpty(map)) { throw new ParamException(map.toString()); } } }
解释一下上面的方法,就是说controller调用上面工具类的两个方法。一个是返回map,一个是直接抛异常。map里面是包含的错误信息。因为注解里面带的用错误信息。然后我们的全局捕获异常类会捕获到里面的信息。搞不清也没关系。工具类而已。拿起来就用,一顿粘贴复制。美滋滋~~~
写个实体类
package com.mmall.model; import lombok.Data; import org.hibernate.validator.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * Created by 敲代码的卡卡罗特 * on 2018/3/24 23:59. */ @Data public class TestVo { @NotNull private Integer id; @NotBlank private String name; public TestVo(Integer id, String name) { this.id = id; this.name = name; } }
然后controller层测试下
@RequestMapping("test.json") public ModelAndView ss(){ BeanValidator.check(new TestVo(null,null)); HashMap map = new HashMap(); map.put("name","lzh"); map.put("age",12); ModelAndView view=new ModelAndView("jsonView",map); return view; }
会直接抛出异常。当然如果javax提供的异常信息不能满足你,你也可以自定义。自行百度把。。。。