过滤器学习笔记

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值