2014-06-30 56 views
9

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號線&其餘部分是直接從超類複製。我希望有更好的方法來做到這一點。

+0

我不知道爲什麼他們沒有通過一些'protected'方法使'DispatcherServlet'可見,但自定義解決方案看起來不錯。 –

+0

爲什麼你不重寫只是createDispatcherServlet – Ysak

回答

13

By default, the DispatcherServlet does not throw a NoHandlerFoundException.您需要啓用該功能。

AbstractAnnotationConfigDispatcherServletInitializer應該讓你重寫DispatcherServlet的創建方式。這樣做並致電

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

感謝@Sotirios的迴應。但我似乎無法獲得'AbstractAnnotationConfigDispatcherServletInitializer'中的'dispatcherServlet'。 – Chantz

+0

@Chantz覆蓋'registerDispatcherServlet'。查看超級類型的實現以瞭解要做什麼。 –

+1

一年後...有沒有更簡單的方法來做到這一點?我通常不會在我的初始化程序中重寫registerDispatcherServlet,所以我覺得這個方法太冗長了。所有這些行重寫只是添加一行。 – Link

4

啓用DispatcherServlet通過web.xml配置文件引發NoHandlerFoundException。

<init-param> 
    <param-name>throwExceptionIfNoHandlerFound</param-name> 
    <param-value>true</param-value> 
</init-param> 
2

相反重寫registerDispatcherServlet一個可以覆蓋createDispatcherServlet方法如下。

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

我不能@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(); 
} 

} 

有了這個設置爲Enable,沒有拋出異常。一旦我刪除這一行並設置手動資源處理程序,一切都按預期工作。

由於這種簡單的一行方法,花了大約2.5小時設置404重定向。

0

我在我的應用程序中解決了以下條目的問題。陽明海運

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」