Java Web过滤器和拦截器

目录

 

拦截器

过滤器(Filter)

拦截器和过滤器的区别:

过滤器的使用



拦截器

  • 在AOP中用于在某个方法或字段被访问之前,进行拦截然后再加入某些操作。拦截是AOP的一种实现策略。
  • 拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者定义一个action前后执行的代码,也可以在一个action执行阻止其执行,同时也是提供了一种可以提取action可重用部分的方式。
  • 实现原理:大部分是通过代理的方式来调用的。
  • 自定义拦截器步骤:
    • 自定义一个实现了Interceptor接口的类,或者继承抽象类AbstractInterceptor。
    • 在配置文件中注册定义的拦截器。
    • 在需要使用Action中引入定义的拦截器,为了方便也可以把拦截器定义为默认的拦截器。所有的Action都会被这个拦截器拦截

过滤器(Filter)

过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理。通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理

过滤器的三个方法:

  • init()
  • destroy()

  • doFilter()

注意:过滤器是在服务器启动时就会创建的,只会创建一个实例,常驻内存,也就是说服务器一启动就会执行Filter的init(FilterConfig config)方法。当Filter被移除或服务器正常关闭时,会执行destroy方法

使用注解配置过滤器

利用注解配置管理器可配置的属性有这些


urlPatterns配置要拦截的资源

  1. 以指定资源匹配。例如"/index.jsp"
  2. 以目录匹配。例如"/servlet/*"
  3. 以后缀名匹配,例如"*.jsp"
  4. 通配符,拦截所有web资源。"/*"

initParams配置初始化参数,跟Servlet配置一样

DispatcherType是个枚举类型,有下面几个值

    FORWARD,//转发的
    INCLUDE,//包含在页面的
    REQUEST,//请求的
    ASYNC,//异步的
    ERROR;//出错的

使用xml配置过滤器

<filter>
  	<filter-name>loginFilter</filter-name>
  	<filter-class>com.dgm.util.LoginFilter</filter-class>
  </filter>
  
  <filter-mapping>
  	<filter-name>loginFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

多个Filter的执行顺序
在我们的请求到达Servle之间是可以经过多个Filter的,一般来说,建议Filter之间不要有关联,各自处理各自的逻辑即可。这样,我们也无需关心执行顺序问题。如果一定要确保执行顺序,就要对配置进行修改了,执行顺序如下

  • 在web.xml中,filter执行顺序跟<filter-mapping>的顺序有关,先声明的先执行
  • 使用注解配置的话,filter的执行顺序跟名称的字母顺序有关,例如AFilter会比BFilter先执行
  • 如果既有在web.xml中声明的Filter,也有通过注解配置的Filter,那么会优先执行web.xml中配置的Filter

 拦截器和过滤器的区别:

  • 拦截器是基于java的反射机制的,而过滤器是基本函数回调。
  • 拦截器不依赖于servlet容器,过滤器依赖于servlet容器
  • 拦截器只能对action请求起作用,过滤器可以对几乎所有的请求起作用
  • 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问
  • 在action的生命周期中,拦截器可以被多次调用,而过滤器只能在容器初始化时被调用过一次。

过滤器的使用

统一设置编码格式

public class EncodingFilter implements Filter {
    public EncodingFilter(){
    }

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
       FilterChain chain) throws IOException, ServletException {
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=UTF-8");
    chain.doFilter(request, response);

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

}

}

登录过滤

  1. 登录时将登录的账号密码保存到cookie中,下次访问时携带账号和密码,过滤器中进行校验
  2. 用户没有登录直接访问主页时,要跳转到登录页面
  3. 登录过滤器不对登录页面进行过滤
package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(filterName = "LoginFilter", urlPatterns = "*.jsp", dispatcherTypes = {})
public class LoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {


        System.out.println("LoginFilter doFilter");

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        String url = request.getRequestURI();

        System.out.println("请求的url:" + url);
        /*登录页面不需要过滤*/

        int idx = url.lastIndexOf("/");
        String endWith = url.substring(idx + 1);


        if (!endWith.equals("login.jsp")) {
            /*不是登录页面  进行拦截处理*/

            System.out.println("不是登录页面,进行拦截处理");

            if (!isLogin(request)) {
                System.out.println("没有登录过或者账号密码错误,跳转到登录界面");
                response.sendRedirect("login.jsp");
            } else {
                System.out.println("已经登录,进行下一步");
                chain.doFilter(req, resp);
            }

        } else {

            System.out.println("是登录页面,不进行拦截处理");
            chain.doFilter(req, resp);
        }


    }


    private boolean isLogin(HttpServletRequest request) {

        Cookie[] cookies = request.getCookies();

        String account = "";
        String pwd = "";

        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("account")) {
                    account = cookie.getValue();
                } else if (cookie.getName().equals("pwd")) {
                    pwd = cookie.getValue();
                }
            }
        }

        if (account.equals("") || pwd.equals("")) {
            return false;

        } else if (account.equals("yzq") && pwd.equals("123")) {
            return true;
        }


        return false;
    }

    public void init(FilterConfig config) throws ServletException {
        System.out.println("LoginFilter  init");
    }

}

