JavaWeb静态资源映射ResourceMappingFilter
对网站中的目录进行映射,让资源引用更加简单,
## 源码
```
package com.itshidu.ssh.commons.filter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 静态资源映射
* @author 夏增明
* @date 2011-03-25
*
*/
public class ResourceMappingFilter implements Filter {
private List<String> dirs=new ArrayList<String>();//资源文件夹
private String mapping;
private ServletContext application;
private String debug="true";
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
String uri = request.getRequestURI();
if(uri.indexOf(request.getContextPath()+mapping)!=0){
chain.doFilter(arg0, arg1);
return;
}
int start = uri.lastIndexOf(mapping)+mapping.length();
int end = uri.length();
String name = uri.substring(start, end);
for(String patt : dirs){
String resPath = patt+name;
String realPath = application.getRealPath(resPath);
if(new File(realPath).exists()){
RequestDispatcher disp = request.getRequestDispatcher(resPath);
disp.forward(arg0, arg1);
return;
}
}
chain.doFilter(arg0, arg1);
}
@Override
public void init(FilterConfig config) throws ServletException {
String[] arr = config.getInitParameter("location").split(",");
this.mapping = config.getInitParameter("mapping");
this.debug = config.getInitParameter("debug");
application = config.getServletContext();
for(String str : arr){
if(str.endsWith("/*")){
String res = str.substring(0, str.length()-2);
String real = application.getRealPath(res);
File file = new File(real);
readDirectory(res,file, file);
}else if(str.endsWith("/")){
dirs.add(str.substring(0, str.length()-1));
}else{
dirs.add(str);
}
}
for(String dr : dirs){
log("ResourceMapping: "+mapping+" --> "+ dr);
}
}
private void readDirectory(String dir,File src,File file){
if(file.isDirectory()){
String res = dir+file.getAbsolutePath().substring(src.getAbsolutePath().length());
dirs.add(res);
for(File fo : file.listFiles()){
readDirectory(dir,src,fo);
}
}
}
private void log(String info){
if(debug.equals("true")){
System.out.println(info);
}
}
}
```
## 配置web.xml
```
<filter>
<filter-name>resourceMapping</filter-name>
<filter-class>com.itshidu.ssh.commons.filter.ResourceMappingFilter</filter-class>
<init-param>
<param-name>location</param-name>
<param-value>/WEB-INF/static/*,/assets/*,/resource</param-value>
</init-param>
<init-param>
<param-name>mapping</param-name>
<param-value>/res</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>resourceMapping</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</filter>
```
解释说明
location:本地资源目录,多个目录用英文逗号分隔,xxx/*代表xxx目录和所有后代目录
mapping:虚拟目录,location中设置的目录都将映射到这里
debug:启动是否打印映射信息
通过以上配置,访问资源时会方便很多:
| 资源路径 | 映射之后的快捷路径 |
| --- | --- |
| /WEB-INF/static/js/lib/jquery/1.10.js | /res/1.10.js |
| /assets/a/b/c/d/e/f/g/h/hello.js | /res/hello.js |
| /resource/js/cityloader/index.js | /res/index.js |
/assets/a/b/c/d/e/f/g/h/hello.js
除了/res/hello.js外,也可以写得更详细:
/res/h/hello.js
/res/g/h/hello.js
/res/f/g/h/hello.js
通常,当两个目录中文件名冲突时,我们会使用这种方式进行区分处理。