- 浏览: 1188628 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (883)
- Spring (101)
- Swing (1)
- Mysql (21)
- Js (59)
- Jsp (2)
- Hibernate (19)
- Myeclipse (5)
- SqlServer 2000 (2)
- poi (15)
- Java (70)
- SSH (12)
- Html (47)
- Fusion Charts (1)
- C\C++ (2)
- 汇编 (36)
- Jquery (37)
- Struts2 (6)
- Ubuntu (16)
- powerDesinger (4)
- Jboss (3)
- JAX-RS (13)
- JAXB (5)
- JAX-WS (11)
- JMS (4)
- WebSocket (8)
- PHP (16)
- Flash (1)
- maven (3)
- Oracle (8)
- HttpClient (6)
- sqlserver (19)
- svn (5)
- Tomcat (3)
- Jdbc (3)
- EsayUi (11)
- 微信公众平台 (19)
- IIS (2)
- Freemarker (11)
- Comet (1)
- Spring MVC (85)
- JBoss Seam (3)
- 二维码 (9)
- Spring Security (4)
- Ehcache (3)
- Apache Shiro (7)
- jackson (16)
- JPA (8)
- jcaptcha (2)
- RSA (2)
- Ajax (6)
- 跟我学Shiro (0)
- Spring4 (19)
- 跟我学spring3 (0)
- css (32)
- excel (4)
- Filter (3)
- 微信公众帐号开发教程 (0)
- Android (6)
- log4j (6)
- 淘宝接口 (17)
- 支付集成 (3)
- 单点登录 (3)
- Html5 (27)
- 移动平台前端 (3)
- Linux (44)
- FusionCharts (27)
- Json Jackson Xml (5)
- 方培工作室-微信开发 (0)
- Apache与Tomcat与IIS整合 (10)
- Nginx (17)
- webService (2)
- apache (4)
- lucene (3)
- lodop (2)
- Shiro (3)
- zTree (2)
- ireport (12)
- Servlet3.0 (5)
- 前端美工 (19)
- AngularJS (1)
- C#开发微信门户及应用 (0)
- Shell (3)
- bat脚本 (16)
- Bootstrap (26)
- Less (10)
- photoshop (6)
- Redis (6)
- Mongodb (10)
- MyBatis (3)
- 数据结构 (0)
- 读写分离-主从复制 (0)
- JFinal (0)
- 百度地图api (3)
- hadoop-hbase-hive-spark (3)
- WebStorm (2)
- Quartz (5)
- ios (0)
- Mina (8)
- Android Studio (4)
- Ratchet教程 (0)
- 移动端重构系列 (1)
- cubic-bezier贝塞尔曲线CSS3动画工具 (1)
- nginx+tomcat+memcached集群 (0)
- 集群 (0)
- ZooKeeper (3)
- Dubbo (0)
- vpn (0)
- kafka (0)
- JVM垃圾回收机制 (0)
- 微信小程序 (0)
- Lua (0)
- Hystrix (0)
- Vue.js (0)
- mycat (0)
- Openresty (0)
- springBoot (0)
- 新分类 (0)
- guava (0)
- 大数据 (0)
- Sentinel (0)
最新评论
-
JackMacing:
中文怎么解决?
SpringMVC与iReport(JasperReports) 5.6整合开发实例 -
18335864773:
用pageoffice把.可以实现在线的文档操作.直接转pdf ...
转:使用jasperreport动态生成pdf,excel,html -
linhao0907:
推荐一款轻量开源的支付宝组件:https://github.c ...
关于Alipay支付宝接口(Java版) -
songronghu:
太好了,非常有用,谢谢分享~
Java ConcurrentModificationException 异常分析与解决方案 -
wzwahl36:
http://www.atool.org/json2javab ...
Java下利用Jackson进行JSON解析和序列化
JAX-RS与Conneg
JAX-RS有一些用来帮助用户管理他的conneg的工具:
- 基于Accept头的方法派发
- 允许直接查看内容信息
- 用于处理多约束条件的APIs
1. 方法派发
前几节中,我们看到怎么使用@Produces注释来指示响应的Media Type。 JAX-RS也使用这个注释来分发请求到恰当的方法上,通过匹配最佳的请求的Accept头信息的Media Type 列表到由@Produces标注的元数据。例如:
- @Path("/customers")
- public class CustomerResource {
- @GET
- @Path("{id}")
- @Produces("application/xml")
- public Customer getCustomerXml(@PathParam("id") int id) {...}
- @GET
- @Path("{id}")
- @Produces("text/plain")
- public String getCustomerText(@PathParam("id") int id) {...}
- @GET
- @Path("{id}")
- @Produces("application/json")
- public Customer getCustomerJson(@PathParam("id") int id) {...}
- }
这里三个方法对应的服务路径一样,但是@Produces的元数据不同。JAX-RS会基于请求信息的Accept头信息来选择恰当的处理方法,例如:
根据头一节的介绍,这里,Accept的数据类型的优先级为:
- application/json
- application/xml
因此对这个请求,getCustomerJson()方法将被调用。
2. JAXB与Conneg
之前的章节里介绍了怎么通过使用JAXB来实现从java对象到xml或者json的映射。而通过在JAX-RS中使用conneg,我们也可以实现一个可以服务于这两种格式的方法,例如:
- @Path("/service")
- public class MyService {
- @GET
- @Produces({"application/xml", "application/json"})
- public Customer getCustomer(@PathParam("id") int id) {...}
- }
3. 复杂的内容协议
有时候,简单的Accept头与@Produces之间的映射可能不足以解决问题,服务于同一路径的不同的JAX-RS方法可能需要处理不同的Media Type、Language、Encoding等等。 不幸的是JAX-RS并没有提供类似于@ProduceLanguages或者@ProduceEncodings注释。相反,我们必须实现自己的头信息查找方法,或者是使用JAX-RS API管理复杂的Conneg。接下来分别介绍这两种方式。
> 查看Accept头
在之前的章节里介绍过javax.ws.rs.core.HttpHeaders接口。这个接口包含了预处理的与Http请求相关的Conneg信息:
- public interface HttpHeaders {
- public List<MediaType> getAcceptableMediaTypes();
- public List<Locale> getAcceptableLanguages();
- ...
- }
getAcceptableMediaTypes()得到包含定义在HTTP请求的Accept头信息的Media Type列表,其中的项被解析成一个个javax.ws.rs.core.MediaType对象,并且这个列表已经是基于其中的"q"值(显式或隐式的)排序的。
getAcceptableLanguages()处理HTTP请求的Accept-Language头信息,其中的项已经被解析成一个个java.util.Locale对象。并且和上面的MediaType一样,已经是根据"q"值有序的了。
通过使用@javax.ws.rs.core.Context注释来注入HttpHeaders对象。例如:
- @Path("/myservice")
- public class MyService {
- @GET
- public Response get(@Context HttpHeaders headers) {
- MediaType type = headers.getAcceptableMediaTypes().get(0);
- Locale language = headers.getAcceptableLanguages().get(0);
- Object responseObject = ...;
- Response.ResponseBuilder builder = Response.ok(responseObject, type);
- builder.language(language);
- return builder.build();
- }
- }
> variant处理
JAX-RS也提供了API用来处理当你有多个Media Type、Language或Encoding集的情况。通过使用javax.ws.rs.core.Request和javax.ws.rs.core.Variant类来处理这些复杂的匹配。首先看Variant类:
- package javax.ws.rs.core.Variant
- public class Variant {
- public Variant(MediaType mediaType, Locale language, String encoding) {...}
- public Locale getLanguage() {...}
- public MediaType getMediaType() {...}
- public String getEncoding() {...}
- }
Variant类就是一个简单的包含Media Type,Language和Encoding的结构。它表示一个简单的你JAX-RS资源方法所支持的集合。然后通过在Request接口中设置一列这个类的对象来进行交互:
- package javax.ws.rs.core.Request
- public interface Request {
- Variant selectVariant(List<Variant> variants) throws IllegalArgumentException;
- ...
- }
其中selectVariant()方法里设置的就是JAX-RS方法中支持的一列Variant对象。它会检查请求中的Accept、Accept-Language和Accept-Encoding头,然后把它们和Variant列表进行比较,找到最匹配的请求的Variant对象。如果没有符合的对象,则返回null。例如:
- @Path("/myservice")
- public class MyService {
- @GET
- Response getSomething(@Context Request request) {
- List<Variant> variants = new ArrayList();
- variants.add(new Variant(new MediaType("application/xml"),"en", "deflate"));
- variants.add(new Variant(new MediaType("application/xml"),"es", "deflate"));
- variants.add(new Variant(new MediaType("application/json"),"en", "deflate"));
- variants.add(new Variant(new MediaType("application/json"),"es", "deflate"));
- variants.add(new Variant(new MediaType("application/xml"),"en", "gzip"));
- variants.add(new Variant(new MediaType("application/xml"),"es", "gzip"));
- variants.add(new Variant(new MediaType("application/json"),"en", "gzip"));
- variants.add(new Variant(new MediaType("application/json"),"es", "gzip"));
- // Pick the variant
- Variant v = request.selectVariant(variants);
- Object entity = ...; // get the object you want to return
- ResponseBuilder builder = Response.ok(entity);
- builder.type(v.getMediaType()).language(v.getLanguage()).header("Content-Encoding", v.getEncoding());
- return builder.build();
- }
- }
这里花了很多代码去提供所支持的Variant。也有更好的方法去做自动选择,JAX-RS提供了javax.ws.rs.core.Variant.VariantBuilder类用来创建这些复杂的选择器:
- public static abstract class VariantListBuilder {
- public static VariantListBuilder newInstance() {...}
- public abstract VariantListBuilder mediaTypes(MediaType... mediaTypes);
- public abstract VariantListBuilder languages(Locale... languages);
- public abstract VariantListBuilder encodings(String... encodings);
- public abstract List<Variant> build();
- public abstract VariantListBuilder add();
- }
它支持使用Builder的模式来创建variant列表。例如重写前面的例子:
- @Path("/myservice")
- public class MyService {
- @GET
- Response getSomething(@Context Request request) {
- Variant.VariantBuilder vb = Variant.VariantBuilder.newInstance();
- vb.mediaTypes(new MediaType("application/xml"),
- new MediaType("application/json"))
- .languages(new Locale("en"), new Locale("es"))
- .encodings("deflate", "gzip");
- List<Variant> variants = vb.build();
- // Pick the variant
- Variant v = request.selectVariant(variants);
- Object entity = ...; // get the object you want to return
- ResponseBuilder builder = Response.ok(entity);
- builder.type(v.getMediaType())
- .language(v.getLanguage())
- .header("Content-Encoding", v.getEncoding());
- return builder.build();
- }
- }
通过调用VariantBuilder的mediaTypes()、languages()和encodings()方法设置可能的值,最后调用build()方法,它会生成一个Variant列表,包含所有可能的组合。
VariantBuilder也支持多个不同的Variant集体,通过使用VariantBuilder.add()方法可以分隔和定义不同的Variant集。例如:
- Variant.VariantBuilder vb = Variant.VariantBuilder.newInstance();
- vb.mediaTypes(new MediaType("application/xml"),new MediaType("application/json"))
- .languages(new Locale("en"), new Locale("es"))
- .encodings("deflate", "gzip")
- .add()
- .mediaTypes(new MediaType("text/plain"))
- .languages(new Locale("en"), new Locale("es"), new Locale("fr"))
- .encodings("compress");
上例中VariantBuilder创建了两组Variant,最后builder后就是这两组的合集。
现实中使用Request.selectVariant()方法的例子并不多。首先,content encoding在JAX-RS并不是一个很容易处理的东西,如果你想灵活的处理content encoding,你最好是自己去处理所有的流。大多数JAX-RS的实现应该都自动支持了GZIP。
其次,多数JAX-RS的服务都会根据@Produces注释和Accept头信息自动处理响应的Media Type。
4. URI模式约定
Conneg是一个很强大的HTTP特性。问题是有的客户端,特别是浏览器并不支持它。例如Firefox浏览器的Accept头信息被硬编码为:
如果你希望访问的是JSON数据,那可能就失败了。
一个常用的解决此类问题的方法就是把Conneg信息内嵌在URI中,而不是使用Accept头,例如:
内容信息以分隔的路径或文件名后缀被嵌在URI中。上例中,客户端要求的是XML格式,英文的信息。在JAX-RS中可以如下实现:
- @Path("/customers/{id}.{type}.{language}")
- @GET
- public Customer getCustomer(@PathParam("id") int id,
- @PathParam("type") String type,
- @PathParam("language") String language) {...}
在JAX-RS规范完成之前,围绕着文件名后缀的使用确实被定义为规范的一部分。不幸的是,专业组不同意这个特性的整个语义定义,因此它还是被删除了。很多JAX-RS的实现仍然支持这个特性,因此了解它是怎么工作的还是很重要的。
规范定义和很多JAX-RS实现现在的工作方式是在文件后缀, Media Type和Language之间定义一个映射关系。xml后缀映射到application/xml;en后缀映射到en-US。当一个请求来了,JAX-RS实现就会提取后缀,并使用这个信息作为Conneg的数据,替换任何传入的Accept或Accept-Language头。例如:
- @Path("/customers")
- public class CustomerResource {
- @GET
- @Produces("application/xml")
- public Customer getXml() {...}
- @GET
- @Produces("application/json")
- public Customer getJson() {...}
- }
如果请求为 GET /customers.json ,刚JAX-RS实现会提取.json后缀,并把它从请求路径中移除。然后它会查找匹配json的映射。假设是 application/json ,然后这个信息,而不是Accept头,不会被使用,最后getJson()方法就会被调用。
发表评论
-
JAX-RS入门 十二: 可伸缩的JAX-RS应用
2012-09-11 19:10 641一、HTTP Caching HTTP1.0中定义了E ... -
JAX-RS入门 十一:HATEOAS
2012-09-11 19:09 697HATEOAS全称:超媒体即状态应用引擎 (Hypermedi ... -
JAX-RS入门 十: 兼容与演进
2012-09-11 19:09 818网络服务会随着时间 ... -
JAX-RS入门 九: 内容约定(1)
2012-09-10 23:32 628通常一个SOA的应用都需要足够的灵活,以便于各种不同的客户端或 ... -
JAX-RS入门 八: HTTP响应
2012-09-10 23:32 962首先先看一下HTTP中定义的响应码及其意义: ... -
JAX-RS入门 七: 数据处理(2)
2012-09-10 23:31 838上节介绍了JAX-RS中怎么与一些基础的对象进行交互,这节介绍 ... -
JAX-RS入门 六: 数据处理(1)
2012-09-10 23:30 880接下来要花两小节来介绍一下JAX-RS中的数据处理(Data ... -
JAX-RS入门 五: 自动类型转换
2012-09-09 12:41 682一、默认类型转换规则 在上一节中,已经了解了怎么使用那 ... -
JAX-RS入门 四: 注入
2012-09-09 12:39 1079一、Annotations @javax.ws.rs.Pa ... -
JAX-RS入门 三 :细节
2012-09-09 12:33 718一、若希望一个Java类能够处理REST请求,则这个类必须 ... -
JAX-RS入门 二 :运行
2012-09-09 12:31 934上一节,已经成功的定义了一个REST服务,并且提供了具体的 ... -
JAX-RS入门 一 :基础
2012-09-09 12:29 1684简介 JAX-RS是一套用java实现REST服务的规范,提 ...
相关推荐
[奥莱理] RESTful Java 开发 (Jax-RS 实现) (英文版) [奥莱理] RESTful Java with Jax-RS (E-Book) ☆ 图书概要:☆ Learn how to design and develop distributed web services in Java using RESTful ...
The RESTEasy workbook that follows provides step-by-step instructions for installing, configuring, and running several working JAX-RS examples, using the JBoss RESTEasy implementation of JAX-RS 2.0. ...
使用到的外部jar包有(必须的部分,需要加到Web容器中) •neethi-3.0.2.jar •jsr311-api-1.1.1.jar •cxf-bundle-2.6.0.jar 使用到的外部jar包有(可选的部分,当且仅当作为一个独立的application运行时) ...
赠送jar包:jackson-jaxrs-json-provider-2.7.8.jar; 赠送原API文档:jackson-jaxrs-json-provider-2.7.8-javadoc.jar; 赠送源代码:jackson-jaxrs-json-provider-2.7.8-sources.jar; 赠送Maven依赖信息文件:...
javax.xml.ws.Service 报错需要的包,亲测可以用,直接下载在ide里buildpath一下就可以,四个jar包 ,整合了其他的jar所以配置简单
JAX-RS(JSR 311)指的是Java API for RESTful Web Services,Roy Fielding也参与了JAX-RS的制订,他在自己的博士论文中定义了REST。对于那些想要构建RESTful Web Services的开发者来说,JAX-RS给出了不同于JAX-WS...
jax-rs-test JAX-RS测试
概述这是一个多模块项目,包含用于以下数据格式的基于Jackson的JAX-RS提供程序:(二进制JSON) (另一种二进制JSON) 提供程序实现特定数据格式的JAX-RS MessageBodyReader和MessageBodyWriter处理程序。...
JAX-RS 性能 比较每个请求和单例 JAX-RS 资源类的性能。 请参阅。 该项目包括 4 个资源类:2 个每个请求范围和 2 个单例。 两个只是返回一个查询参数。 在另外两个资源中,我们将通过@Context 注入 UriInfo。 上...
关于JAX-RS的注解详细,本人通过网络及实际应用收集的资料
jax-rs 2.1规范最终版,英文原版。jax-rs规范定义了java平台Rest调用风格的WebService接口。
srb4j, Simple RESTFul backend for Java, 一个JAX-RS服务端代码脚手架(就像AppFuse之于Webapp),基于OAuth2提供了完整的注册、登录、密码恢复等功能。 它本质是一个Maven Archetype, 所以你可以用它快速生成一个...
JAX-RS-演示学术项目的 JAX-RS(用于 RESTful Web 服务的 Java API)演示。 该演示使用作为 JSR 311 规范的参考实现。
使用Eclipse开发基于SpringBoot+JAX-RS的Restful服务.docx使用Eclipse开发基于SpringBoot+JAX-RS的Restful服务.docx使用Eclipse开发基于SpringBoot+JAX-RS的Restful服务.docx使用Eclipse开发基于SpringBoot+JAX-RS的...
JAX-RS REST helloworld 项目源码 下载后引入eclipse jee 启动tomcat可直接访问 访问路径为http://localhost:8080/AndroidJAX-RS/jaxrs/helloworld/html
restlet_jax-rs列子 可直接运行 在我的博客里有一些描述。希望能给大家提供点帮助
JAX-RS-FileUpload-Jersey-Example
JAX-RS+spring
web service rest(jax-rs)整合完整的Jax-rs组件包,内含2个版本,分别是1.0和1.4版本。