JSP知识总结

JSP

简介

Java Server Pages 是Java的动态网页技术 .

JSP引擎

引擎原理:

JSP引擎用于将JSP文件, 转换为Servlet

1.  在服务器启动时 , JSP引擎读取.jsp文件.
2.  将文件转换为Servlet的代码 , 并给servlet添加映射地址为 jsp的文件名称.
3.  当用户浏览器访问 jsp文件名称时,  其实请求的不是jsp文件, 而是生成的servlet
4.  servlet负责给浏览器进行响应.

JSP语法结构 *

JSP文件保存的路径: webContent目录下

JSP文件 可以包含HTML代码, Java代码, 以及JSP特有的标记.

Java代码 声明区 *

指的是Java的成员代码位置,  在JSP声明区中编写的Java代码, 会生成到servlet的成员位置.

语法:
    <%!
        这里用于编写Java代码, 且会生成到声明区
    %>

Java代码 执行区 ***

指的是Servlet的service方法中. 用户每次请求 都会执行

语法:
    <%
        Java代码
    %>

表达式 ***

用于快速的将Java代码中的变量输出到网页中.

语法:
    <%=变量名%>

转换的Java:
    out.print(变量名);

JSP中如何编写注释

因为JSP文件包含了三种语法结构 (java/html/jsp)
所以 ,三种语法结构的注释 都可以起到注释的效果:

html注释: 
        <!--     html的注释 -->
        在JSP中, HTML的注释会被JSP引擎认为是HTML代码 , 会转换为out.write("<!-- -->");
Java注释:
        单行: //
        多行: /*  */
        文档: /** */
        在JSP中, Java的注释 会被JSP引擎认为是Java代码 ,会原封不动的放到_jsp.java文件中.
JSP注释:
        <%-- JSP注释 --%>
        在JSP引擎将jsp文件 转换为.java文件时, 会忽略JSP注释的部分.

JSP 三大指令

指令的格式:
    <%@ 指令名称 属性名=值 属性名2=... 属性n=%>

page指令

用于设置页面

完整格式:
<%@ page
    language="java"
    extends="继承的类"
    buffer="数值|none" -- 缓冲大小 ,none表示不缓冲 ,默认是8kb
    session="true|false" --true:自动创建session  false时表示不自动创建
    autoFlush="true|false" --true:缓冲器自动清除, 默认true
    isThreadSafe="true|false" --<%%>中的代码 是否是同步的 , true表示同步, 默认false
    contentType="text/html;charset=utf-8" -- 内容类型以及编码格式
    errorPage="网页地址" -- 当JSP代码出错误,页面由指定地址进行显示 *
    isErrorPage="true|false" --true:当前页面是处理错误的页面. 只有为true, 才可以查看异常信息. *
    import="导包列表" -- 属性值是一个或多个导入的包,包于包之间使用逗号隔开即可
   %>

指定项目全局错误页面

编写项目的web.xml

在根节点中, 加入子节点:
    <error-page>
        <error-code>404</error-code>
        <location>处理404的页面地址</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>处理500的页面地址</location>
    </error-page>

include 指令 熟悉

用于将一个JSP 或 HTML文件 引入到另一个JSP中.

格式:

 <%@ include file="引入的路径" %>

include 动作

用于将一个 JSP 或 HTML文件 引入到另一个JSP中.

格式:
    <jsp:include page="引入的路径" flush="true"/>
include 指令 与 include动作得到区别 *****
include指令:      在JSP程序的转换时期, 将被引入的JSP文件嵌入到include指令的位置, 然后统一编译执行 (最终生成了一个.java文件)
include动作:      在JSP程序的转换时期, 被引入的文件不会嵌入到include动作的位置, 而是等客户端请求时, 再临时将被引入的文件以额外的servlet的方式加载到响应中, (最终生成的是多个.java文件)

JSP的内置对象 (隐含对象)

内置对象指的是: JSP引擎在转换JSP文件时, 帮我们的代码在执行之前 创建的一些 供我们使用的对象,
内置对象具备大量的JSP中的常用功能 , 使用JSP内置对象可以大大的简化我们的开发流程.

JSP的九大内置对象 *****

request:
    类型: HttpServletRequest
    作用: 请求对象, 包含了请求相关的信息和参数.

response:
    类型: HttpServletResponse
    作用: 响应对象, 包含了一些用于响应的功能.

