SpringMVCエラー:HTTP Status 405-JSPs only permit GET POST or HEAD

20513 ワード

最近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"; 
	}
}

プロジェクトの実行:SpringMVC报错:HTTP Status 405 - JSPs only permit GET POST or HEAD_第1张图片点GET、POSTは問題ありませんが、DELETEとPUTをクリックするとプログラムが間違っています.エラーメッセージは以下の通りです.SpringMVC报错:HTTP Status 405 - JSPs only permit GET POST or HEAD_第2张图片エラーメッセージヒント:jspはGET POSTまたはHEADのみを許可します.
この新聞の間違いは実はずっと前に出会ったので、その時調べてみると、全部で4つの方法で解決しました.
  • tomcatを7.0に変更し、次のバージョン
  • に変更します.
  • メソッドに@ResponseBody
  • と表記
  • 要求は、まず1つのControllerに転送され、jspページ
  • に戻る.
  • あなたのsuccessページのヘッダにisErrorPageプロパティをtrue
  • に設定します.
    当時は確かに問題を解決していたが、なぜなのかは深く考えていなかった.ここ数日、大まかに調べてみると、ネット上でこの間違いを書いている人が多かったが、解決策を提示しただけで、なぜこのように解決したのかは言っていない.
    tomcatを7.0以降に変更
    多くの資料を調べた後、私はいくつかの結論を出しました.間違った情報は実は明らかです.jspはGET、POST、HEADしか許可されていませんが、RESTスタイルのDELETEとPUTを使っていると、明らかに間違っています.
    ではなぜtomcatバージョンを7.0または7.0以下に切り替えるとこのような問題は起こらないのでしょうか.
    Tomcatは、JCP仕様(JSP 2.3バージョン)の規定に従い、Tomcat 8から.xバージョンから、HTTP PUT方式でのJSPページへのアクセスはサポートされなくなり、GET、POST、HEAD方式のみがサポートされるようになった.
    コントローラメソッドで作成した戻り値は文字列で、SpringMVCはjspページだと思っていたので、エラーを報告しました.これは、最初の解決策がなぜ機能するのかを完璧に説明していますが、tomcatバージョンを切り替えるのは明らかによくありません.
    メソッドに@ResponseBodyを付ける
    SpringMVCといえば、コントローラメソッドの戻り値をjspページとしてエラーが発生したと判断します.では、処理メソッドに@ResponseBody注記をマークして、プロジェクトを実行してみてください.SpringMVC报错:HTTP Status 405 - JSPs only permit GET POST or HEAD_第3张图片は正常に実行されましたが、戻り値はページに表示されます.
    @ResponseBodyの役割について説明します.
    @ResponseBody注記の役割は、コントローラメソッドの戻り値を適切な変換器で指定されたフォーマットに変換した後、Responseオブジェクトのbody領域に書き込み、通常JSONデータまたはXMLデータを返すために使用されます.注記:この注記を使用した後、ビュープロセッサを使用するのではなく、入力ストリームに直接データを書き込むと、指定したフォーマットのデータがResponseオブジェクトから出力されるのと同じ効果が得られます.
    これを見て、あなたは理解したのではないでしょうか.この注釈を加えると、ビュープロセッサを行かず、もちろんjspページにジャンプすることはありません.jspページにジャンプしないで、もちろん間違いを報告しません.
    しかし、この注釈は通常データを返すために使われています.もしあなたが確かにデータを返すなら、このように書くのはもちろん問題ありません.これも比較的規範的な書き方です.
    リクエストはまずControllerに転送され、jspページに戻ります.
    jspページをジャンプしたいだけなら、3つ目の解決策を使うことができます.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プロパティを設定したページがエラーページとなり、このように表示されます.
    まとめ
    以上のように、この4つの解決策は、同じ問題を解決しているのが、jspがDELETEとPUTをサポートしていないことであり、この2つの要求の下でjspに直接アクセスしないように工夫すればよい.
    しかし、これらの方法はいずれも自分の主観的な意思に反しているので、DELETEとPUTリクエストを使用する必要がある場合にのみ使用します.例えば、データを返すなど、データを使用しないでください.そうしないと、使用しないでください.これは多くのことです.
    先生はいつも私たちに教えてくれた.