zoukankan      html  css  js  c++  java
  • HTTP 405 的错误提示:消息 JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS 的解决方法

    如果项目是运行在 Tomcat 8 及以上,会发现发出的 PUT 请求和 DELETE 请求可以被控制其接收到,但是返回页面时(forward)会报HTTP 405 的错误提示:"消息 JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS"

    解决方案:

    1. 使用 Tomcat 8 以下版本。

    2. 使用 @RestController 或者 @Controller + @ResponseBody 标签,但是这样就无法跳转页面了。

    3. 避免使用 forward 方式跳转页面,改为 重定向redirect方式跳转到另一个控制器方法,再由这个控制器方法跳转页面。

      	@RequestMapping(value = "/rest", method = RequestMethod.PUT)
      	public String put() {
      		// 接收表单中的各种信息
      		System.out.println("PUT --- 更新数据");
      		return "redirect:/success";
      	}
      
      	@RequestMapping(value = "/success")
      	public String success() {
      		return "success";
      	}
      
    4. 给 Tomcat 添加启动参数,使Tomcat允许写操作

      <init-param>
          <param-name>readonly</param-name>
          <param-value>false</param-value>
      </init-param>
      
    5. 创建一个新的 Filter 来过滤 FORWARD

      // HiddenHttpMethodFilter.java
      @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);
      	}
      

      HiddenHttpMethodFilter 中的 doFilterInternal 方法是用来过滤 form 表单中 name 为 _method的请求。可以发现,它把请求作为参数传进 HttpMethodRequestWrapper 中并且返回了一个新的请求,放行的也是新的请求。所以我们可以重写 HttpMethodRequestWrapper 中的 getMethod() 方法,让它支持 forward 方式的跳转。

      // 重写 getMethod()
      package com.pudding.conf;
      
      import java.io.IOException;
      
      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.web.filter.HiddenHttpMethodFilter;
      
      public class MyHttpMethodFilter extends HiddenHttpMethodFilter {
      
      	@Override
      	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      			throws ServletException, IOException {
      
      		HttpServletRequest requestToUse = request;
      
      		String method = requestToUse.getMethod();
      		if (method.equalsIgnoreCase("delete") || method.equalsIgnoreCase("put")) {
      			method = "POST";
      		}
      
      		requestToUse = new HttpMethodRequestWrapper(request, method);
      
      		filterChain.doFilter(requestToUse, 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>
      		<filter-name>myFilter</filter-name>
      		<filter-class>com.pudding.conf.MyHttpMethodFilter</filter-class>
      	</filter>
      	<filter-mapping>
      		<filter-name>myFilter</filter-name>
      		<url-pattern>/*</url-pattern>
      		<dispatcher>FORWARD</dispatcher>
      	</filter-mapping>
      
    6. 在 forward 需要跳转的页面头加上 isErrorPage="true"

      <%@ page language="java" contentType="text/html; charset=UTF-8"
      	pageEncoding="UTF-8" isErrorPage="true"%>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <title>Insert title here</title>
      </head>
      <body>
      	<h1>success</h1>
      </body>
      </html>
      
  • 相关阅读:
    《UNIX环境高级编程》笔记--UNIX标准化及实现
    SPOJ1811最长公共子串问题(后缀自动机)
    一个leetcode解题报告类目,代码很简洁
    字符压缩题目
    求最佳会议地点
    实现树的横向指针
    lower_bound与upper_bound
    求到所有房子距离和最小的新房子
    增加限制条件的矩阵求和
    切分数组来得到一定的和
  • 原文地址:https://www.cnblogs.com/lemon-coke-pudding/p/12727981.html
Copyright © 2011-2022 走看看