Restlet 2.0 边学边写(五)Restlet的POST、PUT和DELETE
程序员文章站
2022-07-12 19:03:02
...
上一次实践是将Restlet与spring集成,本次实践是将实现POST、PUT和DELETE方法。
参考:[url]http://ajaxcn.iteye.com/blog/417596[/url]
[b]1.pojo[/b]
在com.sunny.restlet.order包下创建Customer类,代码如下:
类定义了Customer的属性、构造方法和toString()方法。
[b]2.Dao[/b]
修改com.sunny.restlet.order.OrderDao接口,代码如下:
接口中定义了对Customer的增删改查方法。
修改com.sunny.restlet.order.OrderDaoImpl类,代码如下:
接口中实现了对Customer的增删改查方法,并使用一个HashMap来模拟数据的持久化,新增Customer的key就是HashMap的size。
[b]3.CustomerResource[/b]
接下来要修改com.sunny.restlet.order.CustomerResource类,重写父类ServerResource中的post/put/delete/get方法,代码如下:
类中的post/put/delete/get方法分别对应POST/PUT/DELETE/GET请求。Restlet会自动根据请求类型不同来调用各自对应的方法。其中PUT/DELETE/GET请求需要custId参数,该参数从RequestURI的属性中获得;POST/PUT请求需要Customer数据,数据被封装在Representation entity中,通过Form类来读取。
方法中的处理结果都通过StringRepresentation来返回给调用者。
[b]注[/b]:我们删除了类变量customerId,改成了方法变量。因为在spring配置文件中,我们将CustomerResource bean定义为singleton单例模式,所有请求共用一个CustomerResource实例来提供服务。而单例模式中的类变量相当于static静态变量,后到的请求可能会修改前面请求中的customerId的值,导致运行参数错误,所以将customerId移至各方法中获取。同样,doInit()方法也不需要自行实现了。
[b]4.测试页面[/b]
我们可以通过页面测试一下各个方法能否正常工作。
修改WebRoot/下的index.jsp,代码如下:
页面中定义了一个html form,将name和address属性通过POST方式提交。
[b]5.运行[/b]
重新部署程序后,通过浏览器访问[url]http://localhost:8080/firstSteps/[/url]可以看到页面和表单。填入name和address信息,如图所示。
[img]http://dl.iteye.com/upload/attachment/0078/4359/d247bc68-f857-321e-8c5b-b00e6a47a787.jpg[/img]
点击提交,页面转向
[url]http://localhost:8080/firstSteps/spring/customers/0[/url],同时可以看到提示信息
[list]
[*]post customer id :0,Customer [name=name1, address=address1]
[/list]
说明通过form访问POST请求成功,新增的Customer编号为0。
在另一个页面中访问[url]http://localhost:8080/firstSteps/spring/customers/0[/url]可以看到提示信息
[list]
[*]get customer id :0,Customer [name=name1, address=address1]
[/list]
说明访问GET请求成功。
将index.jsp中form的method修改为get,提交后也显示相同信息。
但默认的html from只能通过post/get,要想访问PUT和DELETE请求,可以使用Restlet提供的ClientResource类。
[b]6.Test[/b]
在com.sunny.restlet.order包中创建Test类,代码如下:
类中通过调用Restlet提供的ClientResource来进行测试。custId参数在创建ClientResource连接时传入;Customer数据通过Form来组装,调用post/put时传递。因为在CustomerResource中定义了返回结果类型是StringRepresentation,所以只需要调用representation.getText()就能得到返回数据。
调用顺序是POST>GET>PUT>GET>DELETE>GET。
[b]7.运行[/b]
重新部署程序(重置通过页面POST的数据)后,运行Test类,可以看到控制台输出以下信息:
[list]
[*]2012-12-26 16:59:09 org.restlet.engine.http.connector.HttpClientHelper start
[*]信息: Starting the default HTTP client
[*]post customer id :0,Customer [name=b, address=b]
[*]get customer id :0,Customer [name=b, address=b]
[*]put customer id:0,Customer [name=c, address=c]
[*]get customer id :0,Customer [name=c, address=c]
[*]delete customer id :0
[*]get customer id :0,null
[/list]
结合CustomerResource和Test类代码,我们可以分析程序运行流程:
[list]
[*]1a. 客户端 封装Customer数据[name=b, address=b],调用服务端POST请求,新增Customer;
[*]1b. 服务端 新增Customer,返回custId为0;
[*]2a. 客户端 调用服务端GET请求,查询custId为0的Customer;
[*]2b. 服务端 查询custId为0的Customer,返回Customer数据[name=b, address=b];
[*]3a. 客户端 封装新的Customer数据[name=c, address=c],调用服务端PUT请求,更新custId为0的Customer;
[*]3b. 服务端 更新custId为0的Customer,返回处理结果;
[*]4a. 客户端 调用服务端GET请求,查询custId为0的Customer;
[*]4b. 服务端 查询custId为0的Customer,返回Customer数据[name=c, address=c];
[*]5a. 客户端 调用服务端DELETE请求,删除custId为0的Customer;
[*]5b. 服务端 删除custId为0的Customer;
[*]6a. 客户端 调用服务端GET请求,查询custId为0的Customer;
[*]7b. 服务端 查询custId为0的Customer,返回null;
[/list]
说明CustomerResource的POST/PUT/DELETE/GET方法测试调用成功。
[b]8.思考[/b]
从index.jsp页面和Test类代码中我们都可以看到,在POST时指定了一个custId。这并不符合逻辑,因为在新增一个Customer之前我们并不知道它的custId,而且这个custId也并没有发挥作用,所以我们POST的对象应该是"/customers"而不是"customers/{custId}"。
在搭建MVC框架测试原型的时候,我们除了CRUD外还需要提供一个额外功能,那就是List,即显示所有资源。因为"customers/{custId}"中已经实现了get方法,可以通过"/customers"的get方法来实现。
我们需要新建一个CustomersResource,实现get/post方法来提供List和Post服务。
在com.sunny.restlet.order包中创建CustomersResource类,代码如下:
类中定义了post/get方法,用来新增和显示所有Customer。
修改com.sunny.restlet.order.CustomerResource类,删除其中的post方法。
修改com.sunny.restlet.order.OrderDao接口,加入getAllCustomers方法:
修改com.sunny.restlet.order.OrderDaoImpl类,实现getAllCustomers方法:
方法中只是简单的返回customers HashMap。
修改src/目录下的applicationContext.xml,加入如下配置:
配置中将CustomersResource发布到"/customers"路径。
修改WebRoot/目录下的index.jsp页面,将form的action地址修改为"/firstSteps/spring/customers"。
[b]9.运行[/b]
重新部署程序后,通过浏览器访问[url]http://localhost:8080/firstSteps/[/url]可以看到页面和表单。填入信息[name=name, address=address]。点击提交,页面转向
[url]http://localhost:8080/firstSteps/spring/customers[/url],同时可以看到提示信息
[list]
[*]post customer id :0,Customer [name=name, address=address]
[/list]
说明通过form访问"customers"的POST请求成功,新增的Customer编号为0。
再次访问[url]http://localhost:8080/firstSteps/[/url],填入信息[name=name1, address=address1]。点击提交,看到提示信息
[list]
[*]post customer id :1,Customer [name=name1, address=address1]
[/list]
在另一个页面中访问[url]http://localhost:8080/firstSteps/spring/customers[/url]可以看到提示信息
[list]
[*]{0=Customer [name=name, address=address], 1=Customer [name=name1, address=address1]}
[/list]
说明访问"customers"的GET请求成功,并且显示了刚才新增的两个Customer。
将index.jsp中form的method修改为get,提交后也显示相同信息。
以上已经将"customers"的POST/GET和"customer"的PUT/DELETE/GET实现并测试完成。
参考:[url]http://ajaxcn.iteye.com/blog/417596[/url]
[b]1.pojo[/b]
在com.sunny.restlet.order包下创建Customer类,代码如下:
package com.sunny.restlet.order;
public class Customer {
private String name;
private String address;
public Customer(String name, String address) {
super();
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Customer [name=" + name + ", address=" + address + "]";
}
}
类定义了Customer的属性、构造方法和toString()方法。
[b]2.Dao[/b]
修改com.sunny.restlet.order.OrderDao接口,代码如下:
package com.sunny.restlet.order;
public interface OrderDao {
public String getOrderById(String orderId);
public String getSubOrderById(String subOrderId);
public Customer getCustomerById(String custId);
public String addCustomer(Customer customer) ;
public void updateCustomerById(Customer customer, String custId);
public void deleteCustomerById(String custId);
}
接口中定义了对Customer的增删改查方法。
修改com.sunny.restlet.order.OrderDaoImpl类,代码如下:
package com.sunny.restlet.order;
import java.util.HashMap;
import java.util.Map;
public class OrderDaoImpl implements OrderDao {
private Map<String, Customer> customers = new HashMap<String, Customer>();
public Customer getCustomerById(String custId) {
// TODO Auto-generated method stub
return customers.get(custId);
}
public String addCustomer(Customer customer) {
// TODO Auto-generated method stub
String index = String.valueOf(customers.size());
customers.put(index, customer);
return index;
}
public void deleteCustomerById(String custId) {
// TODO Auto-generated method stub
customers.remove(custId);
}
public void updateCustomerById(Customer customer, String custId) {
// TODO Auto-generated method stub
customers.put(custId, customer);
}
public String getOrderById(String orderId) {
// TODO Auto-generated method stub
return "order" + orderId;
}
public String getSubOrderById(String subOrderId) {
// TODO Auto-generated method stub
return "subOrder" + subOrderId;
}
}
接口中实现了对Customer的增删改查方法,并使用一个HashMap来模拟数据的持久化,新增Customer的key就是HashMap的size。
[b]3.CustomerResource[/b]
接下来要修改com.sunny.restlet.order.CustomerResource类,重写父类ServerResource中的post/put/delete/get方法,代码如下:
package com.sunny.restlet.order;
import org.restlet.data.Form;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
public class CustomerResource extends ServerResource {
private OrderDao orderDao;
@Override
protected Representation delete() throws ResourceException {
// TODO Auto-generated method stub
String customerId = (String) getRequest().getAttributes().get("custId");
orderDao.deleteCustomerById(customerId);
return new StringRepresentation("delete customer id :" + customerId);
}
@Override
protected Representation get() throws ResourceException {
// TODO Auto-generated method stub
String customerId = (String) getRequest().getAttributes().get("custId");
return new StringRepresentation("get customer id :" + customerId + ","
+ orderDao.getCustomerById(customerId));
}
@Override
protected Representation post(Representation entity)
throws ResourceException {
// TODO Auto-generated method stub
Form form = new Form(entity);
String name = form.getFirstValue("name");
String address = form.getFirstValue("address");
Customer customer = new Customer(name, address);
String id = orderDao.addCustomer(customer);
return new StringRepresentation("post customer id :" + id + ","
+ orderDao.getCustomerById(id));
}
@Override
protected Representation put(Representation entity)
throws ResourceException {
// TODO Auto-generated method stub
String customerId = (String) getRequest().getAttributes().get("custId");
Form form = new Form(entity);
String name = form.getFirstValue("name");
String address = form.getFirstValue("address");
Customer customer = new Customer(name, address);
orderDao.updateCustomerById(customer, customerId);
return new StringRepresentation("put customer id:" + customerId + ","
+ orderDao.getCustomerById(customerId));
}
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}
类中的post/put/delete/get方法分别对应POST/PUT/DELETE/GET请求。Restlet会自动根据请求类型不同来调用各自对应的方法。其中PUT/DELETE/GET请求需要custId参数,该参数从RequestURI的属性中获得;POST/PUT请求需要Customer数据,数据被封装在Representation entity中,通过Form类来读取。
方法中的处理结果都通过StringRepresentation来返回给调用者。
[b]注[/b]:我们删除了类变量customerId,改成了方法变量。因为在spring配置文件中,我们将CustomerResource bean定义为singleton单例模式,所有请求共用一个CustomerResource实例来提供服务。而单例模式中的类变量相当于static静态变量,后到的请求可能会修改前面请求中的customerId的值,导致运行参数错误,所以将customerId移至各方法中获取。同样,doInit()方法也不需要自行实现了。
[b]4.测试页面[/b]
我们可以通过页面测试一下各个方法能否正常工作。
修改WebRoot/下的index.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<form action="/firstSteps/spring/customers/0" method="post">
name:
<input type="text" name="name">
<br>
address:
<input type="text" name="address">
<br>
<input type="submit" value="submit">
</form>
</body>
</html>
页面中定义了一个html form,将name和address属性通过POST方式提交。
[b]5.运行[/b]
重新部署程序后,通过浏览器访问[url]http://localhost:8080/firstSteps/[/url]可以看到页面和表单。填入name和address信息,如图所示。
[img]http://dl.iteye.com/upload/attachment/0078/4359/d247bc68-f857-321e-8c5b-b00e6a47a787.jpg[/img]
点击提交,页面转向
[url]http://localhost:8080/firstSteps/spring/customers/0[/url],同时可以看到提示信息
[list]
[*]post customer id :0,Customer [name=name1, address=address1]
[/list]
说明通过form访问POST请求成功,新增的Customer编号为0。
在另一个页面中访问[url]http://localhost:8080/firstSteps/spring/customers/0[/url]可以看到提示信息
[list]
[*]get customer id :0,Customer [name=name1, address=address1]
[/list]
说明访问GET请求成功。
将index.jsp中form的method修改为get,提交后也显示相同信息。
但默认的html from只能通过post/get,要想访问PUT和DELETE请求,可以使用Restlet提供的ClientResource类。
[b]6.Test[/b]
在com.sunny.restlet.order包中创建Test类,代码如下:
package com.sunny.restlet.order;
import org.restlet.data.Form;
import org.restlet.representation.Representation;
import org.restlet.resource.ClientResource;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
ClientResource client = new ClientResource(
"http://localhost:8080/firstSteps/spring/customers/0");
Form form = new Form();
form.add("name", "b");
form.add("address", "b");
Representation representation = client.post(form);
System.out.println(representation.getText());
representation = client.get();
System.out.println(representation.getText());
form.clear();
form.add("name", "c");
form.add("address", "c");
representation = client.put(form);
System.out.println(representation.getText());
representation = client.get();
System.out.println(representation.getText());
representation = client.delete();
System.out.println(representation.getText());
representation = client.get();
System.out.println(representation.getText());
} catch (Exception e) {
e.printStackTrace();
}
}
}
类中通过调用Restlet提供的ClientResource来进行测试。custId参数在创建ClientResource连接时传入;Customer数据通过Form来组装,调用post/put时传递。因为在CustomerResource中定义了返回结果类型是StringRepresentation,所以只需要调用representation.getText()就能得到返回数据。
调用顺序是POST>GET>PUT>GET>DELETE>GET。
[b]7.运行[/b]
重新部署程序(重置通过页面POST的数据)后,运行Test类,可以看到控制台输出以下信息:
[list]
[*]2012-12-26 16:59:09 org.restlet.engine.http.connector.HttpClientHelper start
[*]信息: Starting the default HTTP client
[*]post customer id :0,Customer [name=b, address=b]
[*]get customer id :0,Customer [name=b, address=b]
[*]put customer id:0,Customer [name=c, address=c]
[*]get customer id :0,Customer [name=c, address=c]
[*]delete customer id :0
[*]get customer id :0,null
[/list]
结合CustomerResource和Test类代码,我们可以分析程序运行流程:
[list]
[*]1a. 客户端 封装Customer数据[name=b, address=b],调用服务端POST请求,新增Customer;
[*]1b. 服务端 新增Customer,返回custId为0;
[*]2a. 客户端 调用服务端GET请求,查询custId为0的Customer;
[*]2b. 服务端 查询custId为0的Customer,返回Customer数据[name=b, address=b];
[*]3a. 客户端 封装新的Customer数据[name=c, address=c],调用服务端PUT请求,更新custId为0的Customer;
[*]3b. 服务端 更新custId为0的Customer,返回处理结果;
[*]4a. 客户端 调用服务端GET请求,查询custId为0的Customer;
[*]4b. 服务端 查询custId为0的Customer,返回Customer数据[name=c, address=c];
[*]5a. 客户端 调用服务端DELETE请求,删除custId为0的Customer;
[*]5b. 服务端 删除custId为0的Customer;
[*]6a. 客户端 调用服务端GET请求,查询custId为0的Customer;
[*]7b. 服务端 查询custId为0的Customer,返回null;
[/list]
说明CustomerResource的POST/PUT/DELETE/GET方法测试调用成功。
[b]8.思考[/b]
从index.jsp页面和Test类代码中我们都可以看到,在POST时指定了一个custId。这并不符合逻辑,因为在新增一个Customer之前我们并不知道它的custId,而且这个custId也并没有发挥作用,所以我们POST的对象应该是"/customers"而不是"customers/{custId}"。
在搭建MVC框架测试原型的时候,我们除了CRUD外还需要提供一个额外功能,那就是List,即显示所有资源。因为"customers/{custId}"中已经实现了get方法,可以通过"/customers"的get方法来实现。
我们需要新建一个CustomersResource,实现get/post方法来提供List和Post服务。
在com.sunny.restlet.order包中创建CustomersResource类,代码如下:
package com.sunny.restlet.order;
import java.util.Map;
import org.restlet.data.Form;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
public class CustomersResource extends ServerResource {
private OrderDao orderDao;
@Override
protected void doInit() throws ResourceException {
// TODO Auto-generated method stub
super.doInit();
}
@Override
protected Representation get() throws ResourceException {
// TODO Auto-generated method stub
Map customers = orderDao.getAllCustomers();
return new StringRepresentation(customers.toString());
}
@Override
protected Representation post(Representation entity)
throws ResourceException {
// TODO Auto-generated method stub
Form form = new Form(entity);
String name = form.getFirstValue("name");
String address = form.getFirstValue("address");
Customer customer = new Customer(name, address);
String id = orderDao.addCustomer(customer);
return new StringRepresentation("post customer id :" + id + ","
+ orderDao.getCustomerById(id));
}
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}
类中定义了post/get方法,用来新增和显示所有Customer。
修改com.sunny.restlet.order.CustomerResource类,删除其中的post方法。
修改com.sunny.restlet.order.OrderDao接口,加入getAllCustomers方法:
public Map getAllCustomers();
修改com.sunny.restlet.order.OrderDaoImpl类,实现getAllCustomers方法:
public Map getAllCustomers() {
// TODO Auto-generated method stub
return customers;
}
方法中只是简单的返回customers HashMap。
修改src/目录下的applicationContext.xml,加入如下配置:
<bean name="/customers" id="customersResrouce"
class="com.sunny.restlet.order.CustomersResource" />
配置中将CustomersResource发布到"/customers"路径。
修改WebRoot/目录下的index.jsp页面,将form的action地址修改为"/firstSteps/spring/customers"。
[b]9.运行[/b]
重新部署程序后,通过浏览器访问[url]http://localhost:8080/firstSteps/[/url]可以看到页面和表单。填入信息[name=name, address=address]。点击提交,页面转向
[url]http://localhost:8080/firstSteps/spring/customers[/url],同时可以看到提示信息
[list]
[*]post customer id :0,Customer [name=name, address=address]
[/list]
说明通过form访问"customers"的POST请求成功,新增的Customer编号为0。
再次访问[url]http://localhost:8080/firstSteps/[/url],填入信息[name=name1, address=address1]。点击提交,看到提示信息
[list]
[*]post customer id :1,Customer [name=name1, address=address1]
[/list]
在另一个页面中访问[url]http://localhost:8080/firstSteps/spring/customers[/url]可以看到提示信息
[list]
[*]{0=Customer [name=name, address=address], 1=Customer [name=name1, address=address1]}
[/list]
说明访问"customers"的GET请求成功,并且显示了刚才新增的两个Customer。
将index.jsp中form的method修改为get,提交后也显示相同信息。
以上已经将"customers"的POST/GET和"customer"的PUT/DELETE/GET实现并测试完成。