A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

MVC&事务&商品信息CRUD操作及分页&AJAX&Listener

MVC模式
是由JSP+Servlet+JaveBean组成
优点:
        JSP用于显示数据   JavaBean用于封装数据和处理数据   Servlet控制
        JSP的模式二JSP+Servlet+JaveBean模式也被称为MVC的设计模式
        M:Model模型层   JavaBean
        V:View 视图层   JSP
        C:Controller 控制层 Servlet
       
JSP的开发模式一:了解
JSP + JavaBean
* 演示模式一的过程:
    * 在模式一开发中提供了一些JSP的标签:<jsp:useBean> ,<jsp:setProperty >,<jsp:getProperty>
* 使用模式一进行简单的测试:
<%
        // 接收数据:
/*         String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 封装数据:
        User user = new User();
        user.setUsername(username);
        user.setPassword(password); */
%>
<jsp:useBean id="user" class="com.itheima.demo1.domain.User" scope="page"></jsp:useBean>
<%-- <jsp:setProperty property="username" name="user"/>
<jsp:setProperty property="password" name="user"/> --%>
<jsp:setProperty property="*" name="user"/><!-- 表单的元素的name属性的值与User中的属性名称一致 就可以自动封装 -->

<jsp:getProperty property="username" name="user"/>

       
JSP的开发模式二:掌握
JSP + Servlet + JavaBean 称为MVC的设计模式.
MVC:
M:Model:模型层
V:View:视图层
C:Controller:控制层

ava中的反射技术:掌握


Java中的内省技术:了解
        内省:用来获得JavaBean的属性及属性的get或set方法.
JavaBean:就是一个满足了特定格式的Java类:
* 需要提供无参数的构造方法:
* 属性私有
* 对私有的属性提供public的get/set方法.
        内省的代码:
        public void demo1() throws Exception{
                // 获得了Bean的信息
                BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
                // 获得Bean的属性描述了
                PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
                for(PropertyDescriptor pd:pds){
                        System.out.println(pd.getName());
                        /*pd.getReadMethod(); // 获得get方法
                        pd.getWriteMethod();// 获得set方法.
*/                }
        }
        使用内省封装一个MyBeanUtils:
public class MyBeanUtils {

        public static void populate(Object obj,Map<String,String[]> map) throws Exception{
                // 获得类的所有的属性的名称:
                BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
                // 获得类中所有的属性:
                PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
                for (PropertyDescriptor pd : pds) {
                        if(map.containsKey(pd.getName())){
                                Method method = pd.getWriteMethod();
                                // 执行set方法:
                                method.invoke(obj, map.get(pd.getName())[0]);
                        }
                }
        }
}

事务的概述
        什么是事务:
事务指的是逻辑上的一组操作,组成这组操作的各个逻辑单元要么一起成功,要么一起失败.
        MYSQL的事务的管理:(了解)
创建一个账号的表:
create database web_13;
use web_13;
create table account(
        id int primary key auto_increment,
        name varchar(20),
        money double
);
insert into account values (null,'张森',10000);
insert into account values (null,'凤姐',10000);
insert into account values (null,'如花',10000);

***** MYSQL的事务管理有两种方式:(MYSQL数据库事务默认是自动提交的.Oracle数据库事务默认是不自动提交.)
1.手动开启事务
start transaction; -- 开启事务
多条sql;
commit/rollback;

2.设置一个自动提交参数
show variables like '%commit%'; -- 查看与commit相关参数.
set autocommit = 0; -- 将autocommit参数设置为OFF.

JDBC中的事务管理】(掌握)
JDBC的事务的管理的API:
void setAutoCommit(boolean autoCommit)
将此链接的自动提交模式设置为给定状态
void commit()
使所有上一次提交/回滚进行的更改成为持久更改,并释放此Connection对象当前持有的所有数据库锁
void rollback()
取消在当前事务中进行的所有更改,并释放此Connectiion对象当前持有所有数据库锁

步骤分析:
步骤一:创建一个页面:
步骤二:导入JDBC相关的jar包和工具类.
步骤三:创建包结构.
步骤四:提交到Servlet-->Service-->DAO
步骤五:页面跳转:

DBUtils实现事务管理:
没有事务管理:
QueryRunner (DataSource ds)
        Contructor for QueryRunner which takes a DataSource.

