茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1658732 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
IMG_00026.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

爪哇咖啡屋 : [轉貼]Servlet simple Restful API

發表者 討論內容
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15766
[轉貼]Servlet simple Restful API

Servlet simple Restful API

Servlet實現Restful API簡單範例。

最近碰到沒用框架單用Servlet硬幹Restful API的老舊專案,已經好久沒碰Servet這Java Web底層的東西,所以試驗一下。

範例環境:

  • Eclipse
  • Java 1.8
  • Servlet 4.0
  • Maven

首先使用 maven-archetype-webapp建立一個Maven Web專案 servlet-demo。context path預設為專案名稱。

WEB-INF/web.xml設定 DemoServlet<servlet-mapping>,將context path下 /demo開頭的請求都導向給 DemoServlet處理。

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>Servlet Web Application</display-name>
<servlet>
<servlet-name>DemoServlet</servlet-name>
<servlet-class>com.abc.demo.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DemoServlet</servlet-name>
<url-pattern>/demo/*</url-pattern>
</servlet-mapping>
</web-app>


建立 DemoServlet繼承 HttpServlet,負責處理請求的Restful API。

DemoServlet


package com.abc.demo;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import com.abc.demo.dto.ApiResposne;
import com.abc.demo.dto.EmployeeDto;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public DemoServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String pathInfo = request.getPathInfo();
if (StringUtils.isEmpty(pathInfo)) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "";
PrintWriter writer = response.getWriter();
if ("/employee".equalsIgnoreCase(pathInfo)) {
EmployeeDto employeeDto = new EmployeeDto(1L, "john", "john@abc.com", 28);
ApiResposne apiResposne = new ApiResposne("success", employeeDto);
jsonString = objectMapper.writeValueAsString(apiResposne);
writer.write(jsonString);
return;
}
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}


DemoServlet.doGet()程式中用到的值類別。

EmployeeDto


package com.abc.demo.dto;
public class EmployeeDto {
private Long id;
private String name;
private String email;
private Integer age;
public EmployeeDto(Long id, String name, String email, Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
// getters and setters
}


ApiResposne


package com.abc.demo.dto;
public class ApiResposne {
private String message;
private Object data;
public ApiResposne(String message, Object data) {
this.message = message;
this.data = data;
}
// getters and setters
}


以上邏輯建立的API為 GET|/demo/employeedoGet()是用來處理HTTP GET請求的方法。若url輸入正確會把 EmployeeDto轉為json字串回應出去。

設定完以上後啟動專案。

使用Postman測試,在url欄位使用 GET,位址輸入 http://localhost:8080/servlet-demo/demo/employee送出請求。

回應結果如下。


{"message":"success","data":{"id":1,"name":"john","email":"john@abc.com","age":28}}


參考 github



原文出處:菜鳥工程師 肉豬: Servlet simple Restful API
*/
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15766
[轉貼]用 Java 技術創建 RESTful Web 服務

用 Java 技術創建 RESTful Web 服務/@Path@Produces@PathParam

用 Java 技術創建 RESTful Web 服務

2018-01-14 254
對象實例 web 位置 nta pro devel util iter ali

簡介

JAX-RS (JSR-311) 是為 Java EE 環境下的 RESTful 服務能力提供的一種規範。它能提供對傳統的基於 SOAP 的 Web 服務的一種可行替代。

在本文中,了解 JAX-RS 的主要組件。本文用一個例子展示了一個企業如何使用 JAX-RS 內的功能以一種 Restful 的方式公開員工的聯系信息。

背景

多年來,開發人員使用各種工具在其 Java 應用程序內創建 RESTful 服務。由於 REST 架構的簡單性,主要需求 — 接收 HTTP 消息和頭部的能力 — 可以由一個簡單的 Java Web 容器實現。

Java servlets 常被用來開發 RESTful 應用程序。如何使用 servlet 並沒有固定的模式。通常,servlet 會接受請求並自己解析這個 HTTP 請求 URI,以將此請求與一個已知資源相匹配。對於 REST 服務開發,這個簡單的 servlet 模型以更為正式的 API 得到擴展。但是,因為這些 API 是在 servlet 模型之上開發的,所以這些 API 中沒有一個是作為正式的標準開發的。


