Apache CXF 3.0:JAX-RS 2.0和Bean验证1.1最终一起

即将发布的出色的Apache CXF框架3.0版 (当前处于里程碑2阶段)带来了许多有趣且有用的功能,越来越接近提供完整的JAX-RS 2.0支持。 Bean Validation 1.1的支持是我们中许多人期盼已久的功能之一:简单而简洁的模型可为您的REST服务层添加验证功能。

在这篇博客中,我们将研究如何在Apache CXF项目中配置Bean Validation 1.1 ,并讨论一些有趣的用例。 为了使本篇文章简短而集中,我们将不讨论Bean Validation 1.1本身,而将更多的精力放在与JAX-RS 2.0资源的集成上(我们已经在较早的文章中介绍了一些Bean验证基础知识)。

目前, Hibernate Validator是Bean Validation 1.1规范的实际参考实现,最新版本为5.1.0.Final ,因此它将是我们选择的验证提供程序(目前Apache BVal项目仅支持Bean验证1.0 )。 值得一提的是, Apache CXF与实现无关,并且与Hibernate Validator或Apache BVal一经发布便可以很好地兼容 。

我们将构建一个非常简单的应用程序来管理人员。 我们的模型由一个名为Person的单个类组成。

package com.example.model;import javax.validation.constraints.NotNull;import org.hibernate.validator.constraints.Email;public class Person {@NotNull @Email private String email;@NotNull private String firstName;@NotNull private String lastName;public Person() {}public Person( final String email ) {this.email = email;}public String getEmail() {return email;}public void setEmail( final String email ) {this.email = email;}public String getFirstName() {return firstName;}public String getLastName() {return lastName;}public void setFirstName( final String firstName ) {this.firstName = firstName;}public void setLastName( final String lastName ) {this.lastName = lastName;}        
}

从上面的代码片段中,我们可以看到Person类对其属性施加了一些限制:它们都不应该为null 。 此外, 电子邮件属性应包含有效的电子邮件地址(将由Hibernate Validator特定的约束@Email进行验证)。 很简单

现在,让我们看一下具有验证约束的JAX-RS 2.0资源。 PeopleRestService类的框架绑定到/ people URL路径,如下所示。

package com.example.rs;import java.util.Collection;import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;import org.hibernate.validator.constraints.Length;import com.example.model.Person;
import com.example.services.PeopleService;@Path( "/people" ) 
public class PeopleRestService {@Inject private PeopleService peopleService;// REST methods here
}

它看起来应该很熟悉,没有什么新意。 我们将使用验证约束添加和装饰的第一种方法是getPerson ,它将通过其电子邮件地址查找一个人。

@Produces( { MediaType.APPLICATION_JSON } )
@Path( "/{email}" )
@GET
public @Valid Person getPerson( @Length( min = 5, max = 255 ) @PathParam( "email" ) final String email ) {return peopleService.getByEmail( email );
}

与传统的JAX-RS 2.0方法声明有几个区别。 首先,我们希望电子邮件地址( 电子邮件路径参数)的长度至少为5个字符(但不超过255个字符),这由@Length(min = 5,max = 255)注释强加。 其次,我们要确保此方法仅返回有效人,因此我们使用@Valid注释对方法的返回值进行注释。 @Valid的作用非常有趣:将根据其类( Person )声明的所有验证约束检查该人员的实例。

目前,在您的Apache CXF项目中,默认情况下Bean Validation 1.1不处于活动状态,因此,如果您运行应用程序并调用此REST端点,则所有验证约束都将被忽略。 好消息是,激活Bean Validation 1.1非常容易,因为它只需将三个组件添加到您的常规配置中(请查看此功能文档以获取更多详细信息和高级配置):

  • JAXRSBeanValidationInInterceptor in-inteceptor:对JAX-RS 2.0资源方法的输入参数进行验证
  • JAXRSBeanValidationOutInterceptor外接收器:执行JAX-RS 2.0资源方法返回值的验证
  • ValidationExceptionMapper异常映射器:将验证冲突映射到HTTP状态码 。 根据规范,所有输入参数验证冲突都将导致400 Bad Request错误。 分别,所有返回值验证冲突导致500内部服务器错误错误。 目前, ValidationExceptionMapper尚未在响应中包括其他信息(因为它可能违反应用程序协议),但是可以轻松地对其进行扩展以提供有关验证错误的更多详细信息。