<T> T query(String sql, ResultSetHandler<T> rsh, Object...params)
        Executes the given SELECT SQL query and returns a returns a result object
       
int updata(String sql,Object...params)
        Executes the given INSERT,UPDATE, or DELETE SQL statement
       
有事务管理:
QueryRunner()
Contructor for QueryRunner

<T> T query(Connertion conn,String sql,ResultSetHandler<T> rsh,Object..params)
        Execute an SQL SELECT query with replacement parameters
       
int update(Connectiion conn,String sql, Object parm)
        Execute an SQL INSERT, UPDATE , or DETELE query with a single replacement parameters
       
总结:
事务特性:
        原子性:强调事务的不可分割.
        一致性:强调的是事务的执行的前后,数据的完整性要保持一致.
        隔离性:一个事务的执行不应该受到其他事务的干扰.
        持久性:事务一旦结束(提交/回滚)数据就持久保持到了数据库.
       
如果不考虑事务的隔离性,引发一些安全性问题:
一类读问题:
脏读                :一个事务读到另一个事务还没有提交的数据.
不可重复读        :一个事务读到了另一个事务已经提交的update的数据,导致在当前的事务中多次查询结果不一致.
虚读/幻读        :一个事务读到另一个事务已经提交的insert的数据,导致在当前的事务中多次的查询结果不一致.
一类写问题:
引发两类丢失更新:

解决引发的读问题:
设置事务的隔离级别:
read uncommitted                :未提交读.脏读,不可重复读,虚读都可能发生.
read committed                :已提交读.避免脏读.但是不可重复读和虚读有可能发生.
repeatable read                :可重复读.避免脏读,不可重复读.但是虚读有可能发生.
serializable                        :串行化的.避免脏读,不可重复读,虚读的发生.

***** MYSQL隔离级别:repeatable read  Oracle隔离级别:read committed

演示脏读的发生:
演示脏读的发生:
        分别开启两个窗口:A,B
        分别查看两个窗口的隔离级别:select @@tx_isolation;
        设置A窗口的隔离级别为:read uncommitted:
* set session transaction isolation level read uncommitted;
        分别在两个窗口中开启事务:
* start transaction;
        在B窗口完成转账的操作:
* update account set money = money - 1000 where name = '张森';
* update account set money = money + 1000 where name = '凤姐';
        在A窗口查询数据:(钱已经到账---脏读)
* select * from account;  -- A事务读到了B事务还没有提交的数据.

演示避免不可重复读:
        分别开启两个窗口:A,B
        分别查看两个窗口的隔离级别:select @@tx_isolation;
        设置A窗口的隔离级别为:repeatable read:
set session transaction isolation level repeatable read;
        分别在两个窗口中开启事务:
start transaction;
        在B窗口完成转账的操作:
update account set money = money - 1000 where name = '张森';
update account set money = money + 1000 where name = '凤姐';
        在A窗口查询:
select * from account; -- 转账没有成功:避免脏读.
        在B窗口提交事务:
commit;
        在A窗口中再次查询:
select * from account; -- 转账没有成功:避免不可重复读.

演示避免虚读的发生:
        分别开启两个窗口:A,B
        分别查看两个窗口的隔离级别:select @@tx_isolation;
        设置A窗口的隔离级别为:serializable:
set session transaction isolation level serializable;
        在A,B两个窗口中分别开启事务:
start transaction;
        在B窗口中完成一个insert操作:
insert into account values (null,'王老师',10000);
        在A创建中进行查询的操作:
select * from account; -- 没有查询到任何结果.
        在B窗口提交事务:
commit; -- A窗口马上就会显示数据
******************************************************************************************
完成对商品的CRUD的操作,进行条件查询,分页查询
分析:
        技术分析:
                使用MVC设计模式JSP + Servlet + JavaBean + JDBC实现商品信息的CRUD的操作
        步骤分析:
                步骤一: 创建数据库和表
                        create database web;
                        use web;
                        create table product;
                        ....
                       
                步骤二:创建工程导入jar包
                        建立一个JAVAEE的动态web工程
                        需要导入的包为
                        mysql 驱动
                        c3po 的连接池的包
                        dbutils 的包
                        beanUtils 的包:两个(但是由Apache公司开发的BeanUtils会更常用,同时,BeanUtils还需要配合第三方日志工具来使用,这里我们同样使用Apache公司的common logging)
                        JSTL:的包 引入JSP的标准标签库的包 两个包(JSTL必须引用的jstl.jar和 standard.jar两个包)
               
                步骤三:创建包的结构MVC
               
                步骤四:创建一个首页
               