隨著 REST 越來越多地被采用為一種架構,Java Community Process (JCP) 計劃在未來的 Java Enterprise Edition 6 發布版中包括對 REST 的正式支持。JSR-311 也已創建好,並已有了 JAX-RS 1.0 規範,提供了一種新的基於註釋的方式來開發 RESTful 服務。與 servlet 模型相比,JAX-RS 註釋讓您能集中於您的資源和數據對象。並且,您不必再開發通訊層(通過 servlet)。

Java 資源

JAX-RS 建立了一種特殊的語言來描述資源,正如由其編程模型所表示的。有五種主要條目:根資源、子資源、資源方法、子資源方法以及子資源定位器。

根資源

根資源是由 @Path 註釋的 Java 類。 @Path 註釋提供了一個 value 屬性,用來表明此資源所在的路徑。 value 屬性可以是文本字符、變量或變量外加一個定制的正則表達式。清單 1 給出了一個例子。


清單 1. JAX-RS 根資源



package com.ibm.jaxrs.sample.organization;
import javax.ws.rs.Path;
@Path(value="/contacts")
public class ContactsResource {
...
}

子資源

子資源是作為 subresource locator 調用的結果返回的 Java 類。它們類似於根資源,只不過它們不是由 @Path 註釋的,因它們的路徑是由子資源定位器給出的。子資源通常包含由 HTTP 請求方法指示符(designator)註釋的方法以便服務此請求。如果它們不包含如此註釋的方法,那麽它們將會通過指派給合適的子資源定位器來進一步解析此資源處理請求。


清單 2. JAX-RS 子資源



package com.ibm.jaxrs.sample.organization;
import javax.ws.rs.GET;
public class Department {
@GET
public String getDepartmentName() {
...
}
}

如上所示的清單 2 展示了由 ContactsResource.getContactDepartment 方法返回的子資源。在這個例子中,如果一個 HTTP GET 請求被發送給 /contact/{contactName}/department 路徑,那麽 Department 子資源內的 getDepartmentName 資源方法就會處理此請求。

資源方法

資源方法是根資源或子資源內綁定到 HTTP 方法的 Java 方法。綁定是通過諸如 @GET 這樣的註釋完成的。


清單 3. JAX-RS 資源方法



package com.ibm.jaxrs.sample.organization;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path(value="/contacts")
public class ContactsResource {
@GET
public List<ContactInfo> getContacts() {
...
}
}

在清單 3 的例子中,發送到 /contacts 路徑的 HTTP GET 請求將會由 getContacts() 資源方法處理。

子資源方法

子資源方法非常類似於資源方法;惟一的區別是子資源方法也是由 @Path 註釋的,此註釋進一步限定了該方法的選擇。


清單 4. JAX-RS 子資源方法



package com.ibm.jaxrs.sample.organization;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path(value="/contacts")
public class ContactsResource {
@GET
public List<ContactInfo> getContacts() {
...
}
@GET
@Path(value="/ids")
public List<String> getContactIds() {
...
}
}

在清單 4 中,發送到 /contacts/ids 路徑的 HTTP GET 請求將會由 getContactIds() 子資源方法處理。

子資源定位器

子資源定位器是能進一步解析用來處理給定請求的資源的一些方法。它們非常類似於子資源方法,因它們具備一個 @Path 註釋,但不具備 HTTP 請求方法指示符,比如 @GET 註釋。


清單 5. JAX-RS 子資源定位器



package com.ibm.jaxrs.sample.organization;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@Path(value="/contacts")
public class ContactsResource {
@GET
public List<ContactInfo> getContactss() {
...
}
@GET
@Path(value="/ids")
public List<String> getContactIds() {
...
}
@Path(value="/contact/{contactName}/department")
public Department getContactDepartment(@PathParam(value="contactName")
String contactName) {
...
}
}

在上述例子中,對 /contact/{contactName}/department 路徑的任何 HTTP 請求都將由 getContactDepartment 子資源定位器處理。 {contactName} 部分表明 contact 路徑部分之後可以是任何合法的 URL 值。

註釋

本節將會探討一些重要的註釋及其使用。對於由 JAX-RS 規範提供的註釋的完整列表,可以參考本文的 參考資料 部分給出的 JSR-311 鏈接。

@Path

@Path 註釋被用來描述根資源、子資源方法或子資源的位置。 value 值可以包含文本字符、變量或具有定制正則表達式的變量。清單 6 的例子展示了 @Path 註釋的主要應用。


