【13 Listener 学习笔记】
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创建的时候执行*/@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("监听到了对象创建");//获取对象ServletContext servletContext = sce.getServletContext();System.out.println(servletContext);}/* @Description ServletContext 销毁的时候执行*/@Overridepublic 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创建的时候执行*/@Overridepublic 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 销毁的时候执行*/@Overridepublic 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 {//添加属性时候的监听@Overridepublic void attributeAdded(ServletContextAttributeEvent event) {System.out.println("监听到了属性的添加...");//获取应用域对象Object username = event.getServletContext().getAttribute("username");System.out.println(username);}//移除属性时候的监听@Overridepublic void attributeRemoved(ServletContextAttributeEvent event) {System.out.println("监听到了属性的移除...");//获取应用域对象Object username = event.getServletContext().getAttribute("username");System.out.println(username);}//替换属性时候的监听@Overridepublic 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 {@Overrideprotected 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);//重定向到首页jspresp.sendRedirect("/student/index.jsp");}else {resp.setContentType("text/html;charset=UTF-8");resp.getWriter().write("用户名密码错误。请重新登录");resp.setHeader("Refresh","2;URL=/student/login.jsp");return;}}@Overrideprotected 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;@Overridepublic 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 {@Overrideprotected 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 100Student 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");}@Overrideprotected 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 {@Overrideprotected 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 100Student 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");}@Overrideprotected 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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic 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);}@Overridepublic 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 {@Overridepublic 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);}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic 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 {@Overrideprotected 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);//重定向到首页jspresp.sendRedirect("/student/index.jsp");}else {
// resp.setContentType("text/html;charset=UTF-8");resp.getWriter().write("用户名密码错误。请重新登录");resp.setHeader("Refresh","2;URL=/student/login.jsp");return;}}@Overrideprotected 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 {@Overrideprotected 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.txtBufferedWriter 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");}@Overrideprotected 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 {@Overrideprotected 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.txtBufferedWriter 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");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doGet(req, resp);}
}
************************过滤器配置上述