商品的添加的功能:
在首页点击【添加】链接:跳转到添加页面.
在添加页面中输入信息:点击【提交】提交到Servlet
在Servlet中:
     接收数据:
     封装数据:
     调用业务层:
     页面跳转


重复提交的问题:
     添加完商品之后,转发到一个页面,刷新该页面.
     网速很慢,点击提交的按钮,其实已经在提交了但是网速慢,不停的点击提交.
解决重复提交的根本解决办法:令牌机制(一次性).
     生成随机的令牌保存在session中.
     在表单的提交的时候,将随机的令牌放入到表单的隐藏字段中.
     在Servlet中获得session中和表单中的令牌是否一致.
     如果一致执行插入操作,不一致跳转到其他页面.将令牌销毁.


代码实现:

                在添加商品页面添加令牌
                <%
                String token=UUIDUtils.getUUID();
                session=setAttribute("token",token);
                %>
               
               
                        // 判断是否是重复提交:
                        String token1 = (String)request.getSession().getAttribute("token");
                        String token2 = request.getParameter("token");
                        // 清空session中的令牌:
                        request.getSession().removeAttribute("token");
                        if(!token2.equals(token1)){
                                request.setAttribute("msg", "亲!您已经提交过!请不要重复提交了!");
                                request.getRequestDispatcher("/jsp/msg.jsp").forward(request, response);
                                return;
                        }
       
商品的信息的修改:
        在列表页面上点击【修改】链接:
        提交到Servlet:根据id查询该商品.将商品的信息显示到修改页面:
        在修改的页面上修改数据,点击【提交】按钮:
        提交到Servlet:完成商品信息的修改:

商品的信息的删除:
        在列表页面上点击【删除】链接:
        提交到Servlet:
        调用业务层完成删除的操作:

        ***** 扩展删除多条记录:

商品模糊查询:


商品分页显示:
        分页条: 【首页】【上一页】[1][2][3][4]【下一页】【尾页】

分页功能的实现:
物理分页:一次只查10条记录,点击下一页,再去查询后10条.使用SQL语句进行控制的分页.
     缺点:经常需要和数据库交互.
     优点:数据量特别大,不会导致内存的溢出.
逻辑分页:一次性将所有数据全都查询出来,根据需要进行截取.List集合进行控制. subList();
     缺点:数据量如果特别大,容易导致内存溢出.
     优点:与数据库交互次数少.

不同的数据库对分页的语句也是不一样的:
     MYSQL进行分页: 使用limit关键字.
        * select * from xxx where .. Group by ... Having ... Order by ... limit a,b; -- a:从哪开始  b:查询的记录数.
         根据页数计算 limit后面的两个参数:
             currPage                        begin             pageSize
                  1                    0                    10
                  2                    10                   10
                  3                    20                   10
            begin = (currPage - 1) * pageSize;
     参数的传递:
          前台--->后台:currPage
          后台--->前台:currPage,totalPage(总页数),totalCount(总记录数),pageSize,List集合.
     使用JavaBean封装参数:
          后台--->前台:传递一个JavaBean就可以.
     Oracle进行分页: 使用SQL语句嵌套.
     SQL Server数据库进行分页: 使用 top 关键字.

在首页上添加一个分页查询的链接:

**************************************************************************************************
AJAX的JQuery
异步校验用户名是否存在:
分析:
        技术分析
        AJAX的概述:
        什么是AJAX:
        AJAX:异步的JavaScript And XML
                使用的是老技术,用的是新思想
        了解同步和异步的区别:
                同步:
        同步的思想是:所有的操作都做完,才返回给用户。这样用户在线等待的时间太长,给用户一种卡死了的感觉(就是系统迁移中,点击了迁移,界面就不动了,但是程序还在执行,卡死了的感觉)。这种情况下,用户不能关闭界面,如果关闭了,即迁移程序就中断了。

        异步:
        将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。这就是异步。但是用户没有卡死的感觉,会告诉你,你的请求系统已经响应了。你可以关闭界面了。

        同步,是所有的操作都做完,才返回给用户结果。即写完数据库之后,在相应用户,用户体验不好。

        异步,不用等所有操作等做完,就相应用户请求。即先相应用户请求,然后慢慢去写数据库,用户体验较好。
       
