在上述的幾個例子中,我們使用的是內(nèi)嵌的 Tomcat 或者 Jetty 的服務(wù)器形式,以此來運行和測試項目。這樣,項目最終會被打包成 WAR 部署在 Tomcat 或者 Jetty 等 Servlet 容器中。這種部署環(huán)境使用廣泛,被稱為基于 Servlet 的部署( Servlet-based Deployment)。
當 Web 應(yīng)用不是很復(fù)雜,不要求應(yīng)用性能很高的時候,我們就需要將 Http Server 內(nèi)嵌在我們的 Java 程序中,只要運行Java程序,相應(yīng)的 Http Server 就會跟著快速啟動。這就是本文所介紹的基于 Java SE 部署環(huán)境(Java SE Deployment)來提供 REST 服務(wù)。
基于 Java 的 HTTP 服務(wù)器展現(xiàn)了一種簡約、靈活的部署 Jersey 應(yīng)用程序的方式。HTTP 服務(wù)器通常是嵌入在應(yīng)用程序中,并通過配置,以編程形式來啟動。一般來說,Jersey 容器為特定的 HTTP 服務(wù)器提供了一個定制化的工廠方法,用來返回一個正確初始化的 HTTP 服務(wù)器實例。
下面展示了常見 HTTP 服務(wù)器的內(nèi)嵌在 Jersey 應(yīng)用中的使用方法:
從 Java SE 6 開始,Java 運行時附帶一個內(nèi)置的輕量級的 HTTP 服務(wù)器。Jersey 通過 jersey-container-jdk-http 容器擴展模塊,提供集成這個 Java SE HTTP 服務(wù)器。此時,不是直接創(chuàng)建 HttpServer 實例,而是使用 JdkHttpServerFactory 的 createHttpServer()方法,它根據(jù) Jersey 容器配置和 Application 子類提供的初始化來創(chuàng)建 HttpServer 實例 。
創(chuàng)建一個 內(nèi)嵌 Jersey 的jdk http server 非常簡單:
Jersey 和 JDK HTTP Server 用法:
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, config);
JDK HTTP 容器依賴:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jdk-http</artifactId>
<version>2.21</version>
</dependency>
Grizzly 是一個建立在 Java NIO 之上的支持多協(xié)議的框架。Grizzly 旨在簡化強大的和可擴展的服務(wù)器開發(fā)。Jersey 提供了一個容器的擴展模塊,可以使用 Grizzly 作為運行 JAX-RS 應(yīng)用普通的 HTTP 容器支持。從 Grizzly 服務(wù)器運行 JAX-RS 或 Jersey 的應(yīng)用是一種最輕量和最容易的方法,用來展現(xiàn) RESTful 服務(wù)。
Grizzly 容器支持 HTTP 注射 Grizzly 的特性 org.glassfish.grizzly.http.server.Request 和org.glassfish.grizzly.http.server.Response 實例到 JAX-RS 和Jersey 應(yīng)用資源和供應(yīng)者。然而,由于 Grizzly 的 Request 是非代理性的,Grizzly Request的注入到單例(默認)的JAX-RS /和Jersey 提供者只可能通過 javax.inject.Provider 實例。(Grizzly Response會遭受同樣的限制。)
Jersey 和 Grizzly HTTP Server 用法:
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, config);
容器擴展模塊依賴要加入:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.21</version>
</dependency>
注意:通過測試框架, Jersey 使用 Grizzly 已經(jīng)廣泛的在項目單元和端到端進行了測試。
Simple 是一個框架允許開發(fā)者創(chuàng)建 HTTP 服務(wù)器,并嵌入到應(yīng)用中。同樣的,通過從 jersey-container-simple-http 容器擴展模塊調(diào)用工廠方法實現(xiàn)創(chuàng)建服務(wù)器實例。
Simple 的框架支持 HTTP 容器注入 Simple 框架特性 的org.simpleframework.http.Request 和 org.simpleframework.http.Response 實例到 JAX-RS 和 Jersey 應(yīng)用資源和供應(yīng)者。
Jersey 和 Simple 框架用法:
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
SimpleContainer server = SimpleContainerFactory.create(baseUri, config);
容器擴展模塊依賴要加入:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-simple-http</artifactId>
<version>2.21</version>
</dependency>
注意:Simple HTTP 容器不支持部署在除了根路徑是 ("/")以外的上下文路徑。非根路徑的上下文路徑在部署中是被忽略的。
Jetty 是流行的 Servlet 容器和 HTTP 服務(wù)器。在此我們不深究 Jetty 作為 Servlet 容器的能力(盡管我們在我們的測試和實例使用它),因為作為基于 Servlet 部署模型并沒有什么特別,具體會在 第4.7節(jié),“基于 Servlet 部署”部分進行描述。我們將在這里只重點描述如何使用 Jetty 的 HTTP 服務(wù)器。
Jetty HTTP 容器支持注入 Jetty 特性的org.eclipse.jetty.server.Request 和 org.eclipse.jetty.server.Response 實例到 JAX-RS 和 Jersey 應(yīng)用資源和供應(yīng)者。然而,由于 Jetty HTTP Request 是非代理性的,Jetty Request 的注入到單例(默認)的JAX-RS /和Jersey 提供者只可能通過 javax.inject.Provider 實例。(Jetty Response 會遭受同樣的限制。)
Jersey 和 Jetty HTTP Server 用法:
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig config = new ResourceConfig(MyResource.class);
Server server = JettyHttpContainerFactory.createServer(baseUri, config);
容器擴展模塊依賴要加入(譯者注:原文中依賴包有誤,這里做了更正):
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.21</version>
</dependency>
注意:Jetty HTTP 容器不支持部署在除了根路徑是 ("/")以外的上下文路徑。非根路徑的上下文路徑在部署中是被忽略的。
回顧之前的內(nèi)容,從《處理 JSON 和 XML》的源代碼,我們進行了修改:
MyBean.java
@XmlRootElement
public class MyBean {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
MyBean 作為我們數(shù)據(jù)相應(yīng)的實體。
MyResource.java
@Path("myresource")
public class MyResource {
/**
* 方法處理 HTTP GET 請求。返回的對象以"text/plain"媒體類型
* 給客戶端
*
* @return String 以 text/plain 形式響應(yīng)
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
/**
* 方法處理 HTTP GET 請求。返回的對象以"application/xml"媒體類型
* 給客戶端
*
* @return MyPojo 以 application/xml 形式響應(yīng)
*/
@GET
@Path("pojoxml")
@Produces(MediaType.APPLICATION_XML)
public MyBean getPojoXml() {
MyBean pojo = new MyBean();
pojo.setName("waylau.com");
pojo.setAge(28);
return pojo;
}
/**
* 方法處理 HTTP GET 請求。返回的對象以"application/json"媒體類型
* 給客戶端
*
* @return MyPojo 以 application/json 形式響應(yīng)
*/
@GET
@Path("pojojson")
@Produces(MediaType.APPLICATION_JSON)
public MyBean getPojoJson() {
MyBean pojo = new MyBean();
pojo.setName("waylau.com");
pojo.setAge(28);
return pojo;
}
}
分別向外暴露各種類型資源,包括:本文、XML、JSON
RestApplication.java
public class RestApplication extends ResourceConfig {
public RestApplication() {
// 資源類所在的包路徑
packages("com.waylau.rest.resource");
// 注冊 MultiPart
register(MultiPartFeature.class);
}
}
該配置說明了要掃描的資源包的路徑com.waylau.rest.resource
,以及支持 JSON 轉(zhuǎn)換 MultiPartFeature
App.java
public class App {
// HTTP server 所要監(jiān)聽的 uri
public static final String BASE_URI = "http://192.168.11.125:8081/";
/**
* Main method.
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// 若使用 Jdk Http Server請去掉下面的注釋
// JdkHttpServerFactory.createHttpServer(URI.create(BASE_URI), new
// RestApplication());
// 若使用 Grizzly Http Server請去掉下面的注釋
// GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), new
// RestApplication());
// 若使用 Simple Http Server請去掉下面的注釋
// SimpleContainerFactory.create(URI.create(BASE_URI), new
// RestApplication());
// 若使用 Jetty Http Server請去掉下面的注釋
JettyHttpContainerFactory.createServer(URI.create(BASE_URI),
new RestApplication());
}
}
各種服務(wù)器的用法在上面已經(jīng)說了,這里就不再解析。
見 javase-rest
項目
更多建議: