Apache cache specific images and css - image

We have website running with tomcat and apache and wish to cache only specific jpg, gif images at apache level to reduce tomcat load.
Regarding CSS and Javascripts, all of them can be cached.
Upon deployment of changed images, css and javascripts it should load automatically.
I am trying to get this configuration but could not find any.. Can someone please share sample configuration?
It is very crucial for us to cache only specific images, and its urgent as well.

In tomcat application context.xml add :
disableCacheProxy="false" securePagesWithPragma="false"
Followed by any one of the below :
1.Use jsp :
Create a new jsp eg. "nocache.jsp" with the below content :
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-store"> <!-- HTTP 1.1 -->
<meta http-equiv="Expires" content="0">
Include this jsp in all jsp's which u dont want to cache as :
<jsp:include page="../nocache.jsp" />
2.Use Filter :
Create a new Filter class - "CacheHeaderFilter" to handle classes which are NOT to be cached as below :
public void doFilter( ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse httpResponse = (HttpServletResponse)response;
httpResponse.setHeader("Cache-Control","no-cache");
httpResponse.setHeader("Pragma","no-cache");
httpResponse.setDateHeader ("Expires", 0);
filterChain.doFilter(request, response);
}
In app web.xml, configure this filter and specify the URL's which are NOT to be cached as below :
<filter>
<filter-name>CacheFilter</filter-name>
<filter-class>com.org.CacheHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>`

Related

Spring Boot UTF-8 encoding issue. I suspect it tries to encode ISO-8859-1 to UTF-8

I'd like to use UTF-8 character encoding but I read somewhere that the controller's default encoding's ISO-8859-1.
I'm using spring boot with velocity.
So what I did, I tried to add the following ones (one at a time) to the header (None of them worked.)
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
Plus added to the application.properties the following lines:
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.velocity.charset=UTF-8
spring.velocity.content-type=text/html
server.tomcat.uri-encoding = UTF-8
I even tried to add the following line to the controller:
#RequestMapping(value = "/", method = RequestMethod.GET, produces={"text/html; charset=UTF-8"})
Plus tried to add the following bean to the application class:
#Bean
public HttpMessageConverter<String> responseBodyConverter() {
HttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
return converter;
}
This's a sample text that I included in the velocity template:
A sötét lovag igazi főhőse azonban valahogy ezúttal mégsem a mostanság nőnemű családtagjait szállodaszobábkban riogató Christian Bale, azaz a denevérember lett - hanem az ellenfél.
And that's the output I get:
A sötét lovag igazi fÅhÅse azonban valahogy ezúttal mégsem a mostanság nÅnemű családtagjait szállodaszobábkban riogató Christian Bale, azaz a denevérember lett - hanem az ellenfél.
Edit:
This's the controller I'm using currently:
#RequestMapping(value = "/", method = RequestMethod.GET, produces={"text/html; charset=UTF-8"})
public String homepage(Map<String, Object> model) {
return "homepage";
}
And I have a homepage.vm file at templates. Which has a header partial that contains this line:
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
Could be due to default Eclipse encoding?
Window -> Preferences -> General -> Workspace : Text file encoding
To resolve same problem, I have used VelocityConfigurer with the following bean definition:
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/pages/"/>
<property name="configLocation" value="/WEB-INF/velocity.properties"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="false"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
<property name="contentType" value="text/html; charset=UTF-8"/>
</bean>
Please note the contentType property set in viewResolver.
When first tried providing it via VelocityEngineFactoryBean, I have realised late that my properties file was ignored.
Also, in velocity.properties make sure you have:
input.encoding=utf-8
output.encoding=utf-8
I didn't need anything else in here for simple case.
In web.xml:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
That was it, I had no use for "produces" attribute in controller, no http meta needed, no xml charset encoding specified in the template file and no messing with messageconverter.
EDIT:
I don't have a playground setup with Spring Boot so can't test the exact implementation for you right now. However, web.xml here only defines a filter which can also be achieved programatically with Spring Boot:
import org.springframework.stereotype.Component;
import javax.servlet.*;
import java.io.IOException;
#Component
public class MyFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//action here
filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
}
I believe Spring Boot scans the sources for #Component automatically, otherwise package with filter's implementation should be added to component scan.
As for ideas on what the filter should do within doFilter(), you could explore the source code of Spring's CharacterEncodingFilter: https://github.com/spring-projects/spring-framework/blob/v4.2.1.RELEASE/spring-web/src/main/java/org/springframework/web/filter/CharacterEncodingFilter.java
Note that the above filter already extends other classes (such as OncePerRequestFilter).
I suppose you could instead add a method returning the filter instance:
#Bean
public Filter getCharacterEncodingFilter() {
org.springframework.web.filter.CharacterEncodingFilter characterEncodingFilter = new org.springframework.web.filter.CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}

CSS not loading in Spring Boot

I am new to spring frame work and spring boot.I am trying to add the static html file with CSS,javascript,js. the file structure is
and my html file head looks like this
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>HeavyIndustry by HTML5Templates.com</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<link rel="stylesheet" type="text/css" media="all" href="css/5grid/core.css" th:href="#{css/5grid/core}" />
<link rel="stylesheet" type="text/css" href="css/5grid/core-desktop.css" />
<link rel="stylesheet" type="text/css" href="css/5grid/core-1200px.css" />
<link rel="stylesheet" type="text/css" href="css/5grid/core-noscript.css" />
<link rel="stylesheet" type="text/css" href="css/style.css" />
<link rel="stylesheet" type="text/css" href="css/style-desktop.css" />
<script src="css/5grid/jquery.js" type="text/javascript"></script>
<script src="css/5grid/init.js?use=mobile,desktop,1000px&mobileUI=1&mobileUI.theme=none" type="text/javascript"></script>
<!--[if IE 9]><link rel="stylesheet" href="css/style-ie9.css" /><![endif]-->
</head>
when i run the spring project only the content is shown and the CSS is not applied.then the browser show the following error in the console
404 Not Found error for the .css,.js files
some body help me to sort out this issue.Thanks in Advance.
You need to put your css in /resources/static/css. This change fixed the problem for me. Here is my current directory structure.
src
main
java
controller
WebAppMain.java
resources
views
index.html
static
css
index.css
bootstrap.min.css
Here is my template resolver:
public class WebAppMain {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(WebAppMain.class);
System.out.print("Starting app with System Args: [" );
for (String s : args) {
System.out.print(s + " ");
}
System.out.println("]");
app.run(args);
}
#Bean
public ViewResolver viewResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setTemplateMode("XHTML");
templateResolver.setPrefix("views/");
templateResolver.setSuffix(".html");
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver);
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(engine);
return viewResolver;
}
}
And just in case, here is my index.html:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring3-3.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Subscribe</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap -->
<link type="text/css" href="css/bootstrap.min.css" rel="stylesheet" />
<link type="text/css" href="css/index.css" rel="stylesheet" />
</head>
<body>
<h1> Hello</h1>
<p> Hello World!</p>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>
Put css files into webapp resources folder:
src/main/webapp/resources/css/
Configure resource handler
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
Example projects:
https://github.com/spring-guides/tut-web/tree/master/6/complete
Spring Boot Service Template with Static Content
Source:
Designing and Implementing a Web Application with Spring
Serving Web Content with Spring MVC
This is what worked for me after many attempts:
css location: /resources/static/css/stylesheet.css
link path in html: th:href="#{/css/stylesheet.css}"
WebSecurityConfig:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**");
}
Spring Boot will attempt to look in some default locations for your views. Have a look at the following link.
http://docs.spring.io/spring-boot/docs/1.1.4.RELEASE/reference/htmlsingle/#common-application-properties
If you're building an executable jar, your resources should be placed under src/main/resources, not src/main/webapp so that they're copied into your jar at build time.
Your index.html should go under src/main/resources/templates like you've got it, but your static resources shouldn't. Spring Boot will look for your Thymeleaf views there by default. And you don't actually need to define your own view resolver for Thymeleaf, Spring Boot will set this up for you if you have the spring-boot-starter-thymeleaf dependency in your project.
# THYMELEAF (ThymeleafAutoConfiguration)
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html # ;charset=<encoding> is added
spring.thymeleaf.cache=true # set to false for hot refresh
As mentioned by others, if you put your css in src/main/resources/static/css or src/main/resources/public/css, then referencing them from href="css/5grid..." in your HTML should work.
I was facing the same issues and solved it the following way:
Make sure the folder you are exporting is available to the web
public class WebMvcConfig extends WebMvcConfigurerAdapter {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"
};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
}
In addition you must put your css or styles folder into your src/main/resources/(static|public|resources|META-INF/resources) folder
Make sure your security policies don't block them
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
//Web resources
web.ignoring().antMatchers("/css/**");
web.ignoring().antMatchers("/scripts/**");
web.ignoring().antMatchers("/images/**");
}
}
That should be enough
In the case of Spring Boot, however, it’s worth mentioning how Spring
Boot deals with static content. When Spring Boot’s web
autoconfiguration is automatically configuring beans for Spring MVC,
those beans include a resource handler that maps /** to several
resource locations. Those resource locations include (relative to the
root of the classpath) the following:
/META-INF/resources/
/resources/
/static/
/public/
In a conventional Maven/Gradle-built application, you’d typically put
static content at src/main/webapp so that it would be placed at the
root of the WAR file that the build produces. When building a WAR file
with Spring Boot, that’s still an option. But you also have the option
of placing static content at one of the four locations mapped to the
resource handler.
I'm new to spring boot too and I have the same problem.
I have put the correct path manually into the browser and have seen the 404 by tomcat.
Then I have found a solution at:
Spring-Boot ResourceLocations not adding the css file resulting in 404
Now the css file is accessible by code.
You must move the css folder to src/main/resources/static/css then the content is readable (at my local configuration).
<link href="<%=request.getContextPath()%>/resources/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="<%=request.getContextPath()%>/resources/css/common.css" rel="stylesheet" media="screen">
[this is the image for my project structure. i added the webapp directory to support .jsp files.this method request.getContextPath() worked for me. Hope i help someone with this... it gets the path so long as it exists.
Nb. You should have a resolver bean in your webconfig
`enter code here`#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new `enter code here`InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}`
for the added directory][1]

How to set content-type in Freemarker views when using Spring MVC?

I'm using Sping MVC with freemarker views. I set up a FreeMarkerViewResolver to resolve the views and it works so far but now I have encoding problems. All my views are HTML 5 pages in UTF-8 encoding and I also added a <meta charset="UTF-8" /> to the HTML page but characters are still printed in the wrong encoding. I checked the HTTP headers with curl and found this:
k#jules:~$ curl -I http://localhost:8080/testweb/test.view
HTTP/1.1 200 OK
Content-Type: */*;charset=ISO-8859-1
But when I request some non-existing resource (Which generates a Tomcat error) then I get this:
k#jules:~$ curl -I http://localhost:8080/testweb/nothere.html
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
So Tomcat itself returns the correct content-type but a Spring MVC Freemarker views don't.
For a JSP I can set the Content-Type in the JSP header but where can I set it for a freemarker template? I guess I have to do this somewhere in the Spring bean configuration but I can't find the right place.
The view resolver (should be in your dispatcher-servlet.xml) has a contentType property for that:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
<property name="contentType" value="text/html;charset=UTF-8"/>
</bean>
I have also experienced a problem with showing UTF-8 characters (special characters like æ. ø and å etc.), when using spring framework and freemarker template.
What i did was.
1. Ensure that your .ftl page is encoded with utf-8
This is an important thing to ensure, that a page not encoded with UTF-8 charset, could show the wrong numbers even though you have all the other requirements set. Check your IDE settings, to find out which default encoding it sets your files to. I think however today that both Eclipse and NetBeans set all files with UTF-8 encoding as standard. You must ensure that it is encoding UTF-8 with no BOM.
2. Include the Meta tag in your template file to set the charset
In your template (.ftl) file, which holds your <head> tag, set a <meta>, with the attribute charset="UTF-8". This is if you use HTML 5. If you use xhtml or HTML 4, your meta tag needs to look like this
HTML 5 <meta charset="UTF-8" />
HTML 4/XHTML <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
3. Make sure you set a Character Encoding Filter in your Deployment Descriptor File
You have to filter all incoming/outgoing requests through a character encoding filter. This filter is set in your deployment descriptor (web.xml / or the java equivalent WebApplicationInitializer).
WebApplicationInitializer (Java File)
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerCharacterEncodingFilter(servletContext);
}
/**
* Filter all incoming requests with character encoding UTF-8
* #param servletContext
*/
private void registerCharacterEncodingFilter(ServletContext servletContext) {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", encodingFilter);
characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
}
web.xml
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4. Set the FreeMarker Character Encoding in configurer and view resolver
You also need to make all your FreeMarker files be standard encoded with UTF-8, this is done by setting their properties to UTF-8 in the FreeMarkerConfigurer and the FreeMarkerViewResolver. This is set in your spring application context file (I will only show the Java equivalent as it is the same in the XML file).
/**
* FreeMarker Configurer will help configure different settings of
* the FreeMarker template engine.
*
* #return an object of the FreeMarkerConfigurer class.
*/
#Bean
public FreeMarkerConfigurer freemarkerConfig() {
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setTemplateLoaderPath("/templates/");
freeMarkerConfigurer.setDefaultEncoding("UTF-8");
return freeMarkerConfigurer;
}
/**
* The View resolver to use when resolving FreeMarker views.
*
* #return the View Resolver Object used to resolve FreeMarker views.
*/
#Bean
public FreeMarkerViewResolver viewResolver() {
FreeMarkerViewResolver viewResolver = new FreeMarkerViewResolver();
viewResolver.setPrefix("");
viewResolver.setSuffix(".ftl");
viewResolver.setCache(false); //Set to true during production
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}
Hope this helps you out :)

