FIlter-过滤器

简介

web过滤器

	过滤器是指拦截请求,并对传给被请求资源的ServletRequest或ServletResponse进行处理的一个对象。

	过滤器可用于登录、加密和解密、对话检查、图片转换等待。过滤器可以配置拦截一个或者多个资源

1.Filter API

	过滤器必须实现javax.servret.Filter接口,这个接口暴露三个生命周期方法:init,doFilter,destroy

	当过滤器启动服务时,Servlet容器就会调用init方法。这个方法指调用一次

	void init(FilterConfig filterConfig)

	filterConfig可用于获取ServletContext对象,或者获取初始化属性(getInitParameter)

	doFilter方法时过滤器核心

	void doFilter(ServletRequest request ,ServletResponse response,FilterChain chain)

	可以在ServletRequest 中添加属性,或者在ServletResponse添加一个标头

	也可以获取HttpServletRequest对象

	doFilter方法实现中的最后一行代码应该时调用FilterChain中的doFilter(request,response)方法

	表示放行,通常会引发下一个过滤器被调用。

	void destroy()

	这个方法在过滤器即将终止服务之前,有servlet容器调用

2.过滤器的配置

	确定要拦截哪些资源 (urlPatterns value)

	要传给init方法的启动初始值(initParams) 可通过getParameterNames 和getParameter方法来获取

	给过滤器七个名字(filterName)

	可以通过@webFilter注解 和部署描述符中声明

1.过滤器创建与配置

/**
 *@WebFilter 用于将一个类声明为过滤器
 */
@WebFilter("/MyFilter")
public class MyFilter implements Filter {

	//创建实例
    public MyFilter(){
        System.out.println("1.创建过滤器实例");
    }

    //初始化方法,在服务器启动时执行
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        System.out.println("2.执行过滤器初始化方法");
        
        //获取过滤器在web.xml中配置的所有初始化参数
        Enumeration<String> enums = filterConfig.getInitParameterNames();
        
        while(enums.hasMoreElements()){
        	
            //获取所有参数
            String name = enums.nextElement();
            
            //获取名称对应的值
            String value = filterConfig.getInitParameter(name);
            
            System.out.println(name+":"+value);
        }
    }

    //过滤器业务处理方法,在请求到达servlet之前县进入此方法处理公用的业务逻辑操作
    //FilterChain   过滤器链参数;一个个过滤器形成一个执行链
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
    	
        System.out.println("3.执行过滤器业务处理方法");
        
        //执行下一个过滤器或放行(去到servlet)
        chain.doFilter(request, response);
        
        //如果有下一个过滤器,进入下一个过滤器,否则就执行访问servlet
        System.out.println("5.Servlet处理完成,又回到过滤器");
        
    }

    //销毁过滤器实例时候调用
    @Override
    public void destroy() {
    	
        System.out.println("6.销毁过滤器实例");
        
    }
}

过滤器创建与配置:web.xml

<!-- 过滤器声明 -->
<filter>

	<!-- 过滤器的名称 -->
    <filter-name>MyFilter</filter-name>
    
    <!-- 过滤器的完整类名:包名+类名 -->
    <filter-class>com.mrkj.ygl.filter.MyFilter</filter-class>
    
    <!-- 设置初始化参数 -->
    <init-param>
    
      <!-- 参数名 -->
      <param-name>***</param-name>
      
      <!-- 参数值 -->
      <param-value>***</param-value>
      
    </init-param>
    
</filter>
  
