Jersey2.x对REST请求处理流程的分析
一个REST请求,始于一个RESTful Web Service资源的地址,终于一个可接受的对资源的表述(比如JSON)。
因此,流程分析的关键点有2个:
- 将请求地址对应到资源类的相应方法上,并触发该方法。
- 将返回值转换成请求所需要的表述,并返回给客户端。
我们使用Eclipse的断点调试服务器端(代码对应本例https://github.com/feuyeux/jax-rs2-guide/),使用cURL脚本作为客户端。
1 cURL测试
curl -H "Accept:application/json" http://localhost:8080/simple-service-webapp-spring-jpa-jquery/webapi/books/book?id=1
该脚本发送了一个REST GET请求,地址是:
http://localhost:8080/simple-service-webapp-spring-jpa-jquery/webapi/books/book?id=1
对应的服务器端方法是:
com.example.resource.BookResource.getBookByQuery(Integer)
要求返回的类型是JSON:
Accept:application/json
2 Jersey2.x流程
2.1 请求地址到REST方法
2.1.1 ServletContainer.service
ServletContainer.service(HttpServletRequest, HttpServletResponse) line: 248
- baseUri http://localhost:8080/simple-service-webapp-spring-jpa-jquery/webapi/
- requestUri http://localhost:8080/simple-service-webapp-spring-jpa-jquery/webapi/books/book?id=1
ServletContainer是HttpServlet的子类,位于Jersey容器包(.m2\repository\org\glassfish\jersey\containers\jersey-container-servlet-core\2.2\jersey-container-servlet-core-2.2.jar)。我们知道,Servlet的service方法是请求的入口,作为子类,HTTP任何方法的请求都要先经过该类的service方法。
断点堆栈中,重要的两个变量是请求地址信息的baseUri和requestUri。
Jersey包依赖关系图
ServletContainer.service(URI, URI, HttpServletRequest, HttpServletResponse) line: 372
- requestContext.header {user-agent=[curl/7.26.0], host=[localhost:8080], accept=[application/json]}
在容器层级,请求上下文变量除了包括请求地址信息外,还包括请求头信息。这里我们关注accept信息。
2.1.2 对应方法
ApplicationHandler.handle(ContainerRequest) line: 982
ServerRuntime.process(ContainerRequest) line: 211 final Runnable task
new Runnable() {
public void run() {
final ContainerRequest data = Stages.process(request, requestProcessingRoot, endpointRef);
final Endpoint endpoint = endpointRef.get();
-
endpoint ResourceMethodInvoker (id=2553)
public com.example.domain.Book com.example.resource.BookResource.getBookByQuery(java.lang.Integer)
从上面的代码片段,可以看到请求被对应到了一个Endpoint对象,该对象是一个资源方法Invoker,从断点堆栈中可以看到,其内容就是我们期待的那个方法,此后的invoke将调用这个对应REST请求的处理方法。
2.1.3 调用方法
ResourceMethodInvoker.invoke(ContainerRequest, Object) line: 353
dispatcher.dispatch(resource, requestContext);JavaResourceMethodDispatcherProvider$TypeOutInvoker(AbstractJavaResourceMethodDispatcher).invoke(Object, Object...) line: 158
invokeMethodAction.run();ResourceMethodInvocationHandlerFactory$1.invoke(Object, Method, Object[]) line: 81
从堆栈中可以轻松定位这个方法:**BookResource.getBookByQuery(Integer) line: 71**
到此,请求地址到方法调用的流程就结束了。在处理业务逻辑方法BookResource.getBookByQuery后,Jersey将开始处理响应信息。
2.2 REST方法到表述
JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(Object, Request) line: 198
- o Book (id=2686)
- Response response = Response.ok().entity(o).build();
REST请求的返回信息应包括表述信息和HTTP响应代码(通常一个成功的请求应该得到200 OK)。这就是上面代码所做的事情。在设置好response的entity后,需要将该entity对象转化成请求所接受的表述,流程如下。
2.2.1 写向response
ServerRuntime$Responder.process(ContainerResponse) line: 351ServerRuntime$Responder.writeResponse(ContainerResponse) line: 486
- entity Book (id=7076)
- executor WriterInterceptorExecutor (id=7125)
从上面的堆栈中可以看到,这个阶段重点的两个对象是返回对象和写处理对象,就是使用后者将前者恰当地写入response中。
2.2.2 JSON表述
REST的表述不局限于JSON,这里我们以JSON作为常用的表述类型为例,来讨论Jersey的表述处理。 Jersey对JSON的支持有4种方式,在第3章会有详细的讲解,本例使用的是EclipseLink项目的MOXy。其底层依赖是JPA的实现之一(另一个著名的JPA实现是JBoss项目下大名鼎鼎的Hibernate)。
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
</dependency>
MOXy依赖关系图
在下面的堆栈中,可以看到JAXB的身影,因为MOXy同样实现了JAXB,其内部实现是以XML的Marshal方式处理对象(OXM:Object-XML-Mapping),然后转化为JSON数据(XML-2-JSON)。
JsonWithPaddingInterceptor.aroundWriteTo(WriterInterceptorContext) line: 91
WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorContext) line: 188
ConfigurableMoxyJsonProvider(MOXyJsonProvider).**writeTo**(Object, Class<?>, Type, Annotation[], MediaType, MultivaluedMap<string,object style="margin: 0px; padding: 0px;">, OutputStream) line: 782
- object Book (id=7076)
- type Class (com.example.domain.Book) (id=568)
- genericType Class (com.example.domain.Book) (id=568)
- annotations Annotation3
- mediaType AcceptableMediaType (id=7120)
- httpHeaders StringKeyIgnoreCaseMultivaluedMap (id=7121)
- entityStream CommittingOutputStream (id=7124)
开始从对象转化为JSON:
JAXBMarshaller.marshal(Object, OutputStream) line: 395
- object Book (id=7076)
- outputStream CommittingOutputStream (id=7124)
XMLMarshaller(XMLMarshaller<abstract_session,context,descriptor,media_type,namespace_prefix_mapper,object_builder style="margin: 0px; padding: 0px;">).marshal(Object, OutputStream, ABSTRACT_SESSION, DESCRIPTOR) line: 852
XMLMarshaller(XMLMarshaller<abstract_session,context,descriptor,media_type,namespace_prefix_mapper,object_builder style="margin: 0px; padding: 0px;">).marshal(Object, Writer, ABSTRACT_SESSION, DESCRIPTOR) line: 1031
- object Book (id=7305)
-
writer OutputStreamWriter (id=7310)
-> BufferedWriter (id=7333)
XMLMarshaller(XMLMarshaller<abstract_session,context,descriptor,media_type,namespace_prefix_mapper,object_builder style="margin: 0px; padding: 0px;">).marshal(Object, MarshalRecord, ABSTRACT_SESSION, DESCRIPTOR, boolean) line: 583
- object Book (id=7305)
- marshalRecord JSONWriterRecord (id=7342)
- session DatabaseSessionImpl (id=7351)
- descriptor XMLDescriptor (id=7353)
- isXMLRoot false
几经辗转,写入对象变成了MarshalRecord。
JSONWriterRecord.startDocument(String, String) line: 171
TreeObjectBuilder.marshalAttributes(MarshalRecord, Object, CoreAbstractSession) line: 122
XPathObjectBuilder.marshalAttributes(MarshalRecord, Object, CoreAbstractSession) line: 552
这里是可以想见的流程...
ServerRuntime$Responder.processResponse(ContainerResponse) line: 362
最后是将response返回并释放。流程到此结束。
本文收录在我的新书《Java Restful Web Service使用指南》中:
请留意写作动态
https://code.csdn.net/delva/jax-rs2-guide/
相关推荐
在本文中,我们将深入探讨如何将Spring 4.x框架与Jersey 2.x结合,以构建一个能够对外提供RESTful接口服务的系统。这个过程包括了配置、组件整合以及实际的API开发。以下是对整个集成过程的详细说明。 首先,让我们...
4. **异步处理**:Jersey 2.x 支持异步请求处理,通过 `@Suspended` 注解和 `AsyncResponse` 接口,可以处理长时间运行的任务而不会阻塞服务器线程。 5. **客户端 API**:除了提供服务器端的支持,Jersey 2.x 还...
Jersey 2.x版本提供了许多新特性,如更强大的过滤器和拦截器、支持Guice和CDI集成、以及对Java 8的兼容性等。通过集成Spring,Jersey可以利用Spring的IoC容器,实现服务组件的管理和依赖注入。 **三、RESTful API...
在IT领域,构建Web应用程序是常见的任务,而`jersey2.x+hibernate4+spring3+jquery`是一个经典的组合,用于构建高效、灵活且功能丰富的后端服务与前端交互。下面将详细阐述这个组合中的各个技术及其整合方式。 **...
基于 Jersey 的 REST 实战。在做 Java RESTful 相关的项目,发现网上中文的资料比较少,而且 Jersey 的更新比较快,利用业余时间写了本书,图文并茂,用大量...有关 Jersey 详细信息,可以参阅《Jersey 2.x 用户指南》
Jersey-2.x-User-Guide Chinese translation of .There is also a GitBook version of the book: . Let's ! 《Jersey 2.x 用户指南》 ,中文翻译。 最近在做Java RESTful 相关的项目,借此机会学习了一把Jersey,...
8. **hk2-api.jar, hk2-utils.jar, aopalliance-repackaged.jar, hk2-locator.jar, hk2-runlevel.jar**:这些是HK2依赖注入框架的组件,Jersey 2.x使用HK2来管理服务的生命周期和依赖关系。 在初学开发Jersey时,...
【jersey jar.zip】是一个包含Jersey框架的压缩文件,Jersey是Java世界中用于构建RESTful Web服务的开源框架。这个zip包很显然是为了方便开发者快速地在项目中引入和运行RESTful服务。REST(Representational State ...
<groupId>org.glassfish.jersey.containers <artifactId>jersey-container-servlet-core <version>YOUR_JERSEY_VERSION ``` 接下来,我们创建一个简单的REST服务。定义一个Java类,用`@Path`注解标记它的根URL...
org.glassfish.jersey.media:jersey-media-multipart:2.24.1 Jersey 上传文件以及下载文件所需的依赖库,maven下载比较慢,我手动下载下来了。放到你的libs目录
Jersey2 提供了强大的功能,包括路由、数据绑定、错误处理、过滤器、拦截器等,使得开发者能够快速、高效地构建符合 REST 原则的服务。 **一、RESTful 架构** REST(Representational State Transfer)是一种网络...
rest包jersey-1.19.1,包含全部的jar包,下载留评论。开发jersey api接口用到的jar包。是一个软件开发框架,Jersey不仅仅是一个JAX-RS的参考实现,Jersey提供自己的API,其API继承自JAX-RS,提供更多的特性和功能以...
**使用Jersey 2.x构建RESTful Web服务(第一部分)** RESTful Web服务是一种遵循Representational State Transfer(表述性状态转移)架构风格的网络应用设计模式,它以简洁、可扩展的方式提供服务。在Java世界中,...
com.sun.jersey.jersey-core-1.4.0.jar jar包下载,jar包下载
10. 持续学习:Jersey不断更新和发展,了解新版本特性,如Jersey 2.x引入了更多现代化的特性,如支持Java 8,更好的性能和灵活性,以及对Java EE 7的兼容性。 总之,"jersey1.18 jar包"是开发RESTful服务的重要工具...
基于v1.17.1的即插即用Android版本的Jersey 1.x客户端库。 当前端口基于上的v1.17.1 要在Android Maven项目中使用它,您需要将以下存储库和依赖项添加到项目pom.xml中。 仓库: <repositories> ... ...
Maven坐标:org.glassfish.jersey.media:jersey-media-jaxb:2.22.2; 标签:glassfish、jersey、media、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容...
Jersey是Java中的一款流行的RESTful Web服务框架,它基于JAX-RS(Java API for RESTful Web ...对于新项目,考虑使用Jersey 2.x或者其他REST框架如Spring Boot的REST支持,可以获得更好的社区支持和更先进的特性。
4. **配置Servlet容器**:在Web应用的`web.xml`配置文件中,配置Jersey的Servlet,让它处理所有的REST请求: ```xml <servlet-name>Jersey Web Application <servlet-class>org.glassfish.jersey.servlet....