SpringMVC报错:HTTP Status 405 - JSPs only permit GET POST or HEAD

简介: SpringMVC报错:HTTP Status 405 - JSPs only permit GET POST or HEAD

最近在写JavaEE系列的文章,在写SpringMVC的REST风格URL的时候出现了一些问题,下面是部分代码。

index.jsp页面代码:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    
    <form action="springmvc/testRest/1" method="post">
        <input type="hidden" name="_method" value="PUT"> 
        <input type="submit" value="TestRest PUT">
    </form>
    <br>
    
    <form action="springmvc/testRest/1" method="post">
        <input type="hidden" name="_method" value="DELETE"> 
        <input type="submit" value="TestRest DELETE">
    </form>
    <br>
    
    <form action="springmvc/testRest" method="post">
        <input type="submit" value="TestRest POST">
    </form>
    <br>
    
    <form action="springmvc/testRest/1" method="get">
        <input type="submit" value="TestRest GET">
    </form>
    <br>
    
</body>
</html>

控制器代码:

@RequestMapping("/springmvc")
@Controller
public class RequestMappingTest {
    
    @RequestMapping(value = "/testRest/{id}",method = RequestMethod.PUT)
    public String testRestPut(@PathVariable("id") Integer id) {
        System.out.println("testRest PUT:" + id);
        return "success"; 
    }
    
    @RequestMapping(value = "/testRest/{id}",method = RequestMethod.DELETE)
    public String testRestDelete(@PathVariable("id") Integer id) {
        System.out.println("testRest DELETE:" + id);
        return "success"; 
    }
    
    @RequestMapping(value = "/testRest",method = RequestMethod.POST)
    public String testRestPost() {
        System.out.println("testRest POST");
        return "success"; 
    }
    
    @RequestMapping(value = "/testRest/{id}",method = RequestMethod.GET)
    public String testRestGet(@PathVariable("id") Integer id) {
        System.out.println("testRest GET:" + id);
        return "success"; 
    }
}

项目运行起来:
在这里插入图片描述
点GET、POST都没有问题,但你点DELETE和PUT的时候程序就报错了,报错信息如下:
在这里插入图片描述
报错信息提示:jsp只允许GET POST或HEAD。

这个报错其实很早之前我就遇到了,当时查了一下,总共有四种方式解决:

  1. tomcat换到7.0以及以下版本
  2. 在方法上标注@ResponseBody
  3. 请求先转给一个Controller,再返回jsp页面
  4. 在你的success页面头部设置isErrorPage属性为true

当时也确实就解决问题了,也没有深究到底是为什么,这几天大概地查了一下,网上写这个错误的人很多,但也只是给出了解决方案,并没有说到底为什么这样解决。

tomcat换到7.0以及以下版本

查阅了很多资料后,我得出一些结论,报错的信息其实很明显了,说的是jsp只允许GET、POST或HEAD,而我们使用了REST风格中的DELETE和PUT,显然就会报错了。

那么为什么把tomcat版本切换到7.0或者7.0以下的版本就不会出现这样的问题呢?

Tomcat按照JCP规范(JSP2.3版本)的规定,从Tomcat8.x版本开始,不再支持以HTTP PUT方式访问JSP页面,仅支持GET、POST和HEAD方式。

而你在控制器方法中编写的返回值是一个字符串,SpringMVC会认为这是一个jsp页面,所以报错了。
这就完美地解释了第一种解决办法为什么能够起作用,但是切换tomcat版本显然并不好。

在方法上标注@ResponseBody

刚刚说到SpringMVC会将控制器方法的返回值认为是一个jsp页面导致出错,那么你就可以在处理方法上标注@ResponseBody注解,再运行项目试一试:
在这里插入图片描述
运行成功,但是返回值显示到了页面上。

这就要来了解一下@ResponseBody的作用了:

@ResponseBody注解的作用是将控制器方法的返回值通过适当的转换器转换为指定的格式之后,写入到Response对象的body区,通常用来返回JSON数据或者是XML数据。
注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过Response对象输出指定格式的数据。

看到这,你是不是就明白了,你加上这个注解,它就不走视图处理器,当然也就不会跳转到jsp页面了,不跳转到jsp页面,当然就不报错了。

不过这个注解通常是用来返回数据的,如果你确实是要返回数据,这样写当然没有问题,这也是比较规范的一种写法。

请求先转给一个Controller,再返回jsp页面

