首页 > 程序开发 > Web开发 > 其他 >

JavaWeb-(JDBC之分页与监听器listener)

2015-04-03

JavaWeb-18 JDBC之分页与监听器listener 一、分页 1、分页概述:分页的结果就是要让指定的记录加载到内存 2、原因: 1、人的习惯 2、内存的限度(核心问题) 3、屏幕的限度 3、如何分页: 不同的环境方式不一样

JDBC之分页与监听器listener

一、分页

1、分页概述:分页的结果就是要让指定的记录加载到内存

2、原因:

1、人的习惯
2、内存的限度(核心问题)
3、屏幕的限度

3、如何分页:

不同的环境方式不一样

3.1、数据库层面:

select * from acount limit startIndex,size;//只是针对MySql而言(startIndex从0开始,size:共查询多少条记录)
select * from acount limit 0,3; 第一页(1,2,3)
select * from acount limit 3,3; 第二页(4,5,6)

转换到编程上的思想:startIndex: (pageNo-1)*size   (pageNo:第几页)

总记录数:
    select count(*) from 表名

3.2、程序代码上思考

a(思路)、直接发送select * from acount limit 0,3;这样的SQL语言(推荐使用该思想)
ResultSet中存的数据就是指定的记录。

b(思路)、发送一个select * from acount;查询所有的SQL语句(一般不考虑,因为没有解决内存本质问题)
ResultSet 结果集中
在内存中处理结果(只加载前10条)

3.3、程序代码上做分页怎么写?怎么控制?JDBC里怎么实现?

使用思路a的思想:

引入一个JavaBean分页组件:PageBean

分页组件:PageBean.java

//分页组件用于实现封装分页的相关信息
{
    private int pageNo=1;//当前是第几页
    private int pageSize=3;//每页最多显示几条
    private int prep;//上一页
    private int nextp;//下一页
    private int totalPage;//总页数
    private int totalRecordes;//总记录数
    //变量之间是有关联的
    private int startIndex;//代表分页的起始的索引(pageNo-1)*pageSize
    private List records;//当前页的所有记录:需要查询数据库获取变量值
}

生成bean

回顾:el表达式其实是调用bean的get方法。

现在在各个属性的get方法加入if语句不断挖掘变量之间的关系。

eg:

    public int getTotalPage(){
        if(totalRecordes%pageSize==0){
            ....
        }else{
                ...
            }
        return ...;

    }


    public int getPrep(){
        if(pageNo<=){
            ...
        }else{
                prep=pageNo-1;
            }
            return prep;
    }

    public int getNextp(){
        if(pageNo>=getTotalPage()){
            ...
        }else{
                ...
            }
        return nextp;
    }


    public int getStartIndex(){
        ....
        return ...;
    }

实验:项目:day1800pagebean

\

web.xml



  
  
    ControllerServlet
    com.itheima.web.controller.ControllerServlet
  

  
    ControllerServlet
    /servlet/ControllerServlet
      
  
    index.jsp
  

AccountDao.java

package com.itheima.dao;

import java.util.List;

import com.itheima.domain.Account;

public interface AccountDao {

    public int getCount();

    public List findRecordesByPage(int startIndex,int size);
}

AccountDaoImpl.java

package com.itheima.dao.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import com.itheima.utils.C3P0Util;

