Filter(过滤器)和监听器(Listener)

一、Filter:过滤器,用来过滤网站的数据;(重点)

处理中文乱码,我们在之前需要每个类里面都需要写,要是有一个机制在每次调用Servlet之前就去把这个乱码处理好就很好。

登录验证。

Servlet要拿到一个Request和Response,就是因为web服务器要给他这两个对象。过滤器也需要这两个对象,才能进行处理。所以说过滤器和servlet一模一样。Servlet实现Servlet接口,过滤器实现过滤器接口。 

Filter开发步骤:

1.导包

我们在pom.xml进行配置如下所示:

  <!--JSP 依赖-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
        <!--Servlet 依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!--JSTL表达式的依赖-->
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>
        <!--standard标签库依赖-->
        <!-- https://mvnrepository.com/artifact/taglibs/standard -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--连接数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>

2.编写过滤器

(1)导包不要错:

我们所导入的包为javax.servlet的Filter

之后进入之后:

点击implement methods,进行重写方法:

 

之后我们可以先体现一个乱码的形式,从而去体现过滤器的作用:
我们创建servlet包下的ShowServlet类,我们的代码如下所示:

package com.rgf.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.getWriter().write("你好,加油");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

 之后我们你在web.xml里面进行注册:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1"
         metadata-complete="true">
<servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>com.rgf.servlet.ShowServlet</servlet-class>
</servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>

</web-app>

我们进行运行后如下所示:

我们发现出现了中文乱码。 

我们在之前的解决方法是在输出之前加入如下代码:

resp.setContentType("text/html;charset=utf-16");

我们还可以在一个项目里面写两个运行名字:

<servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>com.rgf.servlet.ShowServlet</servlet-class>
</servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show</url-pattern>
    </servlet-mapping>

重新运行之后如下所示:

我们发现成功转变成为了中文。

之后,我们利用Filter进行查看:我们将在ShowServlet类中的解决乱码问题的代码:

 resp.setContentType("text/html;charset=utf-16");

进行注释掉,或者删掉。

我们创建新的包filter,创建新的类:ShowServlet。

按照如上方法进行创建方法。之后我们进行编写代码:

(2)实现Filter接口,重写对应的方法即可。

package com.rgf.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter{

//初始化:web服务器启动,就已经初始化了。随时等待过滤对象出现!
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    @Override
    //filterChain:链,可以有很多个过滤器.我们需要通过filterChain来放行对象
    /*
    1.过滤中的所有代码,在过滤特定请求的时候,都会执行
    2.必须要让过滤器继续通行Chain.doFilter(request,response)l,就需要把这个请求往下转交

     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain Chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
       response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        System.out.println("CharacterEncodingFilter执行前..");
        //以下代码起到放行的作用,否则过滤器到这里就停下来了。我们需要通过filterChain来放行对象
        //其中doFilter,我们按住ctrl键进入源码界面,我们会发现他的两个参数为request和response。
        Chain.doFilter(request,response);//让我们的请求继续走,如果不写,程序到这里就拦截停止了。
        System.out.println("CharacterEncodingFilter执行后..");
    }
//销毁 :web服务器关闭的时候,过滤会销毁
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}

如下所示:

 当前有两个过滤器的时候,我们都需要拿到response和request。

通过 Chain.doFilter(request,response);//让我们的请求继续走,如果不写,程序到这里就拦截停止了。这个代码进行交接。

我们完成代码的编写之后,我们进行在web.xml里面进行配置如下所示:

3.在web.xml中配置Filter

<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.rgf.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--只要是/servlet下面的任何请求,都会经过这个过滤器-->
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>

我们在编写上一个类的时候,我们在web.xml里面对于一个请求可以通过两个访问,而我们的过滤器实现功能是在第一个请求里面就。(/servlet/show)

<servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>com.rgf.servlet.ShowServlet</servlet-class>
</servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show</url-pattern>
    </servlet-mapping>

运行之后,我们如下所示:

 之后我们访问的地址为:http://localhost:9571/javaweb_filter01_war_exploded/servlet/show

访问之后如下所示:

 我们进行查看如下所示:

 我们发现这个类进行初始化,web服务器启动的时候,就已经初始化了,随时等待过滤对象出现。

我们来看过滤器什么时候进行销毁:

我们访问这个之后我们发现出现乱码,之后再访问/servlet/show,如下所示:
 

 我们停止服务器之后如下所示:

 我们发现过滤器进行了销毁。

我们查看初始化的时候,我们发现如下所示:

 我们发现可以获取初始化的参数,获取上下文的对象。我们可以再服务器已启动的时候设置一些固有的东西进去,让所有人都可以访问。当然很少这样子做。

二、监听器

我们打开这个浏览器,没有任何问题,浏览器是一个客户端软件,关闭的时候点一下关闭即可关闭。我们点击关闭的时候:点一下它,它受到一个点击事件,收到点击事件之后执行一个动作,把浏览器进程给截了并且关闭窗口。

实现一个监听器的接口:(有N种)

我们进行运行之后如下所示:

但是我们所设计的代码里面只有一个人,为什么会 有两个人在线。我们进行如下所示:

package com.rgf.listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

//统计网站在线人数:统计session
public class OnlineCountListener implements HttpSessionListener {
    @Override
    //创建session的监听:看你的一举一动
    //一旦创建session就会触发一次这个事件。
    public void sessionCreated(HttpSessionEvent se) {
        /*我们监听器假设session创建的话,我们要获取OnlineCount对象,如果OnlineCount对象为空,我们要给他赋一个值,让他为1.
        如果不为空,则每一次都会加1。每一次都会更新onlineCount.
         */
       //HttpSessionEvent代表session事件的一个对象
        //通过getSession拿到session,拿到session之后我们就可以拿到网站的上下文,通过getServletContext
        //我们统计在线人数,是统计所有网站,所有人都可以访问到它,我们要把它提高到最高的作用域:ServletContext或者application
        ServletContext ctx = se.getSession().getServletContext();
        System.out.println(se.getSession().getId());
        //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
        //我们先取一个OnlineCount东西。强转为整型数据(int)
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if(onlineCount==null){
            //网站一个人都没有,我们进行+1.
            onlineCount=new Integer(1);
        }else {
            //将数量的类型count转换为int。
            int count=onlineCount.intValue();

            onlineCount=new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);
    }

    @Override
    //销毁session监听
    //一旦销毁session就会触发一次这个事件。
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
        //我们先取一个OnlineCount东西。强转为整型数据(int)
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if(onlineCount==null){
            //网站一个人都没有,我们记为0.
            onlineCount=new Integer(0);
        }else {
            //将数量的类型count转换为int。
            int count=onlineCount.intValue();

            onlineCount=new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);
    }

}