AppConfig类展示了使用RuntimeDelegateJAXRSServerFactoryBean将所有必需的组件连接在一起的方法之一 (也支持基于XML的配置)。

package com.example.config;import java.util.Arrays;import javax.ws.rs.ext.RuntimeDelegate;import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor;
import org.apache.cxf.jaxrs.validation.JAXRSBeanValidationOutInterceptor;
import org.apache.cxf.jaxrs.validation.ValidationExceptionMapper;
import org.apache.cxf.message.Message;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;import com.example.rs.JaxRsApiApplication;
import com.example.rs.PeopleRestService;
import com.example.services.PeopleService;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;@Configuration
public class AppConfig {    @Bean( destroyMethod = "shutdown" )public SpringBus cxf() {return new SpringBus();}@Bean @DependsOn( "cxf" )public Server jaxRsServer() {final JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );factory.setServiceBeans( Arrays.< Object >asList( peopleRestService() ) );factory.setAddress( factory.getAddress() );factory.setInInterceptors( Arrays.< Interceptor< ? extends Message > >asList( new JAXRSBeanValidationInInterceptor()) );factory.setOutInterceptors( Arrays.< Interceptor< ? extends Message > >asList( new JAXRSBeanValidationOutInterceptor() ) );factory.setProviders( Arrays.asList( new ValidationExceptionMapper(), new JacksonJsonProvider() ) );return factory.create();}@Bean public JaxRsApiApplication jaxRsApiApplication() {return new JaxRsApiApplication();}@Bean public PeopleRestService peopleRestService() {return new PeopleRestService();}@Bean public PeopleService peopleService() {return new PeopleService();}
}

注入了所有输入/输出拦截器和异常映射器。 太好了,让我们构建项目并运行服务器以验证Bean Validation 1.1是否处于活动状态并按预期工作。

mvn clean package
java -jar target/jaxrs-2.0-validation-0.0.1-SNAPSHOT.jar

现在,如果我们使用短(或无效)电子邮件地址a @ b发出REST请求,则服务器应返回400 Bad Request 。 让我们验证一下。

> curl http://localhost:8080/rest/api/people/a@b -iHTTP/1.1 400 Bad Request
Date: Wed, 26 Mar 2014 00:11:59 GMT
Content-Length: 0
Server: Jetty(9.1.z-SNAPSHOT)

优秀的! 完全可以肯定的是,我们可以检查服务器控制台的输出,并在其中找到ConstraintViolationException类型的验证异常及其堆栈跟踪。 另外,最后一行提供了发生问题的详细信息: PeopleRestService.getPerson.arg0:长度必须在5到255之间 (请注意,因为参数名称在编译后当前在JVM上不可用,所以将它们替换为占位符,例如arg0arg1) ,…)。

WARNING: Interceptor for {http://rs.example.com/}PeopleRestService has thrown exception, unwinding now
javax.validation.ConstraintViolationExceptionat org.apache.cxf.validation.BeanValidationProvider.validateParameters(BeanValidationProvider.java:119)at org.apache.cxf.validation.BeanValidationInInterceptor.handleValidation(BeanValidationInInterceptor.java:59)at org.apache.cxf.validation.AbstractValidationInterceptor.handleMessage(AbstractValidationInterceptor.java:73)at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:240)at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:223)at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:197)at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:149)at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167)at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286)at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:211)at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262)at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:711)at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1112)at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:479)at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1046)at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)at org.eclipse.jetty.server.Server.handle(Server.java:462)at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:281)at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:232)at org.eclipse.jetty.io.AbstractConnection$1.run(AbstractConnection.java:505)at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)at java.lang.Thread.run(Unknown Source)Mar 25, 2014 8:11:59 PM org.apache.cxf.jaxrs.validation.ValidationExceptionMapper toResponse
WARNING: PeopleRestService.getPerson.arg0: length must be between 5 and 255