清單 6. @Path 的使用



package com.ibm.jaxrs.sample.organization;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@Path(value="/contacts")
public class ContactsResource {
@GET
@Path(value="/{emailAddress:+\\.[a-z]+}")
public ContactInfo getByEmailAddress(@PathParam(value="emailAddress")
String emailAddress) {
...
}
@GET
@Path(value="/{lastName}")
public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) {
...
}
}

ContactsResource 類上的註釋表明對 /contacts 路徑的所有請求都將由 ContactsResource 根資源處理。 getByEmailAddress 上的 @Path 註釋則表明任何發送到 /contacts/{emailAddress} 的請求(其中 emailAddress 代表的是正則表達式 [email protected]+\\.[a-z]+)都將由 getByEmailAddress 處理。

getByLastName 方法上的 @Path 註釋指定了發送到 /contacts/{lastName} 路徑的所有請求(其中 lastName 代表的是一個與 getByEmailAddress 內的正則表達式不匹配的有效的 URL 部分)都將由 getByLastName 方法處理。

@GET、@POST、@PUT、@DELETE、@HEAD

@GET、@POST、@PUT、@DELETE 以及 @HEAD 均是 HTTP 請求方法指示符註釋。您可以使用它們來綁定根資源或子資源內的 Java 方法與 HTTP 請求方法。HTTP GET 請求被映射到由 @GET 註釋的方法;HTTP POST 請求被映射到由 @POST 註釋的方法,以此類推。用戶可能還需要通過使用 @HttpMethod 註釋定義其自己的定制 HTTP 請求方法指示符。


清單 7. 定制的 HTTP 請求方法指示符註釋



package com.ibm.jaxrs.sample.organization;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.ws.rs.HttpMethod;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@HttpMethod("GET")
public @interface CustomGET {
}

上述的聲明定義了 @CustomGET 註釋。此註釋將具有與 @GET 註釋相同的語義值並可用在其位置上。

@Conumes 和 @Produces

@Consumes 註釋代表的是一個資源可以接受的 MIME 類型。 @Produces 註釋代表的是一個資源可以返回的 MIME 類型。這些註釋均可在資源、資源方法、子資源方法、子資源定位器或子資源內找到。


清單 8. @Consumes/@Produces



package com.ibm.jaxrs.sample.organization;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@Path(value="/contacts")
public class ContactsResource {
@GET
@Path(value="/{emailAddress:[email protected]+\\.[a-z]+}")
@Produces(value={"text/xml", "application/json"})
public ContactInfo getByEmailAddress(@PathParam(value="emailAddress")
String emailAddress) {
...
}
@GET
@Path(value="/{lastName}")
@Produces(value="text/xml")
public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) {
...
}
@POST
@Consumes(value={"text/xml", "application/json"})
public void addContactInfo(ContactInfo contactInfo) {
...
}
}

對於上述的 getByEmailAddressaddContactInfo 方法,它們均能處理 text/xmlapplication/json。被接受或返回的資源表示將依賴於客戶機設置的 HTTP 請求頭。 @Consumes 註釋針對 Content-Type 請求頭進行匹配,以決定方法是否能接受給定請求的內容。

在清單 9 中, application/jsonContent-Type 頭再加上對路徑 /contacts 的 POST,表明我們的 ContactsResource 類內的 addContactInfo 方法將會被調用以處理請求。


清單 9. Content-Type 頭部的使用



POST /contacts HTTP/1.1
Content-Type: application/json
Content-Length: 32

相反地, @Produces 註釋被針對 Accept 請求頭進行匹配以決定客戶機是否能夠處理由給定方法返回的表示。


清單 10. Accept 頭部的使用



GET /contacts/[email protected]HTTP/1.1
Accept: application/json

在清單 10 中,對 /contacts/ [email protected] 的 GET 請求表明了 getByEmailAddress 方法將會被調用並且返回的格式將會是 application/json,而非 text/xml。

Providers

JAX-RS 提供程序是一些應用程序組件,允許在三個關鍵領域進行運行時行為的定制:數據綁定、異常映射以及上下文解析(比如,向運行時提供 JAXBContext 實例)。每個 JAX-RS 提供程序類必須由 @Provider 註釋。如下的例子討論了兩個數據綁定提供程序 MessageBodyWriterMessageBodyReader