而如果你仅仅就是想跳转一个jsp页面,就可以用第三种解决方法。
既然不能直接跳转到jsp页面,你就可以将请求先转给一个控制方法,再通过该控制方法跳转到jsp页面。
修改一下控制类的代码:

@RequestMapping("/springmvc")
@Controller
public class RequestMappingTest {
    
    @RequestMapping("/toSuccess")
    public String toSuccess() {
        System.out.println("toSuccess");
        return "success";
    }
    
    @RequestMapping(value = "/testRest/{id}",method = RequestMethod.PUT)
    public String testRestPut(@PathVariable("id") Integer id) {
        System.out.println("testRest PUT:" + id);
        return "redirect:/springmvc/toSuccess"; 
    }
    
    @RequestMapping(value = "/testRest/{id}",method = RequestMethod.DELETE)
    public String testRestDelete(@PathVariable("id") Integer id) {
        System.out.println("testRest DELETE:" + id);
        return "redirect:/springmvc/toSuccess"; 
    }
    
    @RequestMapping(value = "/testRest",method = RequestMethod.POST)
    public String testRestPost() {
        System.out.println("testRest POST");
        return "success"; 
    }
}
......

通过这样的方式,我们的DELETE和PUT请求就不会直接地去跳转jsp页面,而是先交给了toSuccess控制方法,并由该方法跳转到jsp页面。

在你的success页面头部设置isErrorPage属性为true

至于这种解决方法为什么能够成功,相信你们应该能自己知道了吧?

就是因为DELETE和PUT请求直接跳转jsp页面会出错,当你在待跳转的jsp页面中设置isErrorPage属性为true后,在跳转jsp页面时出错,而设置了isErrorPage属性的页面即为错误页面,它就这样显示出来了。

总结

综上所述,这四种解决方法其实都是在解决同一个问题,就是jsp不支持DELETE和PUT,我们要想办法在这两种请求的方式下不直接去访问jsp就行了。

但这些方法总归是有些违背自己的主观意愿,所以只有当你需要使用DELETE和PUT请求时才去使用它们,比如通过它们返回一些数据,否则就不要去用它们了,这是多此一举。

老师常常教导我们,要知其然,还要知其所以然。
目录
相关文章
|
1月前
|
前端开发 JavaScript Java
如何捕获和处理HTTP GET请求的异常
如何捕获和处理HTTP GET请求的异常
|
1月前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
1月前
|
缓存 安全 API
http 的 get 和 post 区别 1000字
【10月更文挑战第27天】GET和POST方法各有特点,在实际应用中需要根据具体的业务需求和场景选择合适的请求方法,以确保数据的安全传输和正确处理。
|
2月前
|
JSON 编解码 安全
【HTTP】方法(method)以及 GET 和 POST 的区别
【HTTP】方法(method)以及 GET 和 POST 的区别
131 1
|
4月前
automate Flow中如何用HTTP,POST的方式发送短信?
automate Flow中如何用HTTP,POST的方式发送短信?
54 2
|
4月前
|
移动开发 JavaScript 前端开发
"解锁axios GET请求新姿势!揭秘如何将数组参数华丽变身,让你的HTTP请求在云端翩翩起舞,挑战技术极限!"
【8月更文挑战第20天】二维码在移动应用中无处不在。本文详述了在UniApp H5项目中实现二维码生成与扫描的方法。通过对比插件`uni-app-qrcode`和库`qrcode-generator`生成二维码,以及使用插件和HTML5 API进行扫描,帮助开发者挑选最佳方案。无论是即插即用的插件还是灵活的JavaScript实现,都能满足不同需求。
45 0
|
7月前
|
设计模式 前端开发 Java
了解 Spring MVC 架构、Dispatcher Servlet 和 JSP 文件的关键作用
Spring MVC 是 Spring 框架的一部分,是一个 Web 应用程序框架。它旨在使用 Model-View-Controller(MVC) 设计模式轻松构建Web应用程序。
121 0
|
前端开发 Java 程序员
38SpringMVC - SpringMVC架构
38SpringMVC - SpringMVC架构
53 0
|
2月前
|
存储 设计模式 前端开发
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
文章解释了SpringMVC的概念和各部分功能,探讨了应用分层的原因和具体实施的三层架构,以及SpringMVC与三层架构之间的关系和联系。
26 1
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
|
6月前
|
安全 前端开发 Java
挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构
挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构
60 1