servlet过滤器是小型的web组件,它能够处理传入的请求和传出的响应。Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开servlet时处理response。它具有高度的透明性,无需更改应用程序代码,就可以根据需要添加、修改或从应用程序中将它删除。
一个filter 包括:
1. 在servlet被调用之前截获;
2. 在servlet被调用之前检查servlet request;
3. 根据需要修改request头和request数据;
4. 根据需要修改response头和response数据;
5. 在servlet被调用之后截获.
你能够配置一个filter 到一个或多个servlet;单个servlet或servlet组能够被多个filter 使用。几个实用的filter包括:用户辨认filter,日志filter,审核filter,加密filter,符号filter,能改变xml内容的XSLT filter等。
一个客户化的过滤器要实现Filter接口的三个方法:init()、destroy()和doFilter()。
1. init():在容器实例化过滤器时调用,该方法接受一个FilterConfig类型的对象做为输入。
2. destroy():执行一些清理操作。
3. doFilter():类似servlet的doPost()、doGet()方法,执行具体的过滤任务。
下面给出一个可执行程序范例,它包含main函数,也可以部署到web应用中。

package utils; import java.io.IOException; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import bean.User; public class UrlFilter implements Filter { @SuppressWarnings("unused") private FilterConfig filterConfig; private FilterChain chain; private HttpServletRequest request; private HttpServletResponse response; public void destroy() { this.filterConfig = null; } public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { this.chain = chain; this.request = (HttpServletRequest) servletRequest; this.response = ((HttpServletResponse) servletResponse); String url = request.getServletPath(); if (url == null) url = ""; HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); if (noFileUrl(url, request)) { //不需要判断权限的请求如登录页面,则跳过 chain.doFilter(request, response); } else if (user == null) { String action = request.getParameter("action"); if (!"login".equals(action)) { response.sendRedirect("/zmdsl/admin/index.jsp");//返回登录页面 } } else { verifyUrl(url, user);//判断当前user是否拥有访问此url的权限 } } /** * * @param url 当前请求的url * @param user 当前登录用户 * @throws IOException * @throws ServletException */ private void verifyUrl(String url, User user)throws IOException, ServletException { // 获取user拥有的所有资源串 Set<String> royurl = new HashSet<String>(); royurl.add("/newsAction.do?action=adminQueryPage&typeId=3");//为用户分配访问此地址的权限。在真正项目中,此Set集合可能要 //通过查询数据库user、role、menu等表,来获取当前用户所拥有的全部可访问资源 if (royurl != null && royurl.size() > 0 && pass(royurl, url, request.getParameterMap())){ chain.doFilter(request, response); } else { response.setContentType("text/html;charset=GBK"); response .getWriter() .println( "<div style='margin: 100 auto;text-align: center;" + "font: bold 18px 宋体;color: #0066CC;vertical-align: middle'> Sorry,您没有权限访问该资源!</div>"); } } /** * 是否需要判断权限,如客户端浏览、登录页面则不需要判断权限 */ protected boolean noFileUrl(String url, HttpServletRequest request) { if (url.indexOf("/index.jsp") >= 0 || url.indexOf("login") > 0) { return true; } return false; } /** * 判断该用户是否有权请求该url * @param royurl user拥有的授权的的url串集合 * @param url 当前请求的url * @param reqmap 当前request的参数 * @return 是否通过该url */ protected boolean pass(Set royurl, String url, Map reqmap) { boolean match = true; for (Iterator iter = royurl.iterator(); iter.hasNext();) { // 获取资源 match = true; String res_string = (String) iter.next(); if (res_string.indexOf("*") > 0) { res_string = res_string.substring(0, res_string.indexOf("*")); if (url.substring(0, res_string.length()).equalsIgnoreCase(res_string)) { return true; //增加通配符比较 } } // 分割url与参数 String[] spw = res_string.split("\?"); //用"\?" 转义后即可得到正确的结 if (url.indexOf(spw[0]) < 0) {//为了方便,没有写成spw[0].equals(url) match = false; } if (match && spw.length > 1) { String[] spa = spw[1].split("\&"); // 分拆各参数 for (int j = 0; j < spa.length; j++) { String[] spe = spa[j].split("="); // 分拆键与值 String key = spe[0]; String value = ""; if (spe.length > 1) { value = spe[1].trim(); } // 轮询 String[] values = (String[]) reqmap.get(key); if (values != null) { for (int k = 0; k < values.length; k++) { if (value.equalsIgnoreCase(values[k])) { match = true; break; } match = false; } if (!match) { break; } } } } if (match) { break; } } return match; } @SuppressWarnings("unchecked") public static void main(String[] args) { UrlFilter filter = new UrlFilter(); Set royurl = new HashSet();//可访问的URL集合 royurl.add("/newsAction.do?typeId=1"); royurl.add("/newsAction.do?typeId=2"); //typeId为1时可以访问,true String url_1 = "/newsAction.do"; Map reqmap_1 = new HashMap(); reqmap_1.put("typeId", new String[]{"1"}); System.out.println("match false:" + filter.pass(royurl, url_1, reqmap_1)); //typeId为3时不可以访问,false String url_2 = "/newsAction.do"; Map reqmap_2 = new HashMap(); reqmap_2.put("typeId", new String[]{"3"}); System.out.println("match false:" + filter.pass(royurl, url_2, reqmap_2)); //url就不同,不可访问,false String url_3 = "/imageAction.do"; Map reqmap_3 = new HashMap(); reqmap_3.put("typeId", new String[]{"3"}); System.out.println("match false:" + filter.pass(royurl, url_3, reqmap_3)); } }
配置 Servlet过滤器:
非常简单,只需要在web.xml中加入类似下面的代码就可将过滤器部署到应用程序。

<!--================权限 设置================--> <filter> <filter-name>Authentication</filter-name> <filter-class>utils.UrlFilter</filter-class> <init-param> <param-name>onError</param-name> <param-value>/index.jsp</param-value> </init-param> </filter> <filter-mapping> <filter-name>Authentication</filter-name> <!-- 只过滤 .jsp 结尾的url, 其余的如 .do, .html, .jpg, .css 等不作过滤--> <url-pattern>*.do</url-pattern> </filter-mapping>
其中<filter-Class>是过滤器的路径;<filter-mapping>定义了该过滤器只过滤以.do结尾的URL,当然你也可以稍做修改让它过滤.jsp文件。