Encoding problem using Spring MVC

I have a demo web application that creates users. When I try to insert data in other languages (like french) the characters are not encoded correctly. The code on the controller is:
#SuppressWarnings("unchecked")
#RequestMapping(value = "/user/create.htm", params={"id"}, method = RequestMethod.GET)
public String edit(#RequestParam("id") Long id, ModelMap model) {
System.out.println("id is " + id);
User user = userService.get(id);
model.put("user", user);
return "user/create";
}
#RequestMapping(value = "/user/create.htm", method = RequestMethod.POST)
public String save(#ModelAttribute("user") User user, BindingResult result) {
System.out.println(user.getFirstName());
System.out.println(user.getLastName());
validator.validate(user, result);
if(result.hasErrors()) {
return "user/create";
}
userService.save(user);
return "redirect:list.htm";
}
my web.xml is:
...
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
and the page is:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
...
<form:form method="post" commandName="user">
...
<form:input path="firstName" cssErrorClass="form-error-field"/>
...
when I enter some french characters in the first name then the output from the system.out.println is ????+????? or something similar.
I saw other people fixing this with the CharacterEncodingFilter but this doesn't seem to work.
Thanks a lot.
Edited the filter value.
Try making CharacterEncodingFilter the first filter in web.xml.
I realize this question is a little old, but I just ran into the same problem, and moving CharacterEncodingFilter fixed it for me.
If this still does not work and you're using Tomcat as your application server try to set the following option on every <Connector> element in the server.xml:
<Connector URIEncoding="UTF-8" ...>
...
</Connector>
This did the trick for me. There might be similar options for other application servers, so you might want to check the server documentation.
Perhaps I'm missing something, but if the page-encoding in your JSP is "UTF-8", shouldn't the encoding in your CharacterEncodingFilter be UTF-8 rather than ISO-8859-7?
You need to add accept-charset="UTF-8" to your form.
Output of System.out.println() depends on console encoding, so it's not a good way to debug encoding problems.
To check that your values are decoded properly, you should show it at another page. Actually, it's already done in the case of form validation failure, so your system works fine if values in the fields remains the same after validation error.
There are two things to help:
In your setenv.sh file add JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=utf-8"
In the script that starts your tomcat process, set the LANG environment: export LANG='utf-8'
This can then be tested by examining the default character set: Charset.defaultCharset().

