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?
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
.
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>
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
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
, 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>
Réponse Simple pour 100% xml gratuit:
-
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(); }
}
-
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"; }
}
-
Créer 404.page jsp avec n'importe quel contenu
C'est tout.
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."
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) {
}
// ...
}