Определение обработчика исключений в Spring 4 для возврата пользовательских страниц 404 и 500

Я намерен определить одну глобальную настраиваемую страницу 404 для всех моих контроллеров и одну глобальную страницу 500 для всех исключений. Я прочитал здесь кучу вопросов + все статьи со страницы первых результатов Google.

У меня есть WebInitializer:

public class MyWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
          rootContext.register(WebAppConfiguration.class);
          AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
        DispatcherServlet servlet = new DispatcherServlet(dispatcherContext);
        servlet.setThrowExceptionIfNoHandlerFound(true);
        ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", servlet);
          dispatcher.setLoadOnStartup(1);
          dispatcher.addMapping("/");
    }
}

И теперь у меня есть следующий обработчик исключений:

    @ControllerAdvice
    public class CustomGlogalExceptionHandler {
    public static final String DEFAULT_ERROR_VIEW = "/error/500";

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
            throw e;
        ModelAndView mav = new ModelAndView();
        mav.addObject("url", req.getRequestURL());
        mav.setViewName(DEFAULT_ERROR_VIEW);
        return mav;
    }

    @ExceptionHandler(value = NoHandlerFoundException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public ModelAndView noPageFoundHandler(HttpServletRequest req, Exception e) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("url", req.getRequestURL());
        mav.setViewName("/error/404");
        return mav;
    }
}

Он отлично работает при нажатии http://localhost:8080/test: я получаю свою пользовательскую страницу 404 + код ответа 404. Он также отлично работает, если я куда-то кидаю искусственно: он показывает мою пользовательскую страницу 500 + код ответа 500.

Но если произойдет какое-то реальное исключение, я не получу ни кода ответа 500, ни своей пользовательской страницы 500. Например, теперь у меня есть org.hibernate.LazyInitializationException, но то, что я вижу в консоли Chrome, - это всего лишь код ответа 200, хотя я вижу полную трассировку стека в консоли сервера, и исключение - последнее, которое он показывает. Кроме того, если шаблонизатор Thymeleaf выдает ошибку, он показывает полную трассировку стека в браузере. Что еще мне нужно настроить, чтобы он работал правильно? Спасибо.


person Battle_Slug    schedule 24.10.2016    source источник


Ответы (1)


spring не подберет ваш метательный класс. [ExceptionHandlerExceptionResolver][1] ожидает исключения или его подтипов.
так и должно быть

@ExceptionHandler(value = Excepton.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)

Следовательно, независимо от того, что ваши аннотации будут повторно выброшены и обработаны до 500, остальное происходит без весеннего уведомления

 if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
            throw e;

Or.

Другой вариант - использовать SimpleMappingExceptionResolver, просто объявив его

<bean id="simpleMappingExceptionResolver" class=
     "org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
      <map>
         <entry key="Exception" value="gen_error"/>

      </map>
    </property>

    <!-- See note below on how this interacts with Spring Boot -->
    <property name="defaultErrorView" value="error"/>
    <property name="exceptionAttribute" value="ex"/>

    <!-- Name of logger to use to log exceptions. Unset by default, 
           so logging is disabled unless you set a value. -->
    <property name="warnLogCategory" value="example.MvcLogger"/>
  </bean>

= фасоль

@Bean
public SimpleMappingExceptionResolver exceptionResolver() {
    SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();

    Properties exceptionMappings = new Properties();

    exceptionMappings.put("java.lang.Exception", "error/error");
    exceptionMappings.put("java.lang.RuntimeException", "error/error");

    exceptionResolver.setExceptionMappings(exceptionMappings);



    return exceptionResolver;
}
person kuhajeyan    schedule 24.10.2016
comment
Не беда, пробовал value=Exception.class и даже value=HibernateException.class. Я отредактировал свой вопрос, чтобы устранить эту путаницу, хотя в других случаях вы можете быть правы, поэтому, пожалуйста, не удаляйте свой ответ. - person Battle_Slug; 24.10.2016
comment
Это не Spring Boot, это просто Spring 4. У вас есть пример конфигурации java для этого? Я не использую xml-конфиги в своем проекте. Я пробовал этот SimpleMappingExceptionResolver раньше, он не работал, возможно, мне стоит попробовать другой способ, если вы покажете, как. - person Battle_Slug; 24.10.2016
comment
Все тот же. - person Battle_Slug; 24.10.2016