一直对Restful风格的Web Service很感兴趣,正好项目中需要把一个服务包装成Restful服务,就尝试做了一把CRUD。
Restful服务的设计理念:服务的设计以系统资源为中心,而不是以服务的功能为中心。
(1)GET 用来获取集合资源或单个资源。
比如:GET http://www.store.com/products 获取所有商品;
GET http://www.store.com/products/
(2)POST 用来创建一个新资源。
比如:POST http://www.store.com/products 增加一个新商品。
注意,这里不能用型如 http://www.store.com/products/
(3)PUT 用来修改集合资源或单个资源。
比如:PUT http://www.store.com/products 修改所有商品;
PUT http://www.store.com/products/
(4)DELETE 用来删除集合资源或单个资源,与PUT的URI一样。
(5)GET、PUT 和 DELETE 方法是幂等的,POST方法则不是。
1. Employee.java
一个很简单的Java Bean,即有些人常说的Data Object,代码从略。
2. EmployeeServcie.java
所有操作Employee Data Object的服务都在这里,即有些人常说的Service Object,代码如下:
package restfulservice;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/employees")
public class EmployeeService {
private ArrayList
public EmployeeService() {
super();
employees.add(new Employee(3, "test3", 10, 100));
employees.add(new Employee(6, "test6", 10, 100));
employees.add(new Employee(9, "test9", 10, 100));
}
@POST
@Consumes( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response createEmployee(Employee emp) {
employees.add(emp);
return Response.ok(emp).build();
}
@PUT
@Path("{employeeId}")
@Consumes( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response upadteEmployee(@PathParam("employeeId")
int employeeId, Employee emp) {
deleteEmployeeByPathParam(employeeId);
createEmployee(emp);
return Response.ok(emp).build();
}
@PUT
@Consumes( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response upadteEmployees(Employee[] emps) {
deleteEmployees();
employees.addAll(Arrays.asList(emps));
return Response.ok(emps).build();
}
@DELETE
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response deleteEmployeeByQueryParam(@QueryParam("employeeId")
int employeeId) {
Employee emp = getEmployee(employeeId);
employees.remove(emp);
return Response.ok(emp).build();
}
@DELETE
@Path("{employeeId}")
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response deleteEmployeeByPathParam(@PathParam("employeeId")
int employeeId) {
Employee emp = getEmployee(employeeId);
employees.remove(emp);
return Response.ok(emp).build();
}
@DELETE
public void deleteEmployees() {
employees.clear();
}
@GET
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public ArrayList
return employees;
}
@GET
@Path("{employeeId}")
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Employee getEmployee(@PathParam("employeeId")
int employeeId) {
Iterator iter = employees.iterator();
while (iter.hasNext()) {
Employee emp = (Employee)iter.next();
if ((emp.getId()) == employeeId) {
return emp;
}
}
return null;
}
}
3. EmployeeClient.java
调用Restful服务的客户端,我还是费了些功夫的,注意CRUD的调用方式各有不同:
package restfulclient;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.LoggingFilter;
import javax.ws.rs.core.MediaType;
public class EmployeeClient {
public EmployeeClient() {
super();
}
private final static String restfulUrl = "http://localhost:7101/RestfulSample/jersey/employees";
public static void main(String[] args) {
System.out.println("\n***************************************** POST ****************************************");
Client client_post = Client.create();
WebResource resource_post = client_post.resource(restfulUrl);
resource_post.addFilter(new LoggingFilter());
String response_post = resource_post.type(MediaType.APPLICATION_XML).post(String.class, buildPostXml());
System.out.println("\n***************************************** PUT ONE ****************************************");
Client client_putOne = Client.create();
WebResource resource_putOne = client_putOne.resource(restfulUrl + "/1");
resource_putOne.addFilter(new LoggingFilter());
String response_putOne = resource_putOne.type(MediaType.APPLICATION_XML).put(String.class, buildPutXml());
System.out.println("\n******************************* DELETE ONE BY QUERY PARAMETER *********************************");
Client client_deleteOne = Client.create();
WebResource resource_deleteOne = client_deleteOne.resource(restfulUrl + "?employeeId=3");
resource_deleteOne.addFilter(new LoggingFilter());
resource_deleteOne.delete();
System.out.println("\n********************************** DELETE ONE BY PATH PARAMETER ******************************");
Client client_deleteOne2 = Client.create();
WebResource resource_deleteOne2 = client_deleteOne2.resource(restfulUrl + "/6");
resource_deleteOne2.addFilter(new LoggingFilter());
String response_deleteOne2 = resource_deleteOne2.type(MediaType.APPLICATION_XML).delete(String.class);
System.out.println("\n***************************************** GET ALL ****************************************");
Client client_getAll = Client.create();
WebResource resource_getAll = client_getAll.resource(restfulUrl);
resource_getAll.addFilter(new LoggingFilter());
resource_getAll.get(String.class);
resource_getAll.accept(MediaType.APPLICATION_JSON).get(String.class);
System.out.println("\n***************************************** GET ONE ****************************************");
Client client_getOne = Client.create();
WebResource resource_getOne = client_getOne.resource(restfulUrl + "/9");
resource_getOne.addFilter(new LoggingFilter());
resource_getOne.get(String.class);
resource_getOne.accept(MediaType.APPLICATION_JSON).get(String.class);
System.out.println("\n***************************************** PUT ALL ****************************************");
Client client_putAll = Client.create();
WebResource resource_putAll = client_putAll.resource(restfulUrl);
resource_putAll.addFilter(new LoggingFilter());
String response_putAll = resource_putAll.type(MediaType.APPLICATION_XML).put(String.class, buildPutsXml());
System.out.println("\n***************************************** DELETE ALL ****************************************");
Client client_deleteAll = Client.create();
WebResource resource_deleteAll = client_deleteAll.resource(restfulUrl);
resource_deleteAll.addFilter(new LoggingFilter());
resource_deleteAll.delete();
}
private static String buildPostXml() {
StringBuffer xml = new StringBuffer("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("\n");
return xml.toString();
}
private static String buildPutXml() {
StringBuffer xml = new StringBuffer("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("\n");
return xml.toString();
}
private static String buildPutsXml() {
StringBuffer xml = new StringBuffer("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("\n");
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("
xml.append("\n");
xml.append("\n");
return xml.toString();
}
}
4. 修改web.xml,增加com.sun.jersey.config.feature.Formatted参数,这样输出的XML内容是格式化的。
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.feature.Formatted</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Project 下载:RestfulSample.7z
最后再多说一句,什么时候用SOAP Web Service,什么时候用Restful Service?
简单来说,面向资源的服务使用Restful Web Service,面向功能的使用SOAP Web Service。
即如果想本例一样,都是对员工的CRUD,可以使用Restful Web Service;如果还有其它的操作,比如入职、离职,升迁,调岗等等,应该使用SOAP Web Service。
参考文献:
1. http://stackoverflow.com/questions/630453/put-vs-post-in-rest
2. http://zh.wikipedia.org/wiki/REST
3. http://www.infoq.com/cn/articles/understanding-restful-style?utm_source=infoq&utm_medium=popular_links_homepage
4. http://blog.csdn.net/zouzhile/article/details/5017347
5. http://www.restapitutorial.com/httpstatuscodes.html
5. http://www.restapitutorial.com/httpstatuscodes.html
没有评论:
发表评论