23 changed files with 1098 additions and 764 deletions
@ -1,134 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2011 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.springframework.web.servlet.config.annotation; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.web.context.request.WebRequestInterceptor; |
|
||||||
import org.springframework.web.servlet.HandlerInterceptor; |
|
||||||
import org.springframework.web.servlet.handler.MappedInterceptor; |
|
||||||
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter; |
|
||||||
|
|
||||||
/** |
|
||||||
* Helps with configuring an ordered set of Spring MVC interceptors of type {@link HandlerInterceptor} or |
|
||||||
* {@link WebRequestInterceptor}. Interceptors can be registered with a set of path patterns. |
|
||||||
* |
|
||||||
* @author Rossen Stoyanchev |
|
||||||
* @since 3.1 |
|
||||||
*/ |
|
||||||
public class InterceptorConfigurer { |
|
||||||
|
|
||||||
private final List<Object> interceptors = new ArrayList<Object>(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Add a {@link HandlerInterceptor} that should apply to any request. |
|
||||||
*/ |
|
||||||
public void addInterceptor(HandlerInterceptor interceptor) { |
|
||||||
register(interceptor); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add a {@link WebRequestInterceptor} that should apply to any request. |
|
||||||
*/ |
|
||||||
public void addInterceptor(WebRequestInterceptor interceptor) { |
|
||||||
register(asHandlerInterceptorArray(interceptor)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add {@link HandlerInterceptor}s that should apply to any request. |
|
||||||
*/ |
|
||||||
public void addInterceptors(HandlerInterceptor... interceptors) { |
|
||||||
register( interceptors); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add {@link WebRequestInterceptor}s that should apply to any request. |
|
||||||
*/ |
|
||||||
public void addInterceptors(WebRequestInterceptor... interceptors) { |
|
||||||
register(asHandlerInterceptorArray(interceptors)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add a {@link HandlerInterceptor} with a set of URL path patterns it should apply to. |
|
||||||
*/ |
|
||||||
public void mapInterceptor(String[] pathPatterns, HandlerInterceptor interceptor) { |
|
||||||
registerMappedInterceptors(pathPatterns, interceptor); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add a {@link WebRequestInterceptor} with a set of URL path patterns it should apply to. |
|
||||||
*/ |
|
||||||
public void mapInterceptor(String[] pathPatterns, WebRequestInterceptor interceptors) { |
|
||||||
registerMappedInterceptors(pathPatterns, asHandlerInterceptorArray(interceptors)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add {@link HandlerInterceptor}s with a set of URL path patterns they should apply to. |
|
||||||
*/ |
|
||||||
public void mapInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors) { |
|
||||||
registerMappedInterceptors(pathPatterns, interceptors); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add {@link WebRequestInterceptor}s with a set of URL path patterns they should apply to. |
|
||||||
*/ |
|
||||||
public void mapInterceptors(String[] pathPatterns, WebRequestInterceptor... interceptors) { |
|
||||||
registerMappedInterceptors(pathPatterns, asHandlerInterceptorArray(interceptors)); |
|
||||||
} |
|
||||||
|
|
||||||
private static HandlerInterceptor[] asHandlerInterceptorArray(WebRequestInterceptor...interceptors) { |
|
||||||
HandlerInterceptor[] result = new HandlerInterceptor[interceptors.length]; |
|
||||||
for (int i = 0; i < result.length; i++) { |
|
||||||
result[i] = new WebRequestHandlerInterceptorAdapter(interceptors[i]); |
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Stores the given set of {@link HandlerInterceptor}s internally. |
|
||||||
* @param interceptors one or more interceptors to be stored |
|
||||||
*/ |
|
||||||
protected void register(HandlerInterceptor...interceptors) { |
|
||||||
Assert.notEmpty(interceptors, "At least one interceptor must be provided"); |
|
||||||
for (HandlerInterceptor interceptor : interceptors) { |
|
||||||
this.interceptors.add(interceptor); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Stores the given set of {@link HandlerInterceptor}s and path patterns internally. |
|
||||||
* @param pathPatterns path patterns or {@code null} |
|
||||||
* @param interceptors one or more interceptors to be stored |
|
||||||
*/ |
|
||||||
protected void registerMappedInterceptors(String[] pathPatterns, HandlerInterceptor...interceptors) { |
|
||||||
Assert.notEmpty(interceptors, "At least one interceptor must be provided"); |
|
||||||
Assert.notEmpty(pathPatterns, "Path patterns must be provided"); |
|
||||||
for (HandlerInterceptor interceptor : interceptors) { |
|
||||||
this.interceptors.add(new MappedInterceptor(pathPatterns, interceptor)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Returns all registered interceptors. |
|
||||||
*/ |
|
||||||
protected List<Object> getInterceptors() { |
|
||||||
return interceptors; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,68 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2011 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.web.servlet.config.annotation; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.web.servlet.HandlerInterceptor; |
||||||
|
import org.springframework.web.servlet.handler.MappedInterceptor; |
||||||
|
|
||||||
|
/** |
||||||
|
* Encapsulates a {@link HandlerInterceptor} and an optional list of URL patterns. |
||||||
|
* Results in the creation of a {@link MappedInterceptor} if URL patterns are provided. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @author Keith Donald |
||||||
|
* @since 3.1 |
||||||
|
*/ |
||||||
|
public class InterceptorRegistration { |
||||||
|
|
||||||
|
private final HandlerInterceptor interceptor; |
||||||
|
|
||||||
|
private final List<String> pathPatterns = new ArrayList<String>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates an {@link InterceptorRegistration} instance. |
||||||
|
*/ |
||||||
|
public InterceptorRegistration(HandlerInterceptor interceptor) { |
||||||
|
Assert.notNull(interceptor, "Interceptor is required"); |
||||||
|
this.interceptor = interceptor; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds one or more URL patterns to which the registered interceptor should apply to. |
||||||
|
* If no URL patterns are provided, the interceptor applies to all paths. |
||||||
|
*/ |
||||||
|
public void addPathPatterns(String... pathPatterns) { |
||||||
|
this.pathPatterns.addAll(Arrays.asList(pathPatterns)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the underlying interceptor. If URL patterns are provided the returned type is |
||||||
|
* {@link MappedInterceptor}; otherwise {@link HandlerInterceptor}. |
||||||
|
*/ |
||||||
|
protected Object getInterceptor() { |
||||||
|
if (pathPatterns.isEmpty()) { |
||||||
|
return interceptor; |
||||||
|
} |
||||||
|
return new MappedInterceptor(pathPatterns.toArray(new String[pathPatterns.size()]), interceptor); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,75 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2011 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.web.servlet.config.annotation; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.springframework.web.context.request.WebRequestInterceptor; |
||||||
|
import org.springframework.web.servlet.HandlerInterceptor; |
||||||
|
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Stores and provides access to a list of interceptors. For each interceptor you can optionally |
||||||
|
* specify one or more URL patterns it applies to. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @author Keith Donald |
||||||
|
* |
||||||
|
* @since 3.1 |
||||||
|
*/ |
||||||
|
public class InterceptorRegistry { |
||||||
|
|
||||||
|
private final List<InterceptorRegistration> registrations = new ArrayList<InterceptorRegistration>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds the provided {@link HandlerInterceptor}. |
||||||
|
* @param interceptor the interceptor to add |
||||||
|
* @return An {@link InterceptorRegistration} that allows you optionally configure the |
||||||
|
* registered interceptor further for example adding URL patterns it should apply to. |
||||||
|
*/ |
||||||
|
public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) { |
||||||
|
InterceptorRegistration registration = new InterceptorRegistration(interceptor); |
||||||
|
registrations.add(registration); |
||||||
|
return registration; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds the provided {@link WebRequestInterceptor}. |
||||||
|
* @param interceptor the interceptor to add |
||||||
|
* @return An {@link InterceptorRegistration} that allows you optionally configure the |
||||||
|
* registered interceptor further for example adding URL patterns it should apply to. |
||||||
|
*/ |
||||||
|
public InterceptorRegistration addWebRequestInterceptor(WebRequestInterceptor interceptor) { |
||||||
|
WebRequestHandlerInterceptorAdapter adapted = new WebRequestHandlerInterceptorAdapter(interceptor); |
||||||
|
InterceptorRegistration registration = new InterceptorRegistration(adapted); |
||||||
|
registrations.add(registration); |
||||||
|
return registration; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all registered interceptors. |
||||||
|
*/ |
||||||
|
protected List<Object> getInterceptors() { |
||||||
|
List<Object> interceptors = new ArrayList<Object>(); |
||||||
|
for (InterceptorRegistration registration : registrations) { |
||||||
|
interceptors.add(registration.getInterceptor()); |
||||||
|
} |
||||||
|
return interceptors ; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,197 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2011 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.springframework.web.servlet.config.annotation; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.LinkedHashMap; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import javax.servlet.ServletContext; |
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext; |
|
||||||
import org.springframework.core.io.Resource; |
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.util.CollectionUtils; |
|
||||||
import org.springframework.web.HttpRequestHandler; |
|
||||||
import org.springframework.web.servlet.HandlerMapping; |
|
||||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; |
|
||||||
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; |
|
||||||
|
|
||||||
/** |
|
||||||
* Helps with configuring a handler for serving static resources such as images, css files and others through |
|
||||||
* Spring MVC including setting cache headers optimized for efficient loading in a web browser. Resources can |
|
||||||
* be served out of locations under web application root, from the classpath, and others. |
|
||||||
* |
|
||||||
* <p>To configure resource handling, use {@link #addPathMappings(String...)} to add one or more URL path patterns |
|
||||||
* within the current Servlet context, to use for serving resources from the handler, such as {@code "/resources/**"}. |
|
||||||
* |
|
||||||
* <p>Then use {@link #addResourceLocations(String...)} to add one or more locations from which to serve |
|
||||||
* static content. For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}} allows resources |
|
||||||
* to be served both from the web application root and from any JAR on the classpath that contains a |
|
||||||
* {@code /META-INF/public-web-resources/} directory, with resources in the web application root taking precedence. |
|
||||||
* |
|
||||||
* <p>Optionally use {@link #setCachePeriod(Integer)} to specify the cache period for the resources served by the |
|
||||||
* handler and {@link #setOrder(int)} to set the order in which to serve requests relative to other |
|
||||||
* {@link HandlerMapping} instances in the Spring MVC web application context. |
|
||||||
* |
|
||||||
* @author Rossen Stoyanchev |
|
||||||
* @since 3.1 |
|
||||||
* |
|
||||||
* @see DefaultServletHandlerConfigurer |
|
||||||
*/ |
|
||||||
public class ResourceConfigurer { |
|
||||||
|
|
||||||
private final List<String> pathPatterns = new ArrayList<String>(); |
|
||||||
|
|
||||||
private final List<Resource> locations = new ArrayList<Resource>(); |
|
||||||
|
|
||||||
private Integer cachePeriod; |
|
||||||
|
|
||||||
private int order = Integer.MAX_VALUE -1; |
|
||||||
|
|
||||||
private final ServletContext servletContext; |
|
||||||
|
|
||||||
private final ApplicationContext applicationContext; |
|
||||||
|
|
||||||
public ResourceConfigurer(ApplicationContext applicationContext, ServletContext servletContext) { |
|
||||||
Assert.notNull(applicationContext, "ApplicationContext is required"); |
|
||||||
this.applicationContext = applicationContext; |
|
||||||
this.servletContext = servletContext; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add a URL path pattern within the current Servlet context to use for serving static resources |
|
||||||
* using the Spring MVC {@link ResourceHttpRequestHandler}, for example {@code "/resources/**"}. |
|
||||||
* @return the same {@link ResourceConfigurer} instance for chained method invocation |
|
||||||
*/ |
|
||||||
public ResourceConfigurer addPathMapping(String pathPattern) { |
|
||||||
return addPathMappings(pathPattern); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add several URL path patterns within the current Servlet context to use for serving static resources |
|
||||||
* using the Spring MVC {@link ResourceHttpRequestHandler}, for example {@code "/resources/**"}. |
|
||||||
* @return the same {@link ResourceConfigurer} instance for chained method invocation |
|
||||||
*/ |
|
||||||
public ResourceConfigurer addPathMappings(String...pathPatterns) { |
|
||||||
for (String path : pathPatterns) { |
|
||||||
this.pathPatterns.add(path); |
|
||||||
} |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add resource location from which to serve static content. The location must point to a valid |
|
||||||
* directory. <p>For example, a value of {@code "/"} will allow resources to be served both from the web |
|
||||||
* application root. Also see {@link #addResourceLocations(String...)} for mapping several resource locations. |
|
||||||
* @return the same {@link ResourceConfigurer} instance for chained method invocation |
|
||||||
*/ |
|
||||||
public ResourceConfigurer addResourceLocation(String resourceLocation) { |
|
||||||
return addResourceLocations(resourceLocation); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add one or more resource locations from which to serve static content. Each location must point to a valid |
|
||||||
* directory. Multiple locations may be specified as a comma-separated list, and the locations will be checked |
|
||||||
* for a given resource in the order specified. |
|
||||||
* <p>For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}} allows resources to |
|
||||||
* be served both from the web application root and from any JAR on the classpath that contains a |
|
||||||
* {@code /META-INF/public-web-resources/} directory, with resources in the web application root taking precedence. |
|
||||||
* @return the same {@link ResourceConfigurer} instance for chained method invocation |
|
||||||
*/ |
|
||||||
public ResourceConfigurer addResourceLocations(String...resourceLocations) { |
|
||||||
for (String location : resourceLocations) { |
|
||||||
this.locations.add(applicationContext.getResource(location)); |
|
||||||
} |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Specify the cache period for the resources served by the resource handler, in seconds. The default is to not |
|
||||||
* send any cache headers but to rely on last-modified timestamps only. Set to 0 in order to send cache headers |
|
||||||
* that prevent caching, or to a positive number of seconds to send cache headers with the given max-age value. |
|
||||||
* @param cachePeriod the time to cache resources in seconds |
|
||||||
* @return the same {@link ResourceConfigurer} instance for chained method invocation |
|
||||||
*/ |
|
||||||
public ResourceConfigurer setCachePeriod(Integer cachePeriod) { |
|
||||||
this.cachePeriod = cachePeriod; |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the cache period for static resources served by the resource handler. |
|
||||||
*/ |
|
||||||
public Integer getCachePeriod() { |
|
||||||
return cachePeriod; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Specify the order in which to serve static resources relative to other {@link HandlerMapping} instances in the |
|
||||||
* Spring MVC web application context. The default value is {@code Integer.MAX_VALUE-1}. |
|
||||||
*/ |
|
||||||
public ResourceConfigurer setOrder(int order) { |
|
||||||
this.order = order; |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the order in which to serve static resources relative other {@link HandlerMapping} instances. |
|
||||||
* @return the same {@link ResourceConfigurer} instance for chained method invocation |
|
||||||
*/ |
|
||||||
public Integer getOrder() { |
|
||||||
return order; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return a {@link SimpleUrlHandlerMapping} with a {@link ResourceHttpRequestHandler} mapped to one or more |
|
||||||
* URL path patterns. If the no path patterns were specified, the HandlerMapping returned contains an empty map. |
|
||||||
*/ |
|
||||||
protected SimpleUrlHandlerMapping getHandlerMapping() { |
|
||||||
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); |
|
||||||
handlerMapping.setOrder(order); |
|
||||||
handlerMapping.setUrlMap(getUrlMap()); |
|
||||||
return handlerMapping; |
|
||||||
} |
|
||||||
|
|
||||||
private Map<String, HttpRequestHandler> getUrlMap() { |
|
||||||
Map<String, HttpRequestHandler> urlMap = new LinkedHashMap<String, HttpRequestHandler>(); |
|
||||||
if (!pathPatterns.isEmpty()) { |
|
||||||
ResourceHttpRequestHandler requestHandler = createRequestHandler(); |
|
||||||
for (String pathPattern : pathPatterns) { |
|
||||||
urlMap.put(pathPattern, requestHandler); |
|
||||||
} |
|
||||||
} |
|
||||||
return urlMap; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a {@link ResourceHttpRequestHandler} instance. |
|
||||||
*/ |
|
||||||
protected ResourceHttpRequestHandler createRequestHandler() { |
|
||||||
Assert.isTrue(!CollectionUtils.isEmpty(locations), "Path patterns specified but not resource locations."); |
|
||||||
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler(); |
|
||||||
requestHandler.setApplicationContext(applicationContext); |
|
||||||
requestHandler.setServletContext(servletContext); |
|
||||||
requestHandler.setLocations(locations); |
|
||||||
if (cachePeriod != null) { |
|
||||||
requestHandler.setCacheSeconds(cachePeriod); |
|
||||||
} |
|
||||||
return requestHandler; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,105 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2011 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.web.servlet.config.annotation; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.springframework.core.io.Resource; |
||||||
|
import org.springframework.core.io.ResourceLoader; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.CollectionUtils; |
||||||
|
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; |
||||||
|
|
||||||
|
/** |
||||||
|
* Encapsulates information required to create a resource handlers. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @author Keith Donald |
||||||
|
* |
||||||
|
* @since 3.1 |
||||||
|
*/ |
||||||
|
public class ResourceHandlerRegistration { |
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader; |
||||||
|
|
||||||
|
private final String[] pathPatterns; |
||||||
|
|
||||||
|
private final List<Resource> locations = new ArrayList<Resource>(); |
||||||
|
|
||||||
|
private Integer cachePeriod; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a {@link ResourceHandlerRegistration} instance. |
||||||
|
* @param resourceLoader a resource loader for turning a String location into a {@link Resource} |
||||||
|
* @param pathPatterns one or more resource URL path patterns |
||||||
|
*/ |
||||||
|
public ResourceHandlerRegistration(ResourceLoader resourceLoader, String... pathPatterns) { |
||||||
|
Assert.notEmpty(pathPatterns, "At least one path pattern is required for resource handling."); |
||||||
|
this.resourceLoader = resourceLoader; |
||||||
|
this.pathPatterns = pathPatterns; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add one or more resource locations from which to serve static content. Each location must point to a valid |
||||||
|
* directory. Multiple locations may be specified as a comma-separated list, and the locations will be checked |
||||||
|
* for a given resource in the order specified. |
||||||
|
* <p>For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}} allows resources to |
||||||
|
* be served both from the web application root and from any JAR on the classpath that contains a |
||||||
|
* {@code /META-INF/public-web-resources/} directory, with resources in the web application root taking precedence. |
||||||
|
* @return the same {@link ResourceHandlerRegistration} instance for chained method invocation |
||||||
|
*/ |
||||||
|
public ResourceHandlerRegistration addResourceLocations(String...resourceLocations) { |
||||||
|
for (String location : resourceLocations) { |
||||||
|
this.locations.add(resourceLoader.getResource(location)); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the cache period for the resources served by the resource handler, in seconds. The default is to not |
||||||
|
* send any cache headers but to rely on last-modified timestamps only. Set to 0 in order to send cache headers |
||||||
|
* that prevent caching, or to a positive number of seconds to send cache headers with the given max-age value. |
||||||
|
* @param cachePeriod the time to cache resources in seconds |
||||||
|
* @return the same {@link ResourceHandlerRegistration} instance for chained method invocation |
||||||
|
*/ |
||||||
|
public ResourceHandlerRegistration setCachePeriod(Integer cachePeriod) { |
||||||
|
this.cachePeriod = cachePeriod; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the URL path patterns for the resource handler. |
||||||
|
*/ |
||||||
|
protected String[] getPathPatterns() { |
||||||
|
return pathPatterns; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a {@link ResourceHttpRequestHandler} instance. |
||||||
|
*/ |
||||||
|
protected ResourceHttpRequestHandler getRequestHandler() { |
||||||
|
Assert.isTrue(!CollectionUtils.isEmpty(locations), "At least one location is required for resource handling."); |
||||||
|
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler(); |
||||||
|
requestHandler.setLocations(locations); |
||||||
|
if (cachePeriod != null) { |
||||||
|
requestHandler.setCacheSeconds(cachePeriod); |
||||||
|
} |
||||||
|
return requestHandler; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,111 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2011 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.web.servlet.config.annotation; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import javax.servlet.ServletContext; |
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.web.HttpRequestHandler; |
||||||
|
import org.springframework.web.servlet.HandlerMapping; |
||||||
|
import org.springframework.web.servlet.handler.AbstractHandlerMapping; |
||||||
|
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; |
||||||
|
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; |
||||||
|
|
||||||
|
/** |
||||||
|
* Stores registrations of resource handlers for serving static resources such as images, css files and others |
||||||
|
* through Spring MVC including setting cache headers optimized for efficient loading in a web browser. |
||||||
|
* Resources can be served out of locations under web application root, from the classpath, and others. |
||||||
|
* |
||||||
|
* <p>To create a resource handler, use {@link #addResourceHandler(String...)} providing the URL path patterns |
||||||
|
* for which the handler should be invoked to serve static resources (e.g. {@code "/resources/**"}). |
||||||
|
* |
||||||
|
* <p>Then use additional methods on the returned {@link ResourceHandlerRegistration} to add one or more |
||||||
|
* locations from which to serve static content from (e.g. {{@code "/"}, |
||||||
|
* {@code "classpath:/META-INF/public-web-resources/"}}) or to specify a cache period for served resources. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @since 3.1 |
||||||
|
* |
||||||
|
* @see DefaultServletHandlerConfigurer |
||||||
|
*/ |
||||||
|
public class ResourceHandlerRegistry { |
||||||
|
|
||||||
|
private final ServletContext servletContext; |
||||||
|
|
||||||
|
private final ApplicationContext applicationContext; |
||||||
|
|
||||||
|
private final List<ResourceHandlerRegistration> registrations = new ArrayList<ResourceHandlerRegistration>(); |
||||||
|
|
||||||
|
private int order = Integer.MAX_VALUE -1; |
||||||
|
|
||||||
|
public ResourceHandlerRegistry(ApplicationContext applicationContext, ServletContext servletContext) { |
||||||
|
Assert.notNull(applicationContext, "ApplicationContext is required"); |
||||||
|
this.applicationContext = applicationContext; |
||||||
|
this.servletContext = servletContext; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a resource handler for serving static resources based on the specified URL path patterns. |
||||||
|
* The handler will be invoked for every incoming request that matches to one of the specified path patterns. |
||||||
|
* @return A {@link ResourceHandlerRegistration} to use to further configure the registered resource handler. |
||||||
|
*/ |
||||||
|
public ResourceHandlerRegistration addResourceHandler(String... pathPatterns) { |
||||||
|
ResourceHandlerRegistration registration = new ResourceHandlerRegistration(applicationContext, pathPatterns); |
||||||
|
registrations.add(registration); |
||||||
|
return registration; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the order to use for resource handling relative to other {@link HandlerMapping}s configured in |
||||||
|
* the Spring MVC application context. The default value used is {@code Integer.MAX_VALUE-1}. |
||||||
|
*/ |
||||||
|
public ResourceHandlerRegistry setOrder(int order) { |
||||||
|
this.order = order; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a handler mapping with the mapped resource handlers; or {@code null} in case of no registrations. |
||||||
|
*/ |
||||||
|
protected AbstractHandlerMapping getHandlerMapping() { |
||||||
|
if (registrations.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, HttpRequestHandler> urlMap = new LinkedHashMap<String, HttpRequestHandler>(); |
||||||
|
for (ResourceHandlerRegistration registration : registrations) { |
||||||
|
for (String pathPattern : registration.getPathPatterns()) { |
||||||
|
ResourceHttpRequestHandler requestHandler = registration.getRequestHandler(); |
||||||
|
requestHandler.setServletContext(servletContext); |
||||||
|
requestHandler.setApplicationContext(applicationContext); |
||||||
|
urlMap.put(pathPattern, requestHandler); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); |
||||||
|
handlerMapping.setOrder(order); |
||||||
|
handlerMapping.setUrlMap(urlMap); |
||||||
|
return handlerMapping; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,87 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2011 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package org.springframework.web.servlet.config.annotation; |
|
||||||
|
|
||||||
import java.util.LinkedHashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import org.springframework.web.servlet.HandlerMapping; |
|
||||||
import org.springframework.web.servlet.RequestToViewNameTranslator; |
|
||||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; |
|
||||||
import org.springframework.web.servlet.mvc.Controller; |
|
||||||
import org.springframework.web.servlet.mvc.ParameterizableViewController; |
|
||||||
|
|
||||||
/** |
|
||||||
* Helps with view controllers. View controllers provide a direct mapping between a URL path and view name. This is |
|
||||||
* useful when serving requests that don't require application-specific controller logic and can be forwarded |
|
||||||
* directly to a view for rendering. |
|
||||||
* |
|
||||||
* @author Rossen Stoyanchev |
|
||||||
* @since 3.1 |
|
||||||
*/ |
|
||||||
public class ViewControllerConfigurer { |
|
||||||
|
|
||||||
private final Map<String, Controller> urlMap = new LinkedHashMap<String, Controller>(); |
|
||||||
|
|
||||||
private int order = 1; |
|
||||||
|
|
||||||
/** |
|
||||||
* Map the URL path to a view name derived by convention through the DispatcherServlet's |
|
||||||
* {@link RequestToViewNameTranslator}. |
|
||||||
* @return the same {@link ViewControllerConfigurer} instance for convenient chained method invocation |
|
||||||
*/ |
|
||||||
public ViewControllerConfigurer mapViewNameByConvention(String urlPath) { |
|
||||||
return mapViewName(urlPath, null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Map the URL path to the specified view name. |
|
||||||
* @return the same {@link ViewControllerConfigurer} instance for convenient chained method invocation |
|
||||||
*/ |
|
||||||
public ViewControllerConfigurer mapViewName(String urlPath, String viewName) { |
|
||||||
ParameterizableViewController controller = new ParameterizableViewController(); |
|
||||||
controller.setViewName(viewName); |
|
||||||
urlMap.put(urlPath, controller); |
|
||||||
return this; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Specify the order in which to check view controller path mappings relative to other {@link HandlerMapping} |
|
||||||
* instances in the Spring MVC web application context. The default value is 1. |
|
||||||
*/ |
|
||||||
public void setOrder(int order) { |
|
||||||
this.order = order; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the order in which to check view controller path mappings relative to other {@link HandlerMapping}s. |
|
||||||
*/ |
|
||||||
public int getOrder() { |
|
||||||
return order; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return a {@link SimpleUrlHandlerMapping} with URL path to view controllers mappings. |
|
||||||
*/ |
|
||||||
protected SimpleUrlHandlerMapping getHandlerMapping() { |
|
||||||
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); |
|
||||||
handlerMapping.setOrder(order); |
|
||||||
handlerMapping.setUrlMap(urlMap); |
|
||||||
return handlerMapping; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,70 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2011 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.web.servlet.config.annotation; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.web.servlet.RequestToViewNameTranslator; |
||||||
|
import org.springframework.web.servlet.mvc.ParameterizableViewController; |
||||||
|
|
||||||
|
/** |
||||||
|
* Encapsulates information required to create a view controller. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @author Keith Donald |
||||||
|
* @since 3.1 |
||||||
|
*/ |
||||||
|
public class ViewControllerRegistration { |
||||||
|
|
||||||
|
private final String urlPath; |
||||||
|
|
||||||
|
private String viewName; |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a {@link ViewControllerRegistration} with the given URL path. When a request matches |
||||||
|
* to the given URL path this view controller will process it. |
||||||
|
*/ |
||||||
|
public ViewControllerRegistration(String urlPath) { |
||||||
|
Assert.notNull(urlPath, "A URL path is required to create a view controller."); |
||||||
|
this.urlPath = urlPath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the view name to use for this view controller. This field is optional. If not specified the |
||||||
|
* view controller will return a {@code null} view name, which will be resolved through the configured |
||||||
|
* {@link RequestToViewNameTranslator}. By default that means "/foo/bar" would resolve to "foo/bar". |
||||||
|
*/ |
||||||
|
public void setViewName(String viewName) { |
||||||
|
this.viewName = viewName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the URL path for the view controller. |
||||||
|
*/ |
||||||
|
protected String getUrlPath() { |
||||||
|
return urlPath; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the view controllers. |
||||||
|
*/ |
||||||
|
protected Object getViewController() { |
||||||
|
ParameterizableViewController controller = new ParameterizableViewController(); |
||||||
|
controller.setViewName(viewName); |
||||||
|
return controller; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,77 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2011 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.web.servlet.config.annotation; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.springframework.web.servlet.HandlerMapping; |
||||||
|
import org.springframework.web.servlet.handler.AbstractHandlerMapping; |
||||||
|
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; |
||||||
|
|
||||||
|
/** |
||||||
|
* Stores registrations of view controllers. A view controller does nothing more than return a specified |
||||||
|
* view name. It saves you from having to write a controller when you want to forward the request straight |
||||||
|
* through to a view such as a JSP. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @author Keith Donald |
||||||
|
* @since 3.1 |
||||||
|
*/ |
||||||
|
public class ViewControllerRegistry { |
||||||
|
|
||||||
|
private final List<ViewControllerRegistration> registrations = new ArrayList<ViewControllerRegistration>(); |
||||||
|
|
||||||
|
private int order = 1; |
||||||
|
|
||||||
|
public ViewControllerRegistration addViewController(String urlPath) { |
||||||
|
ViewControllerRegistration registration = new ViewControllerRegistration(urlPath); |
||||||
|
registrations.add(registration); |
||||||
|
return registration; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the order to use for ViewControllers mappings relative to other {@link HandlerMapping}s |
||||||
|
* configured in the Spring MVC application context. The default value for view controllers is 1, |
||||||
|
* which is 1 higher than the value used for annotated controllers. |
||||||
|
*/ |
||||||
|
public void setOrder(int order) { |
||||||
|
this.order = order; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a handler mapping with the mapped ViewControllers; or {@code null} in case of no registrations. |
||||||
|
*/ |
||||||
|
protected AbstractHandlerMapping getHandlerMapping() { |
||||||
|
if (registrations.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
Map<String, Object> urlMap = new LinkedHashMap<String, Object>(); |
||||||
|
for (ViewControllerRegistration registration : registrations) { |
||||||
|
urlMap.put(registration.getUrlPath(), registration.getViewController()); |
||||||
|
} |
||||||
|
|
||||||
|
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); |
||||||
|
handlerMapping.setOrder(order); |
||||||
|
handlerMapping.setUrlMap(urlMap); |
||||||
|
return handlerMapping; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,315 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2011 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.web.servlet.config.annotation; |
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertNotNull; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
|
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
import org.springframework.beans.DirectFieldAccessor; |
||||||
|
import org.springframework.beans.TestBean; |
||||||
|
import org.springframework.core.convert.ConversionService; |
||||||
|
import org.springframework.core.convert.converter.Converter; |
||||||
|
import org.springframework.core.io.FileSystemResourceLoader; |
||||||
|
import org.springframework.format.FormatterRegistry; |
||||||
|
import org.springframework.format.support.FormattingConversionService; |
||||||
|
import org.springframework.http.converter.HttpMessageConverter; |
||||||
|
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; |
||||||
|
import org.springframework.mock.web.MockHttpServletRequest; |
||||||
|
import org.springframework.mock.web.MockServletContext; |
||||||
|
import org.springframework.stereotype.Controller; |
||||||
|
import org.springframework.validation.BeanPropertyBindingResult; |
||||||
|
import org.springframework.validation.Errors; |
||||||
|
import org.springframework.validation.Validator; |
||||||
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; |
||||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||||
|
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; |
||||||
|
import org.springframework.web.context.support.StaticWebApplicationContext; |
||||||
|
import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor; |
||||||
|
import org.springframework.web.method.support.HandlerMethodArgumentResolver; |
||||||
|
import org.springframework.web.method.support.HandlerMethodReturnValueHandler; |
||||||
|
import org.springframework.web.servlet.HandlerExceptionResolver; |
||||||
|
import org.springframework.web.servlet.HandlerExecutionChain; |
||||||
|
import org.springframework.web.servlet.handler.AbstractHandlerMapping; |
||||||
|
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; |
||||||
|
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor; |
||||||
|
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite; |
||||||
|
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; |
||||||
|
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; |
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; |
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; |
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.support.DefaultMethodReturnValueHandler; |
||||||
|
|
||||||
|
/** |
||||||
|
* A test fixture for {@link WebMvcConfigurationSupport}. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
*/ |
||||||
|
public class WebMvcConfigurationSupportTests { |
||||||
|
|
||||||
|
private TestWebMvcConfiguration mvcConfiguration; |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() { |
||||||
|
mvcConfiguration = new TestWebMvcConfiguration(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void requestMappingHandlerMapping() throws Exception { |
||||||
|
StaticWebApplicationContext cxt = new StaticWebApplicationContext(); |
||||||
|
cxt.registerSingleton("controller", TestController.class); |
||||||
|
|
||||||
|
RequestMappingHandlerMapping handlerMapping = mvcConfiguration.requestMappingHandlerMapping(); |
||||||
|
assertEquals(0, handlerMapping.getOrder()); |
||||||
|
|
||||||
|
handlerMapping.setApplicationContext(cxt); |
||||||
|
HandlerExecutionChain chain = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/")); |
||||||
|
assertNotNull(chain.getInterceptors()); |
||||||
|
assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[0].getClass()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void emptyViewControllerHandlerMapping() { |
||||||
|
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) mvcConfiguration.viewControllerHandlerMapping(); |
||||||
|
assertNotNull(handlerMapping); |
||||||
|
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder()); |
||||||
|
assertTrue(handlerMapping.getClass().getName().endsWith("EmptyHandlerMapping")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void beanNameHandlerMapping() throws Exception { |
||||||
|
StaticWebApplicationContext cxt = new StaticWebApplicationContext(); |
||||||
|
cxt.registerSingleton("/controller", TestController.class); |
||||||
|
|
||||||
|
HttpServletRequest request = new MockHttpServletRequest("GET", "/controller"); |
||||||
|
|
||||||
|
BeanNameUrlHandlerMapping handlerMapping = mvcConfiguration.beanNameHandlerMapping(); |
||||||
|
assertEquals(2, handlerMapping.getOrder()); |
||||||
|
|
||||||
|
handlerMapping.setApplicationContext(cxt); |
||||||
|
HandlerExecutionChain chain = handlerMapping.getHandler(request); |
||||||
|
assertNotNull(chain.getInterceptors()); |
||||||
|
assertEquals(2, chain.getInterceptors().length); |
||||||
|
assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[1].getClass()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void emptyResourceHandlerMapping() { |
||||||
|
mvcConfiguration.setApplicationContext(new StaticWebApplicationContext()); |
||||||
|
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) mvcConfiguration.resourceHandlerMapping(); |
||||||
|
assertNotNull(handlerMapping); |
||||||
|
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder()); |
||||||
|
assertTrue(handlerMapping.getClass().getName().endsWith("EmptyHandlerMapping")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void emptyDefaultServletHandlerMapping() { |
||||||
|
mvcConfiguration.setServletContext(new MockServletContext()); |
||||||
|
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) mvcConfiguration.defaultServletHandlerMapping(); |
||||||
|
assertNotNull(handlerMapping); |
||||||
|
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder()); |
||||||
|
assertTrue(handlerMapping.getClass().getName().endsWith("EmptyHandlerMapping")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void requestMappingHandlerAdapter() throws Exception { |
||||||
|
RequestMappingHandlerAdapter adapter = mvcConfiguration.requestMappingHandlerAdapter(); |
||||||
|
|
||||||
|
List<HttpMessageConverter<?>> expectedConverters = new ArrayList<HttpMessageConverter<?>>(); |
||||||
|
mvcConfiguration.addDefaultHttpMessageConverters(expectedConverters); |
||||||
|
assertEquals(expectedConverters.size(), adapter.getMessageConverters().size()); |
||||||
|
|
||||||
|
ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer(); |
||||||
|
assertNotNull(initializer); |
||||||
|
|
||||||
|
ConversionService conversionService = initializer.getConversionService(); |
||||||
|
assertNotNull(conversionService); |
||||||
|
assertTrue(conversionService instanceof FormattingConversionService); |
||||||
|
|
||||||
|
Validator validator = initializer.getValidator(); |
||||||
|
assertNotNull(validator); |
||||||
|
assertTrue(validator instanceof LocalValidatorFactoryBean); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void handlerExceptionResolver() throws Exception { |
||||||
|
HandlerExceptionResolverComposite compositeResolver = |
||||||
|
(HandlerExceptionResolverComposite) mvcConfiguration.handlerExceptionResolver(); |
||||||
|
|
||||||
|
assertEquals(0, compositeResolver.getOrder()); |
||||||
|
|
||||||
|
List<HandlerExceptionResolver> expectedResolvers = new ArrayList<HandlerExceptionResolver>(); |
||||||
|
mvcConfiguration.addDefaultHandlerExceptionResolvers(expectedResolvers); |
||||||
|
assertEquals(expectedResolvers.size(), compositeResolver.getExceptionResolvers().size()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void webMvcConfigurerExtensionHooks() throws Exception { |
||||||
|
|
||||||
|
StaticWebApplicationContext appCxt = new StaticWebApplicationContext(); |
||||||
|
appCxt.setServletContext(new MockServletContext(new FileSystemResourceLoader())); |
||||||
|
appCxt.registerSingleton("controller", TestController.class); |
||||||
|
|
||||||
|
WebConfig webConfig = new WebConfig(); |
||||||
|
webConfig.setApplicationContext(appCxt); |
||||||
|
webConfig.setServletContext(appCxt.getServletContext()); |
||||||
|
|
||||||
|
String actual = webConfig.mvcConversionService().convert(new TestBean(), String.class); |
||||||
|
assertEquals("converted", actual); |
||||||
|
|
||||||
|
RequestMappingHandlerAdapter adapter = webConfig.requestMappingHandlerAdapter(); |
||||||
|
assertEquals(1, adapter.getMessageConverters().size()); |
||||||
|
|
||||||
|
ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer(); |
||||||
|
assertNotNull(initializer); |
||||||
|
|
||||||
|
BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(null, ""); |
||||||
|
initializer.getValidator().validate(null, bindingResult); |
||||||
|
assertEquals("invalid", bindingResult.getAllErrors().get(0).getCode()); |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
List<HandlerMethodArgumentResolver> argResolvers= (List<HandlerMethodArgumentResolver>) |
||||||
|
new DirectFieldAccessor(adapter).getPropertyValue("customArgumentResolvers"); |
||||||
|
assertEquals(1, argResolvers.size()); |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
List<HandlerMethodReturnValueHandler> handlers = (List<HandlerMethodReturnValueHandler>) |
||||||
|
new DirectFieldAccessor(adapter).getPropertyValue("customReturnValueHandlers"); |
||||||
|
assertEquals(1, handlers.size()); |
||||||
|
|
||||||
|
HandlerExceptionResolverComposite composite = (HandlerExceptionResolverComposite) webConfig.handlerExceptionResolver(); |
||||||
|
assertEquals(1, composite.getExceptionResolvers().size()); |
||||||
|
|
||||||
|
RequestMappingHandlerMapping rmHandlerMapping = webConfig.requestMappingHandlerMapping(); |
||||||
|
rmHandlerMapping.setApplicationContext(appCxt); |
||||||
|
HandlerExecutionChain chain = rmHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/")); |
||||||
|
assertNotNull(chain.getInterceptors()); |
||||||
|
assertEquals(2, chain.getInterceptors().length); |
||||||
|
assertEquals(LocaleChangeInterceptor.class, chain.getInterceptors()[0].getClass()); |
||||||
|
assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[1].getClass()); |
||||||
|
|
||||||
|
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) webConfig.viewControllerHandlerMapping(); |
||||||
|
handlerMapping.setApplicationContext(appCxt); |
||||||
|
assertNotNull(handlerMapping); |
||||||
|
assertEquals(1, handlerMapping.getOrder()); |
||||||
|
HandlerExecutionChain handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/path")); |
||||||
|
assertNotNull(handler.getHandler()); |
||||||
|
|
||||||
|
handlerMapping = (AbstractHandlerMapping) webConfig.resourceHandlerMapping(); |
||||||
|
handlerMapping.setApplicationContext(appCxt); |
||||||
|
assertNotNull(handlerMapping); |
||||||
|
assertEquals(Integer.MAX_VALUE-1, handlerMapping.getOrder()); |
||||||
|
handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/resources/foo.gif")); |
||||||
|
assertNotNull(handler.getHandler()); |
||||||
|
|
||||||
|
handlerMapping = (AbstractHandlerMapping) webConfig.defaultServletHandlerMapping(); |
||||||
|
handlerMapping.setApplicationContext(appCxt); |
||||||
|
assertNotNull(handlerMapping); |
||||||
|
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder()); |
||||||
|
handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/anyPath")); |
||||||
|
assertNotNull(handler.getHandler()); |
||||||
|
} |
||||||
|
|
||||||
|
@Controller |
||||||
|
private static class TestController { |
||||||
|
|
||||||
|
@SuppressWarnings("unused") |
||||||
|
@RequestMapping("/") |
||||||
|
public void handle() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static class TestWebMvcConfiguration extends WebMvcConfigurationSupport { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The purpose of this class is to test that an implementation of a {@link WebMvcConfigurer} |
||||||
|
* can also apply customizations by extension from {@link WebMvcConfigurationSupport}. |
||||||
|
*/ |
||||||
|
private class WebConfig extends WebMvcConfigurationSupport implements WebMvcConfigurer { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addFormatters(FormatterRegistry registry) { |
||||||
|
registry.addConverter(new Converter<TestBean, String>() { |
||||||
|
public String convert(TestBean source) { |
||||||
|
return "converted"; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { |
||||||
|
converters.add(new MappingJacksonHttpMessageConverter()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Validator getValidator() { |
||||||
|
return new Validator() { |
||||||
|
public void validate(Object target, Errors errors) { |
||||||
|
errors.reject("invalid"); |
||||||
|
} |
||||||
|
public boolean supports(Class<?> clazz) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { |
||||||
|
argumentResolvers.add(new ModelAttributeMethodProcessor(true)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) { |
||||||
|
returnValueHandlers.add(new DefaultMethodReturnValueHandler()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { |
||||||
|
exceptionResolvers.add(new SimpleMappingExceptionResolver()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addInterceptors(InterceptorRegistry registry) { |
||||||
|
registry.addInterceptor(new LocaleChangeInterceptor()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addViewControllers(ViewControllerRegistry registry) { |
||||||
|
registry.addViewController("/path"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addResourceHandlers(ResourceHandlerRegistry registry) { |
||||||
|
registry.addResourceHandler("/resources/**").addResourceLocations("src/test/java"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { |
||||||
|
configurer.enable("default"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue