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

In a recent article in the JavaEE series, there were some problems writing REST-style URL s for Spring MVC. Here is some code.

index.jsp page code:

<%@ 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>

Controller code:

@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"; 
	}
}

The project is running:

Point GET, POST are all okay, but when you point DELETE and PUT, the program will make an error. The error information is as follows:

Error message prompt: jsp only allows GET POST or HEAD.

I actually encountered this error a long time ago and checked it. There are four ways to solve it:

  1. Change tomcat to version 7.0 and below
  2. Label @ResponseBody on Methods
  3. The request is forwarded to a Controller before returning to the jsp page
  4. Set the isErrorPage property to true in the header of your success page

At that time, it really solved the problem, and did not go into the deep reason. I checked it roughly these days. A lot of people wrote this error on the Internet, but it just gave a solution, and did not say why it was solved in the end.

Change tomcat to version 7.0 and below

After consulting a lot of data, I have come to the conclusion that the error message is obvious, that is, jsp only allows GET, POST or HEAD, while we use DELETE and PUT in the REST style, it is obvious that the error will be reported.

So why don't you switch tomcat version to version 7.0 or below?

Tomcat no longer supports HTTP PUT access to JSP pages, only GET, POST, and HEAD, starting with Tomcat version 8.x, as specified in the JCP specification (JSP2.3).

And the return value you write in the controller method is a string, SpringMVC will think it's a jsp page, so it's wrong.
This perfectly explains why the first solution works, but switching tomcat versions is obviously not good.

Label @ResponseBody on Methods

Just mentioned that SpringMVC considers the return value of the controller method to be a jsp page causing an error, then you can label the @ResponseBody comment on the processing method and run the project to try:

The run was successful, but the return value was displayed on the page.

Here's what @ResponseBody does:

The @ResponseBody annotation is used to write the return value of the controller method to the body area of the Response object, usually to return JSON or XML data, after converting it to the specified format through an appropriate converter.
Note: Instead of going out of the view processor after using this annotation, you write the data directly into the input stream, which has the same effect as outputting the data in the specified format through the Response object.

See, you know, if you add this comment, it will not leave the view processor, of course, it will not jump to the jsp page, do not jump to the jsp page, of course, it will not report a mistake.

However, this comment is usually used to return data. If you do want to return data, this is certainly a good way to write. It is also a more standard way to write.

The request is forwarded to a Controller before returning to the jsp page

If you just want to jump to a jsp page, you can use a third solution.
Since you cannot jump directly to a jsp page, you can transfer the request to a control method that jumps to a jsp page.
Modify the code of the control class:

@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"; 
	}
}
......

In this way, instead of jumping directly to the jsp page, our DELETE and PUT requests are first handed over to the toSuccess control method, which jumps to the jsp page.

Set the isErrorPage property to true in the header of your success page

As to why this solution was successful, I'm sure you should know for yourself.

Just because DELETE and PUT request to jump jsp page directly will make an error, when you set isErrorPage property to true in the jsp page to jump, there will be an error when jumping jsp page, and the page with isErrorPage property set will be the error page, so it will be displayed.

summary

To sum up, all four solutions are actually to solve the same problem, that is, jsp does not support DELETE and PUT, we want to find a way to do this without directly accessing jsp in both requests.

However, these methods are somewhat against your will, so use them only when you need to use DELETE and PUT requests, such as by returning some data, otherwise don't use them. That's a lot more.

Teachers often teach us to know what it is and why it is.

119 original articles were published. 9228 were praised. 750,000 visits+
His message board follow

Tags: JSP Tomcat REST JavaEE

Posted on Sat, 14 Mar 2020 20:30:15 -0400 by DrTom