AJAX的功能:完成页面的局部刷新,不中断用户的体验.
早期的时候JS技术根本不受重视.后台开发人员经常将JS当成一种玩具式语言.JS中有一个对象XMLHttpRequest对象可以向服务器异步发送请求.传统的B/S结构的软件,所有实现功能都需要在服务器端编写代码(胖服务器).现在有了AJAX以后,可以将部分代码写到客户端浏览器(RIA:Rich Internet Application).FLEX:AS脚本编程.
XML:使用XML做为数据传递的格式: JSON:
       
XMLHttpRequest
属性:
readyState                        :XMLHttpRequest的状态
0(未初始化)    对象已建立,但是尚未初始化(尚未调用open方法)
1(初始化)      对象已经建立,尚未调用send方法
2(发送数据)        send方法已调用,但是当前的状态及http头未知
3(数据发送中)  已接收部分数据,因为响应及http头不全,这是通过responsBody和responseText获取部分数据会出现错误
4(完成)         数据接收完毕,此时可以通过responseBody和reponseText获取完整的回应数据
onreadystatechange        :当XMLHttpRequest状态改变的时候触发一个函数.
status                                :获得响应的状态码. 200 , 404 ...
responseText                        :获得响应的文本数据.
responseXML                        :获得响应的XML的数据.
        方法:
open(请求方式,请求路径,是否异步)                :异步去向服务器发送请求.
send(请求参数)                                                :发送请求.
setRequestHeader(头信息,头的值)                :处理POST请求方式的中文问题.
创建XMLHttpRequest对象:
IE                :将XMLHttpRequest对象封装在一个ActiveXObject组件.
Firefox        :直接就可以创建XMLHttpRequest对象.
function createXmlHttp(){
   var xmlHttp;
   try{ // Firefox, Opera 8.0+, Safari
        xmlHttp=new XMLHttpRequest();
    }
    catch (e){
           try{// Internet Explorer
                 xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
              }
            catch (e){
              try{
                 xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
              }
              catch (e){}
              }
    }

        return xmlHttp;
}

AJAX的入门
AJAX的编写的步骤:
第一步:创建一个异步对象.
第二步:设置对象状态改变触发一个函数.
第三步:设置向后台提交的路径
第四步:发送请求.
GET方式提交请求:
function ajax_get() {
        // 1.创建异步对象
        var xhr = createXMLHttp();
        // 2.设置状态改变的监听 回调函数.
        xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){ // 请求发送成功
                        if(xhr.status == 200){ // 响应也成功
                                // 获得响应的数据:
                                var data = xhr.responseText;
                                // 将数据写入到DIV中:
                                document.getElementById("d1").innerHTML = data;
                        }
                }
        }
        // 3.设置请求路径
        xhr.open("GET","/day15/ServletDemo1?name=aaa&pass=123",true);
        // 4.发送请求
        xhr.send(null);
}
POST方式提交请求:
function ajax_post(){
        // 创建异步对象:
        var xhr = createXMLHttp();
        // 设置监听:
        xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                        if(xhr.status == 200){
                                document.getElementById("d1").innerHTML = xhr.responseText;
                        }
                }
        }
       
        // 打开路径:
        xhr.open("POST","/day15/ServletDemo1",true);
        xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        // 发送请求:
        xhr.send("name=张三&pass=123");
}
       
异步完成用户名的校验(了解)
步骤分析:       
步骤一:创建表和数据库:
步骤二:设计一个注册页面
步骤三:在用户名的文本框中使用onblur事件触发一个函数.
步骤四:AJAX的异步操作,将文本框的值传入到Servlet中.
步骤五:Servlet中根据传入的用户名去数据库进行查询.
步骤六:查询到了说明用户名已经被占用,没有查询到说明用户名可以使用

