2014-01-11 22 views
28

Ich bin auf der Suche nach einer sauberen Möglichkeit, benutzerdefinierte 404 Fehlerseiten in Spring 4 zurückgegeben, wenn eine angeforderte Ressource nicht gefunden wurde. Abfragen an unterschiedliche Domain-Typen sollten zu unterschiedlichen Fehlerseiten führen.Spring MVC: Wie benutzerdefinierte 404 Fehlerseiten zurückgegeben werden?

Hier einiger Code meine Absicht, zu zeigen (Meter sind eine Domain-Klasse):

@RequestMapping(value = "/{number}", method = RequestMethod.GET) 
public String getMeterDetails(@PathVariable("number") final Long number, final Model model) { 
    final Meter result = meterService.findOne(number); 
    if (result == null) { 
     // here some code to return an errorpage 
    } 

    model.addAttribute("meter", result); 
    return "meters/details"; 
} 

ich für den Umgang mit dem Problem mehr Möglichkeiten vorstellen. Erstens würde es die Möglichkeit RuntimeException s wie

@ResponseStatus(HttpStatus.NOT_FOUND) 
public class MeterNotFoundExcption extends RuntimeException { } 

und dann verwenden, um einen Exception-Handler erstellen Sie eine benutzerdefinierte Error zu machen (vielleicht einen Link zu einer Liste von Metern oder was auch immer enthält, ist geeignet).

Aber ich mag es nicht, meine Anwendung mit vielen kleinen Ausnahmen zu verschmutzen.

wäre Eine andere Möglichkeit HttpServletResponse und stellen Sie den Statuscode manuell mit:

@RequestMapping(value = "/{number}", method = RequestMethod.GET) 
public String getMeterDetails(@PathVariable("number") final Long number, final Model model, 
final HttpServletResponse response) { 
    final Meter meter = meterService.findOne(number); 
    if (meter == null) { 
     response.setStatus(HttpStatus.NOT_FOUND.value()); 
     return "meters/notfound"; 
    } 

    model.addAttribute("meter", meter); 
    return "meters/details"; 
} 

Aber mit dieser Lösung habe ich die ersten 5 Zeilen für viele Controller-Methoden (wie Bearbeiten, Löschen) duplizieren.

Gibt es eine elegante Möglichkeit zu verhindern, dass diese Zeilen mehrfach dupliziert werden?

Antwort

30

Die Lösung ist viel einfacher als gedacht. Man kann eine generische ResourceNotFoundException definiert wie folgt verwenden:

public class ResourceNotFoundException extends RuntimeException { } 

dann kann man Fehler Griff in jedem Controller mit einer ExceptionHandler Anmerkung:

class MeterController { 
    // ... 
    @ExceptionHandler(ResourceNotFoundException.class) 
    @ResponseStatus(HttpStatus.NOT_FOUND) 
    public String handleResourceNotFoundException() { 
     return "meters/notfound"; 
    } 

    // ... 

    @RequestMapping(value = "/{number}/edit", method = RequestMethod.GET) 
    public String viewEdit(@PathVariable("number") final Meter meter, 
          final Model model) { 
     if (meter == null) throw new ResourceNotFoundException(); 

     model.addAttribute("meter", meter); 
     return "meters/edit"; 
    } 
} 

Jeder Controller seine eigene ExceptionHandler für die ResourceNotFoundException definieren.

+7

Uh, nein. Dies funktioniert nicht wirklich wie beabsichtigt, da bei einer solchen Ausnahmebehandlung innerhalb des Controllers der HTTP-Status der Antwort, wenn ein "Meter" nicht gefunden wird, immer noch "200" anstelle von "404" ist. Sie zeigen zwar eine nette Seite für den Benutzer, aber der Browser erhält eine Antwort, die anzeigt, dass die Anfrage erfolgreich bearbeitet wurde. –

+3

Danke für Ihren Hinweis. Ich habe meinen Code nochmals überprüft und Sie haben Recht. Die Annotation "ResponseStatus" sollte auf dem Ausnahmebehandler fortgesetzt werden. Ich habe meine Antwort korrigiert. –

16

geändert Ihre web.xml Datei. Mit folgenden Code.

<display-name>App Name </display-name> 
<error-page> 
<error-code>500</error-code> 
<location>/error500.jsp</location> 
</error-page> 

<error-page> 
<error-code>404</error-code> 
<location>/error404.jsp</location> 
</error-page> 

Greifen Sie auf diesen Code zu.

response.sendError(508802,"Error Message"); 

nun diesen Code in web.xml hinzuzufügen.

<error-page> 
<error-code>508802</error-code> 
<location>/error500.jsp</location> 
</error-page> 
+0

