Jersey 2.22.2 官方文档第18章学习笔记

验证是用来检查某些数据是否遵循预定义的规则。本章将介绍Jersey对Bean Validation的支持,包括所需要的依赖、配置、注册及使用。

18.1 BeanValidation 依赖

Bean Validation在Jersey中是以扩展模块的形式来提供的,使用时需要在pom.xml(如果使用的是Maven)加入依赖。

<dependency>

    <groupId>org.glassfish.jersey.ext</groupId>

    <artifactId>jersey-bean-validation</artifactId>

    <version>2.22.2</version>

</dependency>

这个模块直接依赖Hibernate Validator,Hibernate Validator实现了Bean Validation API规范中的大多数接口。

如果想使用Bean Validation API的其它实现,将HibernateValidator的maven依赖从pom文件中删除,然后加入其它实现的依赖即可。

<dependency>

    <groupId>org.glassfish.jersey.ext</groupId>

    <artifactId>jersey-bean-validation</artifactId>

    <version>2.22.2</version>

    <exclusions>

        <exclusion>

            <groupId>org.hibernate</groupId>

            <artifactId>hibernate-validator</artifactId>

        </exclusion>

    </exclusions>

</dependency>

18.2在Jersey中启用Bean Validation

只要将jersey-bean-validation模块加入classpath,jersey中的自动发现机制就会发现依赖,因此无需显式注册该模块。

18.3 配置Bean Validation

ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK  // 实验了下还没搞明白,等看源码搞懂再补充。ServerProperties.BV_SEND_ERROR_IN_RESPONSE 启用将错误信息存于Response entity中并发送到客户端。


18.4 验证JAX-RS资源与方法

18.4.1 注解约束

Bean validation规范支持使用注解来验证beans,方法参数与方法返回值,例如。

@Path("constraint")
public class MyResourceClass {
	
	@GET
	public void paramTest(@NotNull @QueryParam("q") String q){
		System.out.println(q);
	}
}
public class Main {

	public static void main(String[] args) throws IOException {
		URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
		ResourceConfig config = new ResourceConfig();
		config.packages("jersey.docCh3");
		config.packages("jersey.docCh18");
		config.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true)
			  .property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
		HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(baseUri, config);
		httpServer.start();
	}
}

当发送请求http://localhost:9998/constraint  返回不能为null (path = MyResourceClass.paramTest.arg0, invalidValue = null)上面的代码中@NotNull对查询参数进行验证,验证注解并非只能用在方法参数上,这些注解也可以用在任何支持JAX-RS注解的地方。下面的代码将注解添在变量上,及getter方法上进行验证。

@Path("constraint")
public class MyResourceClass {
	
	@NotNull
	private String test;
	
	private String test2;
	
	@NotNull
	public String getTest() {
		return test;
	}

	public void setTest(String test) {
		this.test = test;
	}

	@GET
	public void paramTest(@NotNull @QueryParam("q") String q){
		System.out.println(q);
	}
}

发出请求http://localhost:9998/constraint 返回

不能为null (path =MyResourceClass.test, invalidValue =null)

不能为null (path =MyResourceClass.paramTest.arg0, invalidValue = null)

不能为null (path =MyResourceClass.test, invalidValue =null)

除了在变量上添加验证注解外,还可以在类上定义注解。有@NonEmptyNames 注解,验证MyResourceClass,代码示例如下。