代码实现:
        $(function(){
        $("#username").blur(function(){
                // 获得文本框的值:
                var username = $(this).val();
                // 演示load方法:
                // $("#s1").load("/day15/ServletDemo3",{"username":username});
                // 演示get/post方法:
                $.get("/day15/ServletDemo3",{"username":username},function(data){
                        if(data == 1){
                                $("#s1").html("<font color='green'>用户名可以使用</font>");
                                $("#regBut").attr("disabled",false);
                        }else if(data == 2){
                                $("#s1").html("<font color='red'>用户名已经存在</font>");
                                $("#regBut").attr("disabled",true);
                        }
                });
        });
});
       
       
使用JQ完成对用户名异步校验的功能:(掌握)
       
技术分析:
        JQuery的AJAX部分方法:
         Jq的对象.load(路径,参数,回调函数);
         $.get(路径,参数,回调函数,数据类型);
         $.post(路径,参数,回调函数,数据类型);
         $.ajax();
         serialize(); -- JQ的AJAX传递参数的时候需要使用的方法

步骤分析:
步骤一:创建表和数据库:
步骤二:设计一个注册页面
步骤三:在用户名的文本框中使用onblur事件触发一个函数.
步骤四:使用JQ的AJAX完成异步操作,将文本框的值传入到Servlet中.
步骤五:Servlet中根据传入的用户名去数据库进行查询.
步骤六:查询到了说明用户名已经被占用,没有查询到说明用户名可以使用

代码实现:       
$(function(){
        $("#username").blur(function(){
                // 获得文本框的值:
                var username = $(this).val();
                // 演示load方法:
                // $("#s1").load("/day15/ServletDemo3",{"username":username});
                // 演示get/post方法:
                $.get("/day15/ServletDemo3",{"username":username},function(data){
                        if(data == 1){
                                $("#s1").html("<font color='green'>用户名可以使用</font>");
                                $("#regBut").attr("disabled",false);
                        }else if(data == 2){
                                $("#s1").html("<font color='red'>用户名已经存在</font>");
                                $("#regBut").attr("disabled",true);
                        }
                });
        });
});

使用JQ完成仿百度提示页面

步骤分析:
步骤一:设计一个商品的搜索页面.
步骤二:keyup事件触发一个函数.
步骤三:获得文本框的值,提交到Servlet中
步骤四:在Servlet中根据提交名称查询相应信息.(显示5个)

create table words(
        id int primary key auto_increment,
        word varchar(20)
);

代码实现:
$(function(){
        // 为文本框绑定事件:
        $("#word").keyup(function(){
                // 获得文本框的值:
                var word = $(this).val();
                // 异步发送请求:
                if(word != ""){
                        $.post("/day15/ServletDemo4",{"word":word},function(data){
                                $("#d1").show().html(data);
                        });
                }else{
                        $("#d1").hide();
                }
        });
});
       
使用JQ完成省市联动的案例:
技术分析:
        AJAX的响应的数据:
        文本,一段HTML的数据,XML,JSON
        使用工具生成XML的文件
        通常使用xStream工具,将集合,数组,对象转换成xml
       
步骤分析:       
步骤一:使用注册页面中省市的下拉列表.
步骤二:当省份发生变化,触发一个事件.
步骤三:将选择的省份的信息传入到Servlet中.
步骤四:根据省份信息查询市的信息.
步骤五:将查询到市的信息转成XML.
步骤六:获得XML的指定信息,显示到第二个列表中.

代码实现:       
        $(function(){
        // 为省份下拉列表绑定事件:
        $("#province").change(function(){
                // 获得选中的省份的id:
                var pid = $(this).val();
                // alert(pid);
                $.post("/day15/ServletDemo6",{"pid":pid},function(data){
                        // alert(data);
                        var $city = $("#city");
                        $city.html("<option>-请选择-</option>");
                        $(data).find("city").each(function(){
                                var cid = $(this).children("cid").text();
                                var cname = $(this).children("cname").text();
                               
                                $city.append("<option value='"+cid+"'>"+cname+"</option>");
                        });
                });
        });
});

