在上述的幾個(gè)例子中,我們使用的是內(nèi)嵌的 Tomcat 或者 Jetty 的服務(wù)器形式,以此來運(yùn)行和測(cè)試項(xiàng)目。這樣,項(xiàng)目最終會(huì)被打包成 WAR 部署在 Tomcat 或者 Jetty 等 Servlet 容器中。這種部署環(huán)境使用廣泛,被稱為基于 Servlet 的部署( Servlet-based Deployment)。
當(dāng) Web 應(yīng)用不是很復(fù)雜,不要求應(yīng)用性能很高的時(shí)候,我們就需要將 Http Server 內(nèi)嵌在我們的 Java 程序中,只要運(yùn)行Java程序,相應(yīng)的 Http Server 就會(huì)跟著快速啟動(dòng)。這就是本文所介紹的基于 Java SE 部署環(huán)境(Java SE Deployment)來提供 REST 服務(wù)。
基于 Java 的 HTTP 服務(wù)器展現(xiàn)了一種簡(jiǎn)約、靈活的部署 Jersey 應(yīng)用程序的方式。HTTP 服務(wù)器通常是嵌入在應(yīng)用程序中,并通過配置,以編程形式來啟動(dòng)。一般來說,Jersey 容器為特定的 HTTP 服務(wù)器提供了一個(gè)定制化的工廠方法,用來返回一個(gè)正確初始化的 HTTP 服務(wù)器實(shí)例。
下面展示了常見 HTTP 服務(wù)器的內(nèi)嵌在 Jersey 應(yīng)用中的使用方法:
從 Java SE 6 開始,Java 運(yùn)行時(shí)附帶一個(gè)內(nèi)置的輕量級(jí)的 HTTP 服務(wù)器。Jersey 通過 jersey-container-jdk-http 容器擴(kuò)展模塊,提供集成這個(gè) Java SE HTTP 服務(wù)器。此時(shí),不是直接創(chuàng)建 HttpServer 實(shí)例,而是使用 JdkHttpServerFactory 的 createHttpServer()方法,它根據(jù) Jersey 容器配置和 Application 子類提供的初始化來創(chuàng)建 HttpServer 實(shí)例 。
創(chuàng)建一個(gè) 內(nèi)嵌 Jersey 的jdk http server 非常簡(jiǎn)單:
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 是一個(gè)建立在 Java NIO 之上的支持多協(xié)議的框架。Grizzly 旨在簡(jiǎn)化強(qiáng)大的和可擴(kuò)展的服務(wù)器開發(fā)。Jersey 提供了一個(gè)容器的擴(kuò)展模塊,可以使用 Grizzly 作為運(yùn)行 JAX-RS 應(yīng)用普通的 HTTP 容器支持。從 Grizzly 服務(wù)器運(yùn)行 JAX-RS 或 Jersey 的應(yīng)用是一種最輕量和最容易的方法,用來展現(xiàn) RESTful 服務(wù)。
Grizzly 容器支持 HTTP 注射 Grizzly 的特性 org.glassfish.grizzly.http.server.Request 和org.glassfish.grizzly.http.server.Response 實(shí)例到 JAX-RS 和Jersey 應(yīng)用資源和供應(yīng)者。然而,由于 Grizzly 的 Request 是非代理性的,Grizzly Request的注入到單例(默認(rèn))的JAX-RS /和Jersey 提供者只可能通過 javax.inject.Provider 實(shí)例。(Grizzly Response會(huì)遭受同樣的限制。)
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);
容器擴(kuò)展模塊依賴要加入:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.21</version>
</dependency>
注意:通過測(cè)試框架, Jersey 使用 Grizzly 已經(jīng)廣泛的在項(xiàng)目單元和端到端進(jìn)行了測(cè)試。
Simple 是一個(gè)框架允許開發(fā)者創(chuàng)建 HTTP 服務(wù)器,并嵌入到應(yīng)用中。同樣的,通過從 jersey-container-simple-http 容器擴(kuò)展模塊調(diào)用工廠方法實(shí)現(xiàn)創(chuàng)建服務(wù)器實(shí)例。
Simple 的框架支持 HTTP 容器注入 Simple 框架特性 的org.simpleframework.http.Request 和 org.simpleframework.http.Response 實(shí)例到 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);
容器擴(kuò)展模塊依賴要加入:
<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 容器的能力(盡管我們?cè)谖覀兊臏y(cè)試和實(shí)例使用它),因?yàn)樽鳛榛?Servlet 部署模型并沒有什么特別,具體會(huì)在 第4.7節(jié),“基于 Servlet 部署”部分進(jìn)行描述。我們將在這里只重點(diǎn)描述如何使用 Jetty 的 HTTP 服務(wù)器。
Jetty HTTP 容器支持注入 Jetty 特性的org.eclipse.jetty.server.Request 和 org.eclipse.jetty.server.Response 實(shí)例到 JAX-RS 和 Jersey 應(yīng)用資源和供應(yīng)者。然而,由于 Jetty HTTP Request 是非代理性的,Jetty Request 的注入到單例(默認(rèn))的JAX-RS /和Jersey 提供者只可能通過 javax.inject.Provider 實(shí)例。(Jetty Response 會(huì)遭受同樣的限制。)
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);
容器擴(kuò)展模塊依賴要加入(譯者注:原文中依賴包有誤,這里做了更正):
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.21</version>
</dependency>
注意:Jetty HTTP 容器不支持部署在除了根路徑是 ("/")以外的上下文路徑。非根路徑的上下文路徑在部署中是被忽略的。
回顧之前的內(nèi)容,從《處理 JSON 和 XML》的源代碼,我們進(jìn)行了修改:
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)的實(shí)體。
MyResource.java
@Path("myresource")
public class MyResource {
/**
* 方法處理 HTTP GET 請(qǐng)求。返回的對(duì)象以"text/plain"媒體類型
* 給客戶端
*
* @return String 以 text/plain 形式響應(yīng)
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
/**
* 方法處理 HTTP GET 請(qǐng)求。返回的對(duì)象以"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 請(qǐng)求。返回的對(duì)象以"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");
// 注冊(cè) 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請(qǐng)去掉下面的注釋
// JdkHttpServerFactory.createHttpServer(URI.create(BASE_URI), new
// RestApplication());
// 若使用 Grizzly Http Server請(qǐng)去掉下面的注釋
// GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), new
// RestApplication());
// 若使用 Simple Http Server請(qǐng)去掉下面的注釋
// SimpleContainerFactory.create(URI.create(BASE_URI), new
// RestApplication());
// 若使用 Jetty Http Server請(qǐng)去掉下面的注釋
JettyHttpContainerFactory.createServer(URI.create(BASE_URI),
new RestApplication());
}
}
各種服務(wù)器的用法在上面已經(jīng)說了,這里就不再解析。
見 javase-rest
項(xiàng)目
更多建議: