Spring MVC: comment renvoyer des pages d'erreur 404 personnalisées?

Je cherche un moyen propre de renvoyer des pages d'erreur 404 personnalisées au printemps 4 lorsqu'une ressource demandée n'a pas été trouvée. Les requêtes vers différents types de domaine doivent entraîner des pages d'erreur différentes.

Voici du code pour montrer mon intention (Meter est une classe de domaine):

@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";
}

J'imagine plusieurs façons de gérer le problème. Tout d'abord, il y aurait la possibilité de créer des RuntimeException comme

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

Puis utilisez un gestionnaire d'exception pour rendre une page d'erreur personnalisée (peut-être contenant un lien vers une liste de compteurs ou tout ce qui est approprié).

Mais je n'aime pas polluer mon application avec beaucoup de petites exceptions.

Une autre possibilité serait d'utiliser HttpServletResponse et de définir le statuscode manuellement:

@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";
}

Mais avec cette solution, je dois dupliquer les 5 premières lignes pour de nombreuses méthodes de contrôleur (comme edit, delete).

Existe-t-il un moyen élégant d'empêcher la duplication de ces lignes plusieurs fois?

30
demandé sur Christian Rudolph 2014-01-11 15:23:52

7 réponses

La solution est beaucoup plus simple que la pensée. On peut utiliser un ResourceNotFoundException Générique défini comme suit:

public class ResourceNotFoundException extends RuntimeException { }

Ensuite, on peut gérer les erreurs dans chaque contrôleur avec une annotation ExceptionHandler:

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";
    }
}

Chaque contrôleur peut définir son propre ExceptionHandler pour le ResourceNotFoundException.

33
répondu Christian Rudolph 2015-02-16 18:07:34

Modifié votre web.fichier xml .En utilisant le code suivant.

<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>

Accédez à ceci en suivant le code.

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

Ajoutez maintenant ce code dans web.XML.

<error-page>
<error-code>508802</error-code>
<location>/error500.jsp</location>
</error-page>
17
répondu Youddh 2014-04-09 11:02:00

Vous pouvez mapper les codes d'erreur dans le web.xml comme le suivant

    <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>

Maintenant, vous pouvez créer un contrôleur pour mapper les url qui sont touchées lorsque l'une de ces erreurs est trouvée.

@Controller
public class HTTPErrorHandler{

    String path = "/error";

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

Pour exemple complet voir ce tutoriel

9
répondu Ekansh Rastogi 2015-02-04 22:51:33

Vous devriez suivre cet article où vous trouverez des informations détaillées sur la gestion des exceptions dans les projets Spring MVC.

Spring-mvc-gestion des exceptions

@ControllerAdvice peut vous aider dans ce cas

4
répondu Taras 2015-01-30 21:52:31

, Nous pouvons simplement ajouter les lignes de code suivantes dans le web.fichier xml et introduire un nouveau fichier JSP nommé errorPage.JSP dans le répertoire racine du projet pour obtenir l'exigence faite.

<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>
4
répondu Manoj Kumar 2015-03-21 11:28:49

Réponse Simple pour 100% xml gratuit:

  1. Définit les propriétés de 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. Créer @ControllerAdvice:

    @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. Créer 404.page jsp avec n'importe quel contenu

C'est tout.

4
répondu SerdukovAA 2018-02-14 23:51:53

J'avais aussi besoin de ne pas utiliser org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.

Selon org.springframework.web.servlet.DispatcherServlet.setThrowExceptionIfNoHandlerFound(boolean): "notez que si DefaultServletHttpRequestHandler est utilisé, les requêtes seront toujours transmises à la servlet par défaut et une exception NoHandlerFoundException ne sera jamais lancée cas."

Https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html#setThrowExceptionIfNoHandlerFound-boolean-

Avant de

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.foo.web")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
  }

  // ...
}

Après

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.foo.web")
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

  @Override
  public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  }

  // ...
}
1
répondu skrueger 2018-04-15 06:11:22