MessageBodyWriter

MessageBodyWriters 被 JAX-RS 運行時用來序列化所返回資源的表示。遵從 JSR-311 的運行時提供了對常見類型(java.lang.String、java.io.InputStream、 JAXB 對象等)的本機支持,但用戶也可以向 JAX-RS 運行時提供他或她自己的 MessageBodyWriter。比如,您可以提供一個定制 MessageBodyWriter 來處理定制 ContactInfo Java 類型,如下所示。


清單 11. 定制 MessageBodyWriter



package com.ibm.jaxrs.sample.organization;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
@Provider
@Produces("text/xml")
public class ContactInfoWriter implements MessageBodyWriter<ContactInfo> {
public long getSize(T t, java.lang.Class<ContactInfo> type,
java.lang.reflect.Type genericType, java.lang.annotation.Annotation[]
annotations, MediaType mediaType) {
...
}
public boolean isWriteable(java.lang.Class<ContactInfo> type,
java.lang.reflect.Type genericType, java.lang.annotation.Annotation[]
annotations, MediaType mediaType) {
return true;
}
public void writeTo(ContactInfo contactInfo, java.lang.Class<ContactInfo> type,
java.lang.reflect.Type genericType, java.lang.annotation.Annotation[]
annotations, MediaType mediaType, MultivaluedMap<
java.lang.String, java.lang.Object> httpHeaders, java.io.OutputStream
entityStream) {
contactInfo.serialize(entityStream);
}
}

ContactInfoWriter 則在所返回的資源表示被序列化之前由 JAX-RS 運行時調用。如果 isWriteable 返回 true 且 @Produces 是此資源方法的 @Produces 值最為接近的匹配,就會調用 writeTo 方法。在這裏, ContactInfoWriter 負責向底層的 OutputStream 序列化 ContactInfo 實例的內容。

MessageBodyReader

MessageBodyReaders 則與 MessageBodyWriters 相反。對於反序列化,JAX-RS 運行時支持與序列化相同的類型。用戶也可以提供他或她自己的 MessageBodyReader 實現。MessageBodyReader 的最主要的功能是讀取請求 InputStream 並將傳入的字節反序列化到一個此資源方法期望的 Java 對象。 ContactInfo 類型的 MessageBodyReader 可以類似於清單 12。



package com.ibm.jaxrs.sample.organization;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
@Provider
@Consumes("text/xml")
public class ContactInfoReader implements MessageBodyReader<ContactInfo> {
public boolean isReadable(java.lang.Class<ContactInfo> type,
java.lang.reflect.Type genericType, java.lang.annotation.Annotation[]
annotations, MediaType mediaType) {
return true;
}
public ContactInfo readFrom(java.lang.Class<ContactInfo> type,
java.lang.reflect.Type genericType, java.lang.annotation.Annotation[]
annotations, MediaType mediaType, MultivaluedMap<
java.lang.String,java.lang.String> httpHeaders, java.io.InputStream
entityStream) {
return ContactInfo.parse(entityStream);
}
}


與 MessageBodyWriter isWriteable 類似, ContactInfoReaderisReadable 方法將被調用以便決定 MessageBodyReader 能否處理此輸入。如果 isReadable 返回 true 且 @Consumes 值與此資源方法的 @Consumes 值最為匹配,就會選擇 ContactInfoReader。當 readFrom 方法被調用時,結果會是基於請求 InputStream 的內容創建 ContactInfo 實例。

配置

至此,我們探討了 JAX-RS 資源類和一些提供程序類(MessageBodyReaders 和 MessageBodyWriters)。那麽,該如何在 JAX-RS 運行時內配置這些類呢?這可以通過擴展 javax.ws.rs.core.Application 類實現。此類提供了一組類或一組單例(singleton)對象實例,在一個 JAX-RS 應用程序內包括所有的 根級別的資源和提供程序(由 @Provider 註釋的類)。若為這個示例聯系信息應用程序擴展這個 Application 類,它應該類似於清單 13。


清單 13. ContactInfoApplication



package com.ibm.jaxrs.sample.organization;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class ContactInfoApplicaiton extends Application {
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSetSet<Class<?>>();
classes.add(ContactsResource.class);
classes.add(ContactInfoWriter.class);
classes.add(ContactInfoReader.class);
}
public SetSet<Object<?>> getSingletons() {
// nothing to do, no singletons
}
}

