Browse Source

mvc resources handler initial commit

pull/1234/head
Keith Donald 15 years ago
parent
commit
5a1bd20864
  1. 1
      org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/MvcNamespaceHandler.java
  2. 88
      org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java
  3. 263
      org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/resources/ResourceHttpRequestHandler.java
  4. 10
      org.springframework.web.servlet/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.0.xsd
  5. 41
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
  6. 1
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/bar.css
  7. 1
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/foo.css
  8. 1
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/js/bar.js
  9. 1
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/js/foo.js
  10. 163
      org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/resources/ResourceHttpRequestHandlerTests.java
  11. 1
      org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/bar.css
  12. 1
      org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/foo.css
  13. 1
      org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/js/bar.js
  14. 1
      org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/js/foo.js

1
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/MvcNamespaceHandler.java

@ -30,6 +30,7 @@ public class MvcNamespaceHandler extends NamespaceHandlerSupport { @@ -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());
}

88
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java

@ -0,0 +1,88 @@ @@ -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;
}
}

263
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/resources/ResourceHttpRequestHandler.java

@ -0,0 +1,263 @@ @@ -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;
}
}
}
}

10
org.springframework.web.servlet/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.0.xsd

@ -49,6 +49,16 @@ @@ -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[

41
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java

@ -16,15 +16,21 @@ @@ -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; @@ -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 { @@ -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 {

1
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/bar.css

@ -0,0 +1 @@ @@ -0,0 +1 @@
h2 { color:white; }

1
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/foo.css

@ -0,0 +1 @@ @@ -0,0 +1 @@
h1 { color:red; }

1
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/js/bar.js

@ -0,0 +1 @@ @@ -0,0 +1 @@
function foo() { console.log("hello bar"); }

1
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/resources/js/foo.js

@ -0,0 +1 @@ @@ -0,0 +1 @@
function foo() { console.log("hello world"); }

163
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/resources/ResourceHttpRequestHandlerTests.java

@ -0,0 +1,163 @@ @@ -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());
}
}

1
org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/bar.css

@ -0,0 +1 @@ @@ -0,0 +1 @@
h2 { color:white; }

1
org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/foo.css

@ -0,0 +1 @@ @@ -0,0 +1 @@
h1 { color:red; }

1
org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/js/bar.js

@ -0,0 +1 @@ @@ -0,0 +1 @@
function foo() { console.log("hello bar"); }

1
org.springframework.web.servlet/src/test/resources/org/springframework/web/servlet/resources/test/js/foo.js

@ -0,0 +1 @@ @@ -0,0 +1 @@
function foo() { console.log("hello world"); }
Loading…
Cancel
Save