接下来,我们将添加另外两种REST方法来演示集合和实际的Response验证。

@Produces( { MediaType.APPLICATION_JSON } )
@GET
public @Valid Collection< Person > getPeople( @Min( 1 ) @QueryParam( "count" ) @DefaultValue( "1" ) final int count ) {return peopleService.getPeople( count );
}

对象集合上的@Valid批注将确保集合中的每个对象都是有效的。 @Min(1)注释还将count参数限制为最小值1 如果未指定查询参数, 则将@DefaultValue考虑在内)。 让我们故意添加没有设置名字和姓氏的人员,这样结果集合将包含至少一个不通过验证过程的人员实例。

> curl http://localhost:8080/rest/api/people -X POST -id "email=a@b3.com"

这样,对getPeople REST方法的调用应返回500 Internal Server Error 。 让我们检查情况是否如此。

> curl -i http://localhost:8080/rest/api/people?count=10HTTP/1.1 500 Server Error
Date: Wed, 26 Mar 2014 01:28:58 GMT
Content-Length: 0
Server: Jetty(9.1.z-SNAPSHOT)

查看服务器控制台输出,就在这里提示错误。

Mar 25, 2014 9:28:58 PM org.apache.cxf.jaxrs.validation.ValidationExceptionMapper toResponse
WARNING: PeopleRestService.getPeople.[0].firstName: may not be null
Mar 25, 2014 9:28:58 PM org.apache.cxf.jaxrs.validation.ValidationExceptionMapper toResponse
WARNING: PeopleRestService.getPeople.[0].lastName: may not be null

最后,还有另一个例子,这次是通用的Response对象。

@Valid
@Produces( { MediaType.APPLICATION_JSON  } )
@POST
public Response addPerson( @Context final UriInfo uriInfo,@NotNull @Length( min = 5, max = 255 ) @FormParam( "email" ) final String email, @FormParam( "firstName" ) final String firstName, @FormParam( "lastName" ) final String lastName ) {        final Person person = peopleService.addPerson( email, firstName, lastName );return Response.created( uriInfo.getRequestUriBuilder().path( email ).build() ).entity( person ).build();
}

最后一个示例有些棘手: Response类是JAX-RS 2.0 API的一部分,并且没有定义验证约束。 因此,在此类的实例上强加任何验证规则都不会触发任何违规行为。 但是Apache CXF会尽力而为,并执行一个简单但有用的技巧:代替响应实例,将对响应的实体进行验证。 我们可以通过尝试创建一个没有设置姓氏和名字的人来轻松验证这一点:预期结果应为500 Internal Server Error

> curl http://localhost:8080/rest/api/people -X POST -id "email=a@b3.com"HTTP/1.1 500 Server Error
Date: Wed, 26 Mar 2014 01:13:06 GMT
Content-Length: 0
Server: Jetty(9.1.z-SNAPSHOT)

服务器控制台输出更加详细:

Mar 25, 2014 9:13:06 PM org.apache.cxf.jaxrs.validation.ValidationExceptionMapper toResponse
WARNING: PeopleRestService.addPerson.<return value>.firstName: may not be null
Mar 25, 2014 9:13:06 PM org.apache.cxf.jaxrs.validation.ValidationExceptionMapper toResponse
WARNING: PeopleRestService.addPerson.<return value>.lastName: may not be null

真好! 在本博文中,我们谈到了Bean验证1.1如何通过提供如此丰富和可扩展的声明式验证支持来使您的Apache CXF项目更好的话题。 绝对可以试试看!

  • 完整项目可在GitHub上获得 。