out:
    类型: JSPWriter
    作用: 是打印流,  用于向响应体中输出数据。

session:
    类型: HttpSession
    作用: 会话对象, 用于状态管理以及 会话跟踪。

application:
    类型: ServletContext
    作用: Servlet的上下文,一个应用内存中同时只有一个上下文对象. 用于多个Servlet/JSP之间通信 , 

------

config:
    类型: ServletConfig
    作用: Servlet的配置对象, 用于配置一些初始的键值对信息.

pageContext:
    类型: PageContext
    作用: 页面的上下文 , 每一个JSP都拥有一个上下文对象, 用于多段代码之间进行通信.

exception:
    类型: Throwable
    作用: 当页面的page指令中 isErrorPage属性值为true, 才会存在此对象, 用于收集错误信息!
            通常此对象值为null , 只有其他页面指定errorPage=当前页面时, 且其他页面发生BUG后,跳转到此页面时,对象才不为null

page:
    类型: Object
    作用: 指当前JSP页面自身 , 在JSP引擎生成的代码中 , page对象的赋值代码为:
            Object page = this;

JSP的四大域对象 *****

九大隐含对象中, 包含了四个较为特殊的隐含对象, 这四个对象我们称其为域对象, 
它们都具备存储数据 / 删除数据 / 获取数据 的方法:
    存储数据:
        setAttribute(String key ,Object value);
    获取数据:
        Object value = getAttribute(String key);
    删除数据:
        removeAttribute(String key);

这四个域对象 , ‘域’ 指的是作用域 ! 分别是:

pageContext :   页面的上下文          作用域:    一个JSP页面
request     :   请求对象                作用域:    一次请求    (请求可以被转发 , 一次请求可能包含多个JSP页面)
session     :   会话对象                作用域:    一次会话    (一次会话可能包含多次请求)
application :   servlet上下文对象    作用域:    一次服务(服务器的启动到关闭) (一次服务可能包含多次会话)

JSP useBean动作 熟悉

作用: 向四大域对象中, 存储bean对象.

格式:
        <jsp:useBean 
            id="存储时的key"
            scope="page/request/session/application"
            class="要存储的对象类型">
        </jsp:useBean>
JSP useBean+ setProperty动作
作用: 向四大域对象中, 存储bean对象. 且设置属性值

格式:
        <jsp:useBean 
            id="存储时的key"
            scope="page/request/session/application"
            class="要存储的对象类型">
        </jsp:useBean>
        <jsp:setProperty name="存储时的key" property="属性名" value="属性值"/>
        //setProperty动作可以出现多次

案例:
    <jsp:useBean id="p" scope="page" class="cn.xdl.bean.Person"></jsp:useBean>
    <jsp:setProperty name="p" property="name" value="刘健健"/>
    <jsp:setProperty name="p" property="age" value="18"/> 
JSP useBean+ setProperty动作 快速获取表单提交的内容 了解
格式:
    <jsp:useBean 
            id="存储时的key"
            scope="page/request/session/application"
            class="要存储的对象类型">
        </jsp:useBean>
    <jsp:setProperty name="存储时的key" property="属性名"/>

注意:
    如果setProperty动作中 , property的值即是对象的属性名, 又是我们用户请求的参数的名称的话, 会自动将参数获取到并赋值给对象

JSP getProperty动作 了解

作用:
    从四大域对象中 取出某个对象的属性, 并显示到网页中
语法格式:
    <jsp:getProperty name="对象的key" property="属性名">

案例:
    <jsp:useBean id="per" scope="session" class="cn.xdl.bean.Person"></jsp:useBean>
    <jsp:setProperty property="name" name="per" value="小明"/>
    <jsp:setProperty property="age" name="per" value="28"/>


    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <jsp:getProperty property="name" name="per"/>

JSTL

通过重写URL , 得到session
//1.    重写普通的网址  , 通常是超链接/表单中使用的网址
//url = response.encodeUrl(url);

//2.    重写重定向的网址, 这种网址用于重定向
url = response.encodeRedirectUrl(url);

EL表达式 ***

作用:
用于快速的从域对象中取出数据, 并将结果输出到网页.
也可以用于一些运算, 运算的结果也会输出到网页

格式:
    ${表达式}
例如: 用于运算:
运算的结果:${ 1+2+3+4+5 }
用于取出域对象中的数据
访问存储数据的格式:
    ${存储的key}

访问存储的对象属性值:
    静态取值:${存储的key.属性名}
    静态取值:${存储的key["属性名"]}

    动态取值:${存储的key[属性名的key]}

访问集合/数组中的对象
    静态取值:${存储的key[下标].属性名}
    静态取值:${存储的key[下标]["属性名"]}

    动态取值:${存储的key[下标][属性名的key]}


有时我们需要使用变量的值. 可以将其先存储到域对象中, 再在el表达式中使用存储的key来操作
例如:
    <%
        User[] data = {new User("root1","123"),new User("root2","223"),new User("root3","323"),new User("root4","423"),};
        pageContext.setAttribute("users", data);
        pageContext.setAttribute("a","username");
    %>
    <%for(int i=0;i<data.length;i++){
        pageContext.setAttribute("index", i);
    %>
        静态取值:   ${ users[index].username }

    <%} %>

EL表达式 取出数据的流程. *

取出的顺序: 范围从小到大

步骤:

    1.  先从pageContext中寻找数据是否存在
    2.  当pageContext中不存在此数据时 , 去request中寻找数据是否存在
    3.  当request中不存在此数据时, 去session中寻找数据是否存在
    4.  当session中不存在此数据时, 去application中寻找数据是否存在.
    5.  当application中不存在此数据时, 向网页输出 长度为0的字符串 ("" , 不是null)

在上述的流程中, 一旦某一个步骤寻找到了数据 , 就会将数据输出到网页中, 且后续流程不再执行.

taglib指令

用于在JSP中引入标签库 .

语法格式:
    <%@ taglib prefix="" uri=""%>

属性: prefix: 是引入的标签库的名称, 用于区分多个标签库.  在使用此标签库中的标签时, 需在标签前添加标签库名称:
        例如: 我们引入一个标签库, prefix=a ,则其中的标签在使用时:  <a:标签名></a:标签>

        uri:    用于匹配标签库. 在引入的tld文件中存在一个uri属性值,  我们uri属性与tld文件中的属性相同时, 则引入这个文件描述的库.

JSTL标签库

是一套JSP的标准标签库. 对JSP的标签进行了扩展. IF标签 作用: 用于判断元素是否显示

格式:

  <库的名称:if test="">></库的名称:if>

    test属性值:
        可以是boolean, 或运算结果为boolean的el表达式 .
案例:
    <%-- <heiheihei:if test="true">
        从前有座山
    </heiheihei:if>
    <heiheihei:if test="false">
        山上有座庙
    </heiheihei:if> --%>

    <%
        pageContext.setAttribute("flag", false) ;
    %>
    <heiheihei:if test="${ flag }">
        从前有座山
    </heiheihei:if>
    <%
        pageContext.setAttribute("flag",true);
    %>
    <heiheihei:if test="${ flag }">
        山上有座庙
    </heiheihei:if>

choose+when+otherwise标签

类似Java中的:   switch+case+default

这三个标签, 只有when是由test属性的 ,属性值是boolean, 允许使用el表达式传入

作用:
    用于多分支 显示 .

案例:

<%
    pageContext.setAttribute("flag",100);
%>
<heiheihei:choose>
    <heiheihei:when test="${ flag== 1}">
        拔毛烧开水 , 铁锅炖大鹅 
    </heiheihei:when>
    <heiheihei:when test="${ flag== 2}">
        英雄不问出处, 流氓不论岁数
    </heiheihei:when>
    <heiheihei:when test="${ flag== 3}">
        衣带渐宽终不悔
    </heiheihei:when>
    <heiheihei:when test="${ flag== 4}">
        好吃不过饺子 , 好闻不过包子
    </heiheihei:when>
    <heiheihei:otherwise>
        二十四桥明月夜 , 玉人何处教吹箫 .
    </heiheihei:otherwise>
</heiheihei:choose>

forEach标签

用于遍历集合 或 数组元素

格式:

 <标签库名称:forEach items="" var="">

    </标签库名称:forEach>

属性:
    items   :   要遍历的数组 或 集合 必须通过el表达式传递
    var     :   在循环遍历时, 从数组或集合中取出的每一个元素会被存储到pageContext中, key就是var的值

案例:

 <%
        ArrayList<String> d = new ArrayList<>();
        d.add("拔毛烧开水 , 铁锅炖大鹅 ");
        d.add("英雄不问出处, 流氓不论岁数 ");
        d.add("衣带渐宽终不悔 ");
        d.add("好吃不过饺子 , 好闻不过包子 ");
        d.add("二十四桥明月夜 , 玉人何处教吹箫 . ");
        d.add("厚积薄发");
        d.add("日月之行若出其中");
        d.add("锄禾日当午 , 复方草珊瑚");
        //将集合存储到域对象pageContext中, 便于EL表达式取出使用
        pageContext.setAttribute("data",d);
    %>
    <heiheihei:forEach items="${ data }" var="x">
        <h4>${x }</h4>
    </heiheihei:forEach>

如何自定义标签库 熟悉

自定义标签库的类:

两种实现方式:
    1.  继承SimpleTagSupport 
    2.  继承TagSupport

SimpleTagSupport案例

public class MyTag1 extends SimpleTagSupport {
    private static ArrayList<String> d = new ArrayList<>();
    static {
        d.add("拔毛烧开水 , 铁锅炖大鹅 ");
        d.add("英雄不问出处, 流氓不论岁数 ");
        d.add("衣带渐宽终不悔 ");
        d.add("好吃不过饺子 , 好闻不过包子 ");
        d.add("二十四桥明月夜 , 玉人何处教吹箫 . ");
        d.add("厚积薄发");
        d.add("日月之行若出其中");
        d.add("锄禾日当午 , 复方草珊瑚");
       

    }
    /**
     * 当用户使用此标签
     */
    @Override
    public void doTag() throws JspException, IOException {
        //1.    先得到向网页输出数据的 输出流
        JspWriter jw = getJspContext().getOut();
        //2.    得到要输出的文本
        String text = getText();
        //3.    将文本输出
        jw.write(text);
        jw.flush();
    }

    public String getText() {
        //生成随机数, 从集合中随机取出一句名言
        Random r = new Random();
        int index = r.nextInt(d.size());
        return d.get(index);
    }
}

TagSupport 案例:

public class MyTag2 extends TagSupport {
    /*  @Override
        public int doAfterBody() throws JspException {
            // TODO Auto-generated method stub
            return super.doAfterBody();
        }

        @Override
        public int doEndTag() throws JspException {
            // TODO Auto-generated method stub
            return super.doEndTag();
        }*/
        /**
         * 总数量
         */
        private int length;
        /**
         * 一页显示的数量
         */
        private int pageSize;
        public int getLength() {
            return length;
        }
        public void setLength(int length) {
            this.length = length;
        }
        public int getPageSize() {
            return pageSize;
        }
        public void setPageSize(int pageSize) {
            this.pageSize = pageSize;
        }

        @Override
        public int doStartTag() throws JspException {
            //总页数
            int num = length/pageSize + (length%pageSize==0?0:1);

            String html = "<div class=\"page\">"
                    + "<button>首页</button>&nbsp;"
                    + "<button>上一页</button>&nbsp;";
                if(num < 5) {
                    for(int i=0;i<num;i++) {
                        html = html+"<button>"+(i+1)+"</button>";
                    }
                }else {
                    html = html+"<button>1</button>";
                    html = html+"<button>2</button>";
                    html = html+"<button>3</button>";
                    html = html+" ... ";
                    html = html+"<button>"+num+"</button>";
                }
                    html = html+ "&nbsp;<button>下一页</button>&nbsp;"
                    + "<button>末页</button>&nbsp;"
                    + "</div>";
            JspWriter jw = pageContext.getOut();
            try {
                jw.write(html);
                jw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return super.doStartTag();
        }
    }

xld文件:

xld文件存储在web-inf中!

案例:

  <?xml version="1.0" encoding="UTF-8" ?>
    <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">

        <!-- 标签库的描述 -->
        <description>
            这个标签库编写的目的是为了 , 不知道为啥.
        </description>
        <!-- 设置标签库名称 -->
        <display-name>xdl</display-name>
        <!-- 描述标签库的版本 -->
        <tlib-version>10.1</tlib-version>
        <!-- 描述标签库的短名称 -->
        <short-name>xdl</short-name>
        <!-- 用于匹配的uri -->
        <uri>http://www.dsb.com/heiheihei</uri>