@Target( {ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckCaseValidator.class)
@Documented
public @interface NonEmptyNames {

    String message() default "{UserDefined NonEmptyNames}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

class CheckCaseValidator implements ConstraintValidator<NonEmptyNames, Param> {

	public void initialize(NonEmptyNames constraintAnnotation) {
	}

	public boolean isValid(Param value, ConstraintValidatorContext context) {
		return false;
	}
}
Resource如下
@Path("constraint")
public class MyResourceClass {
	
	@GET
	@Path("beanAno")
	public Response beanAnoTest(@Valid @QueryParam("q") Param param){
		System.out.println(param);
		return Response.status(200).entity(param).build();
	}
}

Bean的定义如下
@NonEmptyNames
public class Param {
	@NotBlank
	private String s;

	@Range(min = -10,max = -5)
	private int i;
	public Param(String s) {
	}

	public Param() {
	}
}

发出请求http://localhost:9998/constraint/beanAno?q=1234  返回。

需要在-10和-5之间 (path = MyResourceClass.beanAnoTest.arg0.i, invalidValue = 0)
不能为空 (path = MyResourceClass.beanAnoTest.arg0.s, invalidValue = null)
{UserDefined NonEmptyNames} (path = MyResourceClass.beanAnoTest.arg0, invalidValue = jersey.docCh18.Param@763fdff1)
其中{UserDefined NonEmptyNames}返回的是对类进行注解的结果。

18.4.2 注解约束与验证器

注解约束与验证器的定义遵循Bean Validation规范。在域上定义的@Email注解使用@Constraint元注解来定义,定义如下。

@Target({ METHOD, FIELD, PARAMETER })
@Retention(RUNTIME)
@Constraint(validatedBy = EmailValidator.class)
public @interface Email {
 
    String message() default "{com.example.validation.constraints.email}";
 
    Class<?>[] groups() default {};
 
    Class<? extends Payload>[] payload() default {};
}

@Constraint注解必须包含对验证器类的引用,验证器类将用来验证值。EmailValidator类必须实现ConstraintValidator<Email,T>,这里T是要被验证的类型,EmailValidator的定义如下。

public class EmailValidator implements ConstraintValidator<Email, String> {
 
    public void initialize(Email email) {
    }
 
    public boolean isValid(String value, ConstraintValidatorContext context) {
    }
}
EmailValidator用在标有@Email注解的String类型的值上。 而除String外的Java类型也可以以同样的方式使用。

18.4.3 实体验证

请求实体可以被映射到资源方法参数上。有两种方式验证实体。如果请求实体被映射到Java bean上,这个javabean通过注解约束注解,那么可以通过使用@Valid注解可以来启用验证。

@StandardUser
class User {
 
    @NotNull
    private String firstName;
 
    ...
}
 
 
@Path("/")
class MyResourceClass {
 
    @POST
    @Consumes("application/xml")
    public void registerUser(@Valid User user) {
        ...
    }
}

上面的代码中,与@StandardUser关联的验证器将被调用,来对映射到user上的请求实体进行验证。除了将注解参数放在类上,也可以将对Bean验证的注解放在方法参数上,如下面的例子所示。以本文18.4.1中@NonEmptyNames的定义为例,修改并将该注解放到方法参数前对Bean验证。

@Target({ElementType.PARAMETER,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckCaseValidator.class)
@Documented
public @interface NonEmptyNames {

	String message() default "{UserDefined NonEmptyNames}";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};

}

class CheckCaseValidator implements ConstraintValidator<NonEmptyNames, Param> {

	public void initialize(NonEmptyNames constraintAnnotation) {
	}

	public boolean isValid(Param value, ConstraintValidatorContext context) {
		return false;
	}
}

@Path("constraint")
public class MyResourceClass {
	@GET
	@Path("beanAno")
	public Response beanAnoTest(@NonEmptyNames @QueryParam("q") Param param){
		System.out.println(param);
		return Response.status(200).entity(param).build();
	}
}

发出请求http://localhost:9998/constraint/beanAno?q=1234 

返回响应{UserDefined NonEmptyNames} 

(path =MyResourceClass.beanAnoTest.arg0, invalidValue = jersey.docCh18.Param@2d926039)

从资源方法参数中返回的响应实体也可以通过注解的方式来验证,只需要使用方法注解即可,例子如下。

@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE,})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckCaseValidator.class)
@Documented
public @interface NonEmptyNames {
	String message() default "{UserDefined NonEmptyNames}";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}

class CheckCaseValidator implements ConstraintValidator<NonEmptyNames, Param> {

	public void initialize(NonEmptyNames constraintAnnotation) {
	}
	public boolean isValid(Param value, ConstraintValidatorContext context) {
		return false;
	}
}
@Path("constraint")
public class MyResourceClass {
	@GET
	@Path("beanAno")
	@NonEmptyNames
	public Param beanAnoTest(@QueryParam("q") String param){
		System.out.println(param);
		return new Param(param);
	}
}

发送请求http://localhost:9998/constraint/beanAno?q=1234 返回验证信息 {UserDefinedNonEmptyNames} (path =MyResourceClass.beanAnoTest., invalidValue = jersey.docCh18.Param@a4d840d)




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值