복붙노트

[SPRING] Java 기반 어노테이션을 사용하여 구성된 Spring MVC를 사용하여 전역 적으로 404 개의 예외를 처리하는 방법

SPRING

Java 기반 어노테이션을 사용하여 구성된 Spring MVC를 사용하여 전역 적으로 404 개의 예외를 처리하는 방법

(해결책 끝 부분에 해결책이 게시 됨)

Spring 4 MVC 애플리케이션을 구축 중입니다. Java Annotation을 사용하여 완전히 구성되었습니다. web.xml이 없습니다. 응용 프로그램은 AbstractAnnotationConfigDispatcherServletInitializer 및 WebMvcConfigurerAdapter의 인스턴스를 사용하여 구성됩니다.

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.*"})
@EnableTransactionManagement
@PropertySource("/WEB-INF/properties/application.properties")
public class WebAppConfig extends WebMvcConfigurerAdapter {
...
}

public class WebAppInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer {
...
}

현재 404 페이지, 즉 HttpStatus.NOT_FOUND에 대한 범용 / 캐치 올 예외 처리기를 추가하려고했지만 성공하지 못했습니다. 아래는 제가 시도한 몇 가지 방법입니다.

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;

@ControllerAdvice
public class GlobalExceptionHandlerController {

    @ExceptionHandler
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
            ModelAndView mav = new ModelAndView();
            return mav;
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ModelAndView handleExceptiond (NoHandlerFoundException ex) {
            ModelAndView mav = new ModelAndView();
            return mav;
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public void handleConflict() {

    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoSuchRequestHandlingMethodException.class)
    public void handlesdConflict() {
    }

}

이 메소드들 중 어느 것도 실행되지 않습니다. 나는 이것을 처리하는 방법에 관해서는 손해를보고있다. 나는 web.xml을 사용하기를 원하지 않는다.

해결책 나는 여기서 언급 한 @Sotirios를했다. 여기 디스패처를 올바르게 설정하는 부분 인 WebAppInitializer 코드가 있습니다.

public class WebAppInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    ...

    @Override
    protected void registerDispatcherServlet(ServletContext servletContext) {

        String servletName = super.getServletName();
        Assert.hasLength(servletName, "getServletName() may not return empty or null");

        WebApplicationContext servletAppContext = super.createServletApplicationContext();
        Assert.notNull(servletAppContext,
                "createServletApplicationContext() did not return an application " +
                "context for servlet [" + servletName + "]");

        DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext);

        //>>> START: My custom code, rest is exqact copy of the super class
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        //>>> END

        ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
        Assert.notNull(registration,
                "Failed to register servlet with name '" + servletName + "'." +
                "Check if there is another servlet registered under the same name.");

        registration.setLoadOnStartup(1);
        registration.addMapping(getServletMappings());
        registration.setAsyncSupported(isAsyncSupported());

        Filter[] filters = getServletFilters();
        if (!ObjectUtils.isEmpty(filters)) {
            for (Filter filter : filters) {
                super.registerServletFilter(servletContext, filter);
            }
        }

        super.customizeRegistration(registration);
    }

    ...
}

내 유일한 사용자 지정 코드가 1 줄 & 나머지는 수퍼 클래스에서 직접 복사되기 때문에 나는이 솔루션에 특히 만족하지는 않지만. 이렇게 할 수있는 더 좋은 방법이 있었으면 좋겠습니다.

해결법

  1. ==============================

    1.기본적으로 DispatcherServlet은 NoHandlerFoundException을 발생시키지 않습니다. 활성화해야합니다.

    기본적으로 DispatcherServlet은 NoHandlerFoundException을 발생시키지 않습니다. 활성화해야합니다.

    AbstractAnnotationConfigDispatcherServletInitializer는 DispatcherServlet이 생성되는 방법을 오버라이드 할 수 있어야한다. 그걸하고 전화 해.

    DispatcherServlet dispatcherServlet = ...; // might get it from super implementation
    dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    
  2. ==============================

    2.Enable DispatcherServlet이 web.xml 구성을 통해 NoHandlerFoundException을 던졌습니다.

    Enable DispatcherServlet이 web.xml 구성을 통해 NoHandlerFoundException을 던졌습니다.

    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
    
  3. ==============================

    3.대신 registerDispatcherServlet을 재정 의하여 다음과 같이 createDispatcherServlet 메서드를 재정의 할 수 있습니다.

    대신 registerDispatcherServlet을 재정 의하여 다음과 같이 createDispatcherServlet 메서드를 재정의 할 수 있습니다.

    @Override
        protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
            DispatcherServlet ds = new DispatcherServlet(servletAppContext);
            ds.setThrowExceptionIfNoHandlerFound(true);
            return ds;
        }
    
  4. ==============================

    4.@ YSAK (평판 <50)으로 위 게시물에 대해 언급 할 수는 없지만이 방법은 OP에서 설명한 설정으로 작동한다는 것을 확인할 수 있습니다.

    @ YSAK (평판 <50)으로 위 게시물에 대해 언급 할 수는 없지만이 방법은 OP에서 설명한 설정으로 작동한다는 것을 확인할 수 있습니다.

    다른 안내서에서 추가 할 것입니다. 아래 WebConfig에서 DefaultServletHandling을 구성하여 별도의 문제를 해결했습니다.

    @Configuration
    @EnableWebMvc
    @ComponentScan("com.acme.tat.controllers")
    public class WebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
    ...
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
    }
    
    }
    

    이 기능을 사용 가능으로 설정하면 예외가 발생하지 않습니다. 이 줄을 제거하고 수동 resourceHandlers를 설정하면 모든 것이 예상대로 작동했습니다.

    이 간단한 한 줄 방법으로 인해 404 리디렉션을 설정하는 데 약 2.5 시간이 걸렸습니다.

  5. ==============================

    5.내 application.yml에 다음 항목으로 문제를 해결했다.

    내 application.yml에 다음 항목으로 문제를 해결했다.

     server.error.whitelabel.enabled: false
     spring.mvc.throw-exception-if-no-handler-found: true
    

    및 다음 ControllerExceptionHandler :

    @ControllerAdvice
    public class ControllerExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String processMethodNotSupportedException(Exception exception) {
        exception.printStackTrace();
        return "error";
    }
    
    }
    

    마지막으로 템플릿을 추가했습니다. "/html/error.html"

  6. from https://stackoverflow.com/questions/24498662/howto-handle-404-exceptions-globally-using-spring-mvc-configured-using-java-base by cc-by-sa and MIT license