JavaWeb——Filter过滤器概述、FilterConfig、Filter案例 、改造EasyMall

本文详细介绍了JavaWeb中的Filter过滤器技术,包括过滤器的概述、FilterConfig的使用,以及在EasyMall项目中应用过滤器解决全站乱码问题和实现30天内自动登录的功能。过滤器作为Servlet三大核心技术之一,主要负责拦截请求并进行过滤操作,如权限控制、乱码处理和响应压缩等。在web.xml中配置多个过滤器时,它们按照配置顺序依次执行,采用责任链模式。

一、Filter过滤器概述

  1. Filtert概述
    Filter技术,即过滤器技术,是Servlet三大核心技术之一。
    主要用于拦截请求进行过滤操作。
    可以实现权限控制、全站乱码解决、压缩响应等功能。
    过滤器可以拦截对资源的访问,拦截之后,可以控制访问是否放行,如果放行还可以在访问之前或之后做一些额外的操作。
    过滤器可以配置多个,多个过滤器之前采用责任链模式,依次进行拦截。只有所有过滤器都通过,才可以访问到最终的资源。

在这里插入图片描述

  1. 过滤器开发
    a.开发Filter的步骤
    i.写一个类实现Filter接口
    ii.在web.xml中配置Filter
    b.写一个类实现Filter接口

Filter接口

Method Summary
voiddestroy() Called by the web container to indicate to a filter that it is being taken out of service.销毁的方法,当filter在web容器中被销毁时会调用此方法
voiddoFilter(ServletRequest request, ServletResponse response, FilterChain chain) The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.当有请求访问资源被当前过滤器拦截时,此方法执行。request 代表当前拦截下来的请求对象response代表当前拦截下来的响应对象chain代表当前整个过滤器链 提供了doFilter()方法,可以放行过滤器
voidinit(FilterConfig filterConfig) Called by the web container to indicate to a filter that it is being placed into service.初始化的方法,当filter在web容器中被初始化时会调用此方法.filterConfig 代表当前Filter在web.xml中的配置信息

案例:自定义一个过滤器

package cn.tedu.filter;
import javax.servlet.*;
import java.io.IOException;
 
public class MyFilter01 implements Filter {
    /**
     * 服务器启动或web应用初始化时 过滤器被创建
     * 创建出来之后立即调用init方法执行初始化操作
     * 之后过滤器对象一直被保留在服务器内部 为后续过滤器操作服务
     *
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("##MyFilter01..init..");
    }

    /**
     * 在存活期间每次拦截到对资源的访问 都会造成doFilter方法的执行可以在这个方法中完成拦截逻辑
     * 过滤器默认拦截对资源的方法不允许通过
     * 可以手工调用chain.doFilter()方法来放行对资源的访问
     * 放行之后执行过滤器链中的下一个过滤器,如果没有下一个过滤器就访问到目标资源
     * @param request
     * @param response
     * @param chain
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("##MyFilter01..doFilter..");
        chain.doFilter(request,response);
    }
 
    /**
     * 直到服务器关闭或web应用移除出容器时
     * 随着应用的销毁 过滤器对象被销毁
     * 在销毁之前 执行destory方法 进行善后工作
     */
    @Override
    public void destroy() {
        System.out.println("##MyFilter01..destory..");
    }
}

c.在web.xml中配置Filter

在web.xml中配置过滤器的过程非常类似于配置一个Servlet
要通过< filter>< filter-mapping>标签实现
其中< filter-mapping>中可以通过< servlet-name>或< url-pattern>
< servlet-name>可以配置要拦截哪个名字的Servlet
< url-pattern>可以配置要拦截哪个url路径
一个web资源也可以被多个过滤器拦截,拦截顺序取决于过滤器的< filter-mapping>在web.xml中的配置顺序。
案例:配置过滤器

<!--配置过滤器-->
<filter>
    <filter-name>MyFilter01</filter-name>
    <filter-class>cn.tedu.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter01</filter-name>
    <servlet-name>MyServ01</servlet-name>
    <url-pattern>/MyServlet02</url-pattern>
    <url-pattern>/img/*</url-pattern>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>
  1. 过滤器的生命周期
    当服务器启动web应用初始化时,web应用中的过滤器对象被创建出来
    创建出来之后立即执行init方法进行初始化
    之后一直驻留在内存中为后续的拦截进行服务
    拦截到任何资源都会执行doFilter方法执行拦截
    可以在doFilter方法中开发拦截逻辑
    过滤器默认拦截不放行,可以通过调用FilterChain的doFilter方法来放行访问
    也可以在放行之前和之后执行一些额外操作
    直到web应用移除出容器时,随着web应用的销毁过滤器对象被销毁
    在销毁之前会调用destory方法执行善后工作

  2. 多个过滤器执行过程
    多个过滤器执行的先后顺序取决于过滤器的的配置顺序
    先配置的先拦截先执行过滤
    多个过滤器的执行过程,采用了责任链模式,非常类似于方法调用的过程,每当调用chain.doFilter()都会执行后续资源,后续资源执行过后,在返回到当前过滤器执行chain.doFilter()之后的内容。

在这里插入图片描述

二、FilterConfig

  1. FilterConfig概述
    FilterConfig是代表过滤器在web.xml中配置的对象

  2. FilterConfig功能
    获取过滤器名称

在这里插入图片描述

b.获取过滤器中配置的初始化参数

在这里插入图片描述

c.获取ServletContext对象

在这里插入图片描述

三、Filter案例 - 改造EasyMall

  1. 全站乱码解决过滤器
    web应用中,获取请求参数和发送响应数据时都有可能产生乱码,需要手动解决。
    与其在每个Servlet中单独解决乱码,不如开发一个过滤器拦截所有资源,统一进行乱码解决。
    a.开发过滤器类
package cn.tedu.filter;
import javax.servlet.*;
import java.io.IOException;
/**
 *全站乱码解决过滤器
 */
public class EncodingFilter implements Filter {
    private FilterConfig config = null;
    @Override
    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String encoding = config.getInitParameter("encoding");
        //1.解决请求乱码
        request.setCharacterEncoding(encoding);
        //2.解决响应乱码
        response.setContentType("text/html;charset="+encoding);
        //3.放行资源
        chain.doFilter(request,response);
    }
 
    @Override
    public void destroy() {
        this.config = null;
    }
}

b. 配置该Filter,拦截所有的资源

<!--全站乱码解决过滤器-->
<filter>
    <filter-name>EncodingFilter</filter-name>
    <filter-class>cn.tedu.filter.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
  1. 30天内自动登录过滤器

在这里插入图片描述

a. 改造LoginServlet

package cn.tedu.web;
import cn.tedu.domain.User;
import cn.tedu.exception.MsgException;
import cn.tedu.service.UserService;
import cn.tedu.utils.MD5Utils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * 登录
 */
@WebServlet(urlPatterns = "/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0.解决乱码
        //request.setCharacterEncoding("utf-8");
        //response.setContentType("text/html;charset=utf-8");

        //1.获取用户名密码
        String username = request.getParameter("username");
        String password = MD5Utils.md5(request.getParameter("password"));
        //####记住用户名

        if("true".equals(request.getParameter("remname"))){
            //--创建cookie
            Cookie remnameC = new Cookie("remnamec", URLEncoder.encode(username,"utf-8"));
            //--指定MaxAge
            remnameC.setMaxAge(60 * 60 * 24 * 30);
            //--指定Path
            remnameC.setPath(request.getContextPath());
            //--发送cookie
            response.addCookie(remnameC);
        }else{
            //--创建cookie
            Cookie remnameC = new Cookie("remnamec", "");
            //--指定MaxAge
            remnameC.setMaxAge(0);
            //--指定Path
            remnameC.setPath(request.getContextPath());
            //--发送cookie
            response.addCookie(remnameC);
        }
        //####记住用户名
        //2.调用Service完成登录
        try{
            UserService userService = new UserService();
            User user = userService.login(username,password);

            //3.登录
            HttpSession session = request.getSession();
            session.setAttribute("user",user);
 
            //###30天内自动登录
          if("true".equals(request.getParameter("autologin"))){
                //发送cookie保存用户名密码
                String cv = URLEncoder.encode(username+"#"+password,"utf-8");
                Cookie autologinc = new Cookie("autologin",cv);
                autologinc.setMaxAge(60 * 60 * 24 * 30);//设定保存时长,30天              autologinc.setPath(request.getContextPath());//设定访问哪个路径及其子孙路径带着cookie回来
                response.addCookie(autologinc);
            }
            //###30天内自动登录
            //3.回主页
         response.sendRedirect(request.getContextPath()+"/index.jsp");
            return;
        }catch (MsgException e){
            //3.登录失败回登录页面提示
            request.setAttribute("msg",e.getMessage());        request.getRequestDispatcher("/login.jsp").forward(request,response);
            return;
        }
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

b. 开发AutoLoginFilter

package cn.tedu.filter;
import cn.tedu.domain.User;
import cn.tedu.exception.MsgException;
import cn.tedu.service.UserService;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URLDecoder;
public class AutologinFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //1.未登录才做自动登录
        HttpSession session = req.getSession();
        if(session.getAttribute("user")==null){
            //2.带了自动登录cookie才做自动登录
            Cookie[] cs = req.getCookies();
            Cookie findC = null;
            if(cs!=null){
                for(Cookie c : cs){
                   if("autologin".equals(c.getName())){
                        findC = c;
                        break;
                    }
                }
            }
            if(findC!=null){
                //3.自动登录cookie中的用户名密码正确才做自动登录
                String v =  URLDecoder.decode(findC.getValue(),"utf-8");//孙悟空#123
                String username = v.split("#")[0];
                String password = v.split("#")[1];
                UserService userService = new UserService();
                try{
                    User user = userService.login(username,password);
                    //--未登录、带了自动登录cookie、自动登录cookie中的用户名密码正确,自动登录
                    session.setAttribute("user",user);
                }catch (MsgException e){
                    //--自动登录中的用户名密码不正确,不自动登录
                } 

            }

        }

        //--无论是否自动登录,都放行资源
        chain.doFilter(request,response);
    }


    @Override
    public void destroy() {
    }
}
<!--30天内自动登录过滤器-->
<filter>
    <filter-name>AutologinFilter</filter-name>
    <filter-class>cn.tedu.filter.AutologinFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AutologinFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

c. 改造LogoutServlet
需要在登出操作时,删除30天内自动登录cookie

package cn.tedu.web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * 登出
 */

@WebServlet(urlPatterns = "/LogoutServlet")
public class LogoutServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.杀死session
        HttpSession session = request.getSession();
        session.invalidate();
        //##删除30天内自动登录cookie
        Cookie autologinc = new Cookie("autologin","");
        autologinc.setPath(request.getContextPath());
        autologinc.setMaxAge(0);
        response.addCookie(autologinc);
        //##删除30天内自动登录cookie
        //2.重定向回主页
      response.sendRedirect(request.getContextPath()+"/index.jsp");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张艳霞zhangyx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值