2014-01-11 98 views
28

我正在尋找一種乾淨的方式,以便在找不到請求的資源時在Spring 4中返回自定義的404錯誤頁面。對不同的域類型的查詢應該導致不同的錯誤頁面。Spring MVC:如何返回自定義404錯誤頁面?

這裏是一些代碼來顯示我的意圖(儀表是域類):

@RequestMapping(value = "/{number}", method = RequestMethod.GET) 
public String getMeterDetails(@PathVariable("number") final Long number, final Model model) { 
    final Meter result = meterService.findOne(number); 
    if (result == null) { 
     // here some code to return an errorpage 
    } 

    model.addAttribute("meter", result); 
    return "meters/details"; 
} 

我想像處理這個問題的幾種方法。首先將有可能創造RuntimeException就像

@ResponseStatus(HttpStatus.NOT_FOUND) 
public class MeterNotFoundExcption extends RuntimeException { } 

,然後使用異常處理程序來呈現一個自定義的errorPage(也許包含鏈接到米列表或任何爲宜)。

但我不喜歡用很多小例外來污染我的應用程序。

另一種可能性是使用HttpServletResponse和手動設置的StatusCode:

@RequestMapping(value = "/{number}", method = RequestMethod.GET) 
public String getMeterDetails(@PathVariable("number") final Long number, final Model model, 
final HttpServletResponse response) { 
    final Meter meter = meterService.findOne(number); 
    if (meter == null) { 
     response.setStatus(HttpStatus.NOT_FOUND.value()); 
     return "meters/notfound"; 
    } 

    model.addAttribute("meter", meter); 
    return "meters/details"; 
} 

但是這種解決方案我必須重複第一5行許多控制器方法(如修改,刪除)。

有沒有一種優雅的方式來防止重複這些行很多次?

回答

30

該解決方案比想象的要簡單得多。我們可以使用一個通用的ResourceNotFoundException定義如下:

public class ResourceNotFoundException extends RuntimeException { } 

那麼可以每個控制器內的錯誤與ExceptionHandler註釋:

class MeterController { 
    // ... 
    @ExceptionHandler(ResourceNotFoundException.class) 
    @ResponseStatus(HttpStatus.NOT_FOUND) 
    public String handleResourceNotFoundException() { 
     return "meters/notfound"; 
    } 

    // ... 

    @RequestMapping(value = "/{number}/edit", method = RequestMethod.GET) 
    public String viewEdit(@PathVariable("number") final Meter meter, 
          final Model model) { 
     if (meter == null) throw new ResourceNotFoundException(); 

     model.addAttribute("meter", meter); 
     return "meters/edit"; 
    } 
} 

每個控制器可以爲ResourceNotFoundException定義自己ExceptionHandler

+7

呃,沒有。這實際上並沒有如預期的那樣工作,因爲在控制器內部進行這樣的異常處理時,當找不到'meter'時,響應的HTTP狀態仍然是「200」而不是「404」。您確實爲用戶顯示了一個不錯的頁面,但瀏覽器會收到一個響應,指示請求已成功處理。 –

+3

感謝您的提示。我只是重新檢查了我的代碼,你是對的。 'ResponseStatus'註釋應該放在異常處理器上。我確定了我的答案。 –

16

修改了您的web.xml file.Using下面的代碼。

<display-name>App Name </display-name> 
<error-page> 
<error-code>500</error-code> 
<location>/error500.jsp</location> 
</error-page> 

<error-page> 
<error-code>404</error-code> 
<location>/error404.jsp</location> 
</error-page> 

通過以下代碼訪問此項目。

response.sendError(508802,"Error Message"); 

現在在web.xml中添加此代碼。

<error-page> 
<error-code>508802</error-code> 
<location>/error500.jsp</location> 
</error-page> 
+0