public class AccountDaoImpl implements AccountDao {
    private QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
    public int getCount() {
        try {
            return ((Long)qr.query(select count(1) from account,new ScalarHandler())).intValue();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public List findRecordesByPage(int startIndex, int size) {
        try {
            return qr.query(select * from account limit ?,?,new BeanListHandler(Account.class),startIndex,size);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

}

Account.java

package com.itheima.domain;

import java.io.Serializable;

public class Account implements Serializable {

    private int id;
    private String name ;
    private float money;

    public Account(int id, String name, float money) {
        super();
        this.id = id;
        this.name = name;
        this.money = money;
    }

    public Account() {
        super();
    }


    @Override
    public String toString() {
        return Account [id= + id + , name= + name + , money= + money
                + ];
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getMoney() {
        return money;
    }
    public void setMoney(float money) {
        this.money = money;
    }
}

AccountServlice.java

package com.itheima.service;

import com.itheima.web.form.PageBean;

public interface AccountService {

    public void findRecordesByPage(PageBean pb);
}

AccountServletImpl.java
package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.dao.impl.AccountDaoImpl;
import com.itheima.service.AccountService;
import com.itheima.web.form.PageBean;

public class AccountServiceImpl implements AccountService {
    private AccountDao dao = new AccountDaoImpl();
    public void findRecordesByPage(PageBean pb) {
        pb.setTotalRecordes(dao.getCount());//设置分页的总记录数
        pb.setRecordes(dao.findRecordesByPage(pb.getStartIndex(), pb.getPageSize()));//当前页中的记录封装到pageBean
    }

}

JTest.java

package com.itheima.test;

import java.util.List;

import junit.framework.Assert;

import org.junit.Test;

import com.itheima.dao.AccountDao;
import com.itheima.dao.impl.AccountDaoImpl;

public class JTest {

    @Test
    public void testCount(){
        AccountDao dao = new AccountDaoImpl();
        int count = dao.getCount();
        //System.out.println(count);
        Assert.assertEquals(7, count);
    }
    @Test
    public void testFindByPage(){
        AccountDao dao = new AccountDaoImpl();
        List list= dao.findRecordesByPage(0, 3);
        //System.out.println(count);
        Assert.assertNotNull(list);
    }
}

C3P0Util.java

package com.itheima.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0Util {

    private static DataSource ds =  new ComboPooledDataSource(mysql);

    /**
     * 获取连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception{
        return ds.getConnection();
    }

    /**
     * 获取数据源
     * @return
     */
    public static DataSource getDataSource(){
        return ds;
    }

    /**
     * 关闭资源
     * 
     * @param rs
     * @param st
     * @param con
     */
    public static void release(ResultSet rs, Statement st, Connection con) {
        // 6.关闭资源
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st = null;
        }
        if (con != null) {
            try {
                con.close();//不用担心了,肯定还回池中
            } catch (SQLException e) {
                e.printStackTrace();
            }
            con = null;//线程池中也要回收
        }

    }
}

ControllerServlet.java

package com.itheima.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.service.AccountService;
import com.itheima.service.impl.AccountServiceImpl;
import com.itheima.web.form.PageBean;

public class ControllerServlet extends HttpServlet {
    private AccountService as = new AccountServiceImpl();
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.设置编码
        response.setContentType(text/html;charset=UTF-8);
        request.setCharacterEncoding(UTF-8);
        //2.请求当前的页数
        String pageNo = request.getParameter(pageNo);
        //3.生成分页组件,并设置页数
        PageBean pb = new PageBean();
        if(pageNo!=null){
            pb.setPageNo(Integer.parseInt(pageNo));
        }
        //4.实现分页查询
        as.findRecordesByPage(pb);

        pb.setUrl(request.getContextPath()+/servlet/ControllerServlet);
        //5.将分页组件保存到request域
        request.setAttribute(pb, pb);


        //6.转发
        request.getRequestDispatcher(/listaccount.jsp).forward(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);

    }

}

PageBean.java

package com.itheima.web.form;

import java.util.List;

//分页组件用于实现封装分页的相关信息
public class PageBean {
    private int pageNo=1;//当前是第几页
    private int pageSize=3;//每页最多显示几条
    private int prep;//上一页
    private int nextp;//下一页
    private int totalPage;//总页数
    private int totalRecordes;//总记录数
    private int startIndex;//代表分页的起始的索引  (pageNo-1)*pageSize;
    private List recordes;//当前页的所有记录

    private String url;

    //补充添加
    private int startPageNo;//起始页
    private int endPageNo;//结束页


    //每页上面最多有9个数字显示
    public int getStartPageNo() {
        if(getTotalPage()<=9){
            startPageNo=1;
            endPageNo=getTotalPage();
        }else{
            startPageNo=pageNo-4;
            endPageNo=pageNo+4;
            if(startPageNo<=1){
                startPageNo=1;
                endPageNo=startPageNo+8;
            }
            if(endPageNo>=getTotalPage()){
                endPageNo=getTotalPage();
                startPageNo=endPageNo-8;
            }
        }
        return startPageNo;
    }
    public void setStartPageNo(int startPageNo) {
        this.startPageNo = startPageNo;
    }
    public int getEndPageNo() {
        return endPageNo;
    }
    public void setEndPageNo(int endPageNo) {
        this.endPageNo = endPageNo;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public int getPageNo() {
        return pageNo;
    }
    public void setPageNo(int pageNo) {
        this.pageNo = pageNo;
    }
    public int getPageSize() {
        return pageSize;
    }
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
    public int getPrep() {
        if(pageNo<=1){
            prep=1;
        }else{
            prep=pageNo-1;
        }
        return prep;
    }
    public void setPrep(int prep) {
        this.prep = prep;
    }
    public int getNextp() {
        if(pageNo>=getTotalPage()){
            nextp=getTotalPage();
        }else{
            nextp=pageNo+1;
        }
        return nextp;
    }
    public void setNextp(int nextp) {
        this.nextp = nextp;
    }
    public int getTotalPage() {
        if(totalRecordes%pageSize==0){
            totalPage = totalRecordes/pageSize;
        }else{
            totalPage = totalRecordes/pageSize+1;
        }
        return totalPage;
    }
    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }
    public int getTotalRecordes() {
        return totalRecordes;
    }
    public void setTotalRecordes(int totalRecordes) {
        this.totalRecordes = totalRecordes;
    }
    public int getStartIndex() {
        startIndex = (pageNo-1)*pageSize;
        return startIndex;
    }
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }
    public List getRecordes() {
        return recordes;
    }
    public void setRecordes(List recordes) {
        this.recordes = recordes;
    }
}

c3p0-config.xml



    
        com.mysql.jdbc.Driver
        jdbc:mysql://localhost:3306/day15
        root
        root

        5
        10
        5
        20
    

    
        com.mysql.jdbc.Driver
        jdbc:mysql://localhost:3306/day15
        root
        root

        5
        10
        5
        20
    


    
        com.mysql.jdbc.Driver
        jdbc:mysql://localhost:3306/day16
        root
        root

        5
        10
        5
        20
    

index.jsp

<%@ page language=java import=java.util.* pageEncoding=UTF-8%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+://+request.getServerName()+:+request.getServerPort()+path+/;
%>


>

listaccount.jsp

<%@ page language=java import=java.util.* pageEncoding=UTF-8%>
<%@taglib uri=http://java.sun.com/jsp/jstl/core prefix=c %>

ID Name Money 操作
${ss.id } ${ss.name } ${ss.money } 删除 修改
<%@include file=/commons/page.jsp %>

当前数据库中的account表

\

首页

\

页2

\

页3

\

在编程时e.printStackTrace()的报错写有好处,提醒我们错误是什么,当项目要发布了删去就好

不会断点调试,活该一辈子做程序员

单元测试的原因:防止扯皮!一个项目在公司里分很多部分,就是三次模型里衍生来的项目中的很多部分,每个部分都可以使用单元测试来检查该部分有没有出现问题!!!!

各个环节不断排查问题,如果一个项目是一个人完成的话,最好在每完成一个部分就使用单元测试来检查环节有没有问题!!

在测试类@Test XXX{}方法里:需要使用断言来测试!Assert.assertEquals(xxx);才专业!!

在@Test类里使用Assert类来测试方法专业

在方法上加@Test就可以测试单元为什么?反射注解

之前老师在业务逻辑层搞的接口和数据处理层的接口没什么区别,其实是老师偷懒,凉拌菜,实际中业务层需要设计更复杂的业务逻辑处理,红烧牛肉面

改造PageBean,加入String URL属性 为了让jsp的路径更简洁,耦合性更低!适用性更强 并在ControllerServlet里给PageBean的Url设置

在WebRoot里新建commons文件夹,里面新建page.jsp:分页组件。(内容和之前的jsp一样,然后在原来的jsp(空白的jsp里使用标签导入))

以后工程使用这种方式导入效率高!

再想在页面中显示(有超链功能)分页码:

需要在PageBean里继续加入属性:

(
    private int startPageNo;//其实页
    private int endPageNo;//结束页
)

在get方法里加入业务():不断挖掘变量之间的关系

getstartPageNo(){
    if(){
        ..
    }else{
            ...
        }
}:先整体思考再把细节补上!

然后在页面组件里加上新增的PageBean属性,显示在页面jsp上

实验思路:

设计好AccountDao-->AccountDaoImpl的功能后,通过AccountServiceImop的功能去控制,从而获取到当前服务器数据库的用来分页的数据,然后该业务逻辑层和数据处理层就搭建成功,接着就是表现层,首先把要表现的页面框架给设计好,在jsp+el表达式把已经封装好了的PageBean里的数据通过待会要设计的servlet传过来。jsp框架设置完后,接下来设计Servlet,servlet在此充当了表现层的控制器(controler),用来控制业务处理层和页面数据并切换,在serlvet里,控制业务处理层的方法去获取数据库中的分页数据,初始化并自定义了自己需要的分页数据封装成PageBean后,就可以用来转发给jsp来表现到页面上了。在jsp还利用了include机制把别的封装后的jsp去调用过来。节省了开发的时间。

总结:数据库数据分页数据---->控制后的数据封装成属性放入PageBean--->页面获取过滤过的PageBean属性表现出来

二、监听器(观察者模式)

1、概述:

现实中:踹宝马车,宝马车响了,主人知道了

事件:踹
事件源:产生该事件的对象(人)
事件监听:车上的报警器
事件处理程序:一女生出来了,另一个男人跑了

实验:

创造java框架

没加监听器的框架--->连关也关不掉

那么我们添加监听
//添加监听:就像宝马车上的报警器
f.addWindowListener(new WindowAdapter(){
    //处理程序:就像宝马报警器响了
    public void windowClosing(WindowEvent e){
        //得到事件源:就像女人跑了,就是找到要关闭的对象
        //WindowEvent是一个事件,可以通过它去获得事件源
        Frame targetSource = (Frame)e.getSource();//事件源!
        //关闭事件源
        targetSource.dispose();//销毁事件源,这样就看到窗口关闭了
    }
});//匿名内部类

实验:day1801listener

项目架构:

\

package com.itheima.test;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class FrameTest {

    public static void main(String[] args) {
        Frame f = new Frame();
        f.setSize(200, 150);
        f.setVisible(true);

        //添加监听
        f.addWindowListener( new WindowAdapter() {
            //处理程序
            @Override
            public void windowClosing(WindowEvent e) {
                //1.得到事件源,就是找到要关闭的对象        WindowEvent是一个事件,可能通过它去获得事件源
                Frame targetSource = (Frame)e.getSource();

                //2.关闭事件源
                targetSource.dispose();//销毁事件源,这样就看到窗口关闭了
            }
        });
    }
}

点击关闭按钮关闭

\

2、Servlet规范中的8个监听器

1、监听ServletContext、HttpSession、ServletRequest对象的创建和销毁的监听器

它们分别是ServletContextListener、HttpSessionListener、ServletRequestListener

怎么写?

写一个Listener基本步骤:1、写类、2、配置web.xml

web三大组件:Servlet、监听器、过滤器

项目:day1802weblistener

项目架构:

\

MyHttpSessionAttributeListener.java

package com.itheima.attribute.listener;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class MyHttpSessionAttributeListener implements
        HttpSessionAttributeListener {

    public void attributeAdded(HttpSessionBindingEvent arg0) {
        System.out.println(放了);

    }

    public void attributeRemoved(HttpSessionBindingEvent arg0) {
        System.out.println(删了);

    }

    public void attributeReplaced(HttpSessionBindingEvent arg0) {
        System.out.println(换了);

    }

}

User.java

package com.itheima.domain;

import java.io.Serializable;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;

//感知型监听器HttpSessionBindingListener ,HttpSessionActivationListener
public class User implements Serializable, HttpSessionBindingListener ,HttpSessionActivationListener{

    private String name;
    private String password;

    public User() {
        super();
    }

    public User(String name, String password) {
        super();
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    public void valueBound(HttpSessionBindingEvent arg0) {
        System.out.println(User对象被绑架了);

    }

    public void valueUnbound(HttpSessionBindingEvent arg0) {
        System.out.println(User对象被解绑了);

    }

    public void sessionDidActivate(HttpSessionEvent arg0) {
        System.out.println(HttpSessio已激活);

    }

    public void sessionWillPassivate(HttpSessionEvent arg0) {
        System.out.println(HttpSessio钝化);

    }


}

MyServletContextListener.java

package com.itheima.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {

    public void contextDestroyed(ServletContextEvent arg0) {
        System.out.println(ServletContext已被销毁了);
    }

    public void contextInitialized(ServletContextEvent arg0) {
        System.out.println(ServletContext已被创建了);
    }

}

MyServletRequset.java

package com.itheima.listener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class MyServletRequest implements ServletRequestListener {

    public void requestDestroyed(ServletRequestEvent arg0) {
        System.out.println(ServletRequest被销毁了);

    }

    public void requestInitialized(ServletRequestEvent arg0) {
        System.out.println(ServletRequest被创建了);

    }

}

index.jsp

<%@page import=com.itheima.domain.User%>
<%@ page language=java import=java.util.* pageEncoding=UTF-8%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+://+request.getServerName()+:+request.getServerPort()+path+/;
%>


> <% /* session.setAttribute(p,pp); session.setAttribute(pp, ppp); session.removeAttribute(p); */ session.setAttribute(p, new User(cgx,123)); %>

------------------< ServletContextListener>--------------------

Listener---->MyServletContextListener.java--->继承监听器接口(ServletContextListener)
实现接口带来的两个方法(Context销毁{}Context初始化)
然后配置web.xml---->

当服务器启动时,servlet也就开始了,也就是servletContext也生成!!
Servlet的生命周期需要课下巩固!

所以开始测试项目:
已启动服务器:在服务器信息里就存在要输出的信息

MyServletContextListenerjava测试结果:

\

------------------< HttpSessionListener>--------------------

listener--->MyHttpSessionListener.java(继承HttpSessioinListener接口)
实现接口带来的两个方法(Context销毁{}Context初始化)
然后配置web.xml---->把包名/类名复制过去

那么问题来了:session什么被创建呢?当客户端访问servlet时就会产生session,但是如果在servlet声明指令里把session属性改成false时,session就不会产生

tomcat的session周期是30分钟
在tomcat的web.xml配置文件可以查看

MyHttpSessionListenerjava测试结果:

\

------------------< ServletRequestListener>--------------------

Request:当客户端访问时会产生,当客户断开连接时销毁:生命周期短
Listener---->MyServletRequest.java--->继承监听器接口(ServletRequestListener)
实现接口带来的两个方法(Context销毁{}Context初始化)
然后配置web.xml---->把包名/类名复制过去

所以开始测试项目:
已启动服务器:--->用jsp访问—--发生什么?

MyServletRequestjava测试结果:

\

3、监听域中值的属性变化的监听器

监听ServletContext、HttpSession、ServletRequest域中数据变化的监听器
ServletContextAttributeLister:
HttpSessionAttributeLister:
ServletRequestAttributeLister:
怎么触发以上监听器:调用set、get方法

attribute.lister--->MyHttpSessionAttributLister.java(实现接口:HttpSessionAttributeLister)
实现接口带来的三个方法(added、removed、Replaced)
配置Web.xml
在index.jsp里写jsp代码:<%%>
session.setAttribute(p,pp);
然后访问jsp:然后触发

然后session.removeAttribute(p);
然后访问jsp:然后触发


以上已经介绍了6个监听器(两组)

MyHttpSessionAttributeListenerjava测试结果1:

\

MyHttpSessionAttributeListenerjava测试结果2:

\

MyHttpSessionAttributeListenerjava测试结果3:

\

4、感知型监听器:

这些监听器不需要注册(即不用在xml里配置)。给普通类用

HttpSessionBindingListener:普通类实现了该接口,感知自己何时被HttpSession绑和解绑

HttpSessionActivationListener:普通类实现了该接口,感知自己何时随着HttpSession钝化和激活

\

domin--->User{name、password、有参构造、无参构造,get()、set()}
让以上类实现一个HttpSessionBindingListener
实现方法(valueBound+valueUnbound)

怎么实验?

在index.jsp里
session.setAttribute(p,new User(cgx,123));

运行!

然后把session.setAttribute(p,new User(cgx,123));
改成request.setAttribute(p,new User(cgx,123));
没反应:说明只对session反应

继续拿User实现HttpSessionActivationListener接口
注意:Java可以多实现不可以多继承
然后实现接口方法(sessionDidActivate(激活)+sessionWillPassivate(已钝化))

测试:打开IE访问:主页--->tomcat Manager-->在管理器里的项目名点stop管理器!钝化激活
在work的项目目录下会产生session.ser的文件,就是之前学session时把IE的安全性调到最高时把session保存在客户机的硬盘上!
管理器重启项目后--->激活!
(该程序效果测试失败率高!User 要序列化:当应用(项目)被停的时候,服务器会把这对象写入硬盘保存,以便可以当应用激活时从硬盘调出来,所以User需要加上序列化!!!implements Serializable)

现实中是当内存已满是可以监听到。

要测试每一个监听器的效果建议注销之前的配置

对象序列化-->就是把对象写入文件中

三、显示在线人数,并演示踢人示例

项目:day1803kick

项目架构:

\

User.java

package com.itheima.domain;

import java.io.Serializable;

public class User implements Serializable{

    private String username;
    private String password;

    public User() {
        super();
    }

    public User(String username, String password) {
        super();
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }


}

MyHttpSessionAttributeListener.java

package com.itheima.listener;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

import com.itheima.domain.User;

public class MyHttpSessionAttributeListener implements
        HttpSessionAttributeListener {

    public void attributeAdded(HttpSessionBindingEvent se) {
        HttpSession session = se.getSession();
        Object obj =session.getAttribute(user);
        if(obj==null){
            return ;
        }
        if(obj instanceof User){
            User u = (User)obj;

            //2.放入ServletContext中
            ServletContext sc = session.getServletContext();
            //3.因为需要将当前登录的多个用户信息存入ServletContext,所以先产生一个Map集合将登录的所有用户信息
            //存入到Map集合中,最后将Map集合放入ServletContext中

            //Map集合的key:用户名    value:HttpSession
            Map map = (Map)sc.getAttribute(map);
            if(map==null){
                map = Collections.synchronizedMap(new HashMap());//保证线程同步
                sc.setAttribute(map, map);
            }
            map.put(u.getUsername(),session);//这样存值的目的,是在另一台机器上可以得到其它用户的session对象
        }
    }

    public void attributeRemoved(HttpSessionBindingEvent arg0) {
        // TODO Auto-generated method stub

    }

    public void attributeReplaced(HttpSessionBindingEvent arg0) {
        // TODO Auto-generated method stub

    }

}

KickServlet.java

package com.itheima.servlet;

import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class KickServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding(UTF-8);
        //1.获取参数username
        String username1 = request.getParameter(username);
        //2.对username进行重新编码
        String username = new String(username1.getBytes(iso-8859-1),UTF-8);
        //3.找到ServletContext中的Map集合
        ServletContext sc = getServletContext();
        Map map = (Map)sc.getAttribute(map);
        //4.在Map集合中,根据username找到当前的key-value对
        HttpSession session = map.get(username);
        //5.根据value所对应HttpSession,进行销毁操作
        session.invalidate();
        //6.从Map集合中,根据username,删除key-value对
        map.remove(username);

        response.sendRedirect(request.getContextPath());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);

    }

}

