Day61.Filter过滤器 & Listener监听器、Session活化与钝化

目录

Filter 过滤器

一、通过Fliter解决乱码问题

二、Filter的生命周期

三、Filter 的拦截路径

四、过滤器匹配规则

过滤器链

五、 应用:敏感字屏蔽

Listener 监听器

一、Session 的活化与钝化

二、观察者模式简介

三、ServletContextListener


Filter 过滤器

Filter:一个实现了特殊接口(Filter)的Java类. 实现对请求资源(jsp,servlet,html,)的过滤的功能. 过滤器是一个运行在服务器的程序, 优先于请求资源(Servlet或者jsp,html)之前执行. 过滤器是javaweb技术中最为实用的技术之一

Filter的作用是对目标资源(Servlet,jsp)进行过滤,其应用场景有: 登录权限检查,解决网站乱码,过滤敏感字符等等。对请求进行过滤,本质是一个接口。

一、通过Fliter解决乱码问题

1、编写一个类去实现 Filter 接口
2、实现过滤方法 doFilter()
3、到 web.xml 中去配置 Filter 的拦截路径

Filter
public class EncodingFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {
        
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("------------- 到达EncodingFilter -------------");
        //解决乱码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        //请求放行 执行目标资源
        chain.doFilter(request,response);
        System.out.println("------------- 离开EncodingFilter -------------");
    }
}
配置编码过滤器 (web.xml)
<filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>com.atguigu.filter.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/filter01</url-pattern>
    </filter-mapping>
servlet
@WebServlet("/filter01")
public class Filter01Servlet extends HttpServlet {
    //使用Filter解决乱码问题
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("----- 请求:Filter01Servlet -----");

        String username = req.getParameter("username");
        System.out.println("username = " + username);

        resp.getWriter().println("成功");
    }
}
html
<form action="filter01" method="post">
    <span>解决乱码</span><br>
    <span>用户名: <input type="text" name="username"> </span><br>
    <input type="submit"> <br>
</form>

二、Filter的生命周期

生命周期阶段执行时机生命周期方法
创建对象Web服务器启动时init(),通常在该方法中做初始化工作
拦截请求来一次请求执行一次doFilter(),通常在该方法中执行拦截过滤
销毁Web程序卸载时destroy(),通常在该方法中执行资源释放

回顾 servlet声明周期:

Servlet
         init()  当请求需要此Servlet 处理时
        <load-on-startup>x</load-on-startup> 设置初始化时机,x值越小启动越早。
         service()  来一次请求执行一次
         destory() 程序卸载的时

三、Filter 的拦截路径

过滤器匹配的目的是指定当前过滤器要拦截哪些资源

精确匹配 精确匹配

<url-pattern>/filter01</url-pattern>

以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp

Servlet名称 匹配

<servlet-name>Target01Servlet</servlet-name>

目录匹配 目录匹配