使用JQ完成省市联动的案例:使用JSON作为响应数据.
JSON的概述
JSON的概念
        JSON(javaScript Object Notation)是一种轻量级的数据交换格式。它是基于ECMAScrip的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言的家族习惯类似于C语言家族的习惯(包括C、C++、C#、java、javascrtpt、Pert、Python等)。这些特性是JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)

JSON的数据格式的介绍:
{“id”:1,”name”:aaa}
[{“id”:1,”name”:aaa},{“id”:2,”name”:bbb}]
{
    “city”:{“cid”:1,”cname”:”xxx”}
}

JSON的生成工具
JSONLIB 转换JSON数据:
JSONArray                :将数组或List集合转成JSON.
JSONObject        :将对象或Map集合转成JSON.

代码实现:
        $(function(){
        // 为省份下拉列表绑定事件:
        $("#province").change(function(){
                var pid = $(this).val();
                $.post("/day15/ServletDemo8",{"pid":pid},function(data){
                        // alert(data);
                        // JS识别JSON:
                        // var json = eval(data);
                        var $city = $("#city");
                        $city.html("<option>-请选择-</option>");
                        $(data).each(function(i,n){
                                // alert(n.cname);
                                $city.append("<option value='"+n.cid+"'>"+n.cname+"</option>");
                        });
                },"json");
        });
});
               
********************************************************************************************       
监听器:Listener

监听器的概述:

什么是监听器:
监听器:就是一个Java类,用来监听其他的Java的状态的变化.

监听器的用途:
用来监听其他的对象的变化的.
主要应用在图形化界面中比较多:
GUI,Android.

监听器的术语:
事件源:指的是被监听的对象.(汽车)
监听器:值的是监听的对象.(报警器)
事件源与监听器的绑定:就是在汽车上安装报警器.
事件:指的是事件源的改变.(踹汽车一脚)---主要的功能获得事件源对象.

WEB中的监听器的概述:

WEB中的监听器
WEB中的Listener和Filter是属于Servlet规范中的高级的技术.
WEB中的监听器共有三类八种(监听三个域对象)
事件源:Servlet中的三个域对象.ServletContext,HttpSession,ServletRequest.
监听器:自定义类实现8个接口.
事件源和监听器的绑定:配置.

WEB中的监听器的分类
三类八种:
一类:监听三个域对象的创建和销毁的监听器:
     ServletContextListener
     HttpSessionListener
     ServletRequestListener
二类:监听三个域对象的属性变更的监听器(属性添加,移除,替换):
     ServletContextAttributeListener
     HttpSessionAttributeListener
     ServletRequestAttributeListener
三类:监听HttpSession中的JavaBean的状态改变(绑定,解除绑定,钝化,活化)
     HttpSessionBindingListener
     HttpSessionActivationListener

WEB中的监听器的使用
编写一个类实现监听器的接口:
通过配置文件配置监听器:

一类:监听三个域对象的创建和销毁的监听器
ServletContextListener:监听ServletContext对象的创建和销毁:
方法:
        vodi contextDestroyed(ServletContextEvent sce)
        Notification that he servet Context is about to be shut down
       
        void contextInitialized(ServletContextEvent sce)
        Notification that the web application initialization process is starting
       
        ServletContext对象的创建和销毁:
创建:服务器启动的时候,服务器为每个WEB应用创建一个属于该web项目的对象ServletContext.
销毁:服务器关闭或者项目从服务器中移除的时候

应用代码
public class MyServletContextListener implements ServletContextListener{

        @Override
        public void contextInitialized(ServletContextEvent sce) {
                System.out.println("ServletContext对象被创建了...");
        }

        @Override
        public void contextDestroyed(ServletContextEvent sce) {
                System.out.println("ServletContext对象被销毁了...");
        }

}
配置:
  <!-- 配置监听器 -->
  <listener>
          <listener-class>com.itheima.weblistener.MyServletContextListener</listener-class>
  </listener>

企业中的应用:
1.加载框架的配置文件                :Spring框架 ContextLoaderListener
2.定时任务调度:
     Timer,TimerTask

HttpSessionListener:监听HttpSession的创建和销毁的监听器
方法:
        void sessionCreated(HttpSessionEvent se)
         Notification that session was created
       
        sessionDestroyed(HttpSession se)
         Notification that a session is about to be invalidated.
         
HttpSession何时创建和销毁的
创建:服务器端第一次调用getSession();
销毁:
     非正常关闭服务器(正常关闭session会序列化):
     session过期了默认30分钟.
     手动调用session.invalidate();

HttpSession的问题
访问Servlet会不会创建Session        : 不会
访问JSP会不会创建Session                :会.
访问html会不会创建Session                :不会

应用的代码
public class MyHttpSessionListener implements HttpSessionListener{

        @Override
        public void sessionCreated(HttpSessionEvent se) {
                System.out.println("HttpSession被创建了...");
        }

        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
                System.out.println("HttpSession被销毁了...");
        }

}
配置:
  <listener>
    <listener-class>com.itheima.weblistener.MyHttpSessionListener</listener-class>
  </listener>
         