LoginServlet.java

package com.itheima.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.domain.User;

public class LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding(UTF-8);
        response.setContentType(text/html;charset=UTF-8);

        //2.接收参数
        String username = request.getParameter(username);
        String password = request.getParameter(password);
        //3.封装成对象
        User user = new User(username,password);

        //4.将user对象保存到session域中
        //当在session域中放入值时,可以让后台的监听器进行监听,
        //并将当前保存的用户信息放入到ServletContext,以实现全局共享
        request.getSession().setAttribute(user, user);

        //5.重定向  
        response.sendRedirect(request.getContextPath()+/index.jsp);//该页面主要用于显示当前在线的用户,并提供踢人的链接

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);

    }

}

index.jsp

<%@ page language=java import=java.util.* pageEncoding=UTF-8%>
<%@taglib uri=http://java.sun.com/jsp/jstl/core prefix=c %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+://+request.getServerName()+:+request.getServerPort()+path+/;
%>


> ${vv.key } 踢人
你可能被别人踢了,请重新登录:登录

login.jsp

<%@ page language=java import=java.util.* pageEncoding=UTF-8%>


&nbsp;*&nbsp; &nbsp; Title



&nbsp;

web.xml



  
  
    LoginServlet
    com.itheima.servlet.LoginServlet
  
  
    KickServlet
    com.itheima.servlet.KickServlet
  


  
    LoginServlet
    /servlet/LoginServlet
  
  
    KickServlet
    /servlet/KickServlet
      
  
    index.jsp
  

  
        com.itheima.listener.MyHttpSessionAttributeListener
  

