([〜#〜]解決策[〜#〜]質問の最後に投稿)
Spring 4MVCアプリを構築しています。また、Javaアノテーションを使用して完全に構成されています。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
は使いたくないので、このためだけに作成する必要があります。
[〜#〜] 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行であり、残りはスーパークラスから直接コピーされるため、このソリューションには特に満足していません。これを行うためのより良い方法があればいいのにと思います。
デフォルトでは、DispatcherServlet
はNoHandlerFoundException
をスローしません。 これを有効にする必要があります。
AbstractAnnotationConfigDispatcherServletInitializer
を使用すると、DispatcherServlet
の作成方法を上書きできます。それをして電話してください
DispatcherServlet dispatcherServlet = ...; // might get it from super implementation
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
DispatcherServletを有効にして、web.xml構成を介してNoHandlerFoundExceptionをスローします。
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
代わりに、registerDispatcherServlet
をオーバーライドすると、次のようにcreateDispatcherServlet
メソッドをオーバーライドできます。
@Override
protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
DispatcherServlet ds = new DispatcherServlet(servletAppContext);
ds.setThrowExceptionIfNoHandlerFound(true);
return ds;
}
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」を追加しました
@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時間かかりました。