ServletRequestListener:监听ServletRequest对象的创建和销毁的监听器:
方法:
        void requestDestroyed(ServletRequestEvent sre)
                The request is about to go out of scope of the web application
       
        void requestInitialized(ServletRequestEvent sre)
                The request is about co come into scope of the web application
request对象何时创建和销毁:
创建:客户端向服务器发送一次请求,服务器就会创建request对象.
销毁:服务器对这次请求作出响应后就会销毁request对象.

问题:
访问一个Servlet会不会创建request对象:会
访问一个JSP会不会创建request对象:会
访问一个HTML会不会创建request对象:会

应用的代码
public class MyServletRequestListener implements ServletRequestListener{

        @Override
        public void requestDestroyed(ServletRequestEvent sre) {
                System.out.println("ServletRequest被销毁了...");
        }

        @Override
        public void requestInitialized(ServletRequestEvent sre) {
                System.out.println("ServletRequest被创建了...");
        }

}
配置:
  <listener>
    <listener-class>com.itheima.weblistener.MyServletRequestListener</listener-class>
  </listener>
               
二类:监听三个域对象的属性变更的监听器:(属性添加,移除,替换)
ServletContextAttributeListener:监听ServletContext对象的属性变更
       
        void attributeAdded(ServletContextAttributeEven scab)
                Notification that a new attribute was added to the servelt context.
       
        void attributeRemoved(ServeltContextbuteEven scab)
                Notification tha an existing attribute has been removed from the servelt context
       
        void attributeReplaced(ServletContextAttributeEvent scab)
                Notification that an attribute on the servelt context has been replaced
       
HttpSessionAttributeListener:监听HttpSession中的属性变更
        void attributeAdded(HttpSessionBindingEvent se)
          Notification that an attribute has been added to a session.
                  
        void attributeRemoved(HttpSessionBindingEvent se)
          Notification that an attribute has been removed from a session
        void attributeReplaced(HttpSessionBindingEvent se)
          Notification that an attribute has been replaced in a session

ServletRequestAttributeListener:监听ServletRequest对象的属性变更的:               

        void attributeAdded(ServletRequestAttributeEvent srae)
          Notification that a new attribute was added to the servlet request   
        void attributeRemoved(ServletRequestAttributeEvent srae)
          Notification that an existing attribute has been removed from the servlet request.
        void attributeReplaced(ServletRequestAttributeEvent srae)
          Notification that an attribute was replaced on the servlet request
                  
三类:监听HttpSession中的JavaBean的对象的状态改变的监听器
第三类监听器很特殊,不需要进行配置的.作用在JavaBean上的监听器.JavaBean可以自己感知到在Session中的状态.

HttpSessionBindingListener:监听HttpSession中的JavaBean的绑定和解除绑定的       
        void valueBound(HttpSessionBindingEvent event)
          Notifies the object that it is being bound to a session and identifies the session.
        void valueUnbound(HttpSessionBindingEvent event)
          Notifies the object that it is being unbound from a session and identifies the session

HttpSessionActivationListener:监听HttpSession中的JavaBean的钝化和活化的

        void sessionDidActivate(HttpSessionEvent se)
          Notification that the session has just been activated
                  
        void sessionWillPassivate(HttpSessionEvent se)
          Notification that the session is about to be passivated
  sessionDidActivate();                :--活化(反序列化)
sessionWillPassivate();        :--钝化(序列化到硬盘)

优化Session:
      通过配置<Context>标签配置定时session序列化.
          在tomcat/conf/context.xml中配置<Context>:在tomcat中所有的虚拟主机和虚拟路径都会按照这个配置执行.
          在tomcat/conf/Catalina/localhost/context.xml配置<Context>        :在tomcat中的localhost虚拟主机中的所有虚拟路径按照这个配置执行.
          在当前的工程下的META-INF/context.xml配置<Context>:当前这个工程按照配置执行.



       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       









0 个回复

您需要登录后才可以回帖 登录 | 加入黑马