web-dev-qa-db-ja.com

Javaベースのアノテーションを使用して構成されたSpringMVCを使用して404例外をグローバルに処理する方法

[〜#〜]解決策[〜#〜]質問の最後に投稿)

Spring 4MVCアプリを構築しています。また、Javaアノテーションを使用して完全に構成されています。web.xmlはありません。アプリはAbstractAnnotationConfigDispatcherServletInitializerWebMvcConfigurerAdapterのインスタンスを使用して構成されています。 、

@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は使いたくないので、このためだけに作成する必要があります。

[〜#〜] solution [〜#〜]@ 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行であり、残りはスーパークラスから直接コピーされるため、このソリューションには特に満足していません。これを行うためのより良い方法があればいいのにと思います。

11
Chantz

デフォルトでは、DispatcherServletNoHandlerFoundExceptionをスローしません。 これを有効にする必要があります。

AbstractAnnotationConfigDispatcherServletInitializerを使用すると、DispatcherServletの作成方法を上書きできます。それをして電話してください

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

DispatcherServletを有効にして、web.xml構成を介してNoHandlerFoundExceptionをスローします。

<init-param>
    <param-name>throwExceptionIfNoHandlerFound</param-name>
    <param-value>true</param-value>
</init-param>
6
Aborn Jiang

代わりに、registerDispatcherServletをオーバーライドすると、次のようにcreateDispatcherServletメソッドをオーバーライドできます。

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

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」を追加しました

1
Simon Ludwig

@Ysak(reputation <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();
}

}

これを有効に設定すると、例外はスローされません。この行を削除して手動のresourceHandlerを設定すると、すべてが期待どおりに機能しました。

この単純な1行の方法のため、404リダイレクトを設定するのに約2.5時間かかりました。

0
user3559338