SpringでCRUD機能を作り、Spring securityのデフォルト機能を使ってログイン認証機能を取り付けていました。すると、それまでは@PutMappingにきっちりと分岐していたのに急にエラーを発生するようになりました。
エラー内容:
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
@PutMappingをつけたメソッドを通っていないです。アノテーションを@PostMappingに変えると反応します。
hiddenタグで
html
1<input type="hidden" name="_method" value="PUT">
を持たせておけば@PutMappingへ分岐されると書籍には書かれていますが違うのでしょうか。
それともSpringSecurityをフィルターに通すことで条件が変わるのでしょうか。
ドキュメントを読み漁りましたがそもそも@PutMappingの使用法すら書かれておりませんでした。
以下、該当するファイルです。
DemoSecurityConfig.java
java
1package com.example.demo.config; 2 3import org.springframework.context.annotation.Configuration; 4import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 5import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 7import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 8 9@Configuration 10@EnableWebSecurity 11public class DemoSecurityConfig extends WebSecurityConfigurerAdapter { 12 13 @Override 14 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 15 auth.inMemoryAuthentication().withUser("john").password("{noop}test123").roles("EMPLOYEE"); 16 auth.inMemoryAuthentication().withUser("mary").password("{noop}test123").roles("MANAGER"); 17 auth.inMemoryAuthentication().withUser("susan").password("{noop}test123").roles("ADMIN"); 18 } 19 20 @Override 21 protected void configure(HttpSecurity http) throws Exception { 22 23 http.authorizeRequests() 24 .anyRequest().authenticated() 25 .and() 26 .formLogin() 27 .loginPage("/showMyLoginPage") 28 .loginProcessingUrl("/authenticateTheUser") 29 .permitAll() 30 .and() 31 .logout().permitAll(); 32 33 } 34 35} 36
ログインは成功します。POSTで新規インサートも行えます。
TestController.java
java
1package com.example.demo.controllers; 2 3import java.util.List; 4import java.util.Optional; 5 6import org.springframework.beans.factory.annotation.Autowired; 7import org.springframework.http.HttpStatus; 8import org.springframework.stereotype.Controller; 9import org.springframework.transaction.annotation.Transactional; 10import org.springframework.validation.BindingResult; 11import org.springframework.validation.annotation.Validated; 12import org.springframework.web.bind.annotation.DeleteMapping; 13import org.springframework.web.bind.annotation.GetMapping; 14import org.springframework.web.bind.annotation.ModelAttribute; 15import org.springframework.web.bind.annotation.PathVariable; 16import org.springframework.web.bind.annotation.PostMapping; 17import org.springframework.web.bind.annotation.PutMapping; 18import org.springframework.web.bind.annotation.RequestMapping; 19import org.springframework.web.bind.annotation.ResponseStatus; 20import org.springframework.web.servlet.ModelAndView; 21 22import com.example.demo.Instructor; 23import com.example.demo.InstructorDetail; 24import com.example.demo.InstructorForm; 25import com.example.demo.service.InstructorService; 26 27@Controller 28@RequestMapping("/test") 29public class TestController { 30 31 @Autowired 32 InstructorService service; 33 34 //INDEX 35 @GetMapping 36 public ModelAndView test( 37 //@ModelAttributeでInstructorFormは自動的にインスタンス化される 38 //htmlに反映させるにはmav.addObjectが必須 39 @ModelAttribute("InstructorForm") InstructorForm instructorForm, 40 ModelAndView mav) { 41 42 instructorForm.setNewInstructor(true); 43 mav.addObject("instructorForm", instructorForm); 44 List<Instructor> list = service.findAll(); 45 mav.addObject("list", list); 46 mav.addObject("title", "メンバー一覧"); 47 48 mav.setViewName("test"); 49 return mav; 50 } 51 52 //Before UPDATE 53 @GetMapping(value = "/{id}")//編集ページ 54 public ModelAndView showUpdate( 55 @ModelAttribute("InstructorForm") InstructorForm instructorForm, 56 @PathVariable Integer id, 57 ModelAndView mav) { 58 Optional<InstructorForm> form = service.getInstructorForm(id); 59 60 if(!form.isPresent()) { 61 mav.setViewName("redirect:/test"); 62 return mav; 63 //return new ModelAndView("redirect:/test") 64 } 65 66 mav.addObject("instructorId", id); 67 mav.addObject("instructorForm", form.get()); 68 List<Instructor> list = service.findAll(); 69 mav.addObject("list", list); 70 mav.addObject("title", "更新フォーム"); 71 72 mav.setViewName("test"); 73 return mav; 74 } 75 76 77 //INSERT 78 @PostMapping 79 @Transactional(readOnly = false) 80 public ModelAndView insert2( 81 @Validated InstructorForm instructorForm,//ヴァリデーションはフォームクラスに対して行う 82 BindingResult result, 83 ModelAndView mav) { 84 Instructor instructor = makeInstructor(instructorForm); 85 //redirect、失敗したらそのままHTML表示 86 if(!result.hasErrors()) { 87 service.save(instructor); 88 mav.setViewName("redirect:/test"); 89 }else { 90 instructorForm.setNewInstructor(true); 91 mav.addObject("instructorForm", instructorForm); 92 List<Instructor> list = service.findAll(); 93 mav.addObject("list", list); 94 mav.addObject("title", "メンバー一覧2"); 95 mav.setViewName("test"); 96 } 97 return mav; 98 } 99 100 //UPDATE 101 @PutMapping("/{id}") 102 @Transactional(readOnly = false) 103 public ModelAndView update( 104 @PathVariable Integer id, 105 @ModelAttribute("InstructorForm") InstructorForm instructorForm, 106 ModelAndView mav) { 107 Instructor instructor = makeInstructor(id, instructorForm); 108 System.out.println(instructor); 109 service.save(instructor); 110 mav.setViewName("redirect:/test" + "/" + id); 111 return mav; 112 } 113 114 //DELETE 115 @DeleteMapping("/{id}") 116 @ResponseStatus(HttpStatus.NO_CONTENT) 117 @Transactional(readOnly = false)//削除の場合必須 118 public ModelAndView delete( 119 @PathVariable Integer id, 120 ModelAndView mav) { 121 System.out.println("けすよ"); 122 service.deleteById(id); 123 mav.setViewName("redirect:/test"); 124 return mav; 125 } 126 127 128 private Instructor makeInstructor(InstructorForm iForm) { 129 InstructorDetail iD = new InstructorDetail(iForm.getYoutubeChannel(), iForm.getHobby()); 130 Instructor i = new Instructor(iForm.getFirstName(), iForm.getLastName(), iForm.getEmail()); 131 i.setInstructorDetail(iD); 132 return i; 133 } 134 135 private Instructor makeInstructor(int id,InstructorForm iForm) { 136 InstructorDetail iD = new InstructorDetail(iForm.getYoutubeChannel(), iForm.getHobby()); 137 Instructor i = new Instructor(id, iForm.getFirstName(), iForm.getLastName(), iForm.getEmail()); 138 i.setInstructorDetail(iD); 139 return i; 140 } 141 142 143}
PutMappingとDeleteMappingが反応しません。
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
上記エラーを返します。これはSpring Securityを取り付ける前は動作してました。
Test.html
html
1<!DOCTYPE html> 2<html xmlns:th="http://www.thymeleaf.org"> 3<head> 4<meta charset="UTF-8"> 5<title>Insert title here</title> 6</head> 7<body> 8<h1 th:text="${title}">ようこそ</h1> 9<ul> 10 <li th:each="error : ${#fields.detailedErrors()}" 11 th:text="${error.message}" /> 12</ul> 13<form method="post" action="#" th:action="@{/test}" th:if="${instructorForm.isNewInstructor}" th:object="${instructorForm}"> 14 <label>FirstName</label> 15 <input type="text" name="firstName" th:value="*{firstName}" /> 16 <label>LastName</label> 17 <input type="text" name="lastName" th:value="*{lastName}" /> 18 <label>Email</label> 19 <div th:if="${#fields.hasErrors('email')}" 20 th:errors="*{email}"></div> 21 <div th:if="${#fields.hasErrors('validEmail')}" 22 th:errors="*{validEmail}"></div> 23 <input type="text" name="email" th:value="*{email}" /> 24 <div th:if="${#fields.hasErrors('youtubeChannel')}" 25 th:errors="*{youtubeChannel}"></div> 26 <label>YoutubeChannel</label> 27 <input type="text" name="youtubeChannel" th:value="*{youtubeChannel}" /> 28 <label>Hobby</label> 29 <input type="text" name="hobby" th:value="*{hobby}" /> 30 <input type="submit" value="送信"> 31</form> 32<form method="POST" th:action="@{/test/{id}(id=${instructorId})}" th:unless="${instructorForm.isNewInstructor}" th:object="${instructorForm}"> 33 <label>FirstName</label> 34 <input type="text" name="firstName" th:value="*{firstName}" /> 35 <label>LastName</label> 36 <input type="text" name="lastName" th:value="*{lastName}" /> 37 <label>Email</label> 38 <input type="text" name="email" th:value="*{email}" /> 39 <label>YoutubeChannel</label> 40 <input type="text" name="youtubeChannel" th:value="*{youtubeChannel}" /> 41 <label>Hobby</label> 42 <input type="text" name="hobby" th:value="*{hobby}" /> 43 <input type="hidden" name="_method" value="PUT"> 44 <input type="submit" value="変更"> 45</form> 46<table> 47<tr th:each="obj : ${list}"> 48 <td th:text=${obj.id}></td> 49 <td th:text=${obj.firstName}></td> 50 <td th:text=${obj.email}></td> 51 <td th:text=${obj.instructorDetail.hobby}></td> 52 <td><a type="button" th:href="@{/test/{id}(id=${obj.id})}">編集</a></td> 53 <td><form method="POST" th:action="@{/test/{id}(id=${obj.id})}"> 54 <input type="hidden" name="_method" value="DELETE"> 55 <input type="submit" value="削除"> 56 </form> 57</tr> 58</table> 59<form action="#" th:action="@{/logout}" method="POST"> 60 <input type="submit" value="Logout" /> 61</form> 62</body> 63</html>
このエラーから抜け出せずに困っています。
どなたかわかる方はいらっしゃいますでしょうか。
また、該当のドキュメント(@PutMapping)時にhtmlから送信するhiddenの内容などが記載されたドキュメントの場所をご存じであればそれも知りたいです。どこを探しても見つかりませんでした。
よろしくお願いいたします
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/24 14:22
2018/09/24 14:34
2018/09/25 00:19