在系统中使用Bean Validation验证参数
转自:http://www.importnew.com/18561.html
为什么要使用Bean Validation?
|
1
2
3
4
5
|
public String queryValueByKey(String parmTemplateCode, String conditionName, String conditionKey, String resultName) { checkNotNull(parmTemplateCode, "parmTemplateCode not null"); checkNotNull(conditionName, "conditionName not null"); checkNotNull(conditionKey, "conditionKey not null"); checkNotNull(resultName, "resultName not null"); |
该方法输入的四个参数都是必填项。用代码进行参数验证带来几个问题
- 需要写大量的代码来进行参数验证。
- 需要通过注释来直到每个入参的约束是什么。
- 每个程序员做参数验证的方式不一样,参数验证不通过抛出的异常也不一样。
什么是Bean Validation?
Bean Validation是一个通过配置注解来验证参数的框架,它包含两部分Bean Validation API和Hibernate Validator。
- Bean Validation API是Java定义的一个验证参数的规范。
- Hibernate Validator是Bean Validation API的一个实现。
快速开始
引入POM
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<!-- Bean Validation start --><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.1.Final</version></dependency><dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version></dependency><dependency> <groupId>javax.el</groupId> <artifactId>el-api</artifactId> <version>2.2</version></dependency><dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version></dependency><dependency> <groupId>org.jboss.logging</groupId> <artifactId>jboss-logging</artifactId> <version>3.1.3.GA</version></dependency><dependency> <groupId>com.fasterxml</groupId> <artifactId>classmate</artifactId> <version>1.0.0</version></dependency><dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.13</version></dependency><!-- Bean Validation end --> |
实例代码如下,可以验证Bean,也可以验证方法参数
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
import java.lang.reflect.Method;import java.util.Set;import javax.validation.ConstraintViolation;import javax.validation.Validation;import javax.validation.Validator;import javax.validation.constraints.Max;import javax.validation.constraints.NotNull;import javax.validation.executable.ExecutableValidator;public class BeanValidatorTest { public static void main(String[] args) { Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); //验证Bean参数,并返回验证结果信息 Car car = new Car(); Set<ConstraintViolation<Car>> validators = validator.validate(car); for (ConstraintViolation<Car> constraintViolation : validators) { System.out.println(constraintViolation.getMessage()); } // 验证方法参数 Method method = null; try { method = Car.class.getMethod("drive", int.class); } catch (SecurityException e) { } catch (NoSuchMethodException e) { } Object[] parameterValues = { 80 }; ExecutableValidator executableValidator = validator.forExecutables(); Set<ConstraintViolation<Car>> methodValidators = executableValidator.validateParameters(car, method, parameterValues); for (ConstraintViolation<Car> constraintViolation : methodValidators) { System.out.println(constraintViolation.getMessage()); } } public static class Car { private String name; @NotNull(message = "车主不能为空") public String getRentalStation() { return name; } public void drive(@Max(75) int speedInMph) { } }} |
执行代码后,输出如下:
|
1
2
|
车主不能为空最大不能超过75 |
使用代码验证方法参数
Validation验证不成功可能返回多个验证错误信息,我们可以包装下,当有错误时直接返回第一个错误的异常。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import static com.google.common.collect.Iterables.getFirst;import java.util.Set;import javax.validation.ConstraintViolation;import javax.validation.Validation;import javax.validation.Validator;/** * 对象验证器 * * @author tengfei.fangtf * @version $Id: BeanValidator.java, v 0.1 Dec 30, 2015 11:33:40 PM tengfei.fangtf Exp $ */public class BeanValidator { /** * 验证某个bean的参数 * * @param object 被校验的参数 * @throws ValidationException 如果参数校验不成功则抛出此异常 */ public static <T> void validate(T object) { //获得验证器 Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); //执行验证 Set<ConstraintViolation<T>> constraintViolations = validator.validate(object); //如果有验证信息,则将第一个取出来包装成异常返回 ConstraintViolation<T> constraintViolation = getFirst(constraintViolations, null); if (constraintViolation != null) { throw new ValidationException(constraintViolation); } }} |
我们可以在每个方法的第一行调用BeanValidator.validate来验证参数,测试代码如下,
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
import static junit.framework.Assert.assertEquals;import javax.validation.constraints.Max;import javax.validation.constraints.NotNull;import org.junit.Test;/** * * @author tengfei.fangtf * @version $Id: BeanValidatorTest.java, v 0.1 Dec 30, 2015 11:33:56 PM tengfei.fangtf Exp $ */public class BeanValidatorTest { @Test public void test() { try { BeanValidator.validate(new Car()); } catch (Exception e) { assertEquals("rentalStation 车主不能为空", e.getMessage()); } } public static class Car { private String name; @NotNull(message = "车主不能为空") public String getRentalStation() { return name; } public void drive(@Max(75) int speedInMph) { } }} |
使用拦截器验证方法参数
我们在对外暴露的接口的入参中使用Bean Validation API配置参数约束,如下XXXService接口
|
1
2
3
4
5
|
public interface XXXService {GetObjectResponse getObject(GetObjectRequest getObjectRequest);} |
在getObject的GetObjectRequest参数中配置注解来约束参数。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class GetObjectRequest { @Valid @NotNull private ObjectKey objectKey; @Size(max = 9) private Map<String, Object> parameters; @AssertTrue public boolean isEntityNameOrCodeAtLeastOneIsNotBlank() { return isNotBlank(entityName) || isNotBlank(entityCode); }//代码省略} |
编写参数验证拦截器,当方法被调用时,触发Validator验证器执行验证,如果不通过则抛出ParameterValidationException。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
import static com.google.common.collect.Iterables.getFirst;import java.util.Set;import javax.validation.ConstraintViolation;import javax.validation.Validation;import javax.validation.Validator;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.xx.ParameterValidationException;/** * 参数验证拦截器,基于JSR-303 BeanValidation * * @author tengfei.fangtf * * @version $Id: TitanValidateInterceptor.java, v 0.1 Nov 23, 2015 11:13:55 PM tengfei.fangtf Exp $ */public class TitanValidateInterceptor implements MethodInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(TitanValidateInterceptor.class); private final Validator validator; public TitanValidateInterceptor() { validator = Validation.buildDefaultValidatorFactory().getValidator(); } @Override public Object invoke(MethodInvocation invocation) throws Throwable { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Validate arguments"); } //获取参数,并检查是否应该验证 Object[] arguments = invocation.getArguments(); for (Object argument : arguments) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Validate argument: {}", argument); } Set<ConstraintViolation<Object>> constraintViolations = validator.validate(argument); ConstraintViolation<Object> constraintViolation = getFirst(constraintViolations, null); if (constraintViolation == null) { continue; } if (LOGGER.isInfoEnabled()) { LOGGER.info("ConstraintViolation: {}", constraintViolation); } throw new ParameterValidationException(constraintViolation.getPropertyPath() + " " + constraintViolation.getMessage()); } return invocation.proceed(); }} |
配置拦截器core-service.xml,拦截XXXService的所有方法。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:webflow="http://www.springframework.org/schema/webflow-config" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd" default-autowire="byName"> <bean id="XXXService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <bean class="com.XXXService" /> </property> <property name="interceptorNames"> <list> <value>validateInterceptor</value> </list> </property> </bean> <bean id="validateInterceptor" class="com.mybank.bkloanapply.common.validator.ValidateInterceptor" /></beans> |
参考资料
- 注解配置参考
- http://beanvalidation.org
- http://www.ibm.com/developerworks/cn/java/j-lo-jsr303/
- http://hibernate.org/validator/
在系统中使用Bean Validation验证参数的更多相关文章
- Java Bean Validation(参数校验) 最佳实践
转载来自:http://www.cnblogs.com 参数校验是我们程序开发中必不可少的过程.用户在前端页面上填写表单时,前端js程序会校验参数的合法性,当数据到了后端,为了防止恶意操作,保持程序的 ...
- SpringMVC中实现Bean Validation(JSR 303 JSR 349 JSR 380)
JSR 303是针对bean数据校验提出的一个规范.使用注解方式实现数据校验. 每个注解的用法这里就不多介绍,请移步JSR 303 - Bean Validation 介绍及最佳实践 笔者上面提到的J ...
- 利用 Bean Validation 来简化接口请求参数校验
团队新来了个校招实习生静静,相互交流后发现竟然是我母校同实验室的小学妹,小学妹很热情地认下了我这个失散多年的大湿哥,后来... 小学妹:大湿哥,咱们项目里的 Controller 怎么都看不到参数校验 ...
- JSR 303 - Bean Validation 介绍及最佳实践
JSR 303 - Bean Validation 介绍及最佳实践 JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 ...
- JSR教程1——JSR 303 - Bean Validation介绍
1.Bean Validation 在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情.应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在通常的情况下, ...
- JSR 303 - Bean Validation 介绍及最佳实践(转)
JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 Java EE 6 发布,Bean Validation 作为一个 ...
- Bean Validation规范
以下内容转载自:https://www.ibm.com/developerworks/cn/java/j-lo-beanvalid/ Bean Validation规范介绍 JSR303 规范(Bea ...
- 一个新人如何学习在大型系统中添加新功能和Debug
文章背景: 今年七月份正式入职,公司主营ERP软件,楼主所在的组主要负责二次开发,使用的语言是Java. 什么叫二次开发呢?ERP软件的客户都是企业.而这些企业之间的情况都有所不同,一套标准版本的企业 ...
- 系统中异常公共处理模块 in spring boot
最近在用spring boot 做微服务,所以对于异常信息的 [友好展示]有要求,我设计了两点: 一. 在业务逻辑代码中,异常的抛出 我做了限定,一般只会是三种: 1. OmcException // ...
随机推荐
- 不同版本Eclipse对JDK版本要求
原文:https://blog.csdn.net/kevin_pso/article/details/54971739 1.Eclipse 4.6 (Neon)---需要JDK1.8版本,官网解释如下 ...
- Mysql之 配置文件读取顺序
On Unix, Linux and Mac OS X, MySQL programs read startup options from the following files, in the sp ...
- windows server 2008通过任务计划程序定时访问网站
1.新一个.bat文件,如: @echo offstart 网址exit 2.打windows server 2008,新建任务计划程序定时访问任务
- 第10章 网络安全(3)_安全套接字层SSL
4. 安全套接字层 4.1 安全套接字层(SSL)和传输层安全(TLS) (1)SSL/TLS提供的安全服务 ①SSL服务器鉴别,允许用户证实服务器的身份.支持SSL的客户端通过验证来自服务器的证书, ...
- Noi.ac #309. Mas的童年(贪心)
/* 用所谓的加法拆分操作得到 x + y = (x ^ y) + 2 * (x & y) 那么我们这两段异或相当于前缀和 + 2 * 分段使左右两块&最大 记当前前缀异或和为S, 那 ...
- Java 工程名上有个红色叹号
biuldpath把带×号的jar包remove保存,重新添加jar包
- BZOJ2321 [BeiJing2011集训] 星器
2321: [BeiJing2011集训]星器 Time Limit: 1 Sec Memory Limit: 128 MB Description Magic Land上的时间又过了若干世纪…… ...
- 从入门到熟悉 HTTPS 的 9 个问题
九个问题从入门到熟悉HTTPS 最近一边做毕设一边学习编程.前两天她问我 HTTPS 的问题,本来想直接扔一篇网上的教程给她.后来想了一下,那些文章大多直接介绍概念, 对新手不太友好,于是我干脆亲自给 ...
- this 基础使用方法
在Java中,this是调用类中变量和内部类的构造方法的关键词,在对象有同名变量时,可以指定类的变量. 例子1: package example_1; import java.lang.*; publ ...
- 17.docker及scrapy-splash安装-1
docker 安装网址: https://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/ 这就安装成功了!!!