翻译自: https://www.javacodegeeks.com/2014/04/apache-cxf-3-0-jax-rs-2-0-and-bean-validation-1-1-finally-together.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows.onload和body的onload属性的区别

关于windows.onload和body的onload属性的区别网上有些说法说的也不太统一,现在系统说下: 先看共同点: 都是body内容体加载结束执行&#xff1b; window.onload 内部方式可以 推荐的 body onload属性&#xff1a; 内联或者内嵌方式可以&#xff0c; 内部也可以 首先,这两个onlo…

行高 line-height

一、行高的定义line-height(行高)&#xff1a;两行文字基线之间的距离1、什么是基线&#xff1f;2、为何是基线&#xff1f;3、需要两行吗&#xff1f;1、什么是基线&#xff1f;我们上学的时候都用过&#xff0c;抄写英文字母的时候。其中有一条红线&#xff0c;这个红线就是基…

实验七报告

一、实验结论 part1&#xff1a;验证性实验 1.验证性实验2 如果事先不知道学生人数&#xff0c;尝试对line29做如下修改后&#xff0c;程序运行结果是否正确&#xff1f;回答问题&#xff0c;并给出运行结果截图。 运行结果正确// 将file1.txt中小写字母转换成大写后&#xff…

Lambda表达式和流API:基本示例

该博客文章包含基本Lambda表达式和Stream API示例的列表&#xff0c;我在2014年6月在Java用户组– Politechnica Gedanensis &#xff08;格但斯克技术大学&#xff09;和Goyello的实时编码演示中使用了这些示例。 Lambda表达式 句法 最常见的示例&#xff1a; Runnable runn…

示波器1m和50欧姆示阻抗匹配_阻抗匹配,示波器,50欧姆电阻,他们之间是什么关系?(第一回)...

首先思考这样一个问题&#xff0c;下面这个测量实验中&#xff0c;示波器的测量结果是多少&#xff1f;是和信号源一样的5V吗&#xff1f;先别着急回答&#xff0c;假如里面的信号源和示波器不是理想型 &#xff0c;而是和现实中一样带有内部阻抗的元件&#xff0c;见下图&…

Ajax jquery的库的简化版本

