当前位置: 移动技术网 > IT编程>开发语言>Java > 深入了解JAVA Jersey框架

深入了解JAVA Jersey框架

2020年06月14日  | 移动技术网IT编程  | 我要评论

郝颖,顺义五中脱裤门,童莎莎

java jersey的详情概述

jersey是一个restful请求服务java框架,与常规的java编程使用的struts框架类似,它主要用于处理业务逻辑层。

与springmvc 的区别:

1. jersey同样提供di,是由glassfish hk2实现,也就是说,如果想单独使用jersey一套,需要另外学习bean容器;

2. mvc出发点即是web,但jersey出发点确实restfull,体现点在与接口的设计方面,
如mvc返回复杂结构需要使用modelandview,而jersey仅仅需要返回一个流或者文件句柄;

3. jersey提供一种子资源的概念,这也是restfull中提倡所有url都是资源;

4. jersey直接提供application.wadl资源url说明;

5. mvc提供session等状态管理,jersey没有,这个源自restfull设计无状态化;

6. response方法支持更好返回结果,方便的返回status,包括200,303,401,403;

7. 提供超级特别方便的方式访问restfull;

jersey

1.x的版本是sun公司提供的独立的jar包,在2.x版本中,已经将jersey融合到javase中,在javax.ws.rs.*包中。

与struts类似,它同样可以和hibernate,spring框架整合。

由于struts2+hibernate+spring整合在市场的占有率太高,所以很少一部分人去关注jersey。

所以网上有关于jersey的介绍很少。但是它确实是一个非常不错的框架。对于请求式服务,对于get,delete请求,你甚至只需要给出一个uri即可完成操作。

举个简单的例子:如果你想获得服务器数据库中的所有数据;

那么你可以在浏览器或者利用ajax的get方法,将路径设置好;

例如:localhost:8080/student(项目名称)/studentinfo(项目服务总体前缀)/student(处理student对象的签注)/getstudentinfo(最后前缀)。

你可以选择get获取的数据的返回类型:json,xml,text_html(string)..获取之后,你可以通过js将这些数据塞到html或者jsp页面上。

jersey是jax-rs(jsr311)开源参考实现用于构建 restful web service,它包含三个部分:

核心服务器(core server) :通过提供jsr 311中标准化的注释和api标准化,可以用直观的方式开发restful web服务。

核心客户端(core client) :jersey客户端api能够帮助开发者与restful服务轻松通信;

集成(integration) :jersey还提供可以轻松继承spring、guice、apache abdera的库。

在本次开发中使用jersey2.0,并且仅使用了核心服务器。

设置jersey环境

maven

<!--jersey-->
<dependency>
 <groupid>org.glassfish.jersey.containers</groupid>
 <artifactid>jersey-container-servlet-core</artifactid>
 <version>2.0</version>
</dependency>

<!--jaxb api-->
<dependency>
 <groupid>javax.xml.ws</groupid>
 <artifactid>jaxws-api</artifactid>
 <version>2.1</version>
</dependency>

<!-- json支持 -->
<dependency>
 <groupid>org.codehaus.jackson</groupid>
 <artifactid>jackson-core-asl</artifactid>
 <version>1.9.12</version>
</dependency>
<dependency>
 <groupid>org.codehaus.jackson</groupid>
 <artifactid>jackson-mapper-asl</artifactid>
 <version>1.9.12</version>
</dependency>
<dependency>
 <groupid>org.codehaus.jackson</groupid>
 <artifactid>jackson-jaxrs</artifactid>
 <version>1.9.12</version>
</dependency>

引入jar文件方式

从jersey开发包中将以下库复制的web-inf下的库目录:

1  服务器:jersey-server.jar 、jersey-container-servlet-core.jar、jersey-container-servlet.jar、javax.ws.rs-api-2.0.jar

2  客户端:jersey-client.jar

3  common:jersey-common.jar

4  json支持:在jersey2.0中需要使用 jackson1.9 才能支持json。

hello world

以下将展示一个hello world

第一步: 编写一个名为helloresource的资源,它接受http get请求并响应“hello jersey”

@path("/hello")
public class helloresource {
 @get
 @produces(mediatype.text_plain)
 public string sayhello() {
  return "hello jersey";
 }
}

第二步: 编写jax-rs application

public class apiapplication extends resourceconfig {
  public apiapplication() {
 //加载resource
 register(helloresource.class);

 //注册数据转换器
 register(jacksonjsonprovider.class);

 // logging.
 register(loggingfilter.class);
  }
}