Can SpringMVC be configured to process all requests, but exclude static content directories?

If I map my spring application to process all incoming requests ('/*'), then requests for static content return 404's. For example, a request for "myhost.com/css/global.css" would return a 404, even though the resource exists as Spring intercepts the request.
The alternative is to map SpringMVC to a subdirectory (for example '/home/'), but in this case, you must pass this directory in all links within the application. Is there a way to map SpringMVC to '/' and exclude a set of directories from processing?
My current web.xml configuration is:
<servlet>
<servlet-name>springApp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springApp</servlet-name>
<url-pattern>/home/*</url-pattern>
</servlet-mapping>
Idealy I would like to have the mapping be something like the following:
<servlet-mapping>
<servlet-name>springApp</servlet-name>
<url-pattern>/*</url-pattern>
<exclude>/css/*,/js/*</exclude>
</servlet-mapping>
Is this type of thing possible?
NOTE: this answer applies to Spring 3.0.4+ ONLY
(BTW, this question has also been dealt with here: Spring serving static content with mvc:resources, invalid xsd)
Check out the Spring mvc-showcase project in the Spring subversion samples repository. It shows exactly what you want to do, namely that you can delineate static resources which will not be processed by the DisapatcherServlet. See file /mvc-showcase/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml. Here's a snippet of how I handle these exclusions, where the JS, CSS, and images are in the app context root (with the MVC namespace mapped to mvc:
<!-- resources exclusions from servlet mapping -->
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/js/**" location="/js/" />
I solved by serving static content through the 'default' servlet, that just serve the content to the client. So my web.xml looks like this:
<servlet>
<servlet-name>MyApp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyApp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!-- The 'dynamic' content -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping> <!-- The 'static' content -->
Hope this helps.
If you want to do this with Spring only, it's possible but a bit messy:
You'll either need to use a SimpleUrlHandlerMapping for which you can explicitly specify URL patterns which should be mapped to controllers OR extend it to support "ignore" URLs like "css/**".
You'll need to write your own HttpRequestHandler implementation that would basically consist of "getServletContext().getRequestDsipatcher().include()" call to return the requested resource as is.
You'll have to register that handler as defaultHandler for the above SimpleUrlHandlerMapping.
Once all that is done, all requests that can't be mapped to your controllers will be forwarded to your HttpRequestHandler and served "as is".
Simplest way for me (if using a late enough version of Spring) is
<mvc:resources mapping="/**/*.js" location="/"/>
<mvc:resources mapping="/**/*.css" location="/"/>
...
One way to do it would be with Filters. You'd have to write a little bit of custom code but it's not bad. Here's an example if you don't want to pass *.css or *.js files to your Spring servlet:
web.xml:
<filter-mapping>
<filter-name>fileTypeFilter</filter-name>
<filter-class>foo.FileTypeFilter</filter-class>
<url-pattern>/*</url-pattern>
</filter-mapping>
Java class:
public class FileTypeFilter implements Filter {
public void init(FilterConfig conf) {
// init logic here
}
public void destroy() {
// release resources here
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
if(shouldExclude(req)) {
chain.doFilter(req, res);
//some logic so the request doesnt go to the servlet
//maybe you could just forward
//the request directly to the file getting accessed. not sure if that would work
}
//file should be passed to the servlet; you can do some logic here
//if you want
}
private boolean shouldExclude(ServletRequest req) {
if(req instanceof HttpServletRequest) {
HttpServletRequest hreq = (HttpServletRequest) req;
return (hreq.getRequestURI().endsWith(".css") ||
hreq.getRequestURI().endsWith(".js"));
}
return false;
}
}
I haven't tested this, but I think it will work.
EDIT: There's isn't any exclude functionality in the servlet spec. I don't think there is a good way to do this within Spring, but it essentially achieves the same thing in your post.
EDIT 2: If you want to be able to easily change what gets filtered, you could just use Spring to inject something into the Filter at runtime.
EDIT 3: I just realized if you forward directly to the file, it'll do the filter again and you'll get caught in an infinite loop. There might be another way to do this with filters, but I'm honestly not sure what it is.
What are you using to serve your static images?
If it's Apache then you could configure Apache to not pass css/js requests to your app server.
If you are using Tomcat you'd put something like this in your httpd.conf:
JkUnMount /*.css webapp
Where 'webapp' is the entry from your workers.properties.
Sorry I can't give you a pure Spring solution, but this is how I do it.
I got the same problem and here is how I solved it:
The following was added to the web.xml file:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.ico</url-pattern>
<url-pattern>*.png</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.htc</url-pattern>
<url-pattern>*.gif</url-pattern>
<url-pattern>*.html</url-pattern>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
The following was added to the spring3 MVC servlet bean definition file (such as applicationContext.xml, the file that is configured in web.xml as the contextConfigLocation.):
<mvc:annotation-driven />
<mvc:default-servlet-handler />
Do you have a consistent extension(s) for the requests you want processed by the Spring dispatcher (I believe most of the Spring examples use a *.htm)? In that case, you could map to the extensions you wish to have processed which would bypass your css and js files.
Otherwise I'd agree with Nalandial, the Filter approach is probably the best work around at this point.
I use virtual URL path to retrieve the resource I need. Typically I use Spring MVC, so I couldn't have javascripts and css under /WEB-INF/views folder. I came up with this custom servlet to ONLY allow access to .js & .css files within /WEB-INF/views folder. In your case, if you move the /css folder and /js folder to a parent folder such as /resource then my solution will be applicable to you.
You can change the String url = "YOUR_RESOURCE_FOLDER"
So for example, virtual path can be something like http://www.mysite.com/resources/path/path/app.js
That will map to my /WEB-INF/views/path/path/app.js
web.xml
<servlet>
<servlet-name>ResourceDispatcherServlet</servlet-name>
<servlet-class>mywebapp.web.ResourceDispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ResourceDispatcherServlet</servlet-name>
<url-pattern>/resource/*</url-pattern>
</servlet-mapping>
servlet
public class ResourceDispatcherServlet extends HttpServlet {
public void init() throws ServletException {
}
public void doGet(HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException {
String servletPath = req.getServletPath(); // /resource
String pathInfo = req.getPathInfo(); // /path/path/app.js
String url = "/WEB-INF/views" + pathInfo;
String lastPath = StringUtil.substringAfterLast(pathInfo, "/");
String extension = StringUtil.substringAfterLast(lastPath, ".");
try {
RequestDispatcher dispatcher = null;
if (!StringUtil.isEmpty(extension) && ("js".equals(extension) || "css".equals(extension))) {
dispatcher = req.getRequestDispatcher(url);
}
if (dispatcher != null) {
dispatcher.include(req, rsp);
}
else {
rsp.sendError(404);
}
}
catch (Exception e) {
if (!rsp.isCommitted()) {
rsp.sendError(500);
}
}
}
}
If you are using Spring 3.0.4 and above you should use solution provided by atrain
Otherwise, you can do this simple thing:
perhaps you have following static directory structure you want to serve:
WebContent
|
WEB-INF
|
public
|
css
|
js
|
img
Eclipse Dynamic web projects by default generate following structure: WebContent/WEB-INF. Move the public folder out of your WEB-INF directory into WebContentdirectory.
On client side
refer your static files in following way:
<link rel="stylesheet" type="text/css" href="public/css/mystyles.css">
Here is my reference.
In my case everything was ok. But i have a problem in a Controller
that was my problem
#RequestMapping( method = RequestMethod.GET)
y change for this:
#RequestMapping(value = "/usuario", method = RequestMethod.GET)
and it works
look for a controller that has bad #RequestMappgin and change.
It's cleaner to use UrlRewriteFilter to redirect the request to your servlet, here an example of urlrewrite.xml
<urlrewrite>
<rule>
<from>^/img/(.*)$</from>
<to>/img/$1</to>
</rule>
<rule>
<from>^/js/(.*)$</from>
<to>/js/$1</to>
</rule>
<rule>
<from>^/css/(.*)$</from>
<to>/css/$1</to>
</rule>
<rule>
<from>^/(.*)$</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/(.*)$</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
NOTES:
It's important the last <rule> is in the bottom so img, js, css will be caught first
The <outbound-rule> is optional and is just to make the existing<c:url value="/app/some" /> render /some instead of /app/some
Usually, big websites prefer using another server only to handle static content.
Requests of static content goes to one server and dynamic goes to another (with spring, in this case).
In many cases, Nginx server (http://nginx.com/), a recent and very fast server.
But this is not trivial to do. A lot of configurations.

Resources