Created
August 23, 2013 20:32
-
-
Save UnquietCode/6323695 to your computer and use it in GitHub Desktop.
Revisions
-
UnquietCode created this gist
Aug 23, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,98 @@ package com.sb.server.web; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpStatus; import org.springframework.web.servlet.View; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.view.RedirectView; import java.lang.reflect.Method; /** * Custom implementation of annotation-based handler mapping which * looks for the {@link RedirectTrailingSlash} annotation and registers * a handler to cover the case of the url with or without the slash. * The redirect is handled as 301 Redirect * * @author Ben Fagin * @version 2013-08-22 */ public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping { @Override protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) { super.registerHandlerMethod(handler, method, mapping); RedirectTrailingSlash redirectAnnotation = AnnotationUtils.findAnnotation(method, RedirectTrailingSlash.class); if (redirectAnnotation == null) { return; } for (String pattern : mapping.getPatternsCondition().getPatterns()) { registerRedirectHandler(pattern, redirectAnnotation.code(), mapping); } } private void registerRedirectHandler(String originalURL, int statusCode, RequestMappingInfo info) { // skip when there's an extension if (originalURL.contains(".")) { return; } final String otherURL; // redirect when not trailing if (originalURL.endsWith("/")) { otherURL = originalURL.substring(0, originalURL.length()-1); } // redirect when trailing else { otherURL = originalURL+"/"; } RedirectHandler handler = new RedirectHandler(originalURL, statusCode); registerHandlerMethod(handler, handlerMethod, synthesizeMapping(info, otherURL)); } private RequestMappingInfo synthesizeMapping(RequestMappingInfo existing, String url) { String[] patterns = resolveEmbeddedValuesInPatterns(new String[]{url}); PatternsRequestCondition patternsMatcher = new PatternsRequestCondition( patterns, getUrlPathHelper(), getPathMatcher(), useSuffixPatternMatch(), false, getFileExtensions() ); return new RequestMappingInfo( patternsMatcher, existing.getMethodsCondition(), existing.getParamsCondition(), existing.getHeadersCondition(), existing.getConsumesCondition(), existing.getProducesCondition(), existing.getCustomCondition() ); } private static final Method handlerMethod; static { try { handlerMethod = RedirectHandler.class.getMethod("handle"); } catch (Exception ex) { throw new RuntimeException(ex); } } private static class RedirectHandler { private final String redirectURL; private final int statusCode; public RedirectHandler(String redirectURL, int statusCode) { this.redirectURL = redirectURL; this.statusCode = statusCode; } public View handle() { RedirectView view = new RedirectView(redirectURL); view.setStatusCode(HttpStatus.valueOf(statusCode)); return view; } } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,27 @@ package com.sb.server.web; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Marker annotation which says that a given method should * use a redirect when a trailing slash version is encountered. * * The method should already be annotated with * {@link org.springframework.web.bind.annotation.RequestMapping}. * * @author Ben Fagin * @version 2013-08-22 * @see CustomRequestMappingHandlerMapping */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RedirectTrailingSlash { /** * The status code to use for the redirect. */ int code() default 301; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,27 @@ package com.sb.server.web; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; /** * @author Ben Fagin * @version 2013-04-22 */ @Configuration public class WebConfiguration extends WebMvcConfigurationSupport { @Bean @Override public RequestMappingHandlerMapping requestMappingHandlerMapping() { CustomRequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping(); handlerMapping.setOrder(0); handlerMapping.setInterceptors(getInterceptors()); handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager()); handlerMapping.setUseTrailingSlashMatch(false); handlerMapping.setUseSuffixPatternMatch(false); return handlerMapping; } }