0
点赞
收藏
分享

微信扫一扫

JavaWeb-Servlet+Filter+Listener+Session

SDKB英文 2022-04-19 阅读 55
webjava

JavaWeb

在这里插入图片描述


一、Servlet

  • Servlet 是 JavaEE 规范之一。规范就是接口。
  • Servlet 是 JavaWeb三大组件之一。三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。
  • Servlet 是 运行在服务器上的一个 java程序,它可以接收客户端发送过来的请求,并响应数据给客户端。

1.1、Servlet 概述


1.1.1、Servlet类的继承体系:

在这里插入图片描述

一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现Servlet程序

  1. 编写一个类去继承 HttpServlet 类
  2. 根据业务需要重写 doGet 或 doPost 等分发处理方法
  3. 到web.xml 中配置 自定义Servlet 程序的访问地址

1.1.2、Servlet接口 五种方法介绍 以及生命周期

  1. 执行 Servlet 构造器方法
  2. 执行 init 初始化方法. (第一、二步,是在第一次访问的时候创建Servlet程序会调用)
  3. 执行 service 方法 (第三步每次访问都会调用)
  4. 执行 destroy() 销毁方法(第四步、在web工程停止的时候调用)

在这里插入图片描述

1.1.3、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_4_0.xsd"
         version="4.0">
    <!--servlet 标签给 Tomcat 配置 Servlet程序-->
    <servlet>
        <!--servlet-name 标签 Servlet程序起一个别名(一般是类名)-->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class 是 Servlet 程序的全类名-->
        <servlet-class>com.hgw.javaweb.HelloServlet</servlet-class>
        <!--init-param 是初始化参数-->
        <init-param>
            <!--参数名-->
            <param-name>username</param-name>
            <!--参数值 -->
            <param-value>hgw</param-value>
        </init-param>
    </servlet>
    
    <!--servlet-mapping 标签给 Servlet 程序配置访问地址-->
    <servlet-mapping>
        <!--servlet-name 标签的作用是告诉服务器,我们当前配置的地址给哪个 Servlet 程序使用-->
        <servlet-name>HelloServlet</servlet-name>
        <!--url-pattern 标签访问地址
            / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
            /hello 表示地址为:http://ip:port/工程路径/hello
        -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
      <!--context-param 是上下文参数(它属于整个web工程)-->
     <context-param>
         <param-name>username</param-name>
         <param-value>context</param-value>
     </context-param>
</web-app>

1.2、ServletConfig 接口

在这里插入图片描述

1.3、ServletContext 接口

在这里插入图片描述

1.4、HttpServletRequest 接口

在这里插入图片描述

1.5、HttpServletResponse 接口

在这里插入图片描述


二、Filter

2.1、简介


Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

它主要用于对用户请求进行预处理,也可以对HttpServletResponse 进行后处理。使用Filter 的完整流程:Filter 对用户请求进行预处理,接着将请求交给Servlet 进行处理并生成响应,最后Filter 再对服务器响应进行后处理。

Filter功能:

  • 在HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest 。 根据需要检查 HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
  • 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。 根据需要检查 HttpServletResponse ,也可以修改HttpServletResponse头和数据。

大概流程图如下

Filter

2.2、如何实现拦截


​ Filter 接口中有一个 doFilter 方法,当开发人员编写好Filter,并配置对哪个Web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下的目的:

  1. 调用目标资源之前,让一段代码执行
  2. 是否调用目标资源(即是否让用户访问Web资源)

​ web服务器在调用doFilter方法时,会传递一个 filterChain 对象进来,filterChain对象是 filter 接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需要决定死否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

2.3、Filter 开发两步走


  1. 编写java类实现Filter接口,并实现其doFilter方法。
  2. 在 web.xml 文件中使用<filter><filter-mapping> 元素对编写的filter类进行注册,并设置它所能拦截的资源。

web.xml配置各节点介绍:

<!--filter标签用于配置一个Filter过滤器-->
<filter>
    <!--用于为过滤器指定一个名字,该元素的内容不能为空。 -->
    <filter-name>AdminFilter</filter-name>
    <!--元素用于指定过滤器的完整的限定类名。 -->
    <filter-class>com.atguigu.filter.AdminFilter</filter-class>
  
		<!--元素用于为过滤器指定初始化参数,它的子元素 -->
    <init-param>
      <!--指定参数的名字-->
        <param-name>username</param-name>
      <!--指定参数的值-->
        <param-value>root</param-value>
    </init-param>
</filter>

<!--元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径 -->
<filter-mapping>
    <!--子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字 -->
    <filter-name>AdminFilter</filter-name>
    <!--设置 filter 所拦截的请求路径(过滤器关联的URL样式) 
        / 表示请求地址为:http://ip:port/工程路径/ 映射到Idea 的 web目录
        /admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
    -->
    <url-pattern>/admin/*</url-pattern>
</filter-mapping>

2.4、Filter链


​ 在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。

web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给改方法。在doFilter方法中,开发人员如果调用了 FilterChain 对象的 doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

2.5、Filter的生命周期


public void init(FilterConfig filterConfig) throws ServletException;	// 初始化

和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作**(filter对象只会创建一次,init方法也只会执行一次)**。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws IOException, ServletException

​ 这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain 参数用于访问后续过滤器。

public void destroy();	// 销毁

​  Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

2.6、FilterConfig接口


​ 用户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得以下内容:

String getFilterName();//得到filter的名称。 
String getInitParameter(String name);//返回在部署描述中指定名称的初始化参数的值。如果不存在返回null. 
Enumeration getInitParameterNames();//返回过滤器的所有初始化参数的名字的枚举集合。 
public ServletContext getServletContext();//返回Servlet上下文对象的引用。

2.7、Filter使用案例


2.7.1、使用Filter验证用户是否登录

package com.atguigu.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class AdminFilter implements Filter {

    public AdminFilter() {
        System.out.println("1 Filter构造方法AdminFilter()");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2 Filter的init()初始化");

        System.out.println("filter-name的值是: " + filterConfig.getFilterName());
        System.out.println("初始化参数username的值是: " + filterConfig.getInitParameter("username"));
        System.out.println("初始化参数url的值是: " + filterConfig.getInitParameter("url"));

        System.out.println(filterConfig.getServletContext());
    }

    /**
     * doFilter方法,专门用于拦截请求。可以做权限检查
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws IOException, ServletException {
        System.out.println("3 Filter的doFilter()方法");
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();

        Object user = session.getAttribute("user");
        // 如果等于null,说明还没有登录
        if (user == null) {
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return;
        }else {
            // 让程序继续往下访问用户的目标资源
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {
        System.out.println("4 Filter的destroy()销毁方法");
    }
}
<?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_4_0.xsd"
         version="4.0">

    <!--filter标签用于配置一个Filter过滤器-->
    <filter>
        <!--给filter起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置filter的全类名-->
        <filter-class>com.atguigu.filter.AdminFilter</filter-class>

        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost3306/test</param-value>
        </init-param>
    </filter>
    <!--filter-mapping配置Filter过滤器的拦截路径-->
    <filter-mapping>
        <!--filter-name表示当前的拦截路径给哪个filters使用-->
        <filter-name>AdminFilter</filter-name>
        <!--url-pattern配置拦截路径
            / 表示请求地址为:http://ip:port/工程路径/ 映射到Idea 的 web目录
            /admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
        -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>
</web-app>

三、Listener

3.1、Listener 的定义与作用

监听器Listener 就是在 application、session、request 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。

Listener 是 Servlet 的监听器,可以监听客户端的请求,服务端的操作等。

3.2、Listener 的分类与使用

主要有以下三类:

3.2.1、ServletContext 监听

  • ServletContextListener:用于对Servlet整个上下文进行监听(创建、销毁)。
public void contextInitialized(ServletContextEvent sce);//上下文初始化
public void contextDestroyed(ServletContextEvent sce);//上下文销毁

public ServletContext getServletContext();//ServletContextEvent事件:取得一个ServletContext(application)对象
  • ServletContextAttributeListener:对Servlet上下文属性的监听(增删改属性)。
public void attributeAdded(ServletContextAttributeEvent scab);//增加属性
public void attributeRemoved(ServletContextAttributeEvent scab);//属性删除
public void attributeRepalced(ServletContextAttributeEvent scab);//属性替换(第二次设置同一属性)

//ServletContextAttributeEvent事件:能取得设置属性的名称与内容
public String getName();//得到属性名称
public Object getValue();//取得属性的值

3.2.2、Session监听

Session属于http协议下的内容,接口位于javax.servlet.http.*包下。

  • **HttpSessionListener**接口:对Session的整体状态的监听。
public void sessionCreated(HttpSessionEvent se);//session创建
public void sessionDestroyed(HttpSessionEvent se);//session销毁

//HttpSessionEvent事件:
public HttpSession getSession();//取得当前操作的session
  • **HttpSessionAttributeListener**接口:对session的属性监听。
public void attributeAdded(HttpSessionBindingEvent se);//增加属性
public void attributeRemoved(HttpSessionBindingEvent se);//删除属性
public void attributeReplaced(HttpSessionBindingEvent se);//替换属性

//HttpSessionBindingEvent事件:
public String getName();//取得属性的名称
public Object getValue();//取得属性的值
public HttpSession getSession();//取得当前的session

session的销毁有两种情况:

  1. session超时,web.xml配置:
<session-config>
    <session-timeout>120</session-timeout><!--session120分钟后超时销毁-->
</session-config>
  1. 手工使session失效
public void invalidate();//使session失效方法。session.invalidate();

3.2.3、Request监听

  • ServletRequestListener:用于对Request请求进行监听(创建、销毁)。
public void requestInitialized(ServletRequestEvent sre);//request初始化
public void requestDestroyed(ServletRequestEvent sre);//request销毁

//ServletRequestEvent事件:
public ServletRequest getServletRequest();//取得一个ServletRequest对象
public ServletContext getServletContext();//取得一个ServletContext(application)对象
  • ServletRequestAttributeListener:对Request属性的监听(增删改属性)。
public void attributeAdded(ServletRequestAttributeEvent srae);//增加属性
public void attributeRemoved(ServletRequestAttributeEvent srae);//属性删除
public void attributeReplaced(ServletRequestAttributeEvent srae);//属性替换(第二次设置同一属性)

//ServletRequestAttributeEvent事件:能取得设置属性的名称与内容
public String getName();//得到属性名称
public Object getValue();//取得属性的值

3.2.4、在web.xml中配置

Listener配置信息必须在Filter和Servlet配置之前,Listener的初始化(ServletContentListener初始化)比Servlet和Filter都优先,而销毁比Servlet和Filter都慢。

<listener>
    <listener-class>com.listener.class</listener-class>
</listener>

3.3、Listener 应用实例


1、利用HttpSessionListener统计最多在线用户人数

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class HttpSessionListenerImpl implements HttpSessionListener {

    public void sessionCreated(HttpSessionEvent event) {
        ServletContext app = event.getSession().getServletContext();
        int count = Integer.parseInt(app.getAttribute("onLineCount").toString());
        count++;
        app.setAttribute("onLineCount", count);
        int maxOnLineCount = Integer.parseInt(app.getAttribute("maxOnLineCount").toString());
        if (count > maxOnLineCount) {
            //记录最多人数是多少
            app.setAttribute("maxOnLineCount", count);
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //记录在那个时刻达到上限
            app.setAttribute("date", df.format(new Date()));
        }
    }
    //session注销、超时时候调用,停止tomcat不会调用
    public void sessionDestroyed(HttpSessionEvent event) {
        ServletContext app = event.getSession().getServletContext();
        int count = Integer.parseInt(app.getAttribute("onLineCount").toString());
        count--;
        app.setAttribute("onLineCount", count);    
        
    }
}

四、会话


举报

相关推荐

0 条评论