Listener 笔记记录
- 1. Listener监听器
- 2. 监听对象的监听器
- 2.1 ServletContetListener
- 2.2 HttpSessionListener
- 2.3 ServletRequestListener
 
- 3. 监听域对象属性变化的监听器
- 3.1 ServletContextAttributeListener
- 3.2 HttpSessionAttributeListener
- 3.3 ServletRequestAttributeListener
 
- 4. 监听会话相关的感知型监听器
- 4.1 HttpSessionBindingListener
- 4.2 HttpSessionActivationListener
 
- 5. 监听器的使用
- 5.1 ServletContextListener使用
- 5.2 ServletContextAttributeListener使用
 
- 6. Javaweb综合案例
- version 1.0
- version 2.0
 
 
1. Listener监听器

 
2. 监听对象的监听器
2.1 ServletContetListener

2.2 HttpSessionListener

2.3 ServletRequestListener

3. 监听域对象属性变化的监听器
3.1 ServletContextAttributeListener

3.2 HttpSessionAttributeListener

3.3 ServletRequestAttributeListener

4. 监听会话相关的感知型监听器
4.1 HttpSessionBindingListener

4.2 HttpSessionActivationListener
钝化与活化:
Session的活化和钝化
Session机制很好的解决了Cookie的不足,但是当访问应用的用户很多时,服务器上就会创建非常多的Session对象,如果不对这些Session对象进行处理,那么在Session失效之前,这些Session一直都会在服务器的内存中存在。那么就,就出现了Session活化和钝化的机制。
1)Session钝化:
Session在一段时间内没有被使用时,会将当前存在的Session对象序列化到磁盘上,而不再占用内存空间。
2)Session活化:
Session被钝化后,服务器再次调用Session对象时,将Session对象由磁盘中加载到内存中使用。
如果希望Session域中的对象也能够随Session钝化过程一起序列化到磁盘上,则对象的实现类也必须实现java.io.Serializable接口。不仅如此,如果对象中还包含其他对象的引用,则被关联的对象也必须支持序列化,否则会抛出异常:java.io.NotSerializableException

5. 监听器的使用
一共八个
 
5.1 ServletContextListener使用
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
 * ServletContext对象创建和销毁的监听器
 */
@WebListener
public class ListenerDemo implements ServletContextListener {
    /**
     * @Description ServletContext创建的时候执行
     */
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("监听到了对象创建");
        //获取对象
        ServletContext servletContext = sce.getServletContext();
        System.out.println(servletContext);
    }
    /**
     * @Description ServletContext 销毁的时候执行
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("监听到了对象销毁");
        //获取对象
        ServletContext servletContext = sce.getServletContext();
        System.out.println(servletContext);
    }
}
5.2 ServletContextAttributeListener使用
除了使用@weblistener注解还可以在web.xml中配置监听器
 下面两个监听器注解替换为web.xml中配置
 
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
 * ServletContext对象创建和销毁的监听器
 */
@WebListener
public class ListenerDemo implements ServletContextListener {
    /**
     * @Description ServletContext创建的时候执行
     */
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("监听到了对象创建");
        //获取对象
        ServletContext servletContext = sce.getServletContext();
        System.out.println(servletContext);
        servletContext.setAttribute("username","zhngsan");
        servletContext.setAttribute("username","lisi");
        servletContext.removeAttribute("username");
    }
    /**
     * @Description ServletContext 销毁的时候执行
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("监听到了对象销毁");
        //获取对象
        ServletContext servletContext = sce.getServletContext();
        System.out.println(servletContext);
    }
}
import javax.servlet.*;
import javax.servlet.annotation.WebListener;
/**
 * 应用域对象中的属性变化的监听器
 */