<!-- 过滤器映射 -->
<filter-mapping>
  	
  	<!-- 过滤器的名称 -->
    <filter-name>MyFilter</filter-name>
    
    <!-- 过滤器URL映射:/*  映射所有文件 -->
    <url-pattern>/*</url-pattern>

	<!-- 
    1.拦截所有资源 
    <url-pattern>/*</url-pattern>
    -->

    <!-- 2.拦截指定的jsp -->
    <url-pattern>/index.jsp</url-pattern>
    <url-pattern>/list.jsp</url-pattern>
    <url-pattern>*.jsp</url-pattern>

    <!-- 3.根据servlet的内部名称拦截 -->
    <servlet-name>IndexServlet</servlet-name>
    <url-pattern>/IndexServlet</url-pattern>

    <!-- 
    4.拦截指定的类型 
    REQUEST:默认拦截的类型
    FORWARD:拦截转发
    INCLUDE:拦截包含的页面
    ERROR:拦截声明式异常
    -->

    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>

<!-- 过滤器URL映射 -->
</filter-mapping>

2.字符编码过滤器

@WebFilter(asyncSupported = true, urlPatterns = { "/CharactorFilter" })
public class CharactorFilter implements Filter {

	String encoding = null;
	

    public CharactorFilter() {

    }

	public void init(FilterConfig fConfig) throws ServletException {

		encoding = fConfig.getInitParameter("encoding");
		
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		
		if(encoding != null) {
		
			request.setCharacterEncoding(encoding);
			
			response.setContentType("text/html;charset="+encoding);
			
		}
		
		chain.doFilter(request, response);
		
	}

	public void destroy() {

		encoding = null;
		
	}
}

字符编码过滤器:web.xml

<filter>
    <filter-name>CharactorFilter</filter-name>
    <filter-class>com.mrkj.ygl.filter.CharactorFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
  	<filter-name>CharactorFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3.网站访问计数器

@WebFilter(asyncSupported = true, urlPatterns = { "/CountFilter" })
public class CountFilter implements Filter {

	//来访数量
	private int count;
	
    public CountFilter() {

    }

	public void init(FilterConfig fConfig) throws ServletException {
		
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

		count++;	//访问数量自增
		
		//将ServletRequest转换为HttpServletRequest
		HttpServletRequest req = (HttpServletRequest) request;

		//将来访数量值放入到ServletContext
		ServletContext context = req.getSession().getServletContext();
	
		context.setAttribute("count", count);	
		
		chain.doFilter(request, response);		//向下传递过滤器
		
	}	

	public void destroy() {

	}
}

用于对网站访问的人数进行计数
网站访问计数器:web.xml

<filter>
    <filter-name>CountFilter</filter-name>
    <filter-class>com.mrkj.ygl.filter.CountFilter</filter-class>
    <init-param>
      <param-name>count</param-name>
      <param-value>5000</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CountFilter</filter-name>
    <url-pattern>/index.jsp</url-pattern>
</filter-mapping>

对应网站:index.jsp

<h2>
欢迎光临,<br>
你是本站第【<%=application.getAttribute("count") %>】位访客!
</h2>

4.无效数据处理

package com.mrkj.ygl.filter;

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.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class EncodingFilter implements Filter {

    // 初始化无效数据
    private List<String> dirtyData;
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    	
        // 模拟几个数据,过滤词汇
        dirtyData = new ArrayList<String>();
        dirtyData.add("nmd");
        dirtyData.add("炸使馆");
        dirtyData.add("买了否认");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {

        // 转型
        final HttpServletRequest request = (HttpServletRequest) req;    
        HttpServletResponse response = (HttpServletResponse) res;

        // 一、处理公用业务
        request.setCharacterEncoding("UTF-8");                 // POST提交有效
        response.setContentType("text/html;charset=UTF-8");

        HttpServletRequest proxy =  (HttpServletRequest) Proxy.newProxyInstance(
        		
        		// 指定当前使用的累加载器
                request.getClass().getClassLoader(),        
                
                // 对目标对象实现的接口类型
                new Class[]{HttpServletRequest.class},      
                
                // 事件处理器
                new InvocationHandler() {    
                	
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                    	
                        // 定义方法返回值
                        Object returnValue = null;
                        
                        // 获取方法名
                        String methodName = method.getName();
                        
                        // 判断:对getParameter方法进行GET提交中文处理
                        if ("getParameter".equals(methodName)) {

                            // 获取请求数据值【 <input type="text" name="userName">】
                            String value = request.getParameter(args[0].toString());    // 调用目标对象的方法

                            // 获取提交方式
                            String methodSubmit = request.getMethod(); // 直接调用目标对象的方法

                            // 判断如果是GET提交,需要对数据进行处理  (POST提交已经处理过了)
                            if ("GET".equals(methodSubmit)) {
                                if (value != null && !"".equals(value.trim())){
                                	
                                    // 处理GET中文
                                    value = new String(value.getBytes("ISO8859-1"),"GB2312");
                                    
                                }
                            } 

                            // 中文数据已经处理完: 下面进行无效数据过滤   
                            //【如何value中出现dirtyData中数据,用****替换】  
                            for (String data : dirtyData) {
                            	
                                // 判断当前输入数据(value), 是否包含无效数据
                                if (value.contains(data)){
                                	
                                    value = value.replace(data, "*****");
                                    
                                }
                            }
                            
                            // 处理完编码、无效数据后的正确数据
                            return value;
                            
                        }else {
                        	
                            // 执行request对象的其他方法
                            returnValue = method.invoke(request, args);
                            
                        }

                        return returnValue;
                        
                    }
                });

        //传入代理对象
        chain.doFilter(proxy, response);        
    }

    @Override
    public void destroy() {

    }
}

无效数据处理:web.xml

<filter>
    <filter-name>EncodingFilter</filter-name>
    <filter-class>com.mrkj.ygl.filter.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

5.访问权限过滤器

防止用户直接输入URL直接访问资源。
访问权限过滤器:web.xml

@WebFilter(asyncSupported = true, urlPatterns = { "/LoginFilter" })
public class LoginrFilter implements Filter {


    public UserFilter() {

    }

    public void init(FilterConfig fConfig) throws ServletException {

	}
    
	public void destroy() {

	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {     

        HttpServletRequest req = (HttpServletRequest) request;     
        HttpServletResponse res = (HttpServletResponse) response;  
        
        // 获取Session     
        HttpSession session = req.getSession();   
        
        // 获取Session中存储的对象s     
        Object o = session.getAttribute("LoginSession"); 
        
        // 获取当前请求的URI     
        String url = req.getRequestURI();     
        
        // 判断Session中的对象是否为空;判断请求的URI是否为不允许过滤的URI     
        if (o == null 
        		
        /*
		indexOf() 方法可返回数组中某个指定的元素位置。

		该方法将从头到尾地检索数组,看它是否含有对应的元素。开始检索的位置在数组 start 处或数组的开头(没有指定 start 参数时)。如果找到一个 item,则返回 item 的第一次出现的位置。开始位置的索引为 0。

		如果在数组中没找到指定元素则返回 -1。
		*/
        	&& !url.endsWith("login.jsp")     // 对URL地址为此结尾的文件不过滤     
            && url.indexOf("login.do") < 0    // 对URL地址中包含此字符串的文件不过滤     
            && url.indexOf("/images/") < 0) {     
        	
            res.sendRedirect(req.getContextPath() + "/login.jsp");     
            
        } else {   
        	
            chain.doFilter(request, response);
            
            res.setHeader("Cache-Control","no-store");           
            res.setDateHeader("Expires",0);        
            res.setHeader("Pragma","no-cache");      
            res.flushBuffer();  
            
       		 }     
	}
}

