2014-01-11 2 views
28

요청한 리소스를 찾을 수없는 경우 Spring 4에서 맞춤 404 오류 페이지를 반환하는 깨끗한 방법을 찾고 있습니다. 다른 도메인 유형에 대한 조회는 다른 오류 페이지를 야기합니다. 여기 스프링 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"; 
} 

내가 문제를 처리하기위한 몇 가지 방법을 상상한다. 먼저 가능성이

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

같은 RuntimeException의를 만든 다음 (어쩌면 미터의 목록 또는 어떤 적절한에 대한 링크를 포함) 사용자 정의의 errorpage을 렌더링하기 위해 예외 핸들러를 사용할 수있을 것입니다.

그러나 나는 작은 예외를 제외하고 내 응용 프로그램을 오염시키는 것을 좋아하지 않습니다.

또 다른 가능성은 HttpServletResponse를 사용하고 수동 상태 코드를 설정합니다 :

@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 상태는 여전히'404'가 아니라'200'이되기 때문에 실제로 의도 한대로 작동하지 않습니다. 실제로 사용자에게 멋진 페이지를 보여 주지만 브라우저는 요청이 성공적으로 처리되었음을 나타내는 응답을 수신합니다. –

+3

힌트를 보내 주셔서 감사합니다. 방금 코드를 다시 확인 했으므로 옳습니다. 'ResponseStatus' 주석은 예외 처리기로 가야합니다. 나는 대답을 고쳤다. –

16

web.xml 파일을 수정했습니다. 다음 코드를 사용하십시오.

<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

당신은 웹에서 오류 코드를 매핑 할 수 있습니다이 경우에 당신을 도울 수 있습니다.다음

<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은 이제 URL의 이러한 오류 중 하나가 발견되었을 때 충돌되는지도하는 컨트롤러를 만들 수 있습니다. 전체 예를 들어

@Controller 
public class HTTPErrorHandler{ 

    String path = "/error"; 

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

우리는 단지 요구 사항을 완수하기 위해 web.xml 파일에 코드의 다음 줄을 추가하고 프로젝트의 루트 디렉토리에 errorPage.jsp라는 새 JSP 파일을 소개 할 수 this tutorial

+0

이것은 질문에 대답하지 않습니다. "다른 도메인 유형에 대한 쿼리는 다른 오류 페이지를 발생시킵니다." –

+1

@Ekansh 답장을 보내 주셔서 감사하고 언젠가이 답을 찾기 위해 연결 +1 – Luffy

+0

나도 너무 고마워. @Ekansh – Ernest

4

참조 .

<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 :

  • 의 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(); 
    } 
    

    } 만들기 @ControllerAdvice에 대한

    1. 속성 설정

      }

    2. 다야 어떤 내용

    와 404.jsp 페이지를 만듭니다.

  • +0

    다른 답변과 마찬가지로 : 이것은 질문에 대답하지 않습니다. "다른 도메인 유형에 대한 쿼리는 다른 오류 페이지를 발생시킵니다." - 문제의 제목을 읽는 것만으로는 문제를 완전히 이해할 수 없습니다 ... –

    +3

    봄 4.2 RC 3에서 'throwExceptionIfNoHandlerFound'를 설정하는 더 깨끗한 방법이 있습니다. 세부 정보 [here] (http://stackoverflow.com/a/31436535/3184859). –

    +0

    다른 방법은 작동하지 않습니다. 하지만 나에게 효과가있다. ** 참고 : ** servlate api를 사용해야합니다. 3.10 하위 서블릿 api가 작동하지 않습니다. –

    관련 문제