JAX-RS概述
JAX-RS是Java提供用於開發RESTful Web服務基於註解(annotation)的API。JAX-RS旨在定義一個統一的規範,使得Java程序員可以使用一套固定的接口來開發REST應用,避免了依賴第三方框架。同時JAX-RS使用POJO編程模型和基於註解的配置並集成JAXB,可以有效縮短REST應用的開發週期。JAX-RS只定義RESTful API,具體實現由第三方提供,如Jersey、Apache CXF等。
JAX-RS包含近五十多個接口、註解和抽象類:
- javax.ws.rs包含用於創建RESTful服務資源的高層次(High-level)接 口和註解。
- javax.ws.rs.core包含用於創建RESTful服務資源的低層次(Low-level)接口和註解。
- javax.ws.rs.ext包含用於擴展JAX-RS API支持類型的APIs。
JAX-RS常用註解:
- @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。
服務端
下面用CXF發佈一個圖書館RESTFul服務,實現書籍的查詢、添加、刪除和修改。CXF發佈RESTFul服務需要引入cxf-rt-frontend-jaxrs,pom.xml配置如下。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rvho</groupId>
<artifactId>cxfrestserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- CXF版本 -->
<cxf.version>3.1.1</cxf.version>
</properties>
<dependencies>
<!-- CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- 如果在tomcat或者其他servlet容器中發佈服務,不需要引用cxf-rt-transports-http-jetty -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- End CXF -->
</dependencies>
</project>
書籍XML格式
<Book>
<author>尼古拉·奧斯特洛夫斯基</author>
<id>10</id>
<name>鋼鐵是怎樣煉成的?</name>
<price>3.0</price>
</Book>
書籍實體類
package com.rvho.rest.server;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 書籍實體類
* @author [email protected]
*/
@XmlRootElement(name = "Book")
public class Book {
//id
private String id;
//書名
private String name;
//作者
private String author;
//價格
private Double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
圖書館服務類
package com.rvho.rest.server;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* 圖書館服務
* @author [email protected]
*
*/
@Path("/library")
@Produces("text/xml")
public class LibraryService {
private Map<String, Book> books = new HashMap<String, Book>();
public LibraryService(){
init();
}
/**
* 獲取
* @param id 索引
* @return 書
*/
@GET
@Path("/books/{id}/")
public Book getBook(@PathParam("id") String id){
return books.get(id);
}
/**
* 更新
* @param book
* @return
*/
@PUT
@Path("/books/")
public Response updateBook(Book book){
Response r;
if(book == null){
r = Response.noContent().build();
return r;
}
String id = book.getId();
Book b = books.get(id);
if(b != null){
books.put(id, book);
r = Response.ok(true, MediaType.TEXT_PLAIN).build();
}else{
r = Response.notModified().build();
}
return r;
}
/**
* 添加
* @param book
* @return
*/
@POST
@Path("/books/")
public Response addBook(Book book){
Response r;
if(book == null){
r = Response.notModified().build();
}else{
books.put(book.getId(), book);
r = Response.ok(true, MediaType.TEXT_PLAIN).build();
}
return r;
}
/**
* 刪除
* @param book
* @return
*/
@DELETE
@Path("/books/{id}/")
public Response deleteBook(@PathParam("id") String id){
Response r;
Book book = books.get(id);
if(book == null){
r = Response.notModified("id不存在").build();
}else{
books.remove(id);
r = Response.ok(book, MediaType.APPLICATION_XML).build();
}
return r;
}
/**
* 初始化,在圖書館裏加幾本書
*/
private void init(){
Book book = null;
book = new Book();
book.setAuthor("CSDN");
book.setId("blog");
book.setName("如何使用博客");
book.setPrice(3.0);
books.put(book.getId(), book);
book = new Book();
book.setAuthor("CSDN");
book.setId("app");
book.setName("如何下載CSDN移動客戶端");
book.setPrice(30.0);
books.put(book.getId(), book);
book = new Book();
book.setAuthor("CSDN");
book.setId("resource");
book.setName("如何下載CSDN資源");
book.setPrice(5.0);
books.put(book.getId(), book);
book = new Book();
book.setAuthor("CSDN");
book.setId("rs");
book.setName("JAX-RS詳解");
book.setPrice(15.0);
books.put(book.getId(), book);
}
}
發佈服務
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(LibraryService.class);
sf.setResourceProvider(LibraryService.class, new SingletonResourceProvider(new LibraryService()));
sf.setAddress("http://localhost:8280/rest/");
sf.create();
客戶端
查詢書籍信息,在瀏覽器中輸入http://localhost:8280/rest/library/books/app/
下面用Fiddler模擬POST、DELETE和PUT請求。
添加書籍
<Book>
<author>魯迅</author>
<id>11</id>
<name>朝花夕拾</name>
<price>20.0</price>
</Book>
添加返回結果
HTTP/1.1 200 OK
Date: Fri, 31 Jul 2015 06:50:30 GMT
Content-Type: text/plain
Date: Fri, 31 Jul 2015 06:50:30 GMT
Content-Length: 4
Server: Jetty(9.2.10.v20150310)
true
修改書籍
<Book>
<author>魯迅</author>
<id>11</id>
<name>朝花夕拾</name>
<price>200.0</price>
</Book>
返回結果
HTTP/1.1 200 OK
Date: Fri, 31 Jul 2015 06:52:24 GMT
Content-Type: text/plain
Date: Fri, 31 Jul 2015 06:52:24 GMT
Content-Length: 4
Server: Jetty(9.2.10.v20150310)
true
刪除書籍
返回結果
HTTP/1.1 200 OK
Date: Fri, 31 Jul 2015 06:54:36 GMT
Content-Type: application/xml
Date: Fri, 31 Jul 2015 06:54:36 GMT
Content-Length: 147
Server: Jetty(9.2.10.v20150310)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Book><author>魯迅</author><id>11</id><name>朝花夕拾</name><price>200.0</price></Book>
Tomcat中發佈RESTful
CXF在Tomcat中發佈服務,需要Spring-Web支持,pom.xml配置如下。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rvho</groupId>
<artifactId>cxfrestserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<!-- CXF版本 -->
<cxf.version>3.1.1</cxf.version>
<!-- Spring版本 -->
<spring.version>4.1.7.RELEASE</spring.version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- End Spring -->
<!-- CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- End CXF -->
</dependencies>
</project>
在web.xml中添加CXFServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>cxfrestserver</display-name>
<!-- Spring配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- End Spring配置 -->
<!-- CXF Servlet -->
<servlet>
<servlet-name>cxfservlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxfservlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!-- End CXF Servlet -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
在WEB-INF文件夾下創建cxf-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<bean id="libraryServiceBean" class="com.rvho.rest.server.LibraryService"></bean>
<jaxrs:server id="libraryServer" address="/">
<jaxrs:serviceBeans>
<ref bean="libraryServiceBean"/>
</jaxrs:serviceBeans>
</jaxrs:server>
</beans>
Spring上下文配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- <context:annotation-config /> -->
<!-- 使Spring支持自動檢測組件,如註解的Repository、Service、Controller -->
<context:component-scan base-package="com.rvho" />
</beans>
啓動Tomcat,在瀏覽器中輸入http://<地址>/cxfrestserver/rest即可看到服務