getClasses 方法為 JAX-RS 運行時提供了一組可用於元數據的類。請註意, getSingletons 方法什麽都不返回。通常而言,將 JAX-RS 提供程序視為單例是沒有問題的,但將一個 JAX-RS 資源視為單例則要格外謹慎。常被 JAX-RS 資源類使用的基於註釋的註入可能在一個單例實例的情況內並不受支持。因此,除非仔細計劃,否則應該避免使用 JAX-RS 資源的單例實例。

假設,您正在一個 servlet 容器內部署一個 JAX-RS 應用程序,有兩種方法可以向 JAX-RS 運行時註冊您的 javax.ws.rs.core.Application 子類。這是由 WAR 文件的 web.xml 處理的,如下所示。


清單 14. 不能感知 JAX-RS 的 servlet 容器



<web-app id="WebApp_ID" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>ContactInfoServlet</servlet-name>
<servlet-class>com.sample.RESTSystemServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>
com.ibm.jaxrs.sample.organization.ContactInfoApplication
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ContactInfoServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

在一個被認為是不能感知 JAX-RS 的 servlet 容器內,應該作為 servlet 定義內的 init-param 提供 Application 子類名。init-param 的名字必須是 javax.ws.rs.Application。servlet 類則很可能是 JAX-RS 運行時系統 servlet。您可以列出每個可能的 URL 模式,或者使用 /* 通配符註冊,如下所示。


清單 15. 能感知 JAX-RS 的 servlet 容器



<web-app id="WebApp_ID" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>ContactInfoServlet</servlet-name>
<servlet-class>
com.ibm.jaxrs.sample.organization.ContactInfoApplication
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContactInfoServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

在一個被認為是能感知 JAX-RS 的 servlet 容器內,必須作為 servlet 定義內的 servlet 類元素的值提供 Application 子類名。您仍然可以選擇是列出每個可能的 URL 模式還是使用 /* 通配符註冊。

以 Apache Wink 作為運行時的 JAX-RS

下一步是找到一個能夠支持 JAX-RS 內的可用功能的運行時。Apache Wink 項目就提供了一個能滿足這種要求的運行時,具有上面所述的所有特性(參見 參考資料)。起初,Wink 是由開源社區的多個廠商和成員發起的一個協作項目。該項目的目的是提供最為靈活和輕量級的運行時。

除了標準 JAX-RS 特性之外,Wink 還提供了對 JSON、Atom 和 RSS 序列化格式的增強支持。JAX-RS 本身並不提供客戶機 API,但 Wink 包括了其對客戶機 API 的自身模型,並且是完全以資源為中心的。

為了簡化基於 Wink 的服務的開發,可以下載 Wink 1.0 庫並將它們作為默認 JAX-RS 庫包括到 Rational Application Developer (RAD) 7.5.5 開發環境(參見 參考資料)中。在這個更新版本中,RAD 添加了一個 JAX-RS facet,可供您進行配置以支持驗證器和註釋幫助。這個新的 facet 還能通過自動生成所需的 servlet 項和映射來簡化 servlet 的配置。

結束語

與傳統的 servlet 模型相比,JAX-RS 提供了一種可行的、更為簡便、移植性更好的方式來在 Java 內實現 RESTful 服務。使用註釋讓您能夠輕松提供 Java 資源的路徑位置並將 Java 方法綁定到 HTTP 請求方法。一種可移植的數據綁定架構提供了一些本機的 Java 類型支持並允許進行序列化/反序列化處理的完全定制。javax.ws.rs.core. Application 子類的擴展以及 web.xml 內的相應清單表明了用最少的部署描述符配置就能進行輕松部署。


本文只涉及了 JAX-RS 所能提供功能的一部分。就提供應用程序上下文(比如 JAXBContext 實例)並將運行時異常映射給 HTTP 請求而言,其他兩個 JAX-RS 提供程序類型 ContextResolversExceptionMappingProviders 還能提供對應用程序組件的進一步控制。註釋的定義是為了控制方法參數和類成員的註入,它們在運行時的整個過程向應用程序提供了有價值的上下文信息。總的來說,JAX-RS 必將是一種面向基於 Java 的 RESTful 服務開發的簡便、可移植的、全面的 API。

用 Java 技術創建 RESTful Web 服務/@ [email protected]@PathParam


原文出處: 用 Java 技術創建 RESTful Web 服務/@Path@Produces@PathParam - IT閱讀
*/
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15766
[轉貼]三步驟打通關節開發 API 後端服務