        <!-- 向标签库中 添加一个标签 -->
        <tag>
            <!-- 对于标签的解释, 在使用时会提示给用户 -->
            <description>这个标签用于向网页中随机生成一条名言</description>
            <!-- 标签名称 -->
            <name>heihei</name>
            <!-- 标签的Java类的全名 -->
            <tag-class>cn.xdl.tag.MyTag1</tag-class>
            <!-- 标签是否允许包含内容
                可以设置的值 :    JSP , 表示允许存在JSP代码
                可以设置的值: empty , 表示为空
             -->
            <body-content>empty</body-content>
        </tag>
        <!-- 向标签库中 添加一个标签 -->
        <tag>
            <!-- 对于标签的解释, 在使用时会提示给用户 -->
            <description>这个标签用于向网页中加入分页标签</description>
            <!-- 标签名称 -->
            <name>page</name>
            <!-- 标签的Java类的全名 -->
            <tag-class>cn.xdl.tag.MyTag2</tag-class>
            <!-- 标签是否允许包含内容
                可以设置的值 :    JSP , 表示允许存在JSP代码
                可以设置的值: empty , 表示为空
             -->
            <body-content>empty</body-content>
            <!-- 描述属性 -->
            <attribute>
                <!-- 属性的描述 -->
                <description>这个属性用于设置总数量</description>
                <!-- 属性名 , 与类中的名称必须一致 -->
                <name>length</name>
                <!-- 属性是否必须传递 -->
                <required>true</required>
                <!-- 是否支持el表达式传递 -->
                <rtexprvalue>true</rtexprvalue>
                <!-- 属性的类型 -->
                <type>int</type>
            </attribute>
            <!-- 描述属性 -->
            <attribute>
                <!-- 属性的描述 -->
                <description>这个属性用于一页展示的数量</description>
                <!-- 属性名 , 与类中的名称必须一致 -->
                <name>pageSize</name>
                <!-- 属性是否必须传递 -->
                <required>true</required>
                <!-- 是否支持el表达式传递 -->
                <rtexprvalue>true</rtexprvalue>
                <!-- 属性的类型 -->
                <type>int</type>
            </attribute>
        </tag>

    </taglib>

Fileter & Listener

web三大组件

Servlet是web的三大组件之一 .

1.  Servlet
2.  Fileter  过滤器
3.  Listener 监听器

Filter 过滤器 *

过滤的是请求 .

面向切面编程思想 . 

使用步骤:

 1.  编写一个类 , 实现Filter接口
 2.  通过web.xml 或 注解的方式, 配置过滤器的过滤地址.

doFilter中的请求与响应对象 为什么不是http的 ? 了解

过滤器在早期设计时, 不只是针对HTTP请求. 针对所有协议的请求都可以进行过滤.
因为我们现在都是使用HTTP协议, 所以很感觉怪异

想要操作Http相关的请求对象 与 响应对象 怎么办?

只需要将请求对象强制转换为 HttpServletRequest  将响应对象 强制转换为 HttpServletResponse 即可

案例

Java代码
public class UserFilter implements Filter {
    /**
     * 当过滤器即将销毁时
     */
    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }
    /**
     * 当匹配的请求出现时, 执行. 且执行在 servlet/jsp/html等等所有的服务器资源之前.
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain fc)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        //1.    先得到session
        HttpSession session = req.getSession();
        //2.    判断session中是否存在帐号
        if(session.getAttribute("username")!=null) {
            //3.    存在则放行
            fc.doFilter(request, response);
        }else {
            //4.    不存在则拦截 , 并响应给用户拦截的原因
            res.sendRedirect("userError.jsp");
        }
    }

    /**
     * 当过滤器初始化时
     */
    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }
}
WEB.XML代码
 <filter>
<filter-name>uf</filter-name>
<filter-class>cn.xdl.demo1.UserFilter</filter-class>
<filter-mapping> <filter-name>uf</filter-name> <url-pattern>/home.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>uf</filter-name> <url-pattern>/userCenter.jsp</url-pattern> </filter-mapping>

过滤器链

当多个过滤器的 过滤地址重复时, 就形成了过滤器链, 用户的一次请求, 需要经过多次过滤放行.

过滤器链的执行顺序是:

 web.xml中配置的顺序:
        按照xml中配置的先后顺序 来执行的 , web.xml中配置代码靠前的 ,优先执行.
注解配置的顺序:
    按照类名的自然排序 , 排序执行;
    注意: 注解配置的过滤器, 一定执行在web.xml过滤器之后
    例如: 
        类名Filter1 执行在类名Filter2之前.
        类名Aaa  执行在 类名 Aab之前

