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


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

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

    登录验证

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

    Filter开发步骤:

    1.导包

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

    1. javax.servlet.jsp
    2. javax.servlet.jsp-api
    3. 2.3.3
    4. provided
    5. javax.servlet
    6. javax.servlet-api
    7. 4.0.1
    8. provided
    9. javax.servlet.jsp.jstl
    10. jstl-api
    11. 1.2
    12. taglibs
    13. standard
    14. 1.1.2
    15. mysql
    16. mysql-connector-java
    17. 8.0.27

    2.编写过滤器

    (1)导包不要错:

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

    之后进入之后:

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

     

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

    1. package com.rgf.servlet;
    2. import javax.servlet.ServletException;
    3. import javax.servlet.http.HttpServlet;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpServletResponse;
    6. import java.io.IOException;
    7. public class ShowServlet extends HttpServlet {
    8. @Override
    9. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    10. resp.getWriter().write("你好,加油");
    11. }
    12. @Override
    13. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    14. doGet(req, resp);
    15. }
    16. }

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

    1. "1.0" encoding="UTF-8"?>
    2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
    5. http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    6. version="3.1"
    7. metadata-complete="true">
    8. <servlet>
    9. <servlet-name>ShowServletservlet-name>
    10. <servlet-class>com.rgf.servlet.ShowServletservlet-class>
    11. servlet>
    12. <servlet-mapping>
    13. <servlet-name>ShowServletservlet-name>
    14. <url-pattern>/servlet/showurl-pattern>
    15. servlet-mapping>
    16. web-app>

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

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

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

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

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

    1. ShowServlet
    2. com.rgf.servlet.ShowServlet
    3. ShowServlet
    4. /servlet/show
    5. ShowServlet
    6. /show

    重新运行之后如下所示:

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

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

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

    进行注释掉,或者删掉。

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

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

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

    1. package com.rgf.filter;
    2. import javax.servlet.*;
    3. import java.io.IOException;
    4. public class CharacterEncodingFilter implements Filter{
    5. //初始化:web服务器启动,就已经初始化了。随时等待过滤对象出现!
    6. @Override
    7. public void init(FilterConfig filterConfig) throws ServletException {
    8. System.out.println("CharacterEncodingFilter初始化");
    9. }
    10. @Override
    11. //filterChain:链,可以有很多个过滤器.我们需要通过filterChain来放行对象
    12. /*
    13. 1.过滤中的所有代码,在过滤特定请求的时候,都会执行
    14. 2.必须要让过滤器继续通行Chain.doFilter(request,response)l,就需要把这个请求往下转交
    15. */
    16. public void doFilter(ServletRequest request, ServletResponse response, FilterChain Chain) throws IOException, ServletException {
    17. request.setCharacterEncoding("utf-8");
    18. response.setCharacterEncoding("utf-8");
    19. response.setContentType("text/html;charset=utf-8");
    20. System.out.println("CharacterEncodingFilter执行前..");
    21. //以下代码起到放行的作用,否则过滤器到这里就停下来了。我们需要通过filterChain来放行对象
    22. //其中doFilter,我们按住ctrl键进入源码界面,我们会发现他的两个参数为request和response。
    23. Chain.doFilter(request,response);//让我们的请求继续走,如果不写,程序到这里就拦截停止了。
    24. System.out.println("CharacterEncodingFilter执行后..");
    25. }
    26. //销毁 :web服务器关闭的时候,过滤会销毁
    27. @Override
    28. public void destroy() {
    29. System.out.println("CharacterEncodingFilter销毁");
    30. }
    31. }

    如下所示:

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

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

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

    3.在web.xml中配置Filter

    1. CharacterEncodingFilter
    2. com.rgf.filter.CharacterEncodingFilter
    3. CharacterEncodingFilter
    4. /servlet/*

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

    1. ShowServlet
    2. com.rgf.servlet.ShowServlet
    3. ShowServlet
    4. /servlet/show
    5. ShowServlet
    6. /show

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

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

    访问之后如下所示:

     我们进行查看如下所示:

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

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

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

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

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

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

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

    二、监听器

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

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

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

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

    1. package com.rgf.listener;
    2. import javax.servlet.ServletContext;
    3. import javax.servlet.http.HttpSessionEvent;
    4. import javax.servlet.http.HttpSessionListener;
    5. //统计网站在线人数:统计session
    6. public class OnlineCountListener implements HttpSessionListener {
    7. @Override
    8. //创建session的监听:看你的一举一动
    9. //一旦创建session就会触发一次这个事件。
    10. public void sessionCreated(HttpSessionEvent se) {
    11. /*我们监听器假设session创建的话,我们要获取OnlineCount对象,如果OnlineCount对象为空,我们要给他赋一个值,让他为1.
    12. 如果不为空,则每一次都会加1。每一次都会更新onlineCount.
    13. */
    14. //HttpSessionEvent代表session事件的一个对象
    15. //通过getSession拿到session,拿到session之后我们就可以拿到网站的上下文,通过getServletContext
    16. //我们统计在线人数,是统计所有网站,所有人都可以访问到它,我们要把它提高到最高的作用域:ServletContext或者application
    17. ServletContext ctx = se.getSession().getServletContext();
    18. System.out.println(se.getSession().getId());
    19. //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
    20. //我们先取一个OnlineCount东西。强转为整型数据(int)
    21. Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    22. if(onlineCount==null){
    23. //网站一个人都没有,我们进行+1.
    24. onlineCount=new Integer(1);
    25. }else {
    26. //将数量的类型count转换为int。
    27. int count=onlineCount.intValue();
    28. onlineCount=new Integer(count+1);
    29. }
    30. ctx.setAttribute("OnlineCount",onlineCount);
    31. }
    32. @Override
    33. //销毁session监听
    34. //一旦销毁session就会触发一次这个事件。
    35. public void sessionDestroyed(HttpSessionEvent se) {
    36. ServletContext ctx = se.getSession().getServletContext();
    37. //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
    38. //我们先取一个OnlineCount东西。强转为整型数据(int)
    39. Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    40. if(onlineCount==null){
    41. //网站一个人都没有,我们记为0.
    42. onlineCount=new Integer(0);
    43. }else {
    44. //将数量的类型count转换为int。
    45. int count=onlineCount.intValue();
    46. onlineCount=new Integer(count-1);
    47. }
    48. ctx.setAttribute("OnlineCount",onlineCount);
    49. }
    50. }

    我们增加

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

    从而获取他们的ID号。

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

     

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

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

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

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

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

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

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

     我们发现session是一样的。

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

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

    1.编写一个监听器

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

    1. package com.rgf.listener;
    2. import javax.servlet.ServletContext;
    3. import javax.servlet.http.HttpSessionEvent;
    4. import javax.servlet.http.HttpSessionListener;
    5. //统计网站在线人数:统计session
    6. public class OnlineCountListener implements HttpSessionListener {
    7. @Override
    8. //创建session的监听:看你的一举一动
    9. //一旦创建session就会触发一次这个事件。
    10. public void sessionCreated(HttpSessionEvent se) {
    11. /*我们监听器假设session创建的话,我们要获取OnlineCount对象,如果OnlineCount对象为空,我们要给他赋一个值,让他为1.
    12. 如果不为空,则每一次都会加1。每一次都会更新onlineCount.
    13. */
    14. //HttpSessionEvent代表session事件的一个对象
    15. //通过getSession拿到session,拿到session之后我们就可以拿到网站的上下文,通过getServletContext
    16. //我们统计在线人数,是统计所有网站,所有人都可以访问到它,我们要把它提高到最高的作用域:ServletContext或者application
    17. ServletContext ctx = se.getSession().getServletContext();
    18. System.out.println(se.getSession().getId());
    19. //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
    20. //我们先取一个OnlineCount东西。强转为整型数据(int)
    21. Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    22. if(onlineCount==null){
    23. //网站一个人都没有,我们进行+1.
    24. onlineCount=new Integer(1);
    25. }else {
    26. //将数量的类型count转换为int。
    27. int count=onlineCount.intValue();
    28. onlineCount=new Integer(count+1);
    29. }
    30. ctx.setAttribute("OnlineCount",onlineCount);
    31. }
    32. @Override
    33. //销毁session监听
    34. //一旦销毁session就会触发一次这个事件。
    35. public void sessionDestroyed(HttpSessionEvent se) {
    36. ServletContext ctx = se.getSession().getServletContext();
    37. //有了这个对象之后,我们就可以存东西了(setAttribute)我们先进行取(getAttribute),判断没有在进行存。
    38. //我们先取一个OnlineCount东西。强转为整型数据(int)
    39. Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    40. if(onlineCount==null){
    41. //网站一个人都没有,我们记为0.
    42. onlineCount=new Integer(0);
    43. }else {
    44. //将数量的类型count转换为int。
    45. int count=onlineCount.intValue();
    46. onlineCount=new Integer(count-1);
    47. }
    48. ctx.setAttribute("OnlineCount",onlineCount);
    49. }
    50. /*
    51. session销毁的两种情况
    52. 1.手动销毁 se.getSession.invalidate;
    53. 52.自动销毁 在web.xml里面配置session过期时间。:
    54. 1
    55. */
    56. }

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

    1. com.rgf.listener.OnlineCountListener

    4.看情况是否使用。

  • 相关阅读:
    Javascript笔记 rest VS spread
    1000套HTML5期末大作业——电影我不是药神响应式页面带轮播(4页)
    【算法|双指针系列No.8】leetcode18. 四数之和
    查看端口被占用:lsof
    C语言实现将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5
    基于 SpringBoot+Vue 的企业人事管理系统
    ros2与windows入门教程-控制小乌龟
    【Linux】 df命令使用
    bean 的六种作用域
    富格林:揭露黑幕平台保障安全
  • 原文地址:https://blog.csdn.net/weixin_59448049/article/details/126880009