@WebListener
public class ListenerAttributeDemo implements ServletContextAttributeListener {
    //添加属性时候的监听
    @Override
    public void attributeAdded(ServletContextAttributeEvent event) {
        System.out.println("监听到了属性的添加...");
        //获取应用域对象
        Object username = event.getServletContext().getAttribute("username");
        System.out.println(username);
    }
    //移除属性时候的监听
    @Override
    public void attributeRemoved(ServletContextAttributeEvent event) {
        System.out.println("监听到了属性的移除...");
        //获取应用域对象
        Object username = event.getServletContext().getAttribute("username");
        System.out.println(username);
    }
    //替换属性时候的监听
    @Override
    public void attributeReplaced(ServletContextAttributeEvent event) {
        System.out.println("监听到了属性的替换...");
        //获取应用域对象
        Object username = event.getServletContext().getAttribute("username");
        System.out.println(username);
    }
}
6. Javaweb综合案例
version 1.0
之前实现:
首页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>学生管理系统首页</title>
</head>
<body>
<% Object username = session.getAttribute("username");
  if (username == null) {
%>
<a href="/student/login.jsp">请登录</a>
<%} else {%>
<a href="/student/addStudent.jsp">添加学生</a>
<a href="/student/listStudentServlet">查看学生</a>
<%}%>
</body>
</html>
登录页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>学生登录</title>
</head>
<body>
<form action="/student/loginServlet" method="get" autocomplete="off">
  用户名: <input type="text" name="username"><br>
  密码:<input type="password" name="password"><br>
    <button type="submit">登录</button>
</form>
</body>
</html>
登录页面请求处理
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         //获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //判断用户名
        if (username==null||"".equals(username)){
            //用户名为空 重定向到登录界面
            resp.sendRedirect("/student/login.jsp");
            return;
        }
        if (username.equals("zhufanzhi")&&password.equals("123")){
            //不为空  存入会话域
            HttpSession session = req.getSession();
            session.setAttribute("username",username);
            //重定向到首页jsp
            resp.sendRedirect("/student/index.jsp");
        }else {
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write("用户名密码错误。请重新登录");
            resp.setHeader("Refresh","2;URL=/student/login.jsp");
            return;
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}
添加学生页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加学生</title>
</head>
<body>
<form action="/student/addServlet" method="get" autocomplete="off">
    姓名: <input type="text" name="username"><br>
    年龄:<input type="number" name="age"><br>
    分数:<input type="number" name="score"><br>
    <button type="submit">保存</button>
</form>
</body>
</html>
实体类
public class Student {
  private   String username;
  private   int age;
  private   int score;
    @Override
    public String toString() {
        return "Student{" +
                "username='" + username + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
    public Student() {
    }
    public Student(String username, int age, int score) {
        this.username = username;
        this.age = age;
        this.score = score;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
}
添加学生请求处理
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
@WebServlet("/listStudentServlet")
public class listStudentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 创建字符输入流对象 关联读取文件
        BufferedReader br=new BufferedReader(new FileReader("d:\\stu.txt"));
        //2. 创建集合对象 用于保存Student对象
        ArrayList<Student > list=new ArrayList<>();
        //3.循环读取文件中的数据 将数据封装到Student 对象中 再把多个学生对象添加到集合中
        String line;
        while ((line=br.readLine())!=null){
            // 张三 18 100
            Student stu=new Student();
            String[] arr = line.split(",");
            stu.setUsername(arr[0]);
            stu.setAge(Integer.parseInt(arr[1]));
            stu.setScore(Integer.parseInt(arr[2]));
            list.add(stu);
        }
        //4.遍历集合 将数据响应到浏览器
        //获取输出流对象
        resp.setContentType("text/html;charset=UTF-8");
//        PrintWriter pw = resp.getWriter();
//        for (Student s:list){
//            pw.write(s.getUsername()+","+s.getAge()+","+s.getScore());
//            pw.write("<br>");
//        }
        req.getSession().setAttribute("stus",list);
        //5.重定向
        resp.sendRedirect("/student/list.jsp");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}
学生列表页面展示
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.example.student_manage.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>查看学生</title>
</head>
<body>
<table width="600px" border="1px">
    <tr>
        <th>姓名</th>
        <th>年龄</th>
        <th>成绩</th>
    </tr>
 <%  ArrayList<Student> students= (ArrayList<Student>) session.getAttribute("stus");
   for (Student stu:students ){
 %>
    <tr>
        <td><%=stu.getUsername()%></td>
        <td><%=stu.getAge()%></td>
        <td><%=stu.getScore()%></td>
    </tr>
    <%}%>
</table>
</body>
</html>
学生列表请求处理
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
@WebServlet("/listStudentServlet")
public class listStudentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 创建字符输入流对象 关联读取文件
        BufferedReader br=new BufferedReader(new FileReader("d:\\stu.txt"));
        //2. 创建集合对象 用于保存Student对象
        ArrayList<Student > list=new ArrayList<>();
        //3.循环读取文件中的数据 将数据封装到Student 对象中 再把多个学生对象添加到集合中
        String line;
        while ((line=br.readLine())!=null){
            // 张三 18 100
            Student stu=new Student();
            String[] arr = line.split(",");
            stu.setUsername(arr[0]);
            stu.setAge(Integer.parseInt(arr[1]));
            stu.setScore(Integer.parseInt(arr[2]));
            list.add(stu);
        }
        //4.遍历集合 将数据响应到浏览器
        //获取输出流对象
        resp.setContentType("text/html;charset=UTF-8");
//        PrintWriter pw = resp.getWriter();
//        for (Student s:list){
//            pw.write(s.getUsername()+","+s.getAge()+","+s.getScore());
//            pw.write("<br>");
//        }
        req.getSession().setAttribute("stus",list);
        //5.重定向
        resp.sendRedirect("/student/list.jsp");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}
