1、在项目中引入所需的jar
<!-- 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.1.1.Final</version> </dependency>
2、添加BeanValidators工具类(可选,方便在方法内校验POJO)
package com.huatech.common.validator; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import javax.validation.Validator; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.huatech.common.support.SpringContextHolder; /** * JSR303 Validator(Hibernate Validator)工具类. * * ConstraintViolation中包含propertyPath, message 和invalidValue等信息. * 提供了各种convert方法,适合不同的i18n需求: * 1. List<String>, String内容为message * 2. List<String>, String内容为propertyPath + separator + message * 3. Map<propertyPath, message> * * @author lh * @version 2017-06-06 */ public class BeanValidators { /** * JSR303校验器 */ private static final Validator VALIDATOR = SpringContextHolder.getBean("validator"); public static <T> void validate(final T t) { Set<ConstraintViolation<T>> constraintViolations = VALIDATOR.validate(t); if (constraintViolations.size() > 0) { throw new RuntimeException(constraintViolations.iterator().next().getMessage()); // final StringBuffer buffer = new StringBuffer(); // for (final ConstraintViolation<T> violation : constraintViolations) { // buffer.append(violation.getMessage()).append(";"); // } // throw new BusinessException(buffer.toString()); } } /** * 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static void validateWithException(final Validator validator, final Object object, final Class<?>... groups) throws ConstraintViolationException { final Set constraintViolations = validator.validate(object, groups); if (!constraintViolations.isEmpty()) { throw new ConstraintViolationException(constraintViolations); } } /** * 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>中为List<message>. */ public static List<String> extractMessage(ConstraintViolationException e) { return extractMessage(e.getConstraintViolations()); } /** * 辅助方法, 转换Set<ConstraintViolation>为List<message> */ @SuppressWarnings("rawtypes") public static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) { final List<String> errorMessages = Lists.newArrayList(); for (ConstraintViolation violation : constraintViolations) { errorMessages.add(violation.getMessage()); } return errorMessages; } /** * 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为Map<property, message>. */ public static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) { return extractPropertyAndMessage(e.getConstraintViolations()); } /** * 辅助方法, 转换Set<ConstraintViolation>为Map<property, message>. */ @SuppressWarnings("rawtypes") public static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) { Map<String, String> errorMessages = Maps.newHashMap(); for (ConstraintViolation violation : constraintViolations) { errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage()); } return errorMessages; } /** * 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath message>. */ public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) { return extractPropertyAndMessageAsList(e.getConstraintViolations(), " "); } /** * 辅助方法, 转换Set<ConstraintViolations>为List<propertyPath message>. */ @SuppressWarnings("rawtypes") public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) { return extractPropertyAndMessageAsList(constraintViolations, " "); } /** * 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath +separator+ message>. */ public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) { return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator); } /** * 辅助方法, 转换Set<ConstraintViolation>为List<propertyPath +separator+ message>. */ @SuppressWarnings("rawtypes") public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations, String separator) { final List<String> errorMessages = Lists.newArrayList(); for (ConstraintViolation violation : constraintViolations) { errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage()); } return errorMessages; } }
package com.huatech.common.support; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext. * * @author lh * @date 2017-06-06 */ public class SpringContextHolder implements ApplicationContextAware, DisposableBean { private static ApplicationContext applicationContext = null; private static final Logger LOGGER = LoggerFactory.getLogger(SpringContextHolder.class); /** * 取得存储在静态变量中的ApplicationContext. */ public static ApplicationContext getApplicationContext() { assertContextInjected(); return applicationContext; } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); } /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ public static <T> T getBean(Class<T> requiredType) { assertContextInjected(); return applicationContext.getBean(requiredType); } /** * 清除SpringContextHolder中的ApplicationContext为Null. */ public static void clearHolder() { LOGGER.debug("清除SpringContextHolder中的ApplicationContext:{}" , applicationContext); applicationContext = null; } /** * 实现ApplicationContextAware接口, 注入Context到静态变量中. */ @Override public void setApplicationContext(ApplicationContext applicationContext) { LOGGER.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext); if (SpringContextHolder.applicationContext != null) { LOGGER.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:{}" , SpringContextHolder.applicationContext); } SpringContextHolder.applicationContext = applicationContext; } /** * 实现DisposableBean接口, 在Context关闭时清理静态变量. */ @Override public void destroy() throws Exception { SpringContextHolder.clearHolder(); } /** * 检查ApplicationContext不为空. */ private static void assertContextInjected() { Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder."); } }
3、在spring配置文件中添加资源配置
<mvc:annotation-driven validator="validator"/> <!-- SpringContextHolder:可选 --> <bean class="com.huatech.common.support.SpringContextHolder"/> <!-- 国际化配置 --> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" /> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <property name="providerClass" value="org.hibernate.validator.HibernateValidator" /> <!-- 这里配置将使用上面国际化配置的messageSource --> <property name="validationMessageSource" ref="messageSource" /> </bean> <!-- 资源配置 --> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames"> <list> <value>classpath:messages/Messages</value> <value>classpath:messages/Validation</value> </list> </property> <property name="useCodeAsDefaultMessage" value="true" /> </bean>
配置完成后在resources目录下创建messages文件夹 并在该文件夹下新建Validation_zh_CN.properties文件,为第4步做准备。
4、为Model类的相关属性添加校验注解
package com.huatech.model; import java.lang.reflect.InvocationTargetException; import java.util.Date; import org.apache.commons.beanutils.BeanUtils; import org.hibernate.validator.constraints.NotEmpty; import com.alibaba.fastjson.annotation.JSONField; import com.huatech.domain.SystemConfig; /** * 系统配置 * * @author lh * @version V2.0.0 * @date 2017年05月10日 14时46分16秒 Copyright 杭州融都科技股份有限公司 统一资金接入系统 BDS All Rights * Reserved 官方网站:www.erongdu.com 研发中心:rdc@erongdu.com * 未经授权不得进行修改、复制、出售及商业使用 */ public class SystemConfigModel extends BasePageModel { /** * 主键 */ private Long id; /** * 配置标识 */ @NotEmpty(message = "{systemConfig.configCode.notEmpty}") private String configCode; /** * 配置值 */ @NotEmpty(message = "{systemConfig.configValue.notEmpty}") private String configValue; // 省略其他属性和getter、setter方法 }
在Validation_zh_CN.properties文件中添加message键值对
systemConfig.configCode.notEmpty=配置项标识不能为空 systemConfig.configValue.notEmpty=配置值不能为空
5、在Action的方法头中为model添加@Valid注解并绑定错误信息
/** * 添加系统配置 * * @param model * @return * @throws Exception */ @RequestMapping(value = "/modules/system/config/doAppend", method = RequestMethod.POST) @ResponseBody public String doAppend(@Valid SystemConfigModel model, BindingResult result) throws Exception { Map<String, Object> data = new HashMap<>(); try { if (null == model) { throw new RuntimeException("model can not be null!"); } // 校验参数 if(result.hasErrors()){ data.put("result", false); data.put("msg", getBindErrors(result)); return JSON.toJSONString(data); } //model.validParam(); // 填写补充信息 model.setCreateTime(new Date()); model.setStatus(1); systemConfigService.save(model.copyToDomain()); data.put("result", true); data.put("msg", "success"); } catch (Exception e) { logger.error("addMer_error", e); data.put("result", false); data.put("msg", e.getMessage()); } return JSON.toJSONString(data); }
/** * 取得错误信息 * @param bindingResult * @return */ public String getBindErrors(final BindingResult bindingResult){ final StringBuilder errorStr = new StringBuilder(); final List<ObjectError> errors = bindingResult.getAllErrors(); final int errorLen = errors.size()-1; for (int i = errorLen; i >=0 ; i--) { errorStr.append(errors.get(i).getDefaultMessage()).append("<br>"); } return errorStr.substring(0, errorStr.length()-4); }