(SOLUTION張貼在提問結束)HOWTO全球範圍內使用Spring MVC使用基於Java註解
我建立一個Spring MVC 4應用程序配置處理404個例外。它使用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
,因爲我必須爲此創建一個。
解決方案 我做了什麼@Sotirios mentioned here。這是我的部分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號線&其餘部分是直接從超類複製。我希望有更好的方法來做到這一點。
我不知道爲什麼他們沒有通過一些'protected'方法使'DispatcherServlet'可見,但自定義解決方案看起來不錯。 –
爲什麼你不重寫只是createDispatcherServlet – Ysak