我们增加

System.out.println(se.getSession().getId());

从而获取他们的ID号。

运行之后我们发现如下所示:

 

我们发现有两个ID,输出了两个sessionID,可我们只有一个,另外一个是怎么来的呢:

启动浏览器的时候就在进行连接,有可能连接失败,但是session已经存在了,直到连接成功的时候就成为了2次。

我们发现最后一次输出的ID与该session相同。而第一个已经销毁了。 

我们来重新发布一下项目:

 重新运行之后看是否为一个,如下所示:

 我们可以试试用同一浏览器和不同浏览器进行查看:

我们都在谷歌浏览器进行访问的时候,如下所示:

 我们发现session是一样的。

我们使用双核浏览器进行访问:

 我们发现两个不同的浏览器才是不一样的客户端。

1.编写一个监听器

2.实现监听器的接口,我们的代码如下所示:
 

package com.rgf.listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

//统计网站在线人数:统计session
public class OnlineCountListener implements HttpSessionListener {
    @Override
    //创建session的监听:看你的一举一动
    //一旦创建session就会触发一次这个事件。
    public void sessionCreated(HttpSessionEvent se) {
        /*我们监听器假设session创建的话,我们要获取OnlineCount对象,如果OnlineCount对象为空,我们要给他赋一个值,让他为1.
        如果不为空,则每一次都会加1。每一次都会更新onlineCount.
         */
       //HttpSessionEvent代表session事件的一个对象
        //通过getSession拿到session,拿到session之后我们就可以拿到网站的上下文,通过getServletContext
        //我们统计在线人数,是统计所有网站,所有人都可以访问到它,我们要把它提高到最高的作用域:ServletContext或者application
        ServletContext ctx = se.getSession().getServletContext();
        System.out.println(se.getSession().getId());
        //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
        //我们先取一个OnlineCount东西。强转为整型数据(int)
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if(onlineCount==null){
            //网站一个人都没有,我们进行+1.
            onlineCount=new Integer(1);
        }else {
            //将数量的类型count转换为int。
            int count=onlineCount.intValue();

            onlineCount=new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);
    }

    @Override
    //销毁session监听
    //一旦销毁session就会触发一次这个事件。
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
        //我们先取一个OnlineCount东西。强转为整型数据(int)
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if(onlineCount==null){
            //网站一个人都没有,我们记为0.
            onlineCount=new Integer(0);
        }else {
            //将数量的类型count转换为int。
            int count=onlineCount.intValue();

            onlineCount=new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);
    }
/*
session销毁的两种情况
1.手动销毁  se.getSession.invalidate;
52.自动销毁  在web.xml里面配置session过期时间。: <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
 */
}

3.在web.xml里面注册监听器:

 <!--注册监听器-->
    <listener>
        <listener-class>com.rgf.listener.OnlineCountListener</listener-class>
    </listener>

4.看情况是否使用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一直再追梦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值