mvc resources handler initial commit
This commit is contained in:
@@ -30,6 +30,7 @@ public class MvcNamespaceHandler extends NamespaceHandlerSupport {
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
|
||||
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.springframework.web.servlet.resources.ResourceHttpRequestHandler;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
|
||||
* {@code resources} element to register a {@link ResourceHttpRequestHandler}.
|
||||
* Will also register a {@link SimpleUrlHandlerMapping} for mapping resource requests, if necessary.
|
||||
* Will also register a {@link HttpRequestHandlerAdapter} if necessary.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0.4
|
||||
*/
|
||||
public class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String HANDLER_ADAPTER_BEAN_NAME = "org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter";
|
||||
|
||||
private static final String HANDLER_MAPPING_BEAN_NAME = "org.springframework.web.servlet.config.resourcesHandlerMapping";
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
|
||||
registerHandlerAdapterIfNecessary(parserContext, source);
|
||||
BeanDefinition handlerMappingDef = registerHandlerMappingIfNecessary(parserContext, source);
|
||||
|
||||
String resourceDirectory = "/resources/";
|
||||
RootBeanDefinition resourceHandlerDef = new RootBeanDefinition(ResourceHttpRequestHandler.class);
|
||||
resourceHandlerDef.setSource(source);
|
||||
resourceHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
resourceHandlerDef.getConstructorArgumentValues().addIndexedArgumentValue(0, resourceDirectory);
|
||||
|
||||
Map<String, BeanDefinition> urlMap = getUrlMap(handlerMappingDef);
|
||||
String resourceRequestPath = "/resources/**";
|
||||
urlMap.put(resourceRequestPath, resourceHandlerDef);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void registerHandlerAdapterIfNecessary(ParserContext parserContext, Object source) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_ADAPTER_BEAN_NAME)) {
|
||||
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
|
||||
handlerAdapterDef.setSource(source);
|
||||
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
parserContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
private BeanDefinition registerHandlerMappingIfNecessary(ParserContext parserContext, Object source) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(HANDLER_MAPPING_BEAN_NAME)) {
|
||||
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
|
||||
handlerMappingDef.setSource(source);
|
||||
handlerMappingDef.getPropertyValues().add("order", "2");
|
||||
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
parserContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
|
||||
return handlerMappingDef;
|
||||
}
|
||||
else {
|
||||
return parserContext.getRegistry().getBeanDefinition(HANDLER_MAPPING_BEAN_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, BeanDefinition> getUrlMap(BeanDefinition handlerMappingDef) {
|
||||
Map<String, BeanDefinition> urlMap;
|
||||
if (handlerMappingDef.getPropertyValues().contains("urlMap")) {
|
||||
urlMap = (Map<String, BeanDefinition>) handlerMappingDef.getPropertyValues().getPropertyValue("urlMap").getValue();
|
||||
}
|
||||
else {
|
||||
urlMap = new ManagedMap<String, BeanDefinition>();
|
||||
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
|
||||
}
|
||||
return urlMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package org.springframework.web.servlet.resources;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
|
||||
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
|
||||
|
||||
public class ResourceHttpRequestHandler implements HttpRequestHandler {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ResourceHttpRequestHandler.class);
|
||||
|
||||
private Resource resourceDirectory;
|
||||
|
||||
private int maxAge = 31556926;
|
||||
|
||||
private FileMediaTypeMap fileMediaTypeMap = new DefaultFileMediaTypeMap();
|
||||
|
||||
public ResourceHttpRequestHandler(Resource resourceDirectory) {
|
||||
Assert.notNull(resourceDirectory, "The resource directory may not be null");
|
||||
this.resourceDirectory = resourceDirectory;
|
||||
}
|
||||
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
if (!"GET".equals(request.getMethod())) {
|
||||
throw new HttpRequestMethodNotSupportedException(request.getMethod(),
|
||||
new String[] {"GET"}, "ResourceHttpRequestHandler only supports GET requests");
|
||||
}
|
||||
List<Resource> resources = getResources(request);
|
||||
if (resources.size() == 0) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
boolean notModified = checkNotModified(resources, request, response);
|
||||
if (notModified) {
|
||||
return;
|
||||
}
|
||||
prepareResponse(resources, response);
|
||||
writeResponse(resources, response);
|
||||
}
|
||||
|
||||
private List<Resource> getResources(HttpServletRequest request) throws ServletException, IOException {
|
||||
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
|
||||
if (path == null) {
|
||||
throw new IllegalStateException("Required request attribute '" + HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set");
|
||||
}
|
||||
String[] resourceElements = path.split(",");
|
||||
if (resourceElements.length == 1 && resourceElements[0].length() == 0) {
|
||||
throw new NoSuchRequestHandlingMethodException(request);
|
||||
}
|
||||
List<Resource> resources = new ArrayList<Resource>();
|
||||
String[] dirAndFilename = splitDirectoryAndFilename(resourceElements[0]);
|
||||
String dir = dirAndFilename[0];
|
||||
String filename = dirAndFilename[1];
|
||||
Resource parent = dir != null ? this.resourceDirectory.createRelative(dir) : this.resourceDirectory;
|
||||
addResource(parent, filename, resources);
|
||||
if (resourceElements.length > 1) {
|
||||
for (int i = 1; i < resourceElements.length; i++) {
|
||||
addResource(parent, resourceElements[i], resources);
|
||||
}
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
|
||||
private boolean checkNotModified(List<Resource> resources,HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
long lastModifiedTimestamp = -1;
|
||||
long ifModifiedSince = request.getDateHeader("If-Modified-Since");
|
||||
for (Resource resource : resources) {
|
||||
long resourceLastModified = resource.lastModified();
|
||||
if (resourceLastModified > lastModifiedTimestamp) {
|
||||
lastModifiedTimestamp = resourceLastModified;
|
||||
}
|
||||
}
|
||||
boolean notModified = ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000);
|
||||
if (notModified) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
} else {
|
||||
response.setDateHeader("Last-Modified", lastModifiedTimestamp);
|
||||
}
|
||||
return notModified;
|
||||
}
|
||||
|
||||
private void prepareResponse(List<Resource> resources, HttpServletResponse response) {
|
||||
MediaType mediaType = null;
|
||||
int contentLength = 0;
|
||||
for (Resource resource : resources) {
|
||||
try {
|
||||
File file = resource.getFile();
|
||||
if (mediaType == null) {
|
||||
mediaType = fileMediaTypeMap.getMediaType(file.getName());
|
||||
}
|
||||
contentLength += file.length();
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
if (mediaType != null) {
|
||||
response.setContentType(mediaType.toString());
|
||||
}
|
||||
response.setContentLength(contentLength);
|
||||
if (this.maxAge > 0) {
|
||||
// HTTP 1.0 header
|
||||
response.setDateHeader("Expires", System.currentTimeMillis() + this.maxAge * 1000L);
|
||||
// HTTP 1.1 header
|
||||
response.setHeader("Cache-Control", "max-age=" + this.maxAge);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeResponse(List<Resource> resources, HttpServletResponse response) throws IOException {
|
||||
for (Resource resource : resources) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = resource.getInputStream();
|
||||
int bytesRead = -1;
|
||||
byte[] buffer = new byte[4096];
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
response.getOutputStream().write(buffer, 0, bytesRead);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String[] splitDirectoryAndFilename(String firstResourceElement) {
|
||||
int index = firstResourceElement.lastIndexOf("/");
|
||||
String dir;
|
||||
if (index == -1) {
|
||||
dir = null;
|
||||
} else {
|
||||
dir = firstResourceElement.substring(0, index + 1);
|
||||
}
|
||||
String filename = firstResourceElement.substring(index + 1, firstResourceElement.length());
|
||||
return new String[] { dir, filename };
|
||||
}
|
||||
|
||||
private void addResource(Resource parent, String name, List<Resource> resources) throws IOException {
|
||||
if (name.length() > 0) {
|
||||
Resource resource = parent.createRelative(name);
|
||||
if (isAllowed(resource)) {
|
||||
resources.add(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAllowed(Resource resource) throws IOException {
|
||||
return resource.exists() && resource.getFile().isFile();
|
||||
}
|
||||
|
||||
// TODO promote to top-level and make reusable
|
||||
// TODO check ServletContext.getMimeType(String) first
|
||||
|
||||
public interface FileMediaTypeMap {
|
||||
MediaType getMediaType(String fileName);
|
||||
}
|
||||
|
||||
public static class DefaultFileMediaTypeMap implements FileMediaTypeMap {
|
||||
|
||||
private static final boolean jafPresent =
|
||||
ClassUtils.isPresent("javax.activation.FileTypeMap", ContentNegotiatingViewResolver.class.getClassLoader());
|
||||
|
||||
private boolean useJaf = true;
|
||||
|
||||
private ConcurrentMap<String, MediaType> mediaTypes = new ConcurrentHashMap<String, MediaType>();
|
||||
|
||||
public MediaType getMediaType(String filename) {
|
||||
String extension = StringUtils.getFilenameExtension(filename);
|
||||
if (!StringUtils.hasText(extension)) {
|
||||
return null;
|
||||
}
|
||||
extension = extension.toLowerCase(Locale.ENGLISH);
|
||||
MediaType mediaType = this.mediaTypes.get(extension);
|
||||
if (mediaType == null && useJaf && jafPresent) {
|
||||
mediaType = ActivationMediaTypeFactory.getMediaType(filename);
|
||||
if (mediaType != null) {
|
||||
this.mediaTypes.putIfAbsent(extension, mediaType);
|
||||
}
|
||||
}
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class to avoid hard-coded JAF dependency.
|
||||
*/
|
||||
private static class ActivationMediaTypeFactory {
|
||||
|
||||
private static final FileTypeMap fileTypeMap;
|
||||
|
||||
static {
|
||||
fileTypeMap = loadFileTypeMapFromContextSupportModule();
|
||||
}
|
||||
|
||||
private static FileTypeMap loadFileTypeMapFromContextSupportModule() {
|
||||
// see if we can find the extended mime.types from the context-support module
|
||||
Resource mappingLocation = new ClassPathResource("org/springframework/mail/javamail/mime.types");
|
||||
if (mappingLocation.exists()) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Loading Java Activation Framework FileTypeMap from " + mappingLocation);
|
||||
}
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = mappingLocation.getInputStream();
|
||||
return new MimetypesFileTypeMap(inputStream);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Loading default Java Activation Framework FileTypeMap");
|
||||
}
|
||||
return FileTypeMap.getDefaultFileTypeMap();
|
||||
}
|
||||
|
||||
public static MediaType getMediaType(String fileName) {
|
||||
String mediaType = fileTypeMap.getContentType(fileName);
|
||||
return StringUtils.hasText(mediaType) ? MediaType.parseMediaType(mediaType) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,6 +49,16 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="resources">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="java:org.springframework.web.servlet.resources.ResourceHttpRequestHandler"><![CDATA[
|
||||
Configures support for efficiently serving static resources such as images, js, and, css files.
|
||||
By default, registers a handler mapped to /resources/** capable of serving all resources located in the ${webappRoot}/resources directory.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="interceptors">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
@@ -16,15 +16,21 @@
|
||||
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
@@ -46,14 +52,17 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping;
|
||||
import org.springframework.web.servlet.resources.ResourceHttpRequestHandler;
|
||||
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
|
||||
|
||||
/**
|
||||
@@ -196,6 +205,34 @@ public class MvcNamespaceTests {
|
||||
assertTrue(chain.getInterceptors()[4] instanceof WebRequestHandlerInterceptorAdapter);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResources() throws Exception {
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("mvc-config-resources.xml", getClass()));
|
||||
assertEquals(2, appContext.getBeanDefinitionCount());
|
||||
appContext.refresh();
|
||||
|
||||
HttpRequestHandlerAdapter adapter = appContext.getBean(HttpRequestHandlerAdapter.class);
|
||||
assertNotNull(adapter);
|
||||
|
||||
SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/resources/foo.css");
|
||||
request.setMethod("GET");
|
||||
|
||||
HandlerExecutionChain chain = mapping.getHandler(request);
|
||||
assertTrue(chain.getHandler() instanceof ResourceHttpRequestHandler);
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
for (HandlerInterceptor interceptor : chain.getInterceptors()) {
|
||||
interceptor.preHandle(request, response, chain.getHandler());
|
||||
}
|
||||
ModelAndView mv = adapter.handle(request, response, chain.getHandler());
|
||||
assertNull(mv);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanDecoration() throws Exception {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
h2 { color:white; }
|
||||
@@ -0,0 +1 @@
|
||||
h1 { color:red; }
|
||||
@@ -0,0 +1 @@
|
||||
function foo() { console.log("hello bar"); }
|
||||
@@ -0,0 +1 @@
|
||||
function foo() { console.log("hello world"); }
|
||||
@@ -0,0 +1,163 @@
|
||||
package org.springframework.web.servlet.resources;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
|
||||
import org.springframework.web.servlet.resources.ResourceHttpRequestHandler;
|
||||
|
||||
|
||||
public class ResourceHttpRequestHandlerTests {
|
||||
|
||||
private ResourceHttpRequestHandler handler;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
handler = new ResourceHttpRequestHandler(new ClassPathResource("test/", getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResource() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals("text/css", response.getContentType());
|
||||
assertEquals(17, response.getContentLength());
|
||||
assertTrue(((Long)response.getHeader("Expires")) > System.currentTimeMillis() + (31556926 * 1000) - 10000);
|
||||
assertEquals("max-age=31556926", response.getHeader("Cache-Control"));
|
||||
assertTrue(response.containsHeader("Last-Modified"));
|
||||
assertEquals(response.getHeader("Last-Modified"), new ClassPathResource("test/foo.css", getClass()).getFile().lastModified());
|
||||
assertEquals("h1 { color:red; }", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceBundle() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css,bar.css");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals("text/css", response.getContentType());
|
||||
assertEquals(36, response.getContentLength());
|
||||
assertTrue(((Long)response.getHeader("Expires")) > System.currentTimeMillis() + (31556926 * 1000) - 10000);
|
||||
assertEquals("max-age=31556926", response.getHeader("Cache-Control"));
|
||||
assertTrue(response.containsHeader("Last-Modified"));
|
||||
assertEquals(response.getHeader("Last-Modified"), new ClassPathResource("test/bar.css", getClass()).getFile().lastModified());
|
||||
assertEquals("h1 { color:red; }h2 { color:white; }", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceBundleDifferentTypes() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css,/js/bar.js");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals("text/css", response.getContentType());
|
||||
assertEquals("h1 { color:red; }function foo() { console.log(\"hello bar\"); }", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceFromSubDirectory() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/js/foo.js");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
System.out.println(response.getContentAsString());
|
||||
assertEquals("text/javascript", response.getContentType());
|
||||
assertEquals("function foo() { console.log(\"hello world\"); }", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceBundleDifferentTypesIncludingDirectory() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css,/js,/js/foo.js");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals("text/css", response.getContentType());
|
||||
assertEquals("h1 { color:red; }function foo() { console.log(\"hello world\"); }", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notModified() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css");
|
||||
request.addHeader("If-Modified-Since", new ClassPathResource("test/foo.css", getClass()).getFile().lastModified());
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals(HttpServletResponse.SC_NOT_MODIFIED, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modified() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css");
|
||||
request.addHeader("If-Modified-Since", new ClassPathResource("test/foo.css", getClass()).getFile().lastModified() - 1);
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertEquals("h1 { color:red; }", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void directory() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/js/");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchRequestHandlingMethodException.class)
|
||||
public void missingResourcePath() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void noPathWithinHandlerMappingAttribute() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
}
|
||||
|
||||
@Test(expected=HttpRequestMethodNotSupportedException.class)
|
||||
public void unsupportedHttpMethod() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/foo.css");
|
||||
request.setMethod("POST");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceNotFound() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/not-there.css");
|
||||
request.setMethod("GET");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
handler.handleRequest(request, response);
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
h2 { color:white; }
|
||||
@@ -0,0 +1 @@
|
||||
h1 { color:red; }
|
||||
@@ -0,0 +1 @@
|
||||
function foo() { console.log("hello bar"); }
|
||||
@@ -0,0 +1 @@
|
||||
function foo() { console.log("hello world"); }
|
||||
Reference in New Issue
Block a user