SpringMVC(四):@RequestMapping结合org.springframework.web.filter.HiddenHttpMethodFilter实现REST请求
1)REST具体表现:
--- /account/1 HTTP GET 获取id=1的account
--- /account/1 HTTP DELETE 删除id=1的account
--- /aacount/1 HTTP PUT 更新id=1的account
--- /account HTTP POST 新增account
2)SpringMVC中如何实现REST?
众所周知,浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持。Spring3.0增加了一个过滤器,可以将这些请求转化为标准的http方法,使得支持GET、POST、PUT及DELETE请求。
这个过滤器就是:org.springframework.web.filter.HiddenHttpMethodFilter
package org.springframework.web.filter; import java.io.IOException;
import java.util.Locale;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse; import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.util.WebUtils; /**
* {@link javax.servlet.Filter} that converts posted method parameters into HTTP methods,
* retrievable via {@link HttpServletRequest#getMethod()}. Since browsers currently only
* support GET and POST, a common technique - used by the Prototype library, for instance -
* is to use a normal POST with an additional hidden form field ({@code _method})
* to pass the "real" HTTP method along. This filter reads that parameter and changes
* the {@link HttpServletRequestWrapper#getMethod()} return value accordingly.
*
* <p>The name of the request parameter defaults to {@code _method}, but can be
* adapted via the {@link #setMethodParam(String) methodParam} property.
*
* <p><b>NOTE: This filter needs to run after multipart processing in case of a multipart
* POST request, due to its inherent need for checking a POST body parameter.</b>
* So typically, put a Spring {@link org.springframework.web.multipart.support.MultipartFilter}
* <i>before</i> this HiddenHttpMethodFilter in your {@code web.xml} filter chain.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0
*/
public class HiddenHttpMethodFilter extends OncePerRequestFilter { /** Default method parameter: {@code _method} */
public static final String DEFAULT_METHOD_PARAM = "_method"; private String methodParam = DEFAULT_METHOD_PARAM; /**
* Set the parameter name to look for HTTP methods.
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
} @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException { HttpServletRequest requestToUse = request; if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
requestToUse = new HttpMethodRequestWrapper(request, paramValue);
}
} filterChain.doFilter(requestToUse, response);
} /**
* Simple {@link HttpServletRequest} wrapper that returns the supplied method for
* {@link HttpServletRequest#getMethod()}.
*/
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper { private final String method; public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method.toUpperCase(Locale.ENGLISH);
} @Override
public String getMethod() {
return this.method;
}
} }
从这个filter代码中可以得知,该filter是通过POST方式提交表单,该表单中包含一个名称为_method的隐藏域,该隐藏域的值用来判定将要转化的请求方式。所谓的转化请求方式,就是在该filter中重新生成了一个新的、标准化的请求。
3)如何使用到springmvc项目中?
步骤一:在web.xml中添加filter配置:
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
步骤二:在HelloWord.java中添加get/post/put/delete方法:
package com.dx.springlearn.handlers; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; @Controller
@RequestMapping("class_requestmapping")
public class HelloWord {
private static String SUCCESS = "success"; @RequestMapping(value = "/accountDelete/{id}", method = RequestMethod.DELETE)
public String accountDelete(@PathVariable("id") Integer id) {
System.out.println("test rest DELETE,account id:" + id);
return SUCCESS;
} @RequestMapping(value = "/accountPut/{id}", method = RequestMethod.PUT)
public String accountPut(@PathVariable("id") Integer id) {
System.out.println("test rest PUT,account id:" + id);
return SUCCESS;
} @RequestMapping(value = "/account", method = RequestMethod.POST)
public String account() {
System.out.println("test rest POST");
return SUCCESS;
} @RequestMapping(value = "/account/{id}", method = RequestMethod.GET)
public String account(@PathVariable("id") Integer id) {
System.out.println("test rest GET,account id:" + id);
return SUCCESS;
}
}
步骤三:在index.jsp中添加get/post/put/delete方法请求的html脚本:
<!-- delete提交 -->
<form id="form_testRestMethod_DELETE" name="form_testRestMethod_DELETE" method="POST"
action="class_requestmapping/accountDelete/2">
<input type="hidden" name="_method" value="DELETE" />
<button name="submit" id="submit">test rest DELETE</button>
</form>
<br>
<!-- put提交 -->
<form id="form_testRestMethod_PUT" name="form_testRestMethod_PUT" method="POST"
action="class_requestmapping/accountPut/2">
<input type="hidden" name="_method" value="PUT" />
<button name="submit" id="submit">test rest PUT</button>
</form>
<br>
<!-- post提交 -->
<form id="form_testRestMethod_POST" name="form_testRestMethod_POST"
method="POST" action="class_requestmapping/account">
<button name="submit" id="submit">test rest POST</button>
</form>
<br>
<!-- get提交 -->
<a href="class_requestmapping/account/1">test rest GET</a>
<br>
步骤四:测试打印结果为:
test rest GET,account id:1
test rest POST
test rest PUT,account id:2
test rest DELETE,account id:2
SpringMVC(四):@RequestMapping结合org.springframework.web.filter.HiddenHttpMethodFilter实现REST请求的更多相关文章
- SpringMVC(四) RequestMapping请求方式
常见的Rest API的Get和POST的测试参考代码如下,其中web.xml和Springmvc的配置文件参考HelloWorld测试代码中的配置. 控制类的代码如下: package com.ti ...
- java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast
严重: Exception starting filter encodingFilterjava.lang.ClassCastException: org.springframework.web.fi ...
- java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter
今天在用git merge 新代码后报了如下错误:java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterE ...
- org.springframework.web.filter.CharacterEncodingFilter
感谢:http://blog.csdn.net/heidan2006/article/details/3075730 很简单很实用的一个过滤器,当前台JSP页面和JAVA代码中使用了不同的字符集进行编 ...
- 通过org.springframework.web.filter.CharacterEncodingFilter定义Spring web请求的编码
通过类org.springframework.web.filter.CharacterEncodingFilter,定义request和response的编码.具体做法是,在web.xml中定义一个F ...
- org.springframework.web.filter.DelegatingFilterProxy的理解
org.springframework.web.filter.DelegatingFilterProxy可以将filter交给spring管理. 我们web.xml中配置filter时一般采用下面这种 ...
- java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast to javax.servlet.Filter
java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast ...
- org.springframework.web.filter.DelegatingFilterProxy的作用
一.类结构 DelegatingFilterProxy类继承GenericFilterBean,间接实现了Filter,故而该类属于一个过滤器.那么就会有实现Filter中init.doFilter. ...
- Caused by: java.lang.ClassNotFoundException: org.springframework.web.filter.FormContentFilter
又是一个报错,我写代码真的是可以,所有的bug都会被我遇到,所有的问题我都能踩一遍,以前上学的时候同学就喜欢问我问题,因为他们遇到的问题,我早就遇到了......... 看看报错内容: 2019-04 ...
随机推荐
- Kotlin封装RxJava与Retrofit
代码地址:https://github.com/DarkPointK/RxTrofit.git 前言 Retrofit是Square公司开发的一个类型安全的Java和Android 的REST客户端库 ...
- java之简单工厂模式详解
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...
- 大数据 --> 一致性Hash算法
一致性Hash算法 一致性Hash算法(Consistent Hash)
- Android开发之eclipse 快捷键
转自:<Android开发之eclipse 快捷键>http://www.cnblogs.com/aimeng/archive/2012/08/07/2626909.html Ctrl+1 ...
- Dom属性方法
一.javascript的三大核心 1.ECMAScript js的语法标准 2.DOM Document object Model 文档对象模型,提供的方法可以让js操作html标签 3.BOM B ...
- 剑指Offer-二叉树的下一个结点
题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 思路 分析二叉树的下一个节点,一共有以下情况: 二叉树 ...
- NOIP知识点
基础算法 贪心 枚举 分治 二分 倍增 高精度 模拟 图论 图 最短路(dijkstra.spfa.floyd) 最小生成树(kruskal.prim) 并查集 拓扑排序 二分图染色 Tarjan 树 ...
- KS检验统计量的扩展应用(CMap)
KS检验统计量的扩展应用 KS(Kolmogorov-Smirnov)检验是比较两个经验分布之间是否存在差异. 我们设X1, X2,-, Xm, Y1, Y2,-, Ym为两个独立随机样本,分别满足假 ...
- java之静态属性和静态方法
前言 静态属性和方法必须用static修饰符 静态属性和非静态属性的区别: 1.在内存中存放位置不同 所有带static修饰符的属性或者方法都存放在内存中的方法区 而非静态属性存放在内存中的堆区 ...
- Beta 第六天
今天遇到的困难: github服务器响应很慢 推图的API接口相应较慢,超过了初始设定的最大延迟时间,导致了无法正确返回图片 ListView滑动删除Demo出现了某些Bug,这些Bug可能导致了某些 ...