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请求时才去使用它们,比如通过它们返回一些数据,否则就不要去用它们了,这是多此一举。

老师常常教导我们,要知其然,还要知其所以然。
目录
相关文章
|
19天前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
109 29
|
2月前
|
设计模式 前端开发 Java
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
通过对 `DispatcherServlet`源码的深入剖析,我们了解了SpringMVC请求处理的全流程。`DispatcherServlet`作为前端控制器,负责请求的接收和分发,处理器映射和适配负责将请求分派到具体的处理器方法,视图解析器负责生成和渲染视图。理解这些核心组件及其交互原理,有助于开发者更好地使用和扩展SpringMVC框架。
67 4
|
3月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
234 2
|
3月前
|
缓存 安全 API
http 的 get 和 post 区别 1000字
【10月更文挑战第27天】GET和POST方法各有特点,在实际应用中需要根据具体的业务需求和场景选择合适的请求方法,以确保数据的安全传输和正确处理。
|
3月前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
4月前
|
存储 前端开发 NoSQL
拿下奇怪的前端报错(四):1比特丢失导致的音视频播放时长无限增长-浅析http分片传输核心和一个坑点
在一个使用MongoDB GridFS存储文件的项目中,音频和视频文件在大部分设备上播放时长显示为无限,而单独播放则正常。经调查发现,问题源于HTTP Range请求的处理不当,导致最后一个字节未被正确返回。通过调整请求参数,使JavaScript/MongoDB的操作范围与HTTP Range一致,最终解决了这一问题。此案例强调了对HTTP协议深入理解及跨系统集成时注意细节的重要性。
|
4月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
4月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
79 2
|
4月前
|
JSON 编解码 安全
【HTTP】方法(method)以及 GET 和 POST 的区别
【HTTP】方法(method)以及 GET 和 POST 的区别
176 1
|
4月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
324 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习