version 2.0
优化1:使用过滤器配置全局中文乱码问题
 优化2:将jspjava代码块改为EL表达式和JSTL
 优化3:权限拦截实现,用户未登录不能进行操作
 优化4:虚拟目录变为动态获取
优化1:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 *  解决全局乱码问题
 */
@WebFilter("/*")
public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        //1. 将请求和响应对象转化未Http协议相关
        HttpServletRequest httpServletRequest= (HttpServletRequest) request;
        HttpServletResponse httpServletResponse= (HttpServletResponse) response;
        //2.设置编码格式
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        //3.放行
        filterChain.doFilter(httpServletRequest,httpServletResponse);
    }
    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
优化2:
    <c:forEach items="${stus}" var="s">
    <tr align="center">
        <td>${s.username}</td>
        <td>${s.age}</td>
        <td>${s.score}</td>
    </tr>
    </c:forEach>
优化3:登录拦截
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * 登录拦截请求
 * 未登录 拦截addStudent页面和展示学生页面
 **/
@WebFilter(value = {"/addStudent.jsp","/listStudentServlet"})
public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //1. 将请求和响应对象转化未Http协议相关
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        HttpServletResponse response= (HttpServletResponse) servletResponse;
        //2. 拦截 获取会话域信息 判断用户名
        Object username = request.getSession().getAttribute("username");
        if (username==null||"".equals(username)){
            //重定向到登录页面
            response.sendRedirect(request.getContextPath()+"/login.jsp");
            return;
        }
        //3. 放行
        filterChain.doFilter(request,response);
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }
    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
优化4:

 增加学生页面的请求改为动态虚拟路径
 
 完整代码:
******************首页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
  <title>学生管理系统首页</title>
</head>
<body>
<%--*********************version 1.0--%>
<%--<% Object username = session.getAttribute("username");--%>
<%--  if (username == null) {--%>
<%--%>--%>
<%--<a href="/student/login.jsp">请登录</a>--%>
<%--<%–<%} else {%>–%>--%>
<%--<a href="/student/addStudent.jsp">添加学生</a>--%>
<%--<a href="/student/listStudentServlet">查看学生</a>--%>
<%--<%}%>--%>
<%--************************version 2.0--%>
<c:if test="${sessionScope.username eq null}">
  <a href="${pageContext.request.contextPath}/login.jsp">请登录</a>
</c:if>
<c:if test="${sessionScope.username ne null}">
  <a href="${pageContext.request.contextPath}/addStudent.jsp">添加学生</a>
  <a href="${pageContext.request.contextPath}/listStudentServlet">查看学生</a>
</c:if>
</body>
</html>
******************登录页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>学生登录</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/loginServlet" method="get" autocomplete="off">
  用户名: <input type="text" name="username"><br>
  密码:<input type="password" name="password"><br>
    <button type="submit">登录</button>