第三步: 在web.xml文件中定义servelt调度程序,目的是将所有rest请求发送到jersey容器。除了声明jersey servlet外,还需定义一个初始化参数,指定jax-rs application。

<!--用于定义 restful web service 接口-->
<servlet>
 <servlet-name>jerseyservlet</servlet-name>
 <servlet-class>org.glassfish.jersey.servlet.servletcontainer</servlet-class>
 <init-param>
  <param-name>javax.ws.rs.application</param-name>
  <param-value>cn.com.mink.resource.apiapplication</param-value>
 </init-param>

 <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
 <servlet-name>jerseyservlet</servlet-name>
 <url-pattern>/services/*</url-pattern>
</servlet-mapping>

在命令终端中输入以下命令,将会看到“hello jersey”。

curl http://host:port/services/hello

或者在浏览器中输入以下url,将会看到“hello jersey”

http://host:port/services/hello

使用

资源

root resource and sub-resource

资源是组成restful服务的关键部分,可以使用http方法(如:get、post、put和delete)操作资源。在jax-rx中,资源通过pojo实现,使用 @path 注释组成其标识符。资源可以有子资源,父资源是资源集合,子资源是成员资源。

在以下样例代码中,

resources是"/services" uri组成是集合资源,userresource是“/services/user” uri组成的成员资源;

@path("/services")
public class resources {

 @path("/user")
 public userresource getuserresource() {
  ...
 }

 @path("/book")
 public bookresource getbookresource() {
  ...
 }
}

userresource是“/user” uri组成的集合资源,getuser是“/user/{username}” uri组成的资源方法

@path("/user")
public class userresource {
 @get
 @path("{username"})
 @produces("application/json")
 public user getuser(@pathparam("username") string username) {
  ...
 }
}

http methods

http方法映射到资源的crud(创建、读取、更新和删除)操作,基本模式如下:

http get :读取/列出/检索单个或资源集合。

http post :新建资源。

http put :更新现有资源或资源集合。

http delete :删除资源或资源集合。

@produces

@produces 注释用来指定将要返回给client端的数据标识类型(mime)。@produces 可以作为class注释,也可以作为方法注释,方法的 @produces 注释将会覆盖class的注释。

1  指定一个mime类型

@produces("application/json")

2  指定多个mime类型

@produces({"application/json","application/xml"})

@consumes

@consumes 与 @produces 相反,用来指定可以接受client发送过来的mime类型,同样可以用于class或者method,也可以指定多个mime类型,一般用于 @put ,@post 。

参数(parameter annotations)

parameter annotations用于获取client发送的数据。本文只介绍常用的注解,更多详见 jersey用户手册

@pathparam

使用 @pathparam 可以获取uri中指定规则的参数,比如:

@get
@path("{username"})
@produces(mediatype.application_json)
public user getuser(@pathparam("username") string username) {
  ...
}

当浏览器请求 http://localhost/user/jack 时,username值为jack。

@queryparam

@queryparam 用于获取get请求中的查询参数,如:

@get
@path("/user")
@produces("text/plain")
public user getuser(@queryparam("name") string name,
          @queryparam("age") int age) {
  ...
}

当浏览器请求 http://host:port/user?name=rose&age=25 时,name值为rose,age值为25。如果需要为参数设置默认值,可以使用 @defaultvalue ,如:

@get
@path("/user")
@produces("text/plain")
public user getuser(@queryparam("name") string name,
          @defaultvalue("26") @queryparam("age") int age) {
  ...
}

当浏览器请求 http://host:port/user?name=rose 时,name值为rose,age值为26。

@formparam

@formparam ,顾名思义,从post请求的表单参数中获取数据。如:

@post
@consumes("application/x-www-form-urlencoded")
public void post(@formparam("name") string name) {
  // store the message
}

@beanparam

当请求参数很多时,比如客户端提交一个修改用户的put请求,请求中包含很多项用户信息。这时可以用 @beanparam 。

@post
@consumes("application/x-www-form-urlencoded")
public void update(@beanparam user user) {
  // store the user data
}

user bean定义如下:

@xmlrootelement(name = "user")
public class user {
 @pathparam("username)
 private string username;

 @formparam("name")
 private string name;

 @formparam("telephone")
 private string telephone;

 @formparam("email")
 private string email;

 public string getusername() {
  return username;
 }

 public void setusername(string username) {
  this.username = username;
 }
 ...
}

使用map

在一个大型的server中,因为参数的多变,参数结构的调整都会因为以上几种方式而遇到问题,这时可以考虑使用 @context 注释,并获取uriinfo实例,如下:

@get
public string get(@context uriinfo ui) {
  multivaluedmap<string, string> queryparams = ui.getqueryparameters();
  multivaluedmap<string, string> pathparams = ui.getpathparameters();
}

同样还可以通过 @context 注释获取 servletconfig 、 servletcontext 、httpservletrequest 、 httpservletresponse 和 httpheaders 等,如下:

@path("/")
public class resource {

 @context
 httpservletrequest req;

 @context
 servletconfig servletconfig;

 @context
 servletcontext servletcontext;

 @get
 public string get(@context httpheaders hh) {
  multivaluedmap<string, string> headerparams = hh.getrequestheaders();
  map<string, cookie> pathparams = hh.getcookies();
 }
}

jersey返回json和xml

jax-rs支持使用jaxb(java api for xml binding)将javabean绑定到xml或json,反之亦然。javabean必须使用 @xmlrootelement 标注,没有@xmlelement 注释的字段将包含一个名称与之相同的xml元素,如下:

@xmlrootelement
public class optionresult {
 @xmlelement(name = "code")
 private string result;

 private string errormsg;

 public string getresult() {
  return result;
 }

 public void setresult(string result) {
  this.result = result;
 }

 public string geterrormsg() {
  return errormsg;
 }

 public void seterrormsg(string errormsg) {
  this.errormsg = errormsg;
 }
}

然后在rest服务中使用:

@path("/user")
public class userresource {
 @post
 @produces("application/json")
 public optionresult create(@beanparam user user) {
  ...
 }
}

最后,要注册数据转换器,该转换器会自动将javabean转换为json数据:

public class apiapplication extends resourceconfig {
  public apiapplication() {
 //加载model
 register(optionresult.class);

 //加载与optionresult同一个packge的model
 //packages(optionresult.class.getpackage().getname());

 //加载resource
 register(userresource.class);

 //注册数据转换器
 register(jacksonjsonprovider.class);

 // logging.
 register(loggingfilter.class);
  }
}

说明 :返回xml数据的原理相同,仅仅是数据转换器不同,只需要在apiapplication中同时注册xml数据转换器即可,详见 jersey用户手册

问题总结

ajax请求(post、put和delete)无法将数据提交到jersey容器

问题阐述

在短信平台的开发中,数据的crud全部使用ajax技术完成,因此必须使用post、put和delete请求。此三种请求的content-type均为“application/x-www-form-urlencoded”,使用utf-8编码会变成“application/x-www-form-urlencoded; utf-8”。在使用firefox的tamperdata扩展调试程序的过程中发现,当content-type为“application/x-www-form-urlencoded”时,jersey容器能够通过 @formparam 注解获取到提交的数据,而content-type为“application/x-www-form-urlencoded; utf-8”时便获取不到。

解决方案

最终我使用java filter和jersey requestfilter解决了问题。首先在java filter中使用utf8将request中的数据编码,然后在jersey requestfilter中将request对象中的content-type修改为“application/x-www-form-urlencoded”。如:

public void dofilter(servletrequest request, servletresponse response, filterchain chain) throws ioexception, servletexception {
 httpservletrequest req = (httpservletrequest)request;
 req.setcharacterencoding("utf-8");
}

public class requestfilter implements containerrequestfilter {
 @override
 public void filter(containerrequestcontext context) throws ioexception {
  string headerstring = context.getheaderstring("content-type");
  if (headerstring != null) {
   //如果content-type以"application/x-www-form-urlencoded"开头,则处理
    if (headerstring.startswith(mediatype.application_form_urlencoded))
    context.getheaders().putsingle("content-type", mediatype.application_form_urlencoded);
  }
 }
}

最后在web.xml中注册java filter(要注册在jersey容器之前),在apiapplication中注册jersey requestfilter,如下:

public class apiapplication extends resourceconfig {
  public apiapplication() {
    register(requestfilter.class);
  }
}

说明 :在修复此问题后,在github的jersey源代码仓库中看到已经有人发现并修复了此问题,在下个jersey正式版本中应该不会再出现这样的问题,详见 此discussion

以上就是深入了解java jersey的详细内容,更多关于java jersey的资料请关注移动技术网其它相关文章!

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网