当前位置: 首页 > 科技观察

Springboot集成Jersey实现REST全风格API及原理

时间:2023-03-13 17:14:40 科技观察

概述JerseyRESTful框架是一个开源的RESTful框架,实现了JAX-RS(JSR311&JSR339)规范。它扩展了JAX-RS参考实现并提供了更多功能和工具以进一步简化RESTful服务和客户端开发。尽管它相对年轻,但它已经是一个生产级的RESTful服务和客户端框架。与Struts类似,它也可以与hibernate和spring框架集成。jersey1.X使用sun的com.sun.jerseyjersey2.X使用glassfish的org.glassfish.jerseyJersey与JAX-RS的关系:Jersey是一个实现restful风格的框架;JAX-RS也实现了restful风格。那么Jersey和JAX-RS是什么关系呢?我们可以这样理解:JAX-RS是java本身的一个小框架,实现了restful风格,但是功能不是很强大;至于Jersey,它是一个比较成熟的restful框架。它在设计的时候是基于JAX-RS的,它使用了Java的JAX-RS的一些注解。当然,它也有自己独特的注解等更强大的功能。如果您更喜欢REST端点的JAX-RS编程模型,您可以使用一种可用的实现来代替SpringMVC。Jersey和ApacheCXF开箱即用。CXF要求您在应用程序上下文中将其servlet或过滤器注册为@Bean。Jersey原生支持Spring,所以我们在SpringBoot中也为它提供了自动配置支持,还有一个starter。要开始使用Jersey,你需要spring-boot-starter-jersey作为依赖,然后你需要一个ResourceConfig类型的@Bean来注册所有端点,如下例所示:publicMyJerseyConfig(){注册(MyEndpoint.class);}}Jersey对扫描可执行文件的支持相当有限。例如,当运行可执行的war文件时,它无法扫描在完全可执行的jar文件或WEB-INF/类中找到的包中的端点。为避免此限制,应使用register方法单独注册端点,而不是使用packages方法,如上例所示。对于更高级的自定义,您还可以注册任意数量的实现ResourceConfigCustomizer的bean。所有注册的端点都应该是@Components(@GET等)注解HTTP资源,如下例所示:@Component@Path("/hello")publicclassMyEndpoint{@GETpublicStringmessage(){return“你好”;}}JAX-RS注解1.@Path一个Java类必须能够处理REST请求,那么这个类至少要加一个@Path("/")注解;对于方法,这个注解是可选的,如果不加,则继承类的定义。@Path中的值可以是一个复杂的表达式,例如@Path("/{id}"),其中{id}表达式表示路径请求的一部分。@Path也支持正则表达式,例如:@Path("{id:\\d+}"),其中\\d+代表一个数字。2.@Method一个方法只有加上一个HttpMethod的注解才会生效,比如@GET。资源的特定操作类型由HTTP动词表示。常用的HTTP动词有以下五个:GET(SELECT):从服务器获取资源(一项或多项)POST(CREATE):在服务器上创建一个新资源PUT(UPDATE):更新服务器上的资源(在客户端提供更改的完整资源)PATCH(UPDATE):更新服务器上的资源(客户端提供更改的属性)DELETE(删除):从服务器上删除资源有两种不常见的方法。HEAD:获取资源的元数据OPTIONS:一般由浏览器自动发起,用于描述目标资源的通信选项。下面是一些示例:GET/uses:列出所有用户POST/users:创建一个新用户GET/users/ID:获取具有指定id的用户的信息PUT/users/ID:更新具有指定id的用户的信息specifiedidPATCH/users/ID:更新指定id用户的信息DELETE/users/ID:删除指定iduserGET/users/ID/addresses:列出指定id用户的所有地址信息DELETE/users/ID/addresses/ID:删除指定id下的指定地址用户id信息三:Accept与Content-Type的区别Accept表示接口返回给客户端的数据格式,Content-Type表示客户端发送的数据格式到服务器。四:@Produces定义了javax.ws.rs.ext.MessageBodyWriter的资源类或方法可以生成的媒体类型。如果未指定,容器将假定可以生成任何类型。方法级注解覆盖类级注解。容器负责确保调用的方法能够生成HTTP请求中请求的媒体类型之一。如果没有这样的方法可用,容器必须按照RFC2616中指定的HTTP“406Notaccepted”进行响应。有如下几种格式:@Produces("text/plain")文本类型@Produces("text/html")Html类型@Produces({"application/xml"})Xml类型@Produces({"application/json"})Json类型可以同时注解两种或多种MIME类型。格式为:{"application/xml","application/json"},意思是两个都可以用,但是选择的时候一般选择前者,也就是第一次出现的application/xml。五:@Consumes定义了javax.ws.rs.ext.MessageBodyReader的资源类或方法可以接受的媒体类型。如果未指定,容器将假定任何媒体类型都是可接受的。方法级注解覆盖类级注解。容器负责确保被调用的方法能够使用HTTP请求实体的媒体类型。如果没有这样的方法可用,容器必须按照RFC2616中的规定以HTTP“415UnsupportedMediaType”响应。六:@QueryParam和@PathParam的区别@QueryParam:指定URL中的参数以键值对,在程序中@QueryParam("id")Integerid获取请求参数id如:URL输入为:/api/users?id=1@PathParam:参数作为路径的一部分,如:/api/users/1Jersey详细配置在SpringBoot中引入如下依赖org.springframework.bootspring-boot-starter-jersey引入后上面的依赖,我们只需要定义继承ResourceConfig类型的Bean即可。Jersey自动配置的条件之一是当前CLASSPATH中ResourceConfig类型的Bean生效,如下:@Configuration(proxyBeanMethods=false)@ConditionalOnBean(type="org.glassfish.jersey.server.ResourceConfig")@EnableConfigurationProperties(JerseyProperties.class)publicclassJerseyAutoConfigurationimplementsServletContextAware{}其中@ConditionalOnBean条件限制自动配置只有在当前容器中有ResourceConfig类型的bean时才生效。注册继承ResourceConfig后如何匹配请求?当上面的自动配置生效后,默认会注册一个Servlet:}@Bean@ConditionalOnMissingBean(name="jerseyFilterRegistration")@ConditionalOnProperty(prefix="spring.jersey",name="type",havingValue="filter")publicFilterRegistrationBeanjerseyFilterRegistration(JerseyApplicationPathapplicationPath){Filterregistration=newFilterRegistrationBean<>();registration.setFilter(newServletContainer(this.config));//...返回注册;@Bean@ConditionalOnMissingBean(name="jerseyServletRegistration")@ConditionalOnProperty(prefix="spring.jersey",name="type",havingValue="servlet",matchIfMissing=true)publicServletRegistrationBeanjerseyServletRegistration(JerseyApplicationPathapplicationPath){ServletRegistrationBeanregistration=newServletRegistrationBean<>(newServletContainer(this.config),applicationPath.getUrlMapping());添加初始化参数(注册);registration.setName(getServletRegistrationName());registration.setLoadOnStartup(this.jersey.getServlet().getLoadOnStartup());返回注册;}}Filter和Servlet列在上面。根据上面的配置,spring没有在配置文件中手动设置.jersey.type=filter,那么默认是servlet生效,向容器注册ServletContainerServlet程序。Servlet程序传入自定义的ResourceConfig,Servlet的默认请求映射地址默认为/*。ServletContainer传入ResourceConfig的Servlet:publicclassJerseyAutoConfigurationimplementsServletContextAware{//通过构造函数注入ResourceConfig类型的BeanprivatefinalResourceConfigconfig;publicJerseyAutoConfiguration(JerseyPropertiesjersey,ResourceConfigconfig,ObjectProvider{jersey;this.config=config;customizers.orderedStream().forEach((customizer)->customizer.customize(this.config));}}个性化配置ResourceConfig要自定义配置,您可以注册任意数量的实现ResourceConfigCustomizer的bean。@ComponentpublicclassCustomResourceConfigCustomizerimplementsResourceConfigCustomizer{@Overridepublicvoidcustomize(ResourceConfigconfig){//个性化自定义配置}}配置应用请求路径@Component//添加该注解所有api接口需要添加/api前缀@ApplicationPath("/api")publicclassJerseyConfigextendsResourceConfig{}配置文件方法spring:jersey:type:servlet#这个配置会覆盖@ApplicationPathapplication-path:/api-aExample:@Component@Path("/users")publicclassUserEndpoint{@Path("/{id}")@GET@Produces({"application/json"})publicUserqueryUser(@PathParam("id")Integerid){returnnewUser(id,"Name-"+id,6+id);}}完毕!!!