<url-pattern>/admin/*</url-pattern>

请求地址必须为:http://ip:port/工程路径/admin/*(以admin开头)

后缀名匹配 后缀名匹配(不能以斜杆打头)

<url-pattern>*.html</url-pattern>

以上配置的路径,表示请求地址必须以: .html结尾才会拦截到

不在乎.后面写的什么东西,↓↓↓不管是.action还是.abc结尾等都认

<url-pattern>*.do</url-pattern>

以上配置的路径,表示请求地址必须以.do 结尾才会拦截到

<url-pattern>*.action</url-pattern>

以上配置的路径,表示请求地址必须以.action 结尾才会拦截到

Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在 

四、过滤器匹配规则

一个资源被多个过滤器过滤,执行顺序:

如果采用 <url-pattern> 方式配置 ,按照配置顺序执行

如果采用 <servlet-name> 方式配置,该过滤器最后执行

过滤器链 (责任链模式)

有一种设计模式:责任链模式

多个过滤器组成的链条(chain)。

一个请求可能被多个过滤器所过滤,只有当所有过滤器都放行,请求才能到达目标资源。如果有某一个过滤器没有放行,那么请求则无法到达后续过滤器以及目标资源,多个过滤器组成的链路就是过滤器链。

五、 应用:敏感字屏蔽

过滤器
public class commonFilter implements Filter {
    //敏感字集合
    ArrayList<String> list = null;
    //filter初始化时(启动web服务器)
    public void init(FilterConfig config) throws ServletException {
        try {
            //1.在Filter初始化时,通过各种流,解决敏感,读取敏感字文件
            InputStream is = commonFilter.class.getClassLoader().getResourceAsStream("common");
            InputStreamReader isr = new InputStreamReader(is, "UTF-8");
            //BufferedReader 方便读取一行操作 readLine()
            BufferedReader br = new BufferedReader(isr);

            //2.读取敏感字
            list = new ArrayList<>();
            String line = "";
            while ((line = br.readLine())!=null){
                //按照空格分割
                String[] array = line.split(" ");
                for (String s : array) {
                    //将每一个独立的敏感字符串添加到集合内
                    list.add(s);
                }
            }
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    public void destroy() {
    }
    //匹配路径被访问后
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("----- commonFilter  -----");
        //准备工作
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        //1.获取评论
        String common = request.getParameter("common");
        boolean falg = false;
        //2.判断是否包含敏感字
        for (String s : list) {
            if(common.contains(s)){
                falg=true;
                break;
            }
        }
        //3.如果包含屏蔽,如果不包含放行
        if(falg){
            response.getWriter().println("屏蔽啦");

        }else {
            chain.doFilter(request,response);
        }
    }
}
<filter>
        <filter-name>commonFilter</filter-name>
        <filter-class>com.atguigu.filter.commonFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>commonFilter</filter-name>
        <url-pattern>/filter03</url-pattern>
    </filter-mapping>

Listener 监听器

只要触发了监听器条件,就会触发对应的Listener。

  • Request

    • ServletRequestListener (请求创建和销毁)

    • ServleRequestAttributeListener (属性的设置、获取、修改)

  • Session

    • HttpSessionListener (session的创建和销毁)

    • HttpSessionAttributeListener (session的设置、获取、修改)

    • HttpSessionBindingListener (处理session对象监听器绑定和解绑定接口)

    • HttpSessionActivationListener (处理session对象钝化和活化状态接口)

  • Application

    • ServletContextListener (ServletContext 的创建和销毁)

    • ServletContextAttributeListener (对属性值的设置、获取、修改)

    <!-- 注册监听器-->
    <listener>
        <listener-class>com.atguigu.listener.MyRequestLister</listener-class>
    </listener>
public class MyRequestLister implements ServletRequestListener, ServletRequestAttributeListener {
    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("请求销毁了.......");
    }
    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        String uname = servletRequestEvent.getServletRequest().getParameter("uname");
        System.out.println("请求初始化了:"+  uname);
    }
    @Override
    public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("添加属性了");
        String name = servletRequestAttributeEvent.getName();
        Object value = servletRequestAttributeEvent.getValue();

        System.out.println(name + "-->" + value);
    }
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {

    }
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {

    }
}

一、Session 的活化与钝化

钝化 :将session存储到磁盘上,服务器关闭时钝化。

活化:将磁盘中的 session 加载到程序(内存)内,第一次使用session时活化。 

需要在web目录下创建 META-INF ,context.xml文件,配置存储的目录

<?xml version="1.0" encoding="UTF-8"?>
      <Context>
          <Manager className="org.apache.catalina.session.PersistentManager">
              <!--session钝化存储的路径-->
              <Store className="org.apache.catalina.session.FileStore" directory="d:/session"/>
          </Manager>
      </Context>

如果session内有对象数据,必须实现Serializable接口。否则无法钝化(不报错)。

需要将监听器与session对象进行绑定:将对应监听器添加到session域内

session.setAttribute ("listener", new MySessionActiveListener());

public class MySessionActiveListener implements HttpSessionActivationListener {
    @Override//钝化
    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
        System.out.println(httpSessionEvent.getSession().getId() + " session 即将钝化");
    }

    @Override//活化
    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        System.out.println(httpSessionEvent.getSession().getId() + " session 已经活化");
    }
}
@WebServlet("/set")
public class Servlet1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("--- set ---");
        HttpSession session = req.getSession();
        System.out.println(session.getId()+" isNew:"+session.isNew());
        session.setAttribute("string","abc");
        //将监听器与 session绑定
        session.setAttribute("listener", new MySessionActiveListener());

    }
}
@WebServlet("/get")
public class Servlet2 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("--- get ---");
        HttpSession session = req.getSession();

        String string = (String) session.getAttribute("string");
        System.out.println(session.getId()+" isNew:"+session.isNew());
        System.out.println(string);
    }
}

二、观察者模式简介

观察者模式是二十三中设计模式之一,它是指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。

  • 观察者:监控『被观察者』的行为,一旦发现『被观察者』触发了事件,就会调用事先准备好的方法执行操作。

  • 被观察者:『被观察者』一旦触发了被监控的事件,就会被『观察者』发现。

三、ServletContextListener

ServletContextListener是监听ServletContext对象的创建和销毁的,因为ServletContext对象是在服务器启动的时候创建、在服务器关闭的时候销毁,所以ServletContextListener也可以监听服务器的启动和关闭。

将来学习SpringMVC的时候,会用到一个ContextLoaderListener,这个监听器就实现了ServletContextListener接口,表示对ServletContext对象本身的生命周期进行监控。

public class ContextLoaderListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("在服务器启动的时候,模拟创建SpringMVC的核心容器...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("在服务器启动的时候,模拟销毁SpringMVC的核心容器...");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值