HOWTO Griff 404 Ausnahmen weltweit mit Spring MVC Konfiguration mit Java-basierten Annotationen
(LÖSUNG geschrieben am Ende der Frage)
Baue ich eine Feder 4 MVC-app. Und es ist vollständig konfiguriert, unter Verwendung von Java-Annotationen. Es gibt keine web.xml
. Die app ist so konfiguriert, indem Sie die Instanz von AbstractAnnotationConfigDispatcherServletInitializer
und WebMvcConfigurerAdapter
wie so,
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.*"})
@EnableTransactionManagement
@PropertySource("/WEB-INF/properties/application.properties")
public class WebAppConfig extends WebMvcConfigurerAdapter {
...
}
und
public class WebAppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
...
}
Ich bin jetzt versucht, fügen Sie eine Globale/catch-all exception-handler für 404-Seiten, d.h. HttpStatus.NOT_FOUND
aber keinen Erfolg. Im folgenden sind einige der Möglichkeiten, die ich ausprobiert habe.
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() {
}
}
Keiner dieser Methoden ausgeführt werden. Ich bin an einem Verlust, wie Sie damit umgehen können. Ich will nicht zu verwenden web.xml
denn dann würde ich erstellen, eine nur für diese.
LÖSUNG
Ich Tat, was @Sotirios hier erwähnt. Hier ist mein Teil WebAppInitializer
code, der die dispatcher richtig.
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);
}
...
}
Ich bin zwar nicht besonders glücklich mit dieser Lösung, weil meiner nur custom code 1 Zeile & rest wird direkt kopiert aus der super-Klasse. Ich wünschte, es war ein schöner Weg, dies zu tun.
- Ich weiß nicht, warum Sie nicht die
DispatcherServlet
sichtbar durch einigeprotected
Methode, aber die benutzerdefinierte Lösung scheint gut zu sein. - Warum gehst du nicht einfach überschreiben, nur createDispatcherServlet
Du musst angemeldet sein, um einen Kommentar abzugeben.
Standardmäßig wird der
DispatcherServlet
nicht werfenNoHandlerFoundException
. Die Sie benötigen, zu ermöglichen.Den
AbstractAnnotationConfigDispatcherServletInitializer
sollte Sie außer Kraft setzen, wie dieDispatcherServlet
erstellt. Tun Sie das und rufen SiedispatcherServlet
imAbstractAnnotationConfigDispatcherServletInitializer
.registerDispatcherServlet
. Blick auf die Implementierung der super-Typ um eine Idee zu bekommen, was zu tun ist.Aktivieren DispatcherServlet werfen NoHandlerFoundException durch web.xml configuartion.
Statt überschreiben
registerDispatcherServlet
kann man das überschreiben dercreateDispatcherServlet
- Methode wie folgt.Ich das problem gelöst mit dem folgenden Eintrag in meiner Anwendung.yml
und die folgenden ControllerExceptionHandler:
und nicht zuletzt habe ich ein template "/html/error.html"
Ich kann nicht Kommentar auf obigen post von @Ysak (Ruf<50), jedoch kann ich bestätigen, dass diese Methode funktioniert mit dem setup beschrieben durch die OP.
Ich will hinzufügen, dass aus einer anderen Anleitung hatte ich auch die DefaultServletHandling konfiguriert in meiner WebConfig fix eine andere Frage als unten:
Mit diesem set zu aktivieren, gibt es keine Ausnahme. Sobald ich entfernt diese Zeile, und legen Sie up-Handbuch resourceHandlers funktionierte alles wie erwartet.
Dauerte es rund 2,5 Stunden set auf 404 umleiten, weil dieser einfache line-Methode.