登录login页面

\

进入到index页面

\

总结:

首先设计好javaBean:user,用来把login.jsp传进LoginServlet的数据封装成User对象的。

在Login.jsp里设计的form表单action路径是LoginServlet里,LoginServlet用request.getParament方法去获得Login.jsp传来的信息,封装成对象后就把User对象放入到了Session域对象里了,并把信息利用重定向到index.jsp里了。

然后在MyHttpSessionAttributeListener里实现了session监听器。也就是该servlet本身就是一个监听session对象属性的监听器,因此该监听器会从域对象session里查看session里所存的对象,我们给监听器添加操作,就是当有session存入了对象,监听器就会去判断,但在了解后面的内容之前要明白一个问题:session是域对象,但是只是针对同一个客户端,而servletcontext对象是针对所有客户端。因此在同一个客户端的时候,监听器会把session里的user对象拿出来,为了获得user的具体对象名,并把user的具体对象名和该对象的session存储在servletcontext对象里(注意,存储的方式是把一个Map类型的集合存储进servletcontext对象里,该Map类型集合存储了具体的用户名和对应的session,以供控制踢人的servlet去操作servletcontext对象去删除里面集合的具体用户的session)

然后在先前login.jsp重定向进入到了的index.jsp里,index页面会在当前客户端的session域里检测是否有对象,在有的前提下就利用系统标签去遍历servletcontext域里的所有用户名和session,并把这些信息表现在index页面里,并提供一个连接(连接通向kickservlet),该连接是这个项目的关键部件!通过该连接,kickservlet可以捕获index里的信息,具体用户的用户名,该名可以用来拿出存储在servletcontext对象对应的用户session,在index页面里,如果检查到客户端的session被invalid掉了,所以会强制重定向回login页面

通过超链接《踢出》在kickservlet里获取到了用户名,可以拿出存储在servletcontext对象对应的用户session,并通过从servletcontext对象里,拿到用户的session,把session给invalid掉,并在map里通过用户名取出session,以此来实现把用户踢出的效果。
 
相关文章
最新文章
热点推荐