Restlet 2.0 边学边写(六)使用html form访问Restlet的PUT和DELETE
上一次实践实现了POST、PUT和DELETE方法,并使用htmlform访问了POST和GET方法,本次实践将使用htmlform来访问PUT和DELETE方法。
参考:http://ajaxcn.iteye.com/blog/434449
1.html
修改WebRoot/目录下的index.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> </head> <body> <a href="/firstSteps/spring/customers">get customers</a> <a href="post.jsp">post customers</a> <a href="get.jsp">get customer</a> <a href="put.jsp">put customer</a> <a href="delete.jsp">delete customer</a> </body> </html>
页面上的链接对应了上一次实践创建的各个资源的访问方法。
在WebRoot/目录下新建post.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> </head> <body> <form action="/firstSteps/spring/customers" method="post"> name: <input type="text" name="name"> <br> address: <input type="text" name="address"> <br> <input type="submit" value="submit"> </form> </body> </html>
页面会将form中的信息post到/firstSteps/spring/customers。
在WebRoot/目录下新建get.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <script type="text/javascript"> function getCustomer(){ document.getElementById("form").action="/firstSteps/spring/customers/"+document.getElementById("id").value; document.getElementById("form").submit(); } </script> </head> <body> <form action="/firstSteps/spring/customers/0" method="get" name="form" id="form"> id: <input type="text" name="id" id="id"> <br> <input type="button" value="submit" onclick="getCustomer();"> </form> </body> </html>
页面会使用get方式访问/firstSteps/spring/customers/{custId}。
在WebRoot/目录下新建put.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <script type="text/javascript"> function putCustomer(){ document.getElementById("form").action="/firstSteps/spring/customers/"+document.getElementById("id").value+"?method=put"; document.getElementById("form").submit(); } </script> </head> <body> <form action="/firstSteps/spring/customers/0?method=put" method="post" name="form" id="form"> id: <input type="text" name="id" id="id"> <br> name: <input type="text" name="name"> <br> address: <input type="text" name="address"> <br> <input type="button" value="submit" onclick="putCustomer();"> </form> </body> </html>
页面会使用put方式将form中的信息提交至/firstSteps/spring/customers/{custId}。
在WebRoot/目录下新建delete.jsp,代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <script type="text/javascript"> function deleteCustomer(){ document.getElementById("form").action="/firstSteps/spring/customers/"+document.getElementById("id").value+"?method=delete"; document.getElementById("form").submit(); } </script> </head> <body> <form action="/firstSteps/spring/customers/0?method=delete" method="post" name="form" id="form"> id: <input type="text" name="id" id="id"> <br> <input type="button" value="submit" onclick="deleteCustomer();"> </form> </body> </html>
页面会使用delete方式访问/firstSteps/spring/customers/{custId}。
2.测试
部署firstSteps后,使用浏览器访问http://localhost:8080/firstSteps/,并将页面上的五个链接在新页面中打开访问。
在post.jsp中输入[name=0,address=0]并提交form,可以看到提示信息
- postcustomerid:0,Customer[name=0,address=0]
刷新getcustomers"链接页面,可以看到提示信息
- {0=Customer[name=0,address=0]}
在get.jsp中输入[id=0]并提交form,可以看到提示信息
- getcustomerid:0,Customer[name=0,address=0]
说明通过form访问post和get方法成功。
在put.jsp中输入[id=0,name=0,address=0]并提交form,可以看到提示信息
- MethodNotAllowed
- ThemethodspecifiedintherequestisnotallowedfortheresourceidentifiedbytherequestURI
- Youcangettechnicaldetailshere.
- Pleasecontinueyourvisitatourhomepage.
在delete.jsp中输入[id=0]并提交form,看到提示信息同上。
说明通过form访问put和delete方法失败。
3.TunnelService和methodParameter
从上面的测试中我们可以看到,不能通过form来直接访问put和delete方法。那要怎么才能方便的从页面上调用Rest呢?幸好Restlet中提供了TunnelService来设置方法参数。
参考org.restlet.Application类中代码:
public TunnelService getTunnelService() { return (TunnelService)getServices().get(org/restlet/service/TunnelService); }
参考org.restlet.service.TunnelService类中代码:
public TunnelService(boolean enabled, boolean methodTunnel, boolean preferencesTunnel, boolean queryTunnel, boolean extensionsTunnel, boolean userAgentTunnel, boolean headersTunnel) { super(enabled); this.extensionsTunnel = extensionsTunnel; this.methodTunnel = methodTunnel; this.preferencesTunnel = preferencesTunnel; this.queryTunnel = queryTunnel; this.userAgentTunnel = userAgentTunnel; this.headersTunnel = headersTunnel; characterSetParameter = "charset"; encodingParameter = "encoding"; languageParameter = "language"; mediaTypeParameter = "media"; [b][color=red]methodParameter = "method";[/color][/b] methodHeader = "X-HTTP-Method-Override"; }
可以看到TunnelService构造函数中默认的methodParameter属性值为"method"。这样只要使用了Application并且指定提交时的method参数为post/put/delete/get,就可以方便的调用了。
4.使用Application
修改com.sunny.restlet.order.CustomerApplication类,代码如下:
package com.sunny.restlet.order; import org.restlet.Application; import org.restlet.Context; import org.restlet.Restlet; import org.restlet.routing.Router; public class CustomerApplication extends Application { @Override public Restlet createRoot() { // TODO Auto-generated method stub Router router = new Router(getContext()); router.attach("/", CustomerResource.class); router.attach("/", CustomersResource.class); return router; } }
类中将涉及到的资源CustomerResource和CustomersResource都绑定到"/"路径上。
修改src/目录下的applicationContext.xml,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <beans default-autowire="byName" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- component --> <bean id="component" class="org.restlet.ext.spring.SpringComponent"> <property name="defaultTarget" ref="application" /> </bean> <!-- application --> <bean id="application" class="com.sunny.restlet.order.CustomerApplication"> <lookup-method name="createRoot" bean="restRouter" /> </bean> <!-- router --> <bean id="restRouter" class="org.restlet.ext.spring.SpringBeanRouter"> </bean> <!-- resource --> <bean name="/customers" id="customersResrouce" class="com.sunny.restlet.order.CustomersResource" /> <bean name="/customers/{custId}" id="customerResrouce" class="com.sunny.restlet.order.CustomerResource" /> <bean name="/orders/{orderId}/{subOrderId}" id="orderResrouce" class="com.sunny.restlet.order.OrderResource" /> <!-- dao --> <bean id="orderDao" class="com.sunny.restlet.order.OrderDaoImpl" /> </beans>
配置中加入了CustomerApplication的配置,行成了Component>Application>Router>Resource的配置链。
5.运行
重新部署程序后,按照第二节测试步骤进行测试。
使用浏览器访问http://localhost:8080/firstSteps/,并将页面上的五个链接在新页面中打开访问。
在post.jsp中输入[name=0,address=0]并提交form,可以看到提示信息
- postcustomerid:0,Customer[name=0,address=0]
在get.jsp中输入[id=0]并提交form,可以看到提示信息
- getcustomerid:0,Customer[name=0,address=0]
说明通过form访问post和get方法成功。
在put.jsp中输入[id=0,name=00,address=00]并提交form,可以看到提示信息
- putcustomerid:0,Customer[name=00,address=00]
刷新getcustomers"链接页面,可以看到提示信息
- {0=Customer[name=00,address=00]}
说明访问put方法成功。
在delete.jsp中输入[id=0]并提交form,可以看到提示信息
- deletecustomerid:0
刷新getcustomers"链接页面,可以看到customers为空,说明访问delete方法成功。
6.思考
我们可以直接在提交时使用method参数,也可以更改参数名。
在com.sunny.restlet.order.CustomerApplication类中加入构造方法,代码如下:
public CustomerApplication() { super(); getTunnelService().setMethodParameter("_methodName"); // TODO Auto-generated constructor stub }
构造其中将methodParameter设置为"_methodName",这样在页面提交时,将form的action修改为/firstSteps/spring/customers/0?_methodName=put就可以了。
在提交时,如果form的method属性(非action的method参数)不设置或者为get,那不管method参数是什么值,都只能访问到get方法。
如果form的method属性设置为post,那method参数的值只能是post/put/delete(不设置默认为post),否则会报MethodNotAllowed错误。
虽然Spring在不配置CustomerApplication时会自己创建一个默认的Application,但这个默认Application却不支持method参数。而使用CustomerApplication配合method参数可以在页面上方便的调用put和delete,但是Application的配置却写死在了代码中,也算有得有失。要是大家有好的解决方法,请告诉我,谢谢。