From 53d411dcd6f52a22ec4513a9d43b3b5f737655a1 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Tue, 21 Jun 2016 10:21:13 +0200 Subject: [PATCH] Resolving HTTP-status-codes explicitly to specialized error-pages This is needed, for example, to map the status-code 404 to a specialized page. --- .../java/de/juplo/thymeproxy/Application.java | 17 +++-- .../ExceptionResolverErrorController.java | 71 ++++++++++++++++++- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/juplo/thymeproxy/Application.java b/src/main/java/de/juplo/thymeproxy/Application.java index 6b0ad09..6a3d7da 100644 --- a/src/main/java/de/juplo/thymeproxy/Application.java +++ b/src/main/java/de/juplo/thymeproxy/Application.java @@ -15,6 +15,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; +import org.springframework.http.HttpStatus; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; @@ -124,7 +125,7 @@ public class Application extends WebMvcConfigurerAdapter mappings.setProperty("TemplateInputException", "templates/404"); resolver.setExceptionMappings(mappings); - resolver.setDefaultErrorView("templates/500"); + resolver.setDefaultErrorView("templates/error"); resolver.setWarnLogCategory("exception"); return resolver; } @@ -135,11 +136,15 @@ public class Application extends WebMvcConfigurerAdapter ErrorAttributes errorAttributes ) { - return new ExceptionResolverErrorController( - context, - errorAttributes, - properties.getError() - ); + ExceptionResolverErrorController controller = + new ExceptionResolverErrorController( + context, + errorAttributes, + properties.getError() + ); + controller.addErrorMapping(HttpStatus.NOT_FOUND, "templates/404"); + controller.setDefaultErrorView("templates/error"); + return controller; } diff --git a/src/main/java/de/juplo/thymeproxy/ExceptionResolverErrorController.java b/src/main/java/de/juplo/thymeproxy/ExceptionResolverErrorController.java index 6315100..7339ddf 100644 --- a/src/main/java/de/juplo/thymeproxy/ExceptionResolverErrorController.java +++ b/src/main/java/de/juplo/thymeproxy/ExceptionResolverErrorController.java @@ -4,6 +4,7 @@ package de.juplo.thymeproxy; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -23,6 +24,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.support.PropertiesLoaderUtils; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -52,8 +54,8 @@ public class ExceptionResolverErrorController extends BasicErrorController */ private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties"; - private static final Properties DEFAULT_STRATEGIES; + private static final Properties DEFAULT_STRATEGIES; static { // Load default strategy implementations from properties file. @@ -78,6 +80,12 @@ public class ExceptionResolverErrorController extends BasicErrorController } + /** Name of the default-error-view */ + private String defaultErrorView = "error"; + + /** Mapping from HTTP-status-codes to specialized error-pages */ + private Map errorMappings = new HashMap<>(); + /** List of HandlerExceptionResolvers used by this servlet */ private List handlerExceptionResolvers; @@ -135,7 +143,20 @@ public class ExceptionResolverErrorController extends BasicErrorController } } - return new ModelAndView("error", model); + String viewName = null; + Integer code = (Integer)model.get("status"); + try + { + HttpStatus status = HttpStatus.valueOf(code); + viewName = errorMappings.get(status); + } + catch(Throwable t) + { + LOG.warn("cannot map status-code {}: {}", code, t.getMessage()); + } + if (viewName == null) + viewName = defaultErrorView; + return new ModelAndView(viewName, model); } @@ -280,6 +301,52 @@ public class ExceptionResolverErrorController extends BasicErrorController } + /** + * @ + * @see #addErrorMapping(HttpStatus, String) + */ + public String addErrorMapping(Integer status, String viewName) + { + if (status == null) + throw new IllegalArgumentException("The status must not be null"); + return addErrorMapping(HttpStatus.valueOf(status), viewName); + } + + /** + * Adds a mapping from a {@link HttpStatus} to a view. + * + * @param status The {@link HttpStatus}, that should be mapped. + * @param viewName The name of the view, the status should be mapped to. + * @return The name of the view, the status was previously mapped to, or + * null, if the status was not mapped before. + */ + public String addErrorMapping(HttpStatus status, String viewName) + { + if (!StringUtils.hasText(viewName)) + throw new IllegalArgumentException("The view-name must not be empty!"); + if (status == null) + throw new IllegalArgumentException("The status must not be null!"); + return errorMappings.put(status, viewName); + } + + /** + * Sets mappings from {@link HttpStatus} to specialized error-views. + * @param mappings The mappings to set. + */ + public void setErrorMappings(Map mappings) + { + errorMappings = mappings; + } + + /** + * Sets the default error-view for not-mapped status-codes. + * @param view The default error-view to set. + */ + public void setDefaultErrorView(String view) + { + defaultErrorView = view; + } + /** * Set whether to detect all HandlerExceptionResolver beans in this servlet's * context. Otherwise, -- 2.20.1