文档章节

SpringMVC(五):HiddenHttpMethodFilter实现REST请求

LevelCoder
 LevelCoder
发布于 2017/06/05 10:16
字数 939
阅读 3
收藏 0
点赞 0
评论 0

HiddenHttpMethodFilter 主要针对HTTP的GET,PUT,POST,DELETE请求进行状态转化所实现REST风格

理解REST风格架构转化可参考博客:http://kb.cnblogs.com/page/186516/

配置文件:配置HiddenHttpMethodFilter过滤器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">

	<!-- 配置 HiddenHttpMethodFilter过滤器 -->
	<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>


	<!-- 配置 springDispatcherServlet拦截器 -->
	<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 配置springDispatcherServlet 初始化参数,配置springmvc文件的位置和名称 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath*:springmvc.xml</param-value>
		</init-param>
		<!-- 配置 springDispatcherServlet在项目启动时就被创建 -->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

 

控制器

package com.levelcoder.controller;

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;

/**
 * 
 * 描述:HiddenHttpMethodFilter过滤器
 *
 * 作者:LevelCoder
 *
 * 邮箱:LevelCoder@126.com
 *
 * 日期:2017年5月31日 上午10:32:05
 *
 * 版本:V1.0.0
 */

@Controller
public class HiddenHttpMethodFilterController {

	/**
	 * REST GET请求模式
	 * @return
	 */
	@RequestMapping(value="/hiddenHttpMethodFilter/{id}",method=RequestMethod.GET)
	public String get(@PathVariable("id") Integer id){
		System.out.println("REST GET请求成功,请求参数="+id);
		return "success";
	}

	/**
	 * REST POST请求模式
	 * @return
	 */
	@RequestMapping(value="/hiddenHttpMethodFilter",method=RequestMethod.POST)
	public String post(){
		System.out.println("REST POST请求成功");
		return "success";
	}
	
	
	/**
	 * REST PUT请求模式
	 * @return
	 */
	@RequestMapping(value="/hiddenHttpMethodFilter/{id}",method=RequestMethod.PUT)
	public String put(@PathVariable("id") Integer id){
		System.out.println("REST PUT请求成功,请求参数="+id);
		return "success";
	}
	
	
	/**
	 * REST DELETE请求模式
	 * @return
	 */
	@RequestMapping(value="/hiddenHttpMethodFilter/{id}",method=RequestMethod.DELETE)
	public String delete(@PathVariable("id") Integer id){
		System.out.println("REST DELETE请求成功,请求参数="+id);
		return "success";
	}
}

 

测试index页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p>REST 请求模式</p>
	
	<form action="hiddenHttpMethodFilter/1" method="get">
		<input type="submit" value="GET请求"/>
	</form>
	
	<form action="hiddenHttpMethodFilter" method="post">
		<input type="submit" value="POST请求"/>
	</form>
	
	<form action="hiddenHttpMethodFilter/1" method="post">
		<input type="hidden" name="_method" value="PUT"/>
		<input type="submit" value="PUT请求"/>
	</form>
	
	<form action="hiddenHttpMethodFilter/1" method="post">
		<input type="hidden" name="_method" value="DELETE"/>
		<input type="submit" value="DELETE请求"/>
	</form>
	
</body>
</html>

 

 

我们看下HiddenHttpMethodFilter的运行原理

拿PUT请求作为解说案例

当点击PUT请求时执行OncePerRequestFilter下的doFilter方法

@Override
	public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
			throw new ServletException("OncePerRequestFilter just supports HTTP requests");
		}
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;

		String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
		boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;

		if (hasAlreadyFilteredAttribute || skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) {

			// Proceed without invoking this filter...
			filterChain.doFilter(request, response);
		}
		else {
			// Do invoke this filter...
			request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
			try {
				doFilterInternal(httpRequest, httpResponse, filterChain);
			}
			finally {
				// Remove the "already filtered" request attribute for this request.
				request.removeAttribute(alreadyFilteredAttributeName);
			}
		}
	}

