JavaWeb静态资源映射ResourceMappingFilter

2017-01-10· 5326 次浏览
对网站中的目录进行映射,让资源引用更加简单, ## 源码 ``` 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 通常,当两个目录中文件名冲突时,我们会使用这种方式进行区分处理。