zoukankan      html  css  js  c++  java
  • javaweb之Filter过滤器详解

    快速入门
    1、新建一个类,实现Filter接口
    2、实现doFilter()方法,打印一句话,来证明能够进行拦截
    3、在web.xml中进行配置(参照Servlet配置)
    4、访问一个页面,看看能不能拦截

    例子:

    import java.io.IOException;
    
    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 javax.servlet.http.HttpSession;
    
    public class UserFilter implements Filter {
    
    	@Override
    	public void destroy() {
    		// TODO Auto-generated method stub
    		
    	}
    	
    	@Override
    	public void init(FilterConfig arg0) throws ServletException {
    		// TODO Auto-generated method stub
    	}
    
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response,
    			FilterChain chain) throws IOException, ServletException {
    		// 获取session对象,判断是否登录
    		HttpServletRequest req=(HttpServletRequest)request;
    		HttpServletResponse res=(HttpServletResponse)response;
    		HttpSession session = req.getSession();
    		if(session.getAttribute("user")==null){
    			// 非法访问,没有登录,跳转到登录页面
    			session.setAttribute("error","非法访问");
    			// 保存客户想要去的地址, 登录成功后则直接跳转,而不是到首页
    			// 获取请求的地址, 包括工程名,但是不包括参数
    			System.out.println(req.getRequestURI());
    			// 获取请求的参数
    			System.out.println("参数:" + req.getQueryString());
    			// 获取当前项目的绝对路径,方法已过时,不推荐使用 推荐使用  request.getServletContext().getRealPath("")
    			System.out.println(req.getRealPath(""));
    			// 获取请求的地址, 但是不包括工程名和参数
    			System.out.println(req.getServletPath());
    			// 此方法需要在servlet 3.0的版本上使用, 开发的环境需要J2EE6 运行需要Tomcate7.0
    			//System.out.println("request.getServletContext().getRealPath:" +request.getServletContext().getRealPath(""));
    			String goURL=req.getServletPath();
    			if(req.getQueryString()!=null){
    				goURL += "?" + req.getQueryString();
    			}
    			System.out.println(goURL);
    			session.setAttribute("goURL", goURL);
    			res.sendRedirect(req.getContextPath() + "/login.jsp");
    			System.out.println(req.getContextPath());
    		}else{
    			// 如果有下一个过滤器则跳转到下一个过滤器否则目标页面
    			chain.doFilter(request, response);
    		}
    	}
    }
    

     在web.xml中进行配置

    <filter>
      	<filter-name>userFilter</filter-name>
      	<filter-class>
      		cn.***.UserFilter
      	</filter-class>
      </filter>
      <filter-mapping>
      	<filter-name>userFilter</filter-name>
      	<url-pattern>/user/*</url-pattern>
        <dispatcher>REQUEST</dispatcher> <!-- 没有配置dispatcher就是默认request方式的 -->        <dispatcher>FORWARD</dispatcher>        <dispatcher>ERROR</dispatcher>        <dispatcher>INCLUDE</dispatcher> </filter-mapping>

     四、Filter的应用场景
       通过对filter过滤器的了解,可以得知在以下三种情况下可以做些处理:
        1> 通过控制对chain.doFilter的方法的调用,来决定是否需要访问目标资源。
      比如,可以在用户权限验证等等。判断用户是否有访问某些资源的权限,有权限放行,没权限不执行chain.doFilter方法。
        2> 通过在调用chain.doFilter方法之前,做些处理来达到某些目的。
      比如,解决中文乱码的问题等等。可以在doFilter方法前,执行设置请求编码与响应的编码。甚至可以对request接口进行封装装饰来处理get请求方式的中文乱码问题(重写相  应的request.getParameter方法)。
        3> 通过在调用chain.doFilter方法之后,做些处理来达到某些目的。
      比如对整个web网站进行压缩。在调用chain.doFilter方法之前用类A对response对象进行封装装饰,重写 getOutputStream和重写getWriter方法。在类A内部中,将输出  内容缓存进ByteArrayOutputStream流中,然后在 chain.doFilter方法执行后,获取类A中ByteArrayOutputStream流缓存数据,用GZIPOutputStream流进行 压缩下。
    五、Filter实现拦截的原理
        Filter接口中有一个doFilter方法,当开发人员编写好Filter类实现doFilter方法,并配置对哪个web资源进行拦截后,WEB服 务器每次在调用web资源的service方法之前  (服务器内部对资源的访问机制决定的),都会先调用一下filter的doFilter方法。
    六、Filter生命周期
        和Servlet一样Filter的创建和销毁也是由WEB服务器负责。不过与Servlet区别的是,它是

      1>在应用启动的时候就进行装载 Filter类(与Servlet的load-on-startup配置效  果相同)。

      2>容器创建好Filter对象实例后,调用init()方 法。接着被Web容器保存进应用级的集合容器中去了等待着,用户访问资源。

      3>当用户访问的资源正好被Filter的url-pattern拦截 时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调  用 doFilter方法(Filter对象常驻留Web容器了)。

      4>当应用服务被停止或重新装载了,则会执行Filter的destroy方 法,Filter对象销毁。
      注意:init方法与destroy方法只会直接一次。
    七、Filter部署应用注意事项
       1> filter-mapping标签中servlet-name与url-pattern。
      Filter不仅可以通过url-pattern来指定拦截哪些url匹配的资源。而且还可以通过servlet-name来指定拦截哪个指定的servlet(专门为某个servlet服务了,servlet-name对应    Servlet的相关配置)。
      2> filter-mapping标签中dispatcher。
      指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多 个<dispatcher> 子元素  用来指定 Filter 对资源的多种调用方式进行拦截。


    REQUEST:
    当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问或ERROR情况时,那么该过滤器就不会被调用。
    INCLUDE:
    如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
    FORWARD:
    如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
    ERROR:
    如若在A.jsp页面page指令中指定了error属性=examError.jsp,那么A.jsp中若出现了异常,会跳转到examError.jsp中处理。而在跳转到examError.jsp时,若过滤器配置了ERROR的dispather那么则会拦截,否则不会拦截。

  • 相关阅读:
    js四舍五入
    文本框只能输入整数,输入其他的自动不显示
    [转]关于C#程序部署到Android
    ajax在火狐中传中文出现乱码的解决方法
    Vue 记录 Cannot read property '_withTask' of undefined
    vs中 VMDebugger未能加载导致异常
    System.InvalidOperationException: 支持“XXX”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。
    eclipse中将java项目转换成javaweb项目
    Android之SOAP协议与WebService服务器交互,解决超时的问题
    SymmetricDS 快速和灵活的数据库复制
  • 原文地址:https://www.cnblogs.com/wcyBlog/p/4657971.html
Copyright © 2011-2022 走看看