在doFilter方法中获取过滤器信息,并引用此Filter,然后执行doFilterInternal方法,

/**
	 * Same contract as for {@code doFilter}, but guaranteed to be
	 * just invoked once per request within a single request thread.
	 * See {@link #shouldNotFilterAsyncDispatch()} for details.
	 * <p>Provides HttpServletRequest and HttpServletResponse arguments instead of the
	 * default ServletRequest and ServletResponse ones.
	 */
	protected abstract void doFilterInternal(
			HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException;

因为HiddenHttpMethodFilter 继承 OncePerRequestFilter 所以在 HiddenHttpMethodFilter 中重写doFilterInternal方法

	/** Default method parameter: {@code _method} */
	public static final String DEFAULT_METHOD_PARAM = "_method";

	private String methodParam = DEFAULT_METHOD_PARAM;


    @Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		String paramValue = request.getParameter(this.methodParam);
		if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
			String method = paramValue.toUpperCase(Locale.ENGLISH);
			HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);
			filterChain.doFilter(wrapper, response);
		}
		else {
			filterChain.doFilter(request, response);
		}
	}

 

由上可看到 this.methodParam为默认DEFAULT_METHOD_PARAM,而DEFAULT_METHOD_PARAM又赋值_method,也就是说当为POST请求,获取已_method为参数的时候进行判断,当请求方法为POST,且请求参数不为空,长度大于0的时候 执行 下面过滤方法

1.针对方法请求参数进行大写转换

2.针对请求方法进行HTTP请求封装 其中 HttpMethodRequestWrapper源码如下

