3.3 REST请求流程
\\
从REST请求处理的扩展点上,我们已经讲述了用于实体处理的Provider接口以及上下文处理和异常处理的Provider。本章还将讲述两种在面向切面编程中非常重要的特殊Provider:过滤器(3.4节)和拦截器(3.5节)。在进入这个主题之前,我们需要对REST请求处理的流程这条线有明确的认识,如图3-5所示,这样以来,才会知道这些点都处于流程的什么位置。只有这样才能清楚地实现对扩展点的开发和调试。
\\
在图3-5中,请求流程中存在3种角色,分别是用户、REST客户端和REST服务器。请求始于请求的发送,止于调用Response类的readeEntity()方法,获取响应实体。
\\
1)用户提交请求数据,客户端接收请求,进入第一个扩展点:“客户端请求过滤器ClientRequestFilter实现类”的filter()方法。
\\
2)请求过滤处理完毕后,流程进入第二个扩展点:“客户端写拦截器WriterInterceptor实现类”的aroundWriteTo()方法,实现对客户端序列化操作的拦截。
\\
3)“客户端消息体写处理器MessageBodyWriter”执行序列化,流程从客户端过渡到服务器端。
\\
4)服务器接收请求,流程进入第三个扩展点:“服务器前置请求过滤器Container-RequestFilter实现类”的filter()方法。
\\
\\
图3-5 Jersey的REST请求处理流程
\\
5)过滤处理完毕后,服务器根据请求匹配资源方法,如果匹配到相应的资源方法,流程进入第四个扩展点:“服务器后置请求过滤器ContainerRequestFilter实现类”的filter()方法。
\\
6)后置请求过滤处理完毕后,流程进入第五个扩展点:“服务器读拦截器ReaderInterceptor实现类”的aroundReadFrom()方法,拦截服务器端反序列化操作。
\\
7)“服务器消息体读处理器MessageBodyReader”完成对客户端数据流的反序列化。服务器执行匹配的资源方法。
\\
8)REST请求资源的处理完毕后,流程进入第六个扩展点:“服务器响应过滤器ContainerResponseFilter实现类”的filter()方法。
\\
9)过滤处理完毕后,流程进入第七个扩展点:“服务器写拦截器WriterInterceptor实现类”的aroundWriteTo()方法,对服务器端序列化到客户端这个操作的拦截。
\\
10)“服务器消息体写处理器MessageBodyWriter”执行序列化,流程返回到客户端一侧。
\\
11)客户端接收响应,流程进入第八个扩展点:“客户端响应过滤器Client-ResponseFilter实现类”的filter()方法。
\\
12)过滤处理完毕后,客户端响应实例response返回到用户一侧,用户执行response.readEntity()流程进入第九个扩展点:“客户端读拦截器ReaderInterceptor实现类”的aroundReadFrom()方法,对客户端反序列化进行拦截。
\\
13)“客户端消息体读处理器MessageBodyReader”执行反序列化,将Java类型的对象最终作为readEntity()方法的返回值。到此,一次REST请求处理的完整流程完毕。这期间,如果出现异常或资源不匹配等情况,会从出错点开始结束流程。
\\
3.4 REST过滤器
\\
从上一节的流程讲述中,我们了解JAX-RS2定义的4种过滤器扩展点(Extension Point)接口,供开发者实现业务逻辑,按请求处理流程的先后顺序为:客户端请求过滤器(ClientRequestFilter)-\u0026gt;服务器请求过滤器(ContainerRequestFilter)-\u0026gt;服务器响应过滤器(ContainerResponseFilter)-\u0026gt;客户端响应过滤器(ClientResponseFilter)。本节将全面讲述4种过滤器的使用。
\\
3.4.1 ClientRequestFilter
\\
客户端请求过滤器(ClientRequestFilter)定义的过滤方法filter()包含一个输入参数,是客户端请求的上下文类ClientRequestContext。从该上下文中可以获取请求信息,典型的示例包括获取请求方法context.getMethod(),获取请求资源地址context.getUri()和获取请求头信息context.getHeaders()等。过滤器的实现类中可以利用这些信息,覆写该方法以实现该类特有的过滤功能。ClientRequestFilter接口的实现类如图3-6所示。
\\
\\
图3-6 ClientRequestFilter接口的实现类
\\
图3-6展所示了ClientRequestFilter接口的实现类,包括Jersey内部提供的实现类和本书示例代码中的实现类。我们选择HTTP认证过滤器类HttpAuthenticationFilter作为例子,来感受上面的讲述,(HTTP基本认证的内容请参考10.1节。)示例代码如下所示。
\\
@Override\public void filter(ClientRequestContext request) throws IOException {\ if(!\"true\".equals(request.getProperty(\"org.glassfish.jersey.client.authentication.HttpAuthenticationFilter.reused\"))) {\ if(!request.getHeaders().containsKey(\"Authorization\")) {\ HttpAuthenticationFilter.Type operation = null;\ if(this.mode == Mode.BASIC_PREEMPTIVE) {\ this.basicAuth.filterRequest(request);\ operation = HttpAuthenticationFilter.Type.BASIC;\...\ if(operation != null) {\ request.setProperty(\"org.glassfish.jersey.client.authentication.HttpAuthenticationFilter.operation\