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 ...
随机推荐
- Laravel框架中的make方法详解
为什么网上已经有这么多的介绍Laravel的执行流程了,Laravel的容器详解了,Laravel的特性了,Laravel的启动过程了之类的文章,我还要来再分享呢? 因为,每个人的思维方式和方向是不一 ...
- 【Linux】积累笔记
■ 关于查看系统的一些版本信息 查看系统的发行版本可以用 cat /etc/issue 或者 cat /etc/redhat-release (Centos上) 查看系统的内核版本以及系统位数 una ...
- 配置VIP地址
10.10.10.7 mysql主 redis从 10.10.10.8 mysql从 redis主 现游戏架构如上,游戏后端数据库配置集群.场景描述:若是一台服务器宕机之后,及时切换数据库保持业务 ...
- linux下安装Sublime Text3并将它的快捷方式放进启动器中
Sublime Text是一个代码编辑器,我主要是用它来编辑python.下面就来简单说明下它在linux的安装过程吧! 1.添加sublime text3的仓库 首先按下快捷键ctrl+alt+t打 ...
- [poj3252]Round Numbers_数位dp
Round Numbers poj3252 题目大意:求一段区间内Round Numbers的个数. 注释:如果一个数的二进制表示中0的个数不少于1的个数,我们就说这个数是Round Number.给 ...
- ASP.NET Core MVC 2.1 顶级参数验证
本文讨论ASP.NET Core 2.1中与ASP.NET Core MVC / Web API控制器中的模型绑定相关的功能.虽说这是一个功能,但从我的角度来看,它更像是一个错误修复! 请注意,我使用 ...
- Java日志框架:logback详解
为什么使用logback 记得前几年工作的时候,公司使用的日志框架还是log4j,大约从16年中到现在,不管是我参与的别人已经搭建好的项目还是我自己主导的项目,日志框架基本都换成了logback,总结 ...
- 敏捷冲刺(Beta版本)
评分基准: 按时交 - 有分(计划安排-10分,敏捷冲刺-70分),检查的项目包括后文的三个个方面 冲刺计划安排(单独1篇博客,基本分5分,根据完成质量加分,原则上不超过满分10分) 七天的敏捷冲刺( ...
- 2017-2018-1 20155306 《信息安全系统设计基础》Mybash的实现
2017-2018-1 20155306 <信息安全系统设计基础>Mybash的实现 要求: 使用fork,exec,wait实现mybash 写出伪代码,产品代码和测试代码 发表知识理解 ...
- Java作业-数据库
本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 在Java中使用数据库要经过以下几个步骤: 1. 注册 JDBC 驱动 Class.forName("com ...