Ajax jquery的库的简化版本 (function(){ //面向外界的唯一变量接口&#xff01; var myajax window.myajax {}; //作者、版本号等等信息 myajax.author "考拉"; myajax.version "1.0.0"; //这个对象有两个属性&#xff0c;get、pos…

10月23日java web培训日记

分析了客户端身份认证的例子程序&#xff0c;讲解到Digest认证时&#xff0c;顺便提了一下SSLServerSocket&#xff0c;要求学员们能够通过SSLServerSocket的创建过程阐述工厂模式 为了更好地读懂AuthenticateServlet这个Servlet&#xff0c;要先明白两次请求的处理代码都放在了…

全局参数使用

1. $_SERVER[HTTP_ACCEPT] 返回来自当前请求的请求头。 场景&#xff0c;校验提交的数据前&#xff0c;看是不是 post请求 if ($_SERVER["REQUEST_METHOD"] "POST") { echo "请求方式是post" } 转载于:https://www.cnblogs.com/kaibindirver/p/…

XPath语法规则及实例

XPath语法规则及实例 XPath语法规则一、XPath术语&#xff1a; 1.节点&#xff1a;在XPath中&#xff0c;有七种类型的节点&#xff1a;元素、属性、文本、命名空间、处理指令、注释以及文档&#xff08;根&#xff09;节点。 XML文档是被作为节点树来对待的。树的根被称为文档…

Spring测试上下文缓存+ AspectJ @Transactional + Ehcache的痛苦

您在使用AspectJ Transactionals和Spring吗&#xff1f; 您是否有多个SessionFactory&#xff0c;也许一个用于嵌入式数据库进行单元测试&#xff0c;一个用于实际数据库进行集成测试&#xff1f; 您是否遇到这些例外之一&#xff1f; org.springframework.transaction.Cannot…

WorkPlus超级APP助力企业节省IT人力成本,实现快速移动化

在信息化时代&#xff0c;移动应用已经成为企业发展的重要组成部分。然而&#xff0c;开发和维护原生客户端的成本却相对较高&#xff0c;需要大量的iOS、安卓和桌面端工程师。为了解决这一问题&#xff0c;WorkPlus作为一个功能完备的超级APP&#xff0c;为企业节约了大量的IT…

hujingwei oracle_Oracle收缩表空间

可以使用 alter database datafile file path... resize xM 的命令来缩小数据文件。SELECT alter database datafile || A.FILE_NAME || resize ||ROUND(A.FILESIZE - (A.FILESIZE - C.HWMSIZE - 100) * 0.8) || M;,A.FILESIZE || M AS "数据文件的总大小", C.HWM…

addEventListener的click和onclick的区别

前两节都和addEventListener的click有关&#xff0c;于是在想它与onclick有什么区别呢&#xff0c;自己调试了一下&#xff0c;网上也有相关资料 事件绑定 onclick绑定方式 优点&#xff1a; - 简洁 - 处理事件的this关键字指向当前元素 缺点&#xff1a; - 不能对事件捕获或…

学车日记

今天是正式开始学车&#xff0c;先考交规&#xff0c;今天早上要赶驾校的班车&#xff0c;所以必须6点起床&#xff0c;那叫一个难受呀&#xff0c;好像已经有很长时间没有这么早起过了&#xff0c;不过经过复杂的思想斗争我终于还是如期起床了&#xff0c;今天要是赶不上班车错…

ApiCloud利用NVTabBar模块快速搭建起APP的框架

废话不说&#xff0c;直接上代码 模块地址&#xff1a;https://docs.apicloud.com/Client-API/Nav-Menu/NVTabBar 代码实例&#xff1a; <!doctype html> <html><head><meta charset"utf-8"><meta name"viewport" content"…

Java 8中新的并行API:Glitz和Glamour的背后

我是一个出色的多任务处理者。 即使我在写这篇文章&#xff0c;我仍然可以为昨天在一个大家都对我陌生的聚会上发表的言论感到尴尬。 好消息是&#xff0c;我并不孤单– Java 8在多任务处理方面也相当出色。 让我们看看如何。 Java 8中引入的关键新功能之一是并行数组操作。 这…

有趣的js匿名函数写法(function嵌套)

例子没有什么实际意义&#xff0c;只能做为思路参考 <!DOCTYPE html><html><head><meta charset"UTF-8"><title></title></head><body><script>function ck(a) {console.log(a);return function(b) {console.…

mangouDB和mysql的区别_谈谈mongodb,mysql的区别和具体应用场景

最近对数据库比较感兴趣&#xff0c;于是就去研究了下部分相关热门的数据库。MySQL关系型数据库。在不同的引擎上有不同 的存储方式。查询语句是使用传统的sql语句&#xff0c;拥有较为成熟的体系&#xff0c;成熟度很高。开源数据库的份额在不断增加&#xff0c;mysql的份额页…

ASP.NET 中执行 URL 重写

作者&#xff1a;overred 来源&#xff1a;原创URL 重写就是把URL地址重新改写&#xff08;汗^_^&#xff09;。详情&#xff1a;http://www.microsoft.com/china/msdn/library/webservices/asp.net/URLRewriting.mspx优点&#xff1a;把url缩短等用法&#xff1a;1.下载ms的…

考眼力

题目内容&#xff1a; gmbh{4d850d5c3c2756f67b91cbe8f046eebd} try to find the flag 看到gmbh发现偏移&#xff0c;按照gmbhflag发现字母向左发生偏移&#xff0c;字母全部向左移动一位即可得到flag。 flag&#xff1a;flag{4c850c5b3b2756e67a91bad8e046ddac} 总结&#xf…