/**
	 * 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;
		}

		@Override
		public String getMethod() {
			return this.method;
		}
	}

3.执行过滤请求

执行完后进行过滤器引用移除

简单的@RequestMapping REST 请求模式就这样

 

demo地址: http://git.oschina.net/LevelCoder/demos

© 著作权归作者所有

共有 人打赏支持
LevelCoder
粉丝 7
博文 63
码字总数 33282
作品 0
房山
高级程序员
springMVC笔记系列(7)——HiddenHttpMethodFilter过滤器

什么是REST?首先来段介绍吧。 REST: 即 Representational State Transfer。 (资源)表现层状态转化。 是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、 扩展方便,所...

HappyBKs ⋅ 2015/05/19 ⋅ 7

Spring MVC 入门指南(二):@RequestMapping用法详解

一、@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置 的映射作用一致。让我们先看一...

kolbe ⋅ 2015/09/22 ⋅ 6

SpringMVC控制器接收不了PUT提交的参数的解决方案

这次改造了下框架,把控制器的API全部REST化,不做不知道,SpringMVC的REST有各种坑让你去跳,顺利绕过它们花了我不少时间,这次来提下SpringMVC的PUT提交参数为null的情况。 照常先贴出我的...

BuWStudio ⋅ 2014/01/10 ⋅ 1

SpringMVC ------HiddenHttpMethodFilter 过滤器

Spring3.0以后添加了HiddenHttpMethodFilter过滤器,来支持支持Rest 风格的URL请求。 REST url: — /order/1 HTTP GET :得到 id = 1 的order — /order/1 HTTP DELETE :删除 id = 1 的order......

Rickxue ⋅ 2015/12/17 ⋅ 0

学习SpringMVC——如何获取请求参数

  @RequestParam,你一定见过;@PathVariable,你肯定也知道;@QueryParam,你怎么会不晓得?!还有你熟悉的他(@CookieValue)!她(@ModelAndView)!它(@ModelAttribute)!没错,仅注解...

Java团长 ⋅ 01/13 ⋅ 0

springMvc学习-day02

Spring MVC 使用 @RequestMapping 注解为控制器指定可 以处理哪些 URL 请求 @RequestMapping 的 value、method、params 及 heads 分别表示请求 URL、请求方法、请求参数及请求头的映射条 件...

小四的窝 ⋅ 04/10 ⋅ 0

springmvc 基础内容

springmvc 基础内容 1.需要导入的包 commons-logging-1.2.jar spring-aop-4.1.6.RELEASE.jar spring-beans-4.1.6.RELEASE.jar spring-context-4.1.6.RELEASE.jar spring-core-4.1.6.RELEASE......

新年 ⋅ 2016/07/25 ⋅ 0

spring配置restful格式url

项目中使用了restful格式的url,发生一个奇怪的问题 当 url格式如: /testController/test/test 是能正常拦截 为 /testController/test 时报302 found错误 web.xml配置 org.springframework....

回忆若风 ⋅ 2015/05/27 ⋅ 1

SpringMVC+RestFul详细示例实战教程(实现跨域访问)

一、理解 REST REST(Representational State Transfer),中文翻译叫“表述性状态转移”。是 Roy Thomas Fielding 在他2000年的博士论文中提出的。它与传统的 SOAP Web 服务区别在于,REST关...

sihailoveyan ⋅ 06/11 ⋅ 0

高性能 RESTful 框架 - EasyRest-NAS

EasyRest-NAS English doc EasyRest 与 Netty, Akka 和 Spring 的整合. 这是一个为快速开发而设计的高性能RESTful框架,极易搭建集群和使用分布式。你可以完全专注在你的业务逻辑上。 不需要...

Louie_L ⋅ 05/02 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Cube、Cuboid 和 Cube Segment

1.Cube (或Data Cube),即数据立方体,是一种常用于数据分析与索引的技术;它可以对原始数据建立多维度索引。通过 Cube 对数据进行分析,可以大大加快数据的查询效率 2.Cuboid 在 Kylin 中特...

无精疯 ⋅ 31分钟前 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 33分钟前 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 43分钟前 ⋅ 0

云计算的选择悖论如何对待?

人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云计算为...

linux-tao ⋅ 45分钟前 ⋅ 0

我的第一篇个人博客

虽然这是个技术博客,但是,我总是想写一些自己的东西,所有就大胆的在这里写下了第一篇非技术博客。技术博客也很久没有更新,个人原因。 以后自己打算在这里写一些非技术博客,可能个人观点...

Mrs_CoCo ⋅ 46分钟前 ⋅ 0

Redis 注册为 Windows 服务

Redis 注册为 Windows 服务 redis 注册为 windows 服务相关命令 注册服务 redis-server.exe –service-install redis.windows.conf 删除服务 redis-server –service-uninstall 启动服务 re......

Os_yxguang ⋅ 47分钟前 ⋅ 0

世界那么大,语言那么多,为什么选择Micropython,它的优势在哪?

最近国内MicroPython风靡程序界,是什么原因导致它这么火呢?是因为他功能强大,遵循Mit协议开源么? 错!因为使用它真的是太舒服了!!! Micropython的由来,这得益于Damien George这位伟大...

bodasisiter ⋅ 50分钟前 ⋅ 0

docker 清理总结

杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器(docker rm没有加-f参数,运行中的容器不会删掉) docker rm $(docker ps -a -q) 删除所有未打 dangling 标...

vvx1024 ⋅ 今天 ⋅ 0

关于学习

以前学车的时候,教练说了这样的一句话:如果一个人坐在车上一直学,一直学,反而不如大家轮流着学。因为一个人一直学,就没有给自己留空间来反思和改进。而轮流着学的时候大家下来之后思考上...

mskk ⋅ 今天 ⋅ 0

压缩工具之gzip-bzip2-xz

win下常见压缩工具:rar zip 7z linux下常见压缩工具:zip gz bz2 xz tar.gz tar.bz2 tar.xz gzip 不支持目录压缩 gzip 1.txt #压缩。执行后1.txt消失,生成1.txt.gz压缩文件 gzip -d 1.txt....

ZHENG-JY ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部