2014-07-10 68 views
13

我遇到了有關JSP不接受PUT請求的問題。所以我想知道如何解決它。我已經在堆棧溢出中讀過這個相關的問題,但並沒有解釋如何解決它。405 Put方法的JSP錯誤

HTTP Status 405 - JSPs only permit GET POST or HEAD

從Rails的背景來了,我想使它所以我使用的鐵軌REST風格就像放更新和刪除用戶資源的刪除。

但是,無論何時在此控制器中出現錯誤,它都會嘗試將請求返回到始發JSP,但是Tomcat 8.0.9不接受請求並且出現此錯誤:「HTTP狀態405 - JSP只允許GET POST或頭」。我試過在Tomcat web.xml中禁用readonly - 它沒有任何效果,我仍然得到錯誤。我已將它切換到POST方法,並且流程正常工作。

有沒有辦法強制轉發爲POST方法,同時仍然接受請求的PUT方法?

/** 
    * Edit a user account. 
    * @return the edit user view 
    */ 
    @RequestMapping(value = {"/update/{userId}"}, method = RequestMethod.PUT) 
    public String updateUser(@Valid @ModelAttribute("user") User user, BindingResult result, final RedirectAttributes redirectAttributes) 
    { 
     logger.debug(user); 

     // we check for duplicate email addresses during the update operation. 
     List<User> userCheckList = userRepository.findByEmail(user.getEmail()); 
     if (userCheckList.size() > 0) 
     { 
      // size of list should only ever be 1 
      User userCheck = userCheckList.get(0); 
      if (userCheck.getId() != user.getId()) 
      { 
       result.rejectValue("email", "error.user", "An account already exists for this user email address."); 
      } 
     } 


     if (result.hasErrors()) 
     { 
      return "admin.users.edit"; 
     } 

     // we locate the user and add it to the model 
     userRepository.save(user); 



     // the save operation was successful so we show the user message. 
     redirectAttributes.addFlashAttribute("user", user); 
     redirectAttributes.addFlashAttribute("message", "Updated successfully"); 


     String viewName = "redirect:/admin/users"; 
     logger.debug(viewName); 

     return viewName; 
    } 
+0

這可能會幫助你http://www.codereye.com/2010/12/configure-tomcat-to-accept-http-put.html – mahesh

+0

謝謝我已經嘗試過,但它沒有任何效果,相同錯誤發生。 –

回答

15

的問題是,當你從你的控制器方法返回一個視圖名稱,春節DispatcherServlet會做正向給定的觀點,保留原始PUT方法。

在試圖處理這個轉發時,Tomcat會拒絕它,並且證明JSP的PUT可以被解釋爲「用這個請求的內容替換服務器上的這個JSP文件」。

真的,您希望您的控制器能夠處理您的PUT請求,並隨後轉發給您的JSP作爲GET。幸運的是,Servlet 3.0提供了一種純粹在FORWARD調度程序上進行過濾的方法。

創建一個過濾器:

public class GetMethodConvertingFilter implements Filter { 

    @Override 
    public void init(FilterConfig config) throws ServletException { 
     // do nothing 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
     throws IOException, ServletException { 

     chain.doFilter(wrapRequest((HttpServletRequest) request), response); 
    } 

    @Override 
    public void destroy() { 
     // do nothing 
    } 

    private static HttpServletRequestWrapper wrapRequest(HttpServletRequest request) { 
     return new HttpServletRequestWrapper(request) { 
      @Override 
      public String getMethod() { 
       return "GET"; 
      } 
     }; 
    } 
} 

,並將其連接到您的web.xml正是如此:

<filter> 
    <filter-name>getMethodConvertingFilter</filter-name> 
    <filter-class>my.GetMethodConvertingFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>getMethodConvertingFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
</filter-mapping> 

這將請求轉換爲GET上只能向前,留下通過其他調度請求不變,所以PUT小號將會像平常一樣被你的控制器攔截。

我的(可能不正確)的理解是,Tomcat 8.0.9引入了一個修復,其中ERROR調度程序自動有效地完成 - 請參閱鏈接問題中的answer。但是你沒有使用容器的錯誤處理機制來渲染你的錯誤頁面,你使用Spring MVC手動轉發到視圖,因此你需要這樣做。就我個人而言,我在Jetty 9.2.7下遇到了這個問題,沒有這樣的修復,我將錯誤處理委託給容器,所以我在我的過濾器映射中也配置了<dispatcher>ERROR</dispatcher>

這一切似乎有點神祕,但是我發現成功跳過這個特定的RESTful-Spring-JSP-web-application hoop的唯一途徑。

+0

謝謝我支持將所有內容切換到Post,使用Post v Put並不是什麼大事。我一直在想,如果有一種方法可以重新定向到新的方法,但是當出現錯誤時,同時保持BindingResult可用於請求,那會將它重定向回GET並更適合我的代碼。儘管如此,我還沒有看得太深。儘管這個答案是一個很好的解決方案,所以我會將其標記爲正確的。 –

1

我有同樣的問題,並通過我的JSP頁面的開頭添加

<%@ page isErrorPage="true" %> 

解決它到底。
使用apache-jsp-8.0。33,org/apache/jasper/compiler/Generator.java跳過爲具有此標誌設置的頁面創建此檢查,從而允許JSP回答任何方法。

相關問題