</form>
</body>
</html>
******************登录请求处理
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         //获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //判断用户名
        if (username==null||"".equals(username)){
            //用户名为空 重定向到登录界面
            resp.sendRedirect("/student/login.jsp");
            return;
        }
        if (username.equals("zhufanzhi")&&password.equals("123")){
            //不为空  存入会话域
            HttpSession session = req.getSession();
            session.setAttribute("username",username);
            //重定向到首页jsp
            resp.sendRedirect("/student/index.jsp");
        }else {
//            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write("用户名密码错误。请重新登录");
            resp.setHeader("Refresh","2;URL=/student/login.jsp");
            return;
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}
***************************添加学生页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加学生</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/addServlet" method="get" autocomplete="off">
    姓名: <input type="text" name="username"><br>
    年龄:<input type="number" name="age"><br>
    分数:<input type="number" name="score"><br>
    <button type="submit">保存</button>
</form>
</body>
</html>
**************************添加学生请求处理
@WebServlet("/addServlet")
public class addStudent extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取表单数据
        String username = req.getParameter("username");
        String age = req.getParameter("age");
        String score = req.getParameter("score");
        //2. 创建学生对象并赋值
        Student student = new Student(username, Integer.parseInt(age), Integer.parseInt(score));
        //3.将学生对象的数据保存到d:\\stu.txt
        BufferedWriter bw=new BufferedWriter(new FileWriter("d:\\stu.txt",true));
        bw.write(student.getUsername()+","+student.getAge()+","+student.getScore());
        bw.newLine();
        bw.close();
        //4.通过定时刷新功能响应给浏览器
//        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("添加成功。2秒后自动跳转到首页");
        resp.setHeader("Refresh","2;URL=/student/index.jsp");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}
*****************************展示学生页面
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.example.student_manage.bean.Student" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
    <title>查看学生</title>
</head>
<body>
<%--*************************** version 1.0 --%>
<%--<table width="600px" border="1px">--%>
<%--    <tr>--%>
<%--        <th>姓名</th>--%>
<%--        <th>年龄</th>--%>
<%--        <th>成绩</th>--%>
<%--    </tr>--%>
<%-- <%  ArrayList<Student> students= (ArrayList<Student>) session.getAttribute("stus");--%>
<%--   for (Student stu:students ){--%>
<%-- %>--%>
<%--    <tr>--%>
<%--        <td><%=stu.getUsername()%></td>--%>
<%--        <td><%=stu.getAge()%></td>--%>
<%--        <td><%=stu.getScore()%></td>--%>
<%--    </tr>--%>
<%--    <%}%>--%>
<%--</table>--%>
<%--*************************** version 2.0 --%>
<table width="600px" border="1px">
    <tr>
        <th>学生姓名</th>
        <th>学生年龄</th>
        <th>学生成绩</th>
    </tr>
<%--items 中为后端传来的数据  var 代表遍历买一个元素--%>
    <c:forEach items="${stus}" var="s">
    <tr align="center">
        <td>${s.username}</td>
        <td>${s.age}</td>
        <td>${s.score}</td>
    </tr>
    </c:forEach>
</table>
</body>
</html>
*****************************展示学生页面请求处理
import com.example.student_manage.bean.Student;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
@WebServlet("/addServlet")
public class addStudent extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取表单数据
        String username = req.getParameter("username");
        String age = req.getParameter("age");
        String score = req.getParameter("score");
        //2. 创建学生对象并赋值
        Student student = new Student(username, Integer.parseInt(age), Integer.parseInt(score));
        //3.将学生对象的数据保存到d:\\stu.txt
        BufferedWriter bw=new BufferedWriter(new FileWriter("d:\\stu.txt",true));
        bw.write(student.getUsername()+","+student.getAge()+","+student.getScore());
        bw.newLine();
        bw.close();
        //4.通过定时刷新功能响应给浏览器
//        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("添加成功。2秒后自动跳转到首页");
        resp.setHeader("Refresh","2;URL=/student/index.jsp");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}
************************过滤器配置上述



















