Jersey 入门与Javabean
Jersey是JAX-RS(JSR311)開(kāi)源參考實(shí)現(xiàn)用于構(gòu)建RESTful Web service,它包含三個(gè)部分:
核心服務(wù)器(Core Server)?通過(guò)提供JSR 311中標(biāo)準(zhǔn)化的注釋和API標(biāo)準(zhǔn)化,可以用直觀的方式開(kāi)發(fā)RESTful Web服務(wù)。
核心客戶(hù)端(Core Client)?Jersey客戶(hù)端API能夠幫助開(kāi)發(fā)者與RESTful服務(wù)輕松通信;
集成(Integration)?Jersey還提供可以輕松繼承Spring、Guice、Apache Abdera的庫(kù)
設(shè)置Jersey環(huán)境
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開(kāi)發(fā)包中將以下庫(kù)復(fù)制的WEB-INF下的庫(kù)目錄:
服務(wù)器 jersey-server.jar 、jersey-container-servlet-core.jar、jersey-container-servlet.jar、javax.ws.rs-api-2.0.jar
客戶(hù)端: jersey-client.jar
common: jersey-common.jar
json支持:在Jersey2.0中需要使用Jackson1.9才能支持json。
Demo Hello Wolrd
第一步:編寫(xiě)一個(gè)名為HelloResource的資源,它接受Http Get請(qǐng)求并響應(yīng) ”Hello Jerset”
@Path("/hello") public class HelloResource {@GET@Produces(MediaType.TEXT_PLAIN)public String sayHello() {return "Hello Jersey";} }第二步:編寫(xiě)JAX-RS application
public class APIApplication extends ResourceConfig {public APIApplication() {//加載Resourceregister(HelloResource.class);//注冊(cè)數(shù)據(jù)轉(zhuǎn)換器register(JacksonJsonProvider.class);// Logging.register(LoggingFilter.class);} }第三步:在web.xml文件中定義servelt調(diào)度程序,目的是將所有REST請(qǐng)求發(fā)送到Jersey容器。除了聲明Jersey Servlet外,還需定義一個(gè)初始化參數(shù),指定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>第四步:測(cè)試程序?
在命令終端中輸入以下命令,將會(huì)看到“Hello Jersey”。?
curl?http://host:port/services/hello?
或者在瀏覽器中輸入以下URL,將會(huì)看到“Hello Jersey”?
http://host:port/services/hello
?
使用
資源?
Root Resource And Sub-Resource?
資源是組成RESTful服務(wù)的關(guān)鍵部分,可以使用HTTP方法(如:GET、POST、PUT和DELETE)操作資源。在JAX-RX中,資源通過(guò)POJO實(shí)現(xiàn),使用@Path 注釋組成其標(biāo)識(shí)符。資源可以有子資源,父資源是資源集合,子資源是成員資源。?
Resources是”/services” URI組成是集合資源,UserResource是“/services/user” URI組成的成員資源;
注意,POJO是指簡(jiǎn)單的Java對(duì)象
@Path("/services") public class Resources {@Path("/user")public UserResource getUserResource() {...}@Path("/book")public BookResource getBookResource() {...} }UserResource是“/user” URI組成的集合資源,getUser是“/user/{username}” URI組成的資源方法
大括號(hào)里的內(nèi)容是參數(shù),這樣設(shè)置是合理的,因?yàn)閡sername也會(huì)出現(xiàn)在url中,而path就是url的意思
@Path("/user") public class UserResource {@GET@Path("{username"})@Produces("application/json")public User getUser(@PathParam("username") String userName) {...} }HTTP Methods?
HTTP方法映射到資源的CRUD(創(chuàng)建、讀取、更新和刪除)操作,基本模式如下:
HTTP GET: 讀取/列出/檢索單個(gè)資源
HTTP POST: 新建資源
HTTP PUT: 更新現(xiàn)有資源或資源集合
HTTP DELETE: 刪除資源或資源集合
@Produces?
@Produces注釋用來(lái)指定將要返回給client端的數(shù)據(jù)標(biāo)識(shí)類(lèi)型(MIME)。@Produces可以作為class注釋,也可以作為方法注釋,方法的@Produces注釋將會(huì)覆蓋class的注釋。 覆蓋的意思是假如方法聲明了自己的Produce,那么以方法的為準(zhǔn),class的僅供參考
指定MIME類(lèi)型?
@Produces(“application/json”)?
指定多個(gè)MIME類(lèi)型?
@Produces({“application/json”,“application/xml”})
@Consumes?
@Consumes與@Produces相反,用來(lái)指定可以接受client發(fā)送過(guò)來(lái)的MIME類(lèi)型,同樣可以用于class或者method,也可以指定多個(gè)MIME類(lèi)型,一般用于@PUT,@POST 。
參數(shù)(Parameter Annotations)?
Parameter Annotations用于獲取client發(fā)送的數(shù)據(jù)。本文只介紹常用的注解,更多詳見(jiàn)Jersey用戶(hù)手冊(cè)?
@PathParam?
使用@PathParam可以獲取URI中指定規(guī)則的參數(shù),比如:
當(dāng)瀏覽器請(qǐng)求http://localhost/user/jack時(shí),userName值為jack。?
注意,這里的username并不是說(shuō)Key是username, value是jack而是說(shuō)/usr/后面跟著的東西就是username,這里username只是個(gè)變量
至于key,value的形式,下面也有
@QueryParam?
@QueryParam用于獲取GET請(qǐng)求中的查詢(xún)參數(shù),如:
?
@GET @Path("/user") @Produces("text/plain") public User getUser(@QueryParam("name") String name,@QueryParam("age") int age) {... }當(dāng)瀏覽器請(qǐng)求http://host:port/user?name=rose&age=25時(shí),name值為rose,age值為25。如果需要為參數(shù)設(shè)置默認(rèn)值,可以使用@DefaultValue,如:
@GET @Path("/user") @Produces("text/plain") public User getUser(@QueryParam("name") String name,@DefaultValue("26") @QueryParam("age") int age) {... }當(dāng)瀏覽器請(qǐng)求http://host:port/user?name=rose時(shí),name值為rose,age值為26。?
@FormParam?
@FormParam,顧名思義,從POST請(qǐng)求的表單參數(shù)中獲取數(shù)據(jù)。如:
表單我一直沒(méi)弄清楚到底是什么東西,但就使用的情況來(lái)看,就是key,value之類(lèi)的東西
BeanParam?
當(dāng)請(qǐng)求參數(shù)很多時(shí),比如客戶(hù)端提交一個(gè)修改用戶(hù)的PUT請(qǐng)求,請(qǐng)求中包含很多項(xiàng)用戶(hù)信息。這時(shí)可以用@BeanParam。?
User Bean定義如下:
使用Map?
在一個(gè)大型的server中,因?yàn)閰?shù)的多變,參數(shù)結(jié)構(gòu)的調(diào)整都會(huì)因?yàn)橐陨蠋追N方式而遇到問(wèn)題,這時(shí)可以考慮使用@Context 注釋,并獲取UriInfo實(shí)例,如下:
我覺(jué)得,可以認(rèn)為map是上面幾種情況的超集,因?yàn)樗軌蛱娲陨先我庖环N。map就是context
同樣還可以通過(guò)@Context 注釋獲取ServletConfig、ServletContext、HttpServletRequest、HttpServletResponse和HttpHeaders等,如下:
@Path("/") public class Resource {@ContextHttpServletRequest req;@ContextServletConfig servletConfig;@ContextServletContext servletContext;@GETpublic 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標(biāo)注,沒(méi)有@XmlElement注釋的字段將包含一個(gè)名稱(chēng)與之相同的XML元素,如下:
這里就說(shuō)明了javabean和xml, json的關(guān)系
@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服務(wù)中使用: @Path("/user") public class UserResource {@POST@Produces("application/json")public OptionResult create(@BeanParam User user) {...} }最后,要注冊(cè)數(shù)據(jù)轉(zhuǎn)換器,該轉(zhuǎn)換器會(huì)自動(dòng)將JavaBean轉(zhuǎn)換為json數(shù)據(jù):
public class APIApplication extends ResourceConfig {public APIApplication() {//加載Modelregister(OptionResult.class);//加載與OptionResult同一個(gè)packge的Model//packages(OptionResult.class.getPackage().getName());//加載Resourceregister(UserResource.class);//注冊(cè)數(shù)據(jù)轉(zhuǎn)換器register(JacksonJsonProvider.class);// Logging.register(LoggingFilter.class);} }說(shuō)明:返回XML數(shù)據(jù)的原理相同,僅僅是數(shù)據(jù)轉(zhuǎn)換器不同,只需要在APIApplication中同時(shí)XML數(shù)據(jù)轉(zhuǎn)換器即可。?
Wiki上關(guān)于REST的總結(jié)
含狀態(tài)傳輸(英文:Representational State Transfer,簡(jiǎn)稱(chēng)REST)是Roy Fielding博士在2000年他的博士論文中提出來(lái)的一種軟件架構(gòu)風(fēng)格.
資源是由URI來(lái)指定。
對(duì)資源的操作包括獲取、創(chuàng)建、修改和刪除資源,這些操作正好對(duì)應(yīng)HTTP協(xié)議提供的GET、POST、PUT和DELETE方法。
通過(guò)操作資源的表現(xiàn)形式來(lái)操作資源。
資源的表現(xiàn)形式則是XML或者HTML,取決于讀者是機(jī)器還是人,是消費(fèi)web服務(wù)的客戶(hù)軟件還是web瀏覽器。當(dāng)然也可以是任何其他的格式。
應(yīng)該注意區(qū)別應(yīng)用的狀態(tài)和連接協(xié)議的狀態(tài)。HTTP連接是無(wú)狀態(tài)的(也就是不記錄每個(gè)連接的信息),而REST傳輸會(huì)包含應(yīng)用的所有狀態(tài)信息,因此可以大幅降低對(duì)HTTP連接的重復(fù)請(qǐng)求資源消耗。
實(shí)現(xiàn)舉例:
每種操作都會(huì)對(duì)應(yīng)一個(gè)函數(shù)
列舉所有商品
GET http://www.store.com/products呈現(xiàn)某一件商品
GET http://www.store.com/product/12345下單購(gòu)買(mǎi)
POST http://www.store.com/order <purchase-order><item> ... </item> </purchase-order>REST的優(yōu)點(diǎn)
可更高效利用緩存來(lái)提高響應(yīng)速度
通訊本身的無(wú)狀態(tài)性可以讓不同的服務(wù)器的處理一系列請(qǐng)求中的不同請(qǐng)求,提高服務(wù)器的擴(kuò)展性
瀏覽器即可作為客戶(hù)端,簡(jiǎn)化軟件需求
相對(duì)于其他疊加在HTTP協(xié)議之上的機(jī)制,REST的軟件依賴(lài)性更小
不需要額外的資源發(fā)現(xiàn)機(jī)制
在軟件技術(shù)演進(jìn)中的長(zhǎng)期的兼容性更好
?
JavaBean
JavaBeans是Java語(yǔ)言中可以重復(fù)使用的軟件組件,它們是一種特殊的Java類(lèi)[1],將很多的對(duì)象封裝到了一個(gè)對(duì)象(bean)中。特點(diǎn)是可序列化,提供無(wú)參構(gòu)造器,提供getter方法和setter方法訪問(wèn)對(duì)象的屬性。
優(yōu)點(diǎn)
Bean可以控制它的屬性,事件和方法是否暴露給其他程序
Bean可以接收來(lái)自其他對(duì)象的事件,也可以產(chǎn)生事件給其他對(duì)象
有軟件可以配置Bean
Bean的屬性可以被序列化,以供日后使用
JavaBean規(guī)范
要成為JavaBean類(lèi),必須遵循關(guān)于命名,構(gòu)造器,方法的特定規(guī)范,有了這些規(guī)范,才能使用,復(fù)用,替代和連接javabean的工具。?
規(guī)范是:
有一個(gè)public 無(wú)參構(gòu)造器
屬性可以通過(guò)get, set, is方法或者遵循特定命名規(guī)范的其他方法訪問(wèn)。
可序列化
一個(gè)例子
public class PersonBean implements java.io.Serializable {/*** <code>name</code>屬性(注意大小寫(xiě))*/private String name = null;private boolean deceased = false;/** 無(wú)參構(gòu)造器(沒(méi)有參數(shù)) */public PersonBean() {}/*** <code>name</code>屬性的Getter方法*/public String getName() {return name;}/*** <code>name</code>屬性的Setter方法* @param value*/public void setName(final String value) {name = value;}/*** "deceased"屬性的Getter方法* 布爾型屬性的Getter方法的不同形式(這里使用了is而非get)*/public boolean isDeceased() {return deceased;}/*** <code>deceased</code>屬性的Setter方法* @param value*/public void setDeceased(final boolean value) {deceased = value;} }?
總結(jié)
1. Javabean提供了一種保證,即對(duì)于所有的成員變量,一定有g(shù)et,set方法。并且還可以序列化
2. REST服務(wù)基于底層的保證來(lái)實(shí)現(xiàn),因此可以簡(jiǎn)化很多事情,比如Javabean和XML的轉(zhuǎn)換就可以寫(xiě)得相當(dāng)簡(jiǎn)單。
總結(jié)
以上是生活随笔為你收集整理的Jersey 入门与Javabean的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Javascript OrderBy
- 下一篇: 关于linux特殊重定向的理解