Listener 熟悉

事件驱动, 监听的是tomcat产生的事件:

两类事件:
    1.  生命周期相关事件 

    2.  域对象中数据的变化事件
ServletContextListener

用于监听ServletContext的创建 和 销毁

因为ServletContext的创建, 就表示项目的启动.  ServletContext的销毁 就表示项目的关闭.
所以此监听器 ,是用于监听项目的启动 和 关闭的 .  

我们常在项目启动时, 进行资源初始化的操作 . 准备一些后续项目中会用到的资源.
在项目关闭时, 进行资源的释放操作 . 解除资源的占用句柄 . 

案例:

@WebListener
public class Listener1 implements ServletContextListener {

    /**
     * 用于监听应用关闭
     */
    public void contextDestroyed(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
    }

    /**
     * 用于监听应用启动
     */
    public void contextInitialized(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
    }

}
ServletContextAttributeListener
@WebListener
public class ServletContextAttributeListener1 implements ServletContextAttributeListener {
    /**
     */
    public void attributeAdded(ServletContextAttributeEvent e)  { 
        //从事件对象中, 得到增加的数据 (键和值)
        String key = e.getName();
        Object value = e.getValue();
        System.out.println("添加的数据key:"+key+" , 数据值:"+value);
    }
    /**
     * 当删除数据时
     */
    public void attributeRemoved(ServletContextAttributeEvent e)  { 
        //从事件对象中, 得到删除的数据 (键和值)
        String key = e.getName();
        Object value = e.getValue();
        System.out.println("删除的数据key:"+key+" , 数据值:"+value);
    }
    /**
     * 当数据被替换时
     */
    public void attributeReplaced(ServletContextAttributeEvent e)  { 
        //从事件对象中,  得到被替换的旧值
        String key = e.getName();
        Object oldValue = e.getValue();

        //从事件对象中, 可以得到ServletContex对象
        Object newValue = e.getServletContext().getAttribute(key);
        System.out.println("替换的数据key:"+key+" , 旧的值:"+oldValue+" , 新的值:"+newValue);
    }
}

HttpSessionListener

用于监听session的创建与销毁 .

因为我们服务器中每一个session 表示一次用户的会话.
一个客户端就会创建一个单独的session.  可以将session的数量, 理解为在线用户的数量. 
所以我们经常在session创建与销毁的监听中,  计算当前在线的人数.

案例:

 @WebListener
    public class HttpSessionListener1 implements HttpSessionListener {
        /**
         * session的创建
         */
        public void sessionCreated(HttpSessionEvent e)  { 
            CountUtil.add();
        }
        /**
         * session的销毁
         */
        public void sessionDestroyed(HttpSessionEvent e)  { 
            CountUtil.remove();
        }
    }


    public class CountUtil {
        private static int count = 0;
        private static ArrayList<Integer> countNum = new ArrayList<Integer>();
        private static Random r = new Random();
        public static void add() {
            //5-10的随机数字
            int num = r.nextInt(25)+25;
            //计数
            count+=num;
            //将本次计数的值 存储到集合中
            countNum.add(num);
        }
        public static void remove() {
            //获取并删除最后 一次 计数的  数量值
            int num = countNum.remove(countNum.size()-1);
            count-=num;
        }

        public static int get() {
            return count;
        }
    }

HttpSessionAttributeListener

用于监听session中的数据的增加, 删除 ,修改

/**
 *监听用户会话状态的变化
 */
@WebListener
public class HttpSessionAttributeListener1 implements HttpSessionAttributeListener {


    /**
     *  当session中数据增加
     */
    public void attributeAdded(HttpSessionBindingEvent e)  { 
        String key = e.getName();
        Object value = e.getValue();
        System.out.println("session中增加了数据:  key="+key+" , value="+value);
    }
    /**
     *  当session中数据删除
     */
    public void attributeRemoved(HttpSessionBindingEvent e)  { 
        String key = e.getName();
        Object value = e.getValue();
        System.out.println("session中删除了数据:  key="+key+" , value="+value);
    }
    /**
     *  当session中数据被替换
     */
    public void attributeReplaced(HttpSessionBindingEvent e)  { 
        String key = e.getName();
        Object oldValue = e.getValue();
        Object newValue = e.getSession().getAttribute(key);


        System.out.println("session中替换了数据:  key="+key+" , 旧的值="+oldValue+", 新的值="+newValue);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值