Dies wäre nützlich, wenn ich _one_ benutzerdefinierte Fehlerseite für alle XyzNotFound Fällen haben wollte. Aber was ich will, ist mehrere angepasste Fehlerseiten für mehrere verschiedene Domain-Klassen (eine Domain-Klasse => eine Fehlerseite). Diese können einige Hinweise für den Benutzer enthalten, um weiter zu schauen. Ich habe meine Frage diesbezüglich geklärt. –

+0

Dies ist, wie Sie einen Fehler definieren können ... – Youddh

+0

Mit Ihrer bearbeiteten Antwort konnte ich nicht mehr den korrekten Fehlerstatuscode (404) zurückgeben. –

4

Sie sollten diesem Artikel folgen, wo Sie detaillierte Informationen zur Ausnahmebehandlung in Spring MVC-Projekten finden können.

spring-mvc-exception-handling

@ControllerAdvice können Sie in diesem Fall helfen

8

Sie die Fehlercodes in Web abbilden können.xml wie folgt

<error-page> 
     <error-code>400</error-code> 
     <location>/400</location> 
    </error-page> 

    <error-page> 
     <error-code>404</error-code> 
     <location>/404</location> 
    </error-page> 

    <error-page> 
     <error-code>500</error-code> 
     <location>/500</location> 
    </error-page> 

Jetzt können Sie einen Controller erstellen, die URLs zu kartieren, die getroffen werden, wenn einer dieser Fehler gefunden wird.

@Controller 
public class HTTPErrorHandler{ 

    String path = "/error"; 

    @RequestMapping(value="/404") 
    public String error404(){ 
     // DO stuff here 
     return path+"/404"; 
    } 
    } 

Für vollständige Beispiel siehe this tutorial

+0

Dies beantwortet die Frage nicht. "Abfragen an unterschiedliche Domain-Typen sollten zu unterschiedlichen Fehlerseiten führen." –

+1

@Ekansh danke für Ihre Antwort und Link auf der Suche nach dieser Antwort aus einer Zeit +1 – Luffy

+0

Ich auch Mann, vielen Dank @Ekansh – Ernest

4

Wir können nur folgende Zeilen Code in web.xml-Datei hinzufügen und eine neue Datei mit dem Namen jsp errorPage.jsp in das Hauptverzeichnis des Projekts vorstellen die Anforderung zu erledigen .

<error-page> 
    <error-code>400</error-code> 
    <location>/errorPage.jsp</location> 
</error-page> 
<error-page> 
    <error-code>404</error-code> 
    <location>/errorPage.jsp</location> 
</error-page> 
<error-page> 
    <error-code>500</error-code> 
    <location>/errorPage.jsp</location> 
</error-page> 
+0

Dies beantwortet nicht die Frage. "Abfragen an unterschiedliche Domain-Typen sollten zu unterschiedlichen Fehlerseiten führen." –

4

Einfache Antwort kostenlos xml 100%:

  1. Eigenschaften für DispatcherServlet

    public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 
    
    @Override 
    protected Class<?>[] getRootConfigClasses() { 
        return new Class[] { RootConfig.class }; 
    } 
    
    @Override 
    protected Class<?>[] getServletConfigClasses() { 
        return new Class[] {AppConfig.class }; 
    } 
    
    @Override 
    protected String[] getServletMappings() { 
        return new String[] { "/" }; 
    } 
    
    //that's important!! 
    @Override 
    protected void customizeRegistration(ServletRegistration.Dynamic registration) { 
        boolean done = registration.setInitParameter("throwExceptionIfNoHandlerFound", "true"); // -> true 
        if(!done) throw new RuntimeException(); 
    } 
    

    }

  2. @ControllerAdvice erstellen:

    @ControllerAdvice 
    public class AdviceController { 
    
    @ExceptionHandler(NoHandlerFoundException.class) 
    public String handle(Exception ex) { 
        return "redirect:/404"; 
    } 
    
    @RequestMapping(value = {"/404"}, method = RequestMethod.GET) 
    public String NotFoudPage() { 
        return "404"; 
    
    } 
    

    }

  3. erstellen 404.jsp Seite mit beliebigem Inhalt

Das ist alles.

+0

Wie in einigen der anderen Antworten: Dies beantwortet die Frage nicht. "Abfragen an unterschiedliche Domain-Typen sollten zu unterschiedlichen Fehlerseiten führen." - Das Lesen des Fragetitels reicht nicht aus, um das Problem vollständig zu verstehen ... –

+3

Und ab Frühling 4.2 RC 3 gibt es eine sauberere Methode, 'throwExceptionIfNoHandlerFound' zu setzen. Details [hier] (http://stackoverflow.com/a/31436535/3184859). –

+0

nicht von anderer Methode arbeiten. aber es funktioniert mich. ** Hinweis: ** Muss Servlate API 3.10 unteren Servlet API nicht funktionieren. –

Verwandte Themen