REST 请求处理

一.Providers 详解

javax.ws.rs.ext.Providers 是JAX-RS 2.0定义的一种辅助接口,其实现类用于辅助REST框架完成过滤和读写拦截的功能,可以使用@Provider 注解标注这些类。Providers接口一共定义了四个方法,分别用来获取MessageBodyReader,MessageBodyWriter,ExceptionMapper,ContextResolver


package javax.ws.rs.ext;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.core.MediaType;

public interface Providers {

   
    <T> MessageBodyReader<T> getMessageBodyReader(Class<T> type,
                                                  Type genericType, Annotation[] annotations, MediaType mediaType);

    <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> type,
                                                  Type genericType, Annotation[] annotations, MediaType mediaType);
 
    <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> type);

  
    <T> ContextResolver<T> getContextResolver(Class<T> contextType,
                                              MediaType mediaType);
}

1.实体Providers

Jersey 之所以支持那么多中响应实体的传输格式,是因为其底层实体Providers具备的对不同格式的处理能力。Jersey内部提供了丰富的MessageBodyReader和MessageBodyWriter 接口的实现类,用于处理不同格式的表述

MessageBodyReader实现类
MessageBodyWriter 实现类

二.REST请求流程

REST请求流程

如上图,请求流程中存在三种角色,分别是:用户,REST客户端和REST服务器,请求始于请求的发送,止于调用Resonse的readEntity()方法
(1).用户请求提交数据,客户端接收请求,进入第一个扩展点:客户端请求过滤器 ClientRequestFilter 的filter()方法
(2).请求处理过滤完毕后,流程进入第二个扩展点:客户端写拦截器WriterInterceptor实现类的aroundWriterTo() 方法,实现对客户端序列化操作的拦截
(3).客户端消息体写处理器MessageBodyWriter 执行序列化,流程从客户端过渡到服务器端
(4).服务器接收请求,流程进入第三个扩展点:服务器前置请求过滤器ContainerRequestFilter实现类 的filter()方法
(5).过滤器处理完毕后,服务器根据请求匹配资源方法,如果匹配到相应的资源方法,流程进入第四个扩展点:服务器后置请求过滤器ContainerRequestFilter 实现类 的filter() 方法
(6).后置请求过滤器处理完毕后,力促进入第五个扩展点:服务器读拦截器ReaderInterceptor实现类 的aroundReadFrom() 方法,拦截服务器端反序列化操作
(7).服务器消息体读处理器MessageBodyReader 完成对客户端数据流的反序列化,服务器执行匹配的资源方法
(8).REST请求资源的处理完毕后,流程进入第六个扩展点:服务器响应过滤器 ContainerResponseFilter 实现类 的filter() 方法
(9).过滤器处理完毕后,流程进入第七个扩展点:服务器写拦截器WriterInterceptor实现类 的aroundWriterTo() 方法,实现对服务器端序列化到客户端这个操作的拦截
(10).服务器消息体写处理器MessageBodyWriter 执行序列化,流程返回到客户端一侧
(11).客户端接收响应,流程进入第八个扩展点:客户端响应过滤器ClientResponseFilter 实现类 的filter() 方法
(12).过滤处理完毕后,客户端响应实例response 返回到用户一侧,用户执行response.readEntity(),流程进入第九个扩展点:客户端拦截器ReaderInterceptor实现类 的aroundReadFrom() 方法,对客户端反序列化进行拦截
(13).客服端消息体读处理器MessageBodyReader 执行反序列化,将Java类型的对象最终作为readENtity()方法的返回值

三.REST过滤器

JAX-RS-2.0定义的4种过滤器扩展点接口,供开发者实现其业务逻辑,按请求处理流程的先后顺序为:客户端请求过滤器(ClientRequestFilter) -------> 服务端请求过滤器(ContainerRequestFilter)-------->服务端响应过滤器(ContainerResponseFilter)——>客户端响应过滤器(ClientResponseFilter)

ClientRequestFilter

@Produces
public class AirClientRequestFilter implements ClientRequestFilter {

    private static final Logger LOGGER = Logger.getLogger(AirClientRequestFilter.class);

    @Override
    public void filter(final ClientRequestContext requestContext) throws IOException {
        AirClientRequestFilter.LOGGER.info("AirClientRequestFilter invok " + requestContext.getUri());
    }
}

ClientResponseFilter

@Produces
public class AirClientResponseFilter implements ClientResponseFilter {

    @Override
    public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) throws IOException {

    }
}

ContainerRequestFilter

@PreMatching
@Provider
public class AirContainerRequestPreFilter implements ContainerRequestFilter {
    private static final Logger LOGGER = Logger.getLogger(AirContainerRequestPreFilter.class);

    public AirContainerRequestPreFilter() {
        LOGGER.info("Air-Container-Request-Pre-Filter initialized");
    }
    @Override
    public void filter(final ContainerRequestContext requestContext) throws IOException {
        AirContainerRequestPreFilter.LOGGER.info("Air-Container-Request-Pre-Filter invoked");
    }
}

ContainerResponseFilter

@Provider
public class AirContainerResponseFilter implements ContainerResponseFilter {
    private static final Logger LOGGER = Logger.getLogger(AirContainerResponseFilter.class);

    public AirContainerResponseFilter() {
        LOGGER.info("Air-Container-Response-Filter initialized");
    }
    
    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        LOGGER.info("Air-Container-Response-Filter invoked");
    }
}

四.REST拦截器

Jersey 内部实现了几个典型应用的拦截器,他们是成对出现的
ReaderInterceptor

@Provider
public class AirReaderInterceptor implements ReaderInterceptor {
    private static final Logger LOGGER = Logger.getLogger(AirReaderInterceptor.class);

    public AirReaderInterceptor() {
        LOGGER.info("AirReaderInterceptor initialized");
    }
    
    @Override
    public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, WebApplicationException {
        return null;
    }
}

WriterInterceptor

@Provider
public class AirWriterInterceptor implements WriterInterceptor {
    private static final Logger LOGGER = Logger.getLogger(AirWriterInterceptor.class);

    public AirWriterInterceptor() {
        LOGGER.info("AirWriterInterceptor initialized");
    }
    @Override
    public void aroundWriteTo(final WriterInterceptorContext context) throws IOException, WebApplicationException {
    }
}

编码解码拦截器(ContentEncoder)

public class AirEncoderInterceptor extends ContentEncoder {
    @Override
    public InputStream decode(String s, InputStream inputStream) throws IOException {
        return null;
    }

    @Override
    public OutputStream encode(String s, OutputStream outputStream) throws IOException {
        return null;
    }
}

五.优先级

优先级的定义使用注解@Priority,优先级的值是一个整数值,对于ContainerReauest,PreMatchContainerRequest,ClientRequest 和读写拦截器 采用升序策略,数值越小,优先级越高;对于ContainerResponse和ClientResponse采用降序策略,数值越大,优先级越高

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,652评论 18 139
  • 一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式。”但是在要求详细讲述它所提出的各个约束,以及如...
    时待吾阅读 3,423评论 0 19
  • 编者|极致扬 编辑|肖童鞋 为什么茶叶会有各种各样的名字呢? 有的根据制造方法不同和品质上的差异,将茶叶分...
    极致茶文阅读 790评论 3 2
  • 小孩不知春何在, 何时幻影春晚夜。 忽如何了不知春, 到春才知春何在。
    平安智慧阅读 102评论 0 1
  • 一提起“学习”,很多人可能不以为然,我们从小接受学校的教育,长大了也有自己的思想,我们还要去学习如何学习吗?非也,...
    Hallie果果阅读 422评论 0 0