三步驟打通關節開發 API 後端服務

林彥成
2018-04-05 | 5 min.
文章目錄
  1. 1. Java Web Appication 相關資源
    1. 1.1. 語法教學資源
    2. 1.2. 相關 Framework 學習
    3. 1.3. IDE (Integrated Development Environment) 選擇
  2. 2. 打通三個關節開發 API 後端服務
    1. 2.1. 創建 Java Web Appication
    2. 2.2. 透過 Jersey RESTful Service 寫入資料庫
      1. 2.2.1. 什麼是 JNDI
      2. 2.2.2. 資料物件名詞 (取名主要用來辨識關係)
      3. 2.2.3. @標註

這篇文章會示範從 0 到 1 打造一個網站應用程式,並整理 Java Web Appication 相關資源如基礎建設、前端網頁、後端 Web API 及資料庫。

Java Web Appication 相關資源

一個 Java Web Appication 分成前端、後端及資料庫。


前端網頁(網址) <–Q1–> RESTful Web Service <–Q2–> Web 伺服器 <–Q3–> 實體資料庫

需打通的關節分三個方面,

  1. 建立 Java Web Appication 並提供 RESTful Web Service
  2. 透過 War 檔發佈至容器: 將程式發佈至伺服器供前端存取
  3. 讓撰寫的 RESTful Web Service 存取實體資料庫

語法教學資源

Coding Conventions,推薦撰寫方式及風格上的統一,用意在於方便閱讀及增進效能。

語法教學資源

OpenSource 平台

JDK 多版本管理工具,方便在同樣的機器上使用多版本 Java

相關 Framework 學習

IDE (Integrated Development Environment) 選擇

