HTTP405报错: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";
}
  1. 给 Tomcat 添加启动参数,使Tomcat允许写操作
<init-param>
    <param-name>readonly</param-name>
    <param-value>false</param-value>
</init-param>
  1. 创建一个新的 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()
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.wangxshen.filter.MyHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>myFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>
  1. 在 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>
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值