如何使用RestFul
下表來自wiki說得很清楚,GET一般用于查詢,POST一般用于建立,PUT用于update(如無則建立),DELETE使用者删除。POST和PUT的不同在于,調用兩次POST則建立兩個資源,而調用兩次PUT,仍關聯一個資源。
Uniform Resource Locator (URL) | GET | POST | PUT | DELETE |
---|---|---|---|---|
Collection, such as http://api.example.com/resources/ | List the URIs and perhaps other details of the collection’s members. | Replace the entire collection with another collection. | Create a new entry in the collection. The new entry’s URI is assigned automatically and is usually returned by the operation. | Delete the entire collection. |
Element, such as http://api.example.com/resources/item17 | Retrieve a representation of the addressed member of the collection, expressed in an appropriate Internet media type | Replace the addressed member of the collection, or if it does not exist, create it. | Not generally used. Treat the addressed member as a collection in its own right and create a new entry in it. | Delete the addressed member of the collection. |
Java中使用RestFul
RestFul是個web接口,是以在J2EE中使用。Spring含有對RestFul的支援,但此處,我們隻讨論普通情況下如何實作Restful。
pom:關聯的jar包
<!-- 導入Bundles,可以替代Part1部分
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>2.23.2</version>
</dependency>
-->
<!-- Part 1 -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.23.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.23.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.23.2</version>
</dependency>
<!-- Part 2:支援Json格式 ,否則會報: MessageBodyWriter not found for media type=application/json ... 的錯誤 -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.23.2</version>
</dependency>
<!-- Part 3:支援複雜的Json格式翻譯,例如Map<K,E>,當然我們也可以使用Gson -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.23.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.1</version>
</dependency>
<!-- Part 4: 支援XML格式,否則會報MessageBodyWriter not found for media type=application/xml....-->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-xml-provider</artifactId>
<version>2.8.1</version>
</dependency>
web.xml
在web.xml中,需要加入以下内容。作用也很容易了解,需要在啟動時加載javax.ws.rs.core.Application,對應路徑為/rest/*。Jaxrs通過javax.ws.rs.core.Application這個servlet,關聯到對應的Restful接口
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
GET的小例子:text,json,xml三種輸出格式
@Path("/hello") //本類的Result路徑為/rest/hello/*(結合web.xml),如果直接在rest下面,可以用@path("/")
public class MyService0 {
private final String ROOT_NODE = "root";
//-----------例子1:傳回text ----------
@GET //這是Restful中的GET方法
@Path("/text") //路徑為/rest/hello/text
@Produces(MediaType.TEXT_PLAIN) //response的ContentType為text/plain
public String getHelloWorld() { 因為輸出是text/plain,是以傳回一個String,經過測試,即使有toString(),也不能是其他類型
return "Hello, my frist RESTFul Test";
}
//-----------例子2:傳回Json,JAXBElement<String>格式 ----------
@GET
@Path("/json")
@Produces(MediaType.APPLICATION_JSON)
public JAXBElement<String> getHelloWorldJSON() {
JAXBElement<String> result = new JAXBElement<String>(
new QName("",ROOT_NODE), String.class, "Hello,JSR!");
return result;
}
//-----------例子3:URL帶參數,傳回Json,直接對象格式 ----------
@GET
@Path("/json/user/{id}")
@Produces(MediaType.APPLICATION_JSON)
public User getMe(@PathParam("id") String id) {
User user = new User();
user.setId(id);
user.setName(id + "-Test");
user.setEmail(id + "@hello");
return user;
}
//-----------例子4:URL帶參數,傳回XML格式 ----------
@GET
@Path("/xml/user/{id}")
@Produces(MediaType.APPLICATION_XML)
public User getUserInXML(@PathParam("id") String id) {
User user = new User();
user.setId(id);
user.setName(id + "-TestXML");
user.setEmail(id + "@XML");
return toReturn;
}
}
POST,PUT,DELETE
從程式設計來講,和GET沒有什麼差別,都是從URL中獲得參數,根據需要傳回text,json或者xml,知道如何擷取參數和傳回結果,在程式設計上沒有差別,但是在使用上請看最前的表格說明,什麼情況下該用什麼。
@Path("/test1")
public class MyService1 {
//從結果看,Map适合模拟PUT的方式,對應的Vector适合模拟POST方式
private static final Map<String,User> dbMap = new HashMap<>();
private static final Vector<User> dbVector = new Vector<>();
//為實驗用,預先存放内容在dbMap中
static{
User user= new User();
user.setId("old");
user.setEmail("[email protected]");
user.setName("test1.old");
dbMap.put(user.getId(), user);
}
//【例子1.1】通過POST建立一個User,并存放在dbVector中
//請求消息中帶有消息體,消息體是json格式(@consumes),翻譯存放在user參數中。
@POST
@Path("/json/user/add")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Result addUser(User user) {
dbVector.add(user);
return new Result(,"OK");
}
//【例子1.2】讀取dbVector的内容
@GET
@Path("/json/user")
@Produces(MediaType.APPLICATION_JSON)
public Vector<User> showUser() {
return dbVector;
}
//【例子2.1】通過PUT的方式,就要Id,建立或者更新一個使用者
@PUT
@Path("/json/user/update")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Result updateUser(User user) {
dbMap.put(user.getId(), user);
return new Result(,"OK");
}
//【例子2.2】通過DELETE,參數某ID的使用者
@DELETE
@Path("/json/user/delete/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Result deleteUser(@PathParam("id") String id) {
System.out.println("delete : id = " + id);
dbMap.remove(id);
return new Result(,"OK");
}
//【例子2.3.1】通過GET,使用Gson,來讀取dbMap
@GET
@Path("/json/userdb1")
@Produces(MediaType.APPLICATION_JSON)
public String showUser1() {
Gson g = new Gson();
return g.toJson(dbMap);
}
//【例子2.3.2】通過GET,來讀取dbMap,在pom中需要加上part3,相對而言,我覺得Gson更為簡潔。
@GET
@Path("/json/userdb2")
@Produces(MediaType.APPLICATION_JSON)
public Map<String,User> showUser2() {
return db;
}
}