敏感字符过滤

package cn.liayun.web.filter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

public class WordsFilter implements Filter {
	
	private List<String> banWords = new ArrayList<String>();//禁用词(1)
	private List<String> auditWords = new ArrayList<String>();//审核词(2)
	private List<String> replaceWords = new ArrayList<String>();//替换词(3)
	
	//WordsFilter过滤器只要一装载,WordsFilter对象只要一创建出来,init方法就会执行,init方法一执行,就会往List集合里面装东西。
	/*
     * 首先要将敏感词库读到系统里面去,而且敏感词库只要读一遍就行了。
     * 我们可以在静态代码块里面做,但是我们还有一种方法,即可以在init方法里面做,
     * 因为Filter对象只会创建一次,相应地,init方法也只会执行一次。
     */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		try {
			String path = WordsFilter.class.getClassLoader().getResource("cn/liayun/words").getPath();
			File[] files = new File(path).listFiles();
			for (File file : files) {
				if (!file.getName().endsWith(".txt")) {
					continue;
				}
				BufferedReader br = new BufferedReader(new FileReader(file));
//				BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"));
				String line = null;
				while ((line = br.readLine()) != null) {
					String[] s = line.split("\\|");
					if (s.length != 2) {
						continue;
					}
					if (s[1].trim().equals("1")) {
						banWords.add(s[0].trim());
					}
					if (s[1].trim().equals("2")) {
						auditWords.add(s[0].trim());
					}
					if (s[1].trim().equals("3")) {
						replaceWords.add(s[0].trim());
					}
				}
			}
			//System.out.println("haha");//作断点调试用
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		
		//检查提交的数据中是否包含禁用词
		/*
         * 此刻是不知道客户机要提交过来的数据的,也即不知道客户机会以什么名称提交数据过来,
         * 所以应得到客户机提交的所有数据,然后挨个检查,怎么得到客户机提交的所有数据呢?
         * 可得到客户机提交的所有数据的名称,然后挨个取出来检查即可。
         */
		Enumeration<String> e = request.getParameterNames();
		while (e.hasMoreElements()) {
			String name = (String) e.nextElement();
			String data = request.getParameter(name);//这里有可能会有乱码,例如,82342949842934*76%,所以还要解决乱码
			String regexData = data.replaceAll(" +", "");
			
			for (String regex : banWords) {
				Pattern pattern = Pattern.compile(regex);//编译regex这个正则表达式,得到代表此正则表达式的对象
				Matcher m = pattern.matcher(regexData);//看数据(regexData )里面有没有和该正则表达式相匹配的内容
				if (m.find()) {//匹配器的find方法若返回true,则代表客户机提交的数据(data)里面有和正则表达式相匹配的内容
					request.setAttribute("message", "文章中包含非法词汇,请检查后再提交!!");
					request.getRequestDispatcher("/message.jsp").forward(request, response);
					return;
				}
			}
		}
		
		//检查审核词,审核词高亮之后再显示给管理员看
		chain.doFilter(new MyRequest(request), response);
	}
	
	class MyRequest extends HttpServletRequestWrapper {
		
		private HttpServletRequest request;

		public MyRequest(HttpServletRequest request) {
			super(request);
			this.request = request;
		}

		@Override
		public String getParameter(String name) {
			String data = this.request.getParameter(name);
			if (data == null) {
				return null;
			}
			
			for (String regex : auditWords) {
				Pattern p = Pattern.compile(regex);
				Matcher m = p.matcher(data);
				if (m.find()) {
					String value = m.group();//group方法:找出客户机提交过来的数据中和正则表达式相匹配的数据
					data = data.replaceAll(regex, "<font color='red'>" + value + "</font>");
				}
			}
			
			for (String regex : replaceWords) {
				Pattern p = Pattern.compile(regex);
				Matcher m = p.matcher(data);
				if (m.find()) {
					String value = m.group();//group方法:找出客户机提交过来的数据中和正则表达式相匹配的数据
					data = data.replaceAll(regex, "<font color='red'>******</font>");
				}
			}
			
			return data;
		}
	
	}
	
	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值