這篇附上 Eclipse 的相關快捷鍵,另外建議自動完成須更改一下設定,讓鍵入每一字的時候都可以出現。設定位置在 Window → Preferences → Java → Editor → Content Assist,Auto activation triggers for Java 為 IDE 遇到何種字元會自動啟動提示,請改為 .abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(,;,就會遇到什麼字元都自動提示惹。


快捷鍵功能
Ctrl+Shift+TOpening a class
Ctrl+Shift+ROpening a Resourse
F3 or ctrl+mouse clickgo into a class
Ctrl+OQuick Outline
Ctrl+HSearch menu
Ctrl+JIncremental Find
Ctrl+Shift+/全部收合
Ctrl+*全部展開
Ctrl+Shift+F自動排版

打通三個關節開發 API 後端服務

系統配置上 Java 也有三種,依照需求會選用不同版本,如下:

  • SE(Standard Edition)
  • ME(MicroEdition)
  • EE(Enterprise Edition)

介紹文連結( http://www.codedata.com.tw/book/java-basic/index.php?p=ch1-2

開工前,請先下載 JDK (Java Development Kit),從翻譯來看就是開發工具組,JDK 中就包含 JRE (Java Runtime Environment),有 JRE Java 程式就可以執行了。記得設環境變數,讓電腦找到工具組!!! 不然就!!! 什麼事都不會發生 XD


因為要寫 Web 應用,所以選擇 Java EE,下面是 EE 肚子裡裝 der 東西 XDDD

創建 Java Web Appication

首先!建立 Dynamic Web Project 並選擇 Runtime Server

可勾選自動生成 Web.xml ,或是自己輸入。

  • 目標: 利用 Jersey 這個 Framework 實做功能並發佈到湯姆貓上, 未使用自動建構工具前,需自行下載 Library 並放進 WebContent/Web-INF/lib 資料夾裡,這是 War 檔中固定的架構勿更改。

  • 實作: 新增相關 class,並按照範例寫作,可依照這篇提供的範例 ( http://www.vogella.com/tutorials/REST/article.html ),做到第六章即可。

完成之後我們就一次打通了 Q1 及 Q2 了 ╰( ̄︶ ̄)╯

前端網頁(網址) <—Q1—> RESTful Web Service <—Q2—> Web 伺服器

A1:利用 Jersey 寫出 RESTful Web Service

A2:JBoss 可利用 Export War 檔,將檔案發佈至 Server

透過 Jersey RESTful Service 寫入資料庫

現在剩下最後一個 Q3 惹!!!!!!!!!!

Web 伺服器 <—Q3—> 實體資料庫

Q3:如何讓撰寫的 RESTful Web Service 存取實體資料庫?
A3:複習 Java 連接 MySQL 的練習,並整合進 RESTful Service 中。

按照以下範例:

10
}

為了避免一些問題,可以參考廣為流傳的設計模式,像是 Singleton Design

設計模式,提供了大家程式架構的參考,在 這範例中的 ArticleDao,就有用到 Singleton 的概念,就是單一個 Instance。

Singleton 模式可以保證一個類別只有一個 Instance。

20
}

其他地方則透過
ArticleDao.instance.getModel().values() 來叫用內部資料。底下簡單示範了怎麼從 sqlite 中撈出 thing 中的所有資料。

50

什麼是 JNDI

JNDI (Java Naming and Directory Interface ),看了一陣子原文介紹之後,真心覺得發明一堆奇怪的名詞的目的在於!!!讓人覺得自己很蠢,導致會覺得作者很猛 XDDD 然後留一個小難跨過的 Gap,來讓知識不普及 XDDD

譬如當我們想搞一個後端資料連結用的服務,那顯然需要把他配置到你的 Server 上,同時也會需要一個 JNDI name ,接著這個 JNDI Name 跟 interface 就都會被註冊到 JNDI Service。

當 Client 程式在執行時,要先去找 (lookup()) 到一個後端資料連結的 interface ,如果小幸運找到在 JNDI Service 裡面,這時候 JNDI Service 會回給你一個 remote 的 reference ,取得的這個 remote reference 是一個 Object ,有了這個 Object ,你就可以用它做你想做的事情,譬如去得到一個後端連結(getConnection)…

所以簡單來說,雖然是你做你的我做我的,不過出一張嘴的才是算數的,反正最後給我弄出這樣那樣的 OOO 讓我可以用就好,然後打雜小弟就可以開始努力實做出各種來提供,後人也就不用了解像是帳號密碼 IP 位置或是 Driver 去哪下載惹。

資料物件名詞 (取名主要用來辨識關係)

  1. POJO (pure old java object)

10
}
  1. DAO (data access objects)
    主要配合資料庫
  2. PO (persistant object)
    Hibernate example: 當 POJO 被實體化(instance) 有 set 值,接著進入 session 後。
  3. DTO(data transfer object)
    POJO 永久化成 PO,PO 組合成 DTO。
  4. JavaBean
    POJO 可序列化,有一個無參數的建構子,使用 getter 和 setter 方法來訪問屬性。
  5. XML,JSON
    都是 Web 常用的傳輸格式。

現況:表中有 100 個欄位,則相對應的 PO 有 100 個屬性。
情境:界面上只需顯示 10 個欄位。
實作:Client 向服務端取值,服務端不需傳全部的 PO,此時將只有 10 個屬性及傳遞的參數組成 DTO 來傳遞結果。

Hibernate
操作物件就可以完成讀寫資料庫,是一個結合 JDBC 和物件的 Framework。

@標註

主要就是對程式碼加些@標註,給人看也給機器讀。之前看過的 @Override 就是內建的一個標註,就是要進行 parent 函數覆寫的意思,@Deprecated 被標注的方法或類型已不再推薦使用。

用在其他 Annotation 上的 Annotation

  1. @Retention: 確定標註的生命周期, 用一個 Enum 的 RetentionPolicy 參數設定
  2. @Documented: 文檔化
  3. @Target: 表示標註適用的範圍,也用 Enum 的 EnumType 的參數設定
  4. @SessionScope
  5. @Inject: 針對資料的標註,@JsonProperty 改變 JSON 名稱

4
}

自訂標註則需要用到 @interface,不同於 interface,這次使用的是@interface

3
}

按照上面這樣撰寫後,其他地方就可以使用 @Test 做為自定標註了。

下一篇文章我們會介紹如何 如何使用 Jersey 這套框架來開發 RESTful Web services


原文出處:Java Web API (RESTful API) 教學: 三步驟打通關節開發 API 後端服務 | 前端三分鐘 | 一起用三分鐘分享技術與知識 | 林彥成
前一個主題 | 下一個主題 | 頁首 | | |



Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|