RestEasy簡介
簡介
RESTEasy
RESTEasy是JBoss的一個開源專案,提供各種框架幫助你構建RESTful Web Services和RESTful Java應用程式。它是JAX-RS規範的一個完整實現並透過JCP認證。作為一個JBOSS的專案,它當然能和JBOSS應用伺服器很好地整合在一起。但是,它也能在任何執行JDK5或以上版本的Servlet容器中執行。RESTEasy還提供一個RESTEasy JAX-RS客戶端呼叫框架。能夠很方便與EJB、Seam、Guice、Spring和Spring MVC整合使用。支援在客戶端與伺服器端自動實現GZIP解壓縮。
RESTEasy 專案是 JAX-RS 的一個實現,整合的一些亮點:
- 不需要配置檔案,只要把JARs檔案放到類路徑裡面,新增 @Path 標註就可以了。
- 完全的把 RESTEeasy 配置作為Seam 元件來看待。
- HTTP 請求由Seam來提供,不需要一個額外的Servlet。
- Resources 和providers可以作為 Seam components (JavaBean or EJB),具有全面的Seam injection,lifecycle, interception, 等功能支援。
- 支援在客戶端與伺服器端自動實現GZIP解壓縮。
名詞解釋:
JAX-RS: Java API for RESTful Web Services是一個Java程式語言的應用程式介面,支援按照 表象化狀態轉變 (REST)架構風格建立Web服務Web服務. JAX-RS使用了Java SE 5引入的Java 標註來簡化Web服務客戶端和服務端的開發和部署。
規範內容
JAX-RS提供了一些標註將一個資源類,一個POJOJava類,封裝為Web資源。標註包括:
@Path,標註資源類或方法的相對路徑
@GET,@PUT,@POST,@DELETE,標註方法是用的HTTP請求的型別
@Produces,標註返回的MIME媒體型別
@Consumes,標註可接受請求的MIME媒體型別
@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分別標註方法的引數來自於HTTP請求的不同位置,例如@PathParam來自於URL的路徑,@QueryParam來自於URL的查詢引數,@HeaderParam來自於HTTP請求的頭資訊,@CookieParam來自於HTTP請求的Cookie。
REST
詳細介紹
如何配置
單獨配置
在 WEB-INF/ 中配置如下:
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
配置開關
Resteasy採用
引數名 |
預設值 |
描述 |
resteasy.servlet.mapping.prefix |
no default |
If the url-pattern for the Resteasy servlet-mapping is not /* |
resteasy.scan |
FALSE |
Automatically scan WEB-INF/lib jars and WEB-INF/classes directory for both @Provider and JAX-RS resource classes (@Path, @GET, @POST etc..) and register them |
resteasy.scan.providers |
FALSE |
Scan for @Provider classes and register them |
resteasy.scan.resources |
FALSE |
Scan for JAX-RS resource classes |
resteasy.providers |
no default |
A comma delimited list of fully qualified @Provider class names you want to register
|
resteasy.use.builtin.providers
|
TRUE |
Whether or not to register default, built-in @Provider classes. (Only available in 1.0-beta-5 and later)
|
resteasy.resources
|
no default
|
A comma delimited list of fully qualified JAX-RS resource class names you want to register
|
resteasy.jndi.resources
|
no default
|
A comma delimited list of JNDI names which reference objects you want to register as JAX-RS resources
|
javax.ws.rs.Application
|
no default
|
Fully qualified name of Application class to bootstrap in a spec portable way
|
resteasy.media.type.mappings
|
no default
|
Replaces the need for an Accept header by mapping file name extensions (like .xml or .txt) to a media type. Used when the client is unable to use a Accept header to choose a representation (i.e. a browser). See JAX-RS Content Negotiation chapter for more details.
|
resteasy.language.mappings
|
no default
|
Replaces the need for an Accept-Language header by mapping file name extensions (like .en or .fr) to a language. Used when the client is unable to use a Accept-Language header to choose a language (i.e. a browser). See JAX-RS Content Negotiation chapter for more details
|
使用ServletContextListener來配置
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
<!-- ** INSERT YOUR LISTENERS HERE!!!! -->
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
使用ServletFilter來配置
org.jboss.resteasy.plugins.server.servlet.FilterDispatcher
與Spring整合
使用@Path,@Get,@Post等標註
示例:
@Path("/library")
public class Library {
@GET
@Path("/books")
public String getBooks() {...}
@GET
@Path("/book/{isbn}")
public String getBook(@PathParam("isbn") String id) {
// search my database and get a string representation and return it
}
@PUT
@Path("/book/{isbn}")
public void addBook(@PathParam("isbn") String id, @QueryParam("name") String name) {...}
@DELETE
@Path("/book/{id}")
public void removeBook(@PathParam("id") String id {...}
}
以下操作都是針對library這個資源的
GET 意思為獲得所有的books呼叫的方法為getBooks
GET 意思為獲得ID為333的book呼叫的方法為getBook
PUT 新增一個ID為333的book呼叫的方法為addBook
DELETE 刪除一個ID為333的book呼叫的方法為removeBook
@Path這個標註可以在類上也可以在方法上,如果類和方法上都有的話,那麼方法上的路徑是級聯的如上面例子的/library/book/
@Path和使用正規表示式匹配路徑
@Path不僅僅接收簡單的路徑表示式,也可以使用正規表示式:
@Path("/resources)
public class MyResource {
@GET
@Path("{var:.*}/stuff")
public String get() {...}
}
如下操作就能獲得該資源
GET /resources/stuff
GET /resources/foo/stuff
GET /resources/on/and/on/stuff
表示式的格式為:
"{" variable-name [ ":" regular-expression ] "}"
正規表示式部分是可選的,當未提供時,則會匹配一個預設的表示式"([]*)"
@Path("/resources/{var}/stuff")
會匹配如下路徑
GET /resources/foo/stuff
GET /resources/bar/stuff
下面的則不會匹配
GET /resources/a/bunch/of/stuff
@PathParam
@PathParam 引數標註是用來獲取對映路徑上的變數值供方法使用
@Path("/library")
public class Library {
@GET
@Path("/book/{isbn}")
public String getBook(@PathParam("isbn") String id) {
// search my database and get a string representation and return it
}
}
GET 就會呼叫到getBook方法,id的值就會被自動對映為333
@Path中的變數名要和@PathParam中的變數名一致,引數型別可以是任意型別,一個String,一個Java物件,注意如果是Java物件時,這個物件要擁有一個帶String型別引數的構造器或者一個返回值為String的靜態valueOf方法,例如:
構造器方式:
@GET
@Path("/book/{isbn}")
public String getBook(@PathParam("isbn") ISBN id) {...}
public class ISBN {
public ISBN(String str) {...}
}
valueOf方式:
public class ISBN {
public static ISBN valueOf(String isbn) {...}
}
這樣做的目的是底層會把請求的引數透過String的方式傳遞的前端,構造物件的方式由業務層來自己構建
@PathParam高階使用
允許指定一個或多個路徑引數在一個URI段中。例如:
- @Path("/aaa{param}bbb")
"/aaa111bbb"會匹配,param=111
- @Path("/{name}-{zip}")
"/bill-02115" 會匹配,name=bill,zip=02115
- @Path("/foo{name}-{zip}bar")
"/foobill-02115bar " 會匹配,name=bill,zip=02115
正規表示式方式例子:
@GET
@Path("/aaa{param:b+}/{many:.*}/stuff")
public String getIt(@PathParam("param") String bs, @PathParam("many") String many) {...}
GET /aaabb/some/stuff bs=bb,many=some
GET /aaab/a/lot/of/stuff bs= b,many=a/lot/of
@QueryParam
@QueryParam這個標註是給透過?的方式傳參獲得引數值的,如:
GET /books?num=5&index=1
@GET
public String getBooks(@QueryParam("num") int num,@QueryParam("index") int index) {
...
}
這裡同上面的@PathParam,引數型別可以是任意型別
@HeaderParam
這個標註時用來獲得儲存在HttpRequest頭裡面的引數資訊的,如:
@PUT
public void put(@HeaderParam("Content-Type") MediaType contentType, ...)
這裡同上面的@PathParam,引數型別可以是任意型別
@CookieParam
用來獲取儲存在Cookie裡面的引數,如:
@GET
public String getBooks(@CookieParam("sessionid") int id) {
...
}
@FormParam
用來獲取Form中的引數值,如:
頁面程式碼:
First name:
Middle name:
Last name:
後臺程式碼
@Path("/")
public class NameRegistry {
@Path("/resources/service")
@POST
public void addName(@FormParam("firstname") String first, @FormParam("lastname") String last) {...}
標註了@FormParam,會把表達裡面的值自動對映到方法的引數上去.
如果要取得Form裡面的所有屬性,可以透過在方法上增加一個MultivaluedMap
@Path("/resources/service")
@POST
public void addName(@FormParam("firstname") String first, @FormParam("lastname") String last,MultivaluedMap
@Form
上面已經說的幾種標註都是一個屬性對應一個引數的,那麼如果屬性多了,定義的方法就會變得不好閱讀,此時最好有個東西能夠把上面的幾種自動標註自動封裝成一個物件,@Form這個標註就是用來實現這個功能的,如:
public class MyForm {
@FormParam("stuff")
private int stuff;
@HeaderParam("myHeader")
private String header;
@PathParam("foo")
public void setFoo(String foo) {...}
}
@POST
@Path("/myservice")
public void post(@Form MyForm form) {...}
@DefaultValue
在以上標註使用的時候,有些引數值在沒有值的情況下如果需要有預設值,則使用這個標註,如:
@GET
public String getBooks(@QueryParam("num") @DefaultValue("10") int num) {...}
滿足JAX-RS規範的 Resource Locators和子資源
資源處理類定義的某個方法可以處理某個請求的一部分,剩餘部分由子資源處理類來處理,如:
@Path("/")
public class ShoppingStore {
@Path("/customers/{id}")
public Customer getCustomer(@PathParam("id") int id) {
Customer cust = ...; // Find a customer object
return cust;
}
}
public class Customer {
@GET
public String get() {...}
@Path("/address")
public String getAddress() {...}
}
當我們發起GET /customer/123這樣的請求的時候,程式會先呼叫 ShoppingStore的 getCustomer這個方法,然後接著呼叫 Customer裡面的 get方法
當我們發起GET /customer/123/address這樣的請求的時候,程式會先呼叫 ShoppingStore的 getCustomer這個方法,然後接著呼叫 Customer裡面的 getAddress 方法
JAX-RS Content Negotiation
@Consumes
我們從頁面提交資料到後臺的時候,資料的型別可以是text的,xml的,json的,但是我們在請求資源的時候想要請求到同一個資源路徑上面去,此時怎麼來區分處理呢?使用@Consumes標註,下面的例子將說明:
@Consumes("text/*")
@Path("/library")
public class Library {
@POST
public String stringBook(String book) {...}
@Consumes("text/xml")
@POST
public String jaxbBook(Book book) {...}
當客戶端發起請求的時候,系統會先找到所有匹配路徑的方法,然後根據content-type找到具體的處理方法,比如:
POST /library
content-type: text/plain
就會執行上面的 stringBook這個方法,因為這個方法上面沒有標註@ Consumes,程式找了所有的方法沒有找到標註 @ Consumes(“text/plain”)這個型別的,所以就執行這個方法了.如果請求的content-type=xml,比如:
POST /library
content-type: text/xml
此時就會執行 jaxbBook這個方法
@Produces
當伺服器端實行完成相關的邏輯需要返回物件的時候,程式會根據@Produces返回相應的物件型別
@Produces("text/*")
@Path("/library")
public class Library {
@GET
@Produces("application/json")
public String getJSON() {...}
@GET
public String get() {...}
如果客戶端發起如下請求
GET /library
那麼則會呼叫到get方法並且返回的格式是json型別的
這些標註能不能寫多個呢?答案是可以的,但是系統只認第一個
Content Marshalling/Providers
這個東西是用來根據訊息題格式來組裝物件或者根據物件生成相應的訊息體的,預設的對應關係如下
Media Types |
Java Type
|
application/*+xml, text/*+xml, application/*+json, application/*+fastinfoset, application/atom+*
|
JaxB annotated classes
|
application/*+xml, text/*+xml
|
org.w3c.dom.Document
|
*/*
|
java.lang.String javax.activation.DataSource java.io.File byte[]
|
application/x-www-form-urlencoded
|
javax.ws.rs.core.MultivaluedMap
|
text/plain
|
primtives, java.lang.String, or any type that has a String constructor, or static valueOf(String) method for input, toString() for output
|
生成 JavaScript API
RESTEasy能夠生成JavaScript API使用AJAX來執行 JAX-RS操作,比如:
@Path("orders")
public interface Orders {
@Path("{id}")
@GET
public String getOrder(@PathParam("id") String id){
return "Hello "+id;
}
}
以上程式碼可以在js裡面透過var order = Orders.getOrder({id: 23});
這種方式來呼叫,很酷吧,這裡應該是跟Google的一項技術類似的Java程式碼可以透過js方式來呼叫
透過JavaApi呼叫資源
上面介紹了生成jsapi的方式呼叫,另外如果別的應用需要透過Java的方式呼叫資源該怎麼處理呢,下面的例子將說明:
ClientRequest request = new ClientRequest("");
// request.header("custom-header", "value");
// We're posting XML and a JAXB object
// request.body("application/xml", someJaxb);
// we're expecting a String back
ClientResponse
if (response.getStatus() == 200) // OK!
{
Object str = response.getEntity();
System.out.println(str);
}
把資源當做一個標準servlet接收處理方法
我們可以把一個資源url當做一個接收servlet請求的處理類或者處理方法
對@PathParam, @QueryParam, @MatrixParam, @FormParam, and @HeaderParam引數的處理
@PathParam, @QueryParam, @MatrixParam, @FormParam, and @HeaderParam標註傳遞的引數型別是String型的,對於這些引數我們的方法可能希望接收的引數是經過轉換後的物件型別的引數,比如如下的方法:
void put(@QueryParam("pojo")POJO q, @PathParam("pojo")POJO pp,@MatrixParam("pojo")POJO mp,@HeaderParam("pojo")POJO hp);
這裡的Put方法需要的是一個Pojo型別的引數,但是@PathParam, @QueryParam, @MatrixParam, @FormParam, and @HeaderParam傳遞的都是String型別的,怎麼是怎麼轉換為物件的呢?
可以使用StringConverter或者StringParamUnmarshaller
StringConverter
package org.jboss.resteasy.spi;
public interface StringConverter
{
T fromString(String str);
String toString(T value);
}
實現類如下:
@Provider
public static class POJOConverter implements StringConverter
{
public POJO fromString(String str)
{
System.out.println("FROM STRNG: " + str);
POJO pojo = new POJO();
pojo.setName(str);
return pojo;
}
public String toString(POJO value)
{
return value.getName();
}
}
FromString就是你自己需要實現的如何把接收的String引數轉換為Pojo類
toString方法是用來把Pojo物件轉換為String
現在已經能夠把String引數轉換為物件了,我們更進一步的想使用一些自定義的標註來做一些邏輯,比如說日期的格式化,就要使用下面的StringParamUnmarshaller
StringParamUnmarshaller
package org.jboss.resteasy.spi;
public interface StringParameterUnmarshaller
{
void setAnnotations(Annotation[] annotations);
T fromString(String str);
}
實現類
public class DateFormatter implements StringParameterUnmarshaller
{
private SimpleDateFormat formatter;
public void setAnnotations(Annotation[] annotations)
{
DateFormat format = FindAnnotation.findAnnotation(annotations, DateFormat.class);
formatter = new SimpleDateFormat(format.value());
}
public Date fromString(String str)
{
try
{
return formatter.parse(str);
}
catch (ParseException e)
{
throw new RuntimeException(e);
}
}
}
使用方式:
@Path("/datetest")
public class Service
{
@GET
@Produces("text/plain")
@Path("/{date}")
public String get(@PathParam("date") @DateFormat("MM-dd-yyyy") Date date)
{
System.out.println(date);
Calendar c = Calendar.getInstance();
c.setTime(date);
Assert.assertEquals(3, c.get(Calendar.MONTH));
Assert.assertEquals(23, c.get(Calendar.DAY_OF_MONTH));
Assert.assertEquals(1977, c.get(Calendar.YEAR));
return date.toString();
}
}
在實際使用中,我們有些引數值並不是透過以上方式來傳遞的,比如說我們要對session進行操作,那麼應該怎麼辦呢,resteasy並沒有直接提供使用自定義標註的方法,所以我們可以使用以上的 StringParamUnmarshaller來變通的實現
首先定義自定義標註
@Retention(RetentionPolicy.RUNTIME)
@StringParameterUnmarshallerBinder(SessionOperator.class)
public @interface Session {
public String value();
}
@StringParameterUnmarshallerBinder(SessionOperator.class)是用來指明這個自定義標註是哪個具體的類來處理, SessionOperator這個類就是Session這個自定義標註的處理類
public class SessionOperator implements StringParameterUnmarshaller{
public void setAnnotations(Annotation[] annotations) {
}
public Object fromString(String str) {
return null;
}
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-1649023/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【RESTEasy 介紹】REST
- RestEasy技術說明REST
- seam2.0整合resteasy框架的配置REST框架
- 簡介
- Jira使用簡介 HP ALM使用簡介
- BookKeeper 介紹(1)--簡介
- Amphenol簡介
- Vagrant簡介
- PySimpleGUI 簡介GUI
- Protobuf簡介
- MyBatis 簡介MyBatis
- jango簡介Go
- cookie 簡介Cookie
- Session 簡介Session
- Cookie簡介Cookie
- Virgilio 簡介
- Django簡介Django
- ElasticSearch簡介Elasticsearch
- Javascript 簡介JavaScript
- Electron簡介
- Dubbo 簡介
- JavaScript簡介JavaScript
- CSS 簡介CSS
- 反射簡介反射
- JanusGraph -- 簡介
- CSS簡介CSS
- Bootstrap 簡介boot
- pwa簡介
- Apache簡介Apache
- JAVA簡介Java
- JUC簡介
- sass簡介
- NATS簡介
- Mybatis簡介MyBatis
- Zookeeper簡介
- Handlebars 簡介
- HTML簡介HTML
- jwt簡介JWT