<filter>    
  <filter-name>UsersFilter</filter-name>    
  <filter-class>com.mrkj.ygl.filter.LoginFilter</filter-class>    
</filter>    
<filter-mapping>    
  <filter-name>UsersFilter</filter-name>    
  <url-pattern>/*</url-pattern>    
</filter-mapping>

6.用户登录过滤

public class SessionFilter extends OncePerRequestFilter{
    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.web.filter.OncePerRequestFilter#doFilterInternal(
     * javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain)
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        //request.getSession().setAttribute("loginedUser", "ssss");
        // 不过滤的uri
        String[] notFilter = new String[] { "login.jsp", "index.jsp" };

        // 请求的uri
        String uri = request.getRequestURI();

        // uri中包含background时才进行过滤
        if (uri.indexOf("do") != -1) {
            // 是否过滤
            boolean doFilter = true;
            for (String s : notFilter) {
                if (uri.indexOf(s) != -1) {
                    // 如果uri中包含不过滤的uri,则不进行过滤
                    doFilter = false;
                    break;
                }
            }
            if (doFilter) {
                // 执行过滤
                // 从session中获取登录者实体
                Object obj = request.getSession().getAttribute("loginedUser");
                if (null == obj) {
                    // 如果session中不存在登录者实体,则弹出框提示重新登录
                    // 设置request和response的字符集,防止乱码
                    request.setCharacterEncoding("UTF-8");
                    response.setCharacterEncoding("UTF-8");
                    response.setContentType("text/html");
                    PrintWriter out = response.getWriter();
                    String loginPage = "login-old.jsp";
                    StringBuilder builder = new StringBuilder();
                    builder.append("<script type=\"text/javascript\">");
                    builder.append("alert('网页过期,请重新登录');");
                    builder.append("window.top.location.href='");
                    builder.append(loginPage);
                    builder.append("';");
                    builder.append("</script>");
                    out.print(builder.toString());
                } else {
                    // 如果session中存在登录者实体,则继续
                    filterChain.doFilter(request, response);
                }
            } else {
                // 如果不执行过滤,则继续
                filterChain.doFilter(request, response);
            }
        } else {
            // 如果uri中不包含background,则继续
            filterChain.doFilter(request, response);
        }
    }
    //在web.xml中配置..
}

web.xml

<filter>
        <filter-name>sessionFilter</filter-name>
        <filter-class>com.ssm.student.filter.SessionFilter</filter-class>
</filter>
<filter-mapping>
        <filter-name>sessionFilter</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值