过滤器学习笔记

来源:互联网 发布:最好用的保湿精华知乎 编辑:程序博客网 时间:2024/04/27 16:34

1. 过滤器概念和原理

1.1 定义

过滤器是一个服务器端的组件,它可以截取客户端的请求与响应信息,并对这些信息过滤。

1.2 工作原理

工作原理

2. 过滤器声命周期

2.1 生命周期

声名周期

2.2 三个方法的作用

各个方法作用
生命周期
请求index.jsp页面,触发过滤器,执行doFilter方法,输出“start…doFilter”,filter放行,执行index.jsp,再执行dofilter余下的代码。

2.3 过滤器配置

先创建过滤器类,然后实现Filter接口,在配置Web.xml文件
过滤器配置
过滤器能改变用户请求的Web资源,也就是能改变用户请求的路径,但是,过滤器不能处理用户的请求

2.4 过滤器链

过滤器链
实例验证

3. 过滤器类型

分类
REQUEST,FORWARD,INCLUDE过滤器

@Override    public void doFilter(ServletRequest arg0, ServletResponse arg1,            FilterChain arg2) throws IOException, ServletException {        System.out.println("start.....doFilter----FirstFilter");        arg2.doFilter(arg0, arg1);//放行??        HttpServletRequest req = (HttpServletRequest) arg0;        HttpServletResponse response2 = (HttpServletResponse) arg1;        //重定向(相当于一个新的请求,所以在main界面继续出发FirstFilter) 陷入死循环        response2.sendRedirect(req.getContextPath()+"/main.jsp");        //请求转发,没有进入死循环,但是如果把main页面的过滤器改为forward则同样出现死循环//      req.getRequestDispatcher("main.jsp").forward(arg0, arg1);        //与上面几乎一样//      req.getRequestDispatcher("main.jsp").include(arg0, arg1);        System.out.println("end.....doFilter----FirstFilter");    }

ERROR过滤器:

<!--当输入路径不对,引发404错误,请求error.jsp;触发errorFilter --><filter>  <filter-name>ErrorFilter</filter-name>  <filter-class>com.imooc.filter.ErrorFilter</filter-class> </filter> <filter-mapping>  <filter-name>ErrorFilter</filter-name>  <url-pattern>/error.jsp</url-pattern>  <dispatcher>ERROR</dispatcher> </filter-mapping> <error-page>  <error-code>404</error-code>  <location>/error.jsp</location> </error-page>

AsynFilter(@WebFilter)(servlet3.0新增)
@WebFilter用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。
这里写图片描述
这里写图片描述
创建过滤器类实现Filter接口,配置@WebFilter即完成了过滤器的配置,无需手动去配置Web.xml
怎么体现异步过滤器的异步特性呢?
新建一个servlet,在内部类里设计一个线程,在里面执行一些复杂业务,模拟异步操作(servlet和filter都要设置支持异步)
这里写图片描述
这里写图片描述
从结果可以看出,过滤器并没有等待模拟的复杂业务执行(线程),而是直接执行完了过滤器。

4. 登录认证及编码转换实战案例

login.jsp

<body>  <form action="<%=request.getContextPath() %>/servlet/LoginServlet" method="post">    用户名:<input type="text" name="username">    密码:<input type="password" name="password">    <input type="submit" value="提交">    </form>  </body>

LoginServlet.java

public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        String uesrname = request.getParameter("username");        String password = request.getParameter("password");        //手动解决乱码        //System.out.println(new String(uesrname.getBytes("ISO-8859-1"),"UTF-8"));        //过滤器解决乱码        System.out.println(uesrname);        if ("admin".equals(uesrname)&&"admin".equals(password)) {            //校验通过            HttpSession session = request.getSession();            session.setAttribute("username", uesrname);            response.sendRedirect(request.getContextPath()+"/success.jsp");        }else {            //校验失败            response.sendRedirect(request.getContextPath()+"/fail.jsp");        }    }

到这里,已经可以实现登录,但是完全没有过滤
Login_Filter.java

public class Login_Filter implements Filter {    private FilterConfig config;    @Override    public void destroy() {    }    @Override    public void doFilter(ServletRequest arg0, ServletResponse arg1,            FilterChain arg2) throws IOException, ServletException {        HttpServletRequest request = (HttpServletRequest) arg0;        HttpServletResponse response = (HttpServletResponse) arg1;        HttpSession session = request.getSession();        //在过滤器内直接设置编码        //request.setCharacterEncoding("utf-8");        //过滤器设置初始化参数解决乱码        String charset = config.getInitParameter("charset");        //未指定编码时默认utf-8        if (charset==null) {            charset="utf-8";        }        request.setCharacterEncoding(charset);        String noLonginPaths = config.getInitParameter("noLonginPaths");        //通过设置初始化参数,解决多个不过滤界面问题        if (noLonginPaths != null) {            String[] strArray = noLonginPaths.split(";");            for (int i = 0; i < strArray.length; i++) {                //参数为空和null时不放行                if (strArray[i] == null || "".equals(strArray[i]))                    continue;                //url.indexif(str):如果url包含str,则返回str在url中的位置,如果不包含则返回-1                if (request.getRequestURI().indexOf(strArray[i]) != -1) {                    arg2.doFilter(arg0, arg1);                    return;                }            }        }        //如果请求地址就是登录界面的话,或者loginServlet就放行,否则会进入死循环        //后来发现,fail.jsp也需要放行,这样一来,这里代码会变得很繁琐,以后增加新的页面还需要修改代码,不符合java设计原则        // if (request.getRequestURI().indexOf("login.jsp")!=-1        // ||request.getRequestURI().indexOf("LoginServlet")!=-1) {        // arg2.doFilter(arg0, arg1);        //返回,否则还会执行下面的代码        // return;        // }        //通过session获取用户名,如果有登录信息。就放行;否则,别人只需输入成功页面地址就可以显示登陆成功界面        //如果没有登录信息就跳转到登录界面        if (session.getAttribute("username") != null) {            arg2.doFilter(arg0, arg1);        } else {            response.sendRedirect("login.jsp");        }    }    @Override    public void init(FilterConfig arg0) throws ServletException {        //通过设置初始化参数,解决多个不过滤界面问题        config = arg0;    }}

web.xml

<filter>  <filter-name>LoginFilter</filter-name>  <filter-class>com.imooc.filter.Login_Filter</filter-class>  <init-param>   <param-name>noLonginPaths</param-name>   <param-value>login.jsp;fail.jsp;LoginServlet</param-value>  </init-param>  <init-param>   <param-name>charset</param-name>   <param-value>utf-8</param-value>  </init-param> </filter> <!-- 不允许未登录用户访问界面不止success.jsp一个,所以要对所有界面进行过滤 --> <filter-mapping>  <filter-name>LoginFilter</filter-name>  <url-pattern>/*</url-pattern> </filter-mapping> <servlet>  <description>This is the description of my J2EE component</description>  <display-name>This is the display name of my J2EE component</display-name>  <servlet-name>LoginServlet</servlet-name>  <servlet-class>com.imooc.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping>  <servlet-name>LoginServlet</servlet-name>  <url-pattern>/servlet/LoginServlet</url-pattern> </servlet-mapping>

要注意这里两个主要问题(设置多个不过滤的页面和解决编码)都是通过设置初始化参数完成的!

0 0
原创粉丝点击