如果我想爲所有XyzNotFound案件提供_one_自定義錯誤頁面,這將會非常有用。但我想要的是多個不同的域類的多個自定義錯誤頁面(一個域類=>一個錯誤頁)。這些可能包括對用戶的一些提示,在哪裏可以看得更遠。我澄清了我的問題。 –

+0

這個你如何定義你是一個錯誤... – Youddh

+0

隨着你編輯的答案,我不能夠返回正確的錯誤狀態代碼(這是404)了。 –

4

你應該關注這篇文章,你可以在這裏找到關於Spring MVC項目中異常處理的詳細信息。

spring-mvc-exception-handling

@ControllerAdvice可以幫助你在這種情況下

8

您可以在Web地圖的錯誤代碼。像下面

<error-page> 
     <error-code>400</error-code> 
     <location>/400</location> 
    </error-page> 

    <error-page> 
     <error-code>404</error-code> 
     <location>/404</location> 
    </error-page> 

    <error-page> 
     <error-code>500</error-code> 
     <location>/500</location> 
    </error-page> 

XML現在,您可以創建一個控制器將網址映射的任何時候這些錯誤被發現,被擊中。

@Controller 
public class HTTPErrorHandler{ 

    String path = "/error"; 

    @RequestMapping(value="/404") 
    public String error404(){ 
     // DO stuff here 
     return path+"/404"; 
    } 
    } 

對於完整的示例見this tutorial

+0

這不回答問題。 「對不同域類型的查詢應導致不同的錯誤頁面。」 –

+1

@Ekansh謝謝你的回答和鏈接從某個時間尋找這個答案+1 – Luffy

+0

我也是男人,非常感謝@Ekansh – Ernest

4

我們只需要添加的代碼下面幾行到web.xml文件並引入命名的errorPage.jsp到項目的根目錄下一個新的JSP文件,以獲得要求完成。

<error-page> 
    <error-code>400</error-code> 
    <location>/errorPage.jsp</location> 
</error-page> 
<error-page> 
    <error-code>404</error-code> 
    <location>/errorPage.jsp</location> 
</error-page> 
<error-page> 
    <error-code>500</error-code> 
    <location>/errorPage.jsp</location> 
</error-page> 
+0

這並沒有回答這個問題。 「對不同域類型的查詢應導致不同的錯誤頁面。」 –

4

簡單的答案100%免費的xml:

@ControllerAdvice 
public class AdviceController { 

@ExceptionHandler(NoHandlerFoundException.class) 
public String handle(Exception ex) { 
    return "redirect:/404"; 
} 

@RequestMapping(value = {"/404"}, method = RequestMethod.GET) 
public String NotFoudPage() { 
    return "404"; 

} 
0:

  1. 爲DispatcherServlet的

    public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 
    
    @Override 
    protected Class<?>[] getRootConfigClasses() { 
        return new Class[] { RootConfig.class }; 
    } 
    
    @Override 
    protected Class<?>[] getServletConfigClasses() { 
        return new Class[] {AppConfig.class }; 
    } 
    
    @Override 
    protected String[] getServletMappings() { 
        return new String[] { "/" }; 
    } 
    
    //that's important!! 
    @Override 
    protected void customizeRegistration(ServletRegistration.Dynamic registration) { 
        boolean done = registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); // -> true 
        if(!done) throw new RuntimeException(); 
    } 
    

    }

  2. 創建@ControllerAdvice設置屬性

    }

  3. 與任何內容

這就是創建404.jsp頁。

+0

正如在其他答案中一樣:這不能回答這個問題。 「對不同域類型的查詢應導致不同的錯誤頁面。」 - 閱讀問題的標題不足以完全理解問題... –

+3

從春季4.2 RC 3開始,有一種更簡潔的方式來設置'throwExceptionIfNoHandlerFound'。詳情[here](http://stackoverflow.com/a/31436535/3184859)。 –

+0

非其他方法工作。但它適用於我。 **注意:**必須使用servlate api 3.10較低的servlet API不起作用。 –

相關問題