如何使用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("old@test1");
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(0,"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(0,"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(0,"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;
}
}