*JSPs only permit GET POST or HEAD

博客介绍了RESTful架构,它是流行的互联网软件架构,结构清晰、易扩展。还提到REST风格的URL请求,因浏览器表单只支持GET和POST,Spring提供过滤器转化请求。同时指出运行在Tomcat 8及以上会出现HTTP 405错误,并给出了四种解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)RESTful架构:
RESTful架构,就是目前最流行的一种互联网软件架构,它结构清晰、符合标准、易于理解、扩展方便;so正得到越来越多的网站采用; RESTful(Representational State Transfer),其实是一个开发理念,是对http的很好的诠释;

(2)REST风格的URL请求:

请求路径请求方法作用
-/user/1HTTP GET得到id为1的user
-/user/1HTTP DELETE删除id为1的user
-/user/1HTTP PUT更新id为1的user
-/userHTTP POST新增user

(3)浏览器只支持GET和POST请求:
由于浏览器表单只支持 GET 和 POST 请求,为了实现 DELETE 和 PUT 请求,Spring 为我们提供了一个过滤器org.springframework.web.filter.HiddenHttpMethodFilter,可以为我们将 GET 和 POST 请求通过过滤器转化成 DELETE 和 PUT 请求:

在web.xml文件中配置过滤器:

<!-- 配置 org.springframework.web.filter.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>

(4)在表单中添加隐藏域:
由于浏览器表单无法发送 DELETE 和 PUT 请求,所以为了让 HiddenHttpMethodFilter 识别请求的方法,需要在表单中添加一个隐藏域,name = _methodvalue = DELETE/POST /PUT,修改后 index.jsp 页面代码如下:

<form action="user" method="post">  // 提交方法必须为post
	<input type="hidden" name="_method" value="PUT"/>  // 隐藏域
	<input type="submit" value="Test Rest PUT"/>
</form>

(5)HTTP 405的错误提示:
如果web项目是运行在Tomcat 8及以上,会发现被过滤成DELETE和PUT请求,到达控制器时能顺利执行,但是返回时(forward)会报HTTP 405的错误提示:消息 JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS

(6)解决方法:
1、使用Tomcat7;

2、在Controller当中添加 @ResponseBody 或者 @RestController注解,但是最后执行的结果 , 是在页面当中输出方法 return 的内容;
在这里插入图片描述
在这里插入图片描述

3、将请求转发(forward)改为请求重定向(redirect):重定向到一个Handler,由Handler转发到页面:

@RequestMapping(value = "/testMethod/{id}" , method = RequestMethod.DELETE)  
public String testMethodDELETE(@PathVariable(value = "id") Integer id) {  
        System.out.println("testMethod: DELETE: "+ id);  
        return "redirect:/springmvc/success"; //重定向到一个没有指定 method的 Handler方法   
}
@RequestMapping(value = "/success")  
public String successGenecal() {  
        return "success";  //由该方法 转发到success.jsp页面
} 

4、创建一个Filter来包装HttpRequest中的getMethod()方法:

在这里插入图片描述

  • 客户端发送请求至服务器,这时如果发送的是POST请求且带有以_method为名的参数,会被Spring的HiddenHttpMethodFilter给拦截;
  • HiddenHttpMethodFilter内有一个静态内部类通过继承HttpServletRequestWrapper类并重写getMethod()方法,将该方法返回值设为_method隐藏域的值;
  • HiddenHttpMethodFilter在包装好Request后,将请求发往服务器的控制器中对应的方法处理器,这时的请求变成了图中的WrapperRequest by SpringFilter
  • 服务器处理完请求后,产生了一个forward请求,产生相应的请求处理信息发往客户端,注意这时的request的getMethod()方法仍然是HiddenHttpMethodFilter包装过的;
  • 我们需要在服务器的响应请求到达客户端前进行拦截,这也是最关键的一步,通过自定义过滤器MyHttpMethodFilter进一步包装请求,将getMethod()方法返回值改成POST或GET即可;
    (用HttpRequestWrapper将原始请求包装成一个假的请求并告诉它返回POST来delete和put请求所以Jsp认为这是一个POST请求)
public class MyHttpMethodFilter extends HiddenHttpMethodFilter {
	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		String method = httpServletRequest.getMethod();
		if (method.equalsIgnoreCase("delete") || method.equalsIgnoreCase("put")) { method = "POST"; }
		httpServletRequest = new HttpMethodRequestWrapper(request, method);
		filterChain.doFilter(httpServletRequest, response);
	}
	private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
		private final String method;
		public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
			super(request);    this.method = method;
		} 
		public String getMethod() { return this.method; }
	}
}
  • 在web.xml中配置该filter,注意dispatcher结点值必须为FORWARD:
<filter-mapping>
	<filter-name>myFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值