Listener:
### 监听器(了解) ###
----------
**监听器的概述**
1.概述:监听器是一个Java的类,监听另一个Java类状态的改变。
2.监听器的概念
* 事件源 -- 被监听的对象(电动车)
* 监听器 -- 监听的对象(报警器)
* 绑定监听器 -- 在被监听的对象上,注册一个监听器(在电动车上安装报警器)
* 事件 -- 一旦事件源的状态发生了改变,创建一个事件的对象,传递给监听器的对象,监听器对象中的某一个方法就会执行了。
* 一旦电动车被踢了,产生一个事件的对象,传递给报警器,报警器就响了!!
* 事件对象的作用:在监听器中可以通过事件对象获取到事件源的对象。
----------
### WEB的监听器 ###
----------
**WEB开发中的监听器**
1.WEB中学习监听器特点
* 事件源都已经规定好:监听3个域对象(ServletContext session request)
* 监听器:需要咱们自己来编写(SUN公司已经提供对应的接口,实现这些接口,重写方法就可以了!!)
* 绑定监听器:需要提供一段配置文件
* 事件:事件源的状态发生改变,产生事件对象,传递给监听器对象。
* 总结
* 接口和方法
* 绑定监听器(配置文件怎么编写)
2.编写监听器和完成监听器的配置
3.监听器的种类
* 第一类监听器:监听三个域对象的创建和销毁
* 这3个域对象什么时候创建和销毁?
* 第二类监听器:监听三个域对象中的属性状态的改变
* 注意;上两类监听器需要完成配置文件
* 第三类监听器:只监听HttpSession域对象中JavaBean状态的改变的
* 只监听session对象
* 只监听session对象中的JavaBean
* 最后一类监听器不需要配置文件的
----------
**WEB监听器的开发步骤**
0.目的:监听ServletContext域对象的创建和销毁?
1.编写一个类,实现指定的监听器的接口,实现接口方法。
2.需要配置文件,在web.xml中进行编写。
<listener>
<listener-class>包名+类名</listener-class>
</listener>
3.总结
* 编写监听器的对象(实现特点的接口)
* 提供配置文件(某个域对象创建了,哪个方法执行呢?)
----------
### 第一类:监听三个域对象的创建和销毁 ###
----------
**ServletContextListener监听器**
1.第一个监听器是监听ServletContext对象的创建和销毁?
* ServletContext什么时候创建?什么时候销毁?
* 与天地同寿!!
* 服务器一启动的时候,创建了ServletContext对象。停止服务器的时候,或者移除项目的时候,ServletContext销毁。
2.实现接口,ServletContextListener接口。
* void contextInitialized(ServletContextEvent sce) -- ServletContext对象创建的时候,该方法就会执行
* void contextDestroyed(ServletContextEvent sce) -- ServletContext销毁的时候就会执行
3.启动服务器的时候,ServletContext域对象被创建了,状态发生了改变,产生一个事件对象,传递给监听器的对象,监听器对象中某个方法就会执行了。
4.应用
* 目的:在启动服务器的时候,更容易去操作ServletContext域对象中。
* 来操作ServletContext域对象
* 以前在页面中,每次编写连接
* ${pageContext.request.contextPath} -- 获取项目的名称
----------
**HttpSessionListener监听器**
1.方法:
* void sessionCreated(HttpSessionEvent se)
* void sessionDestroyed(HttpSessionEvent se)
2.session什么时候创建和销毁呢?
* request.getSession()第一次执行的时候,创建session。
* 销毁
* session有默认销毁的时间(在web.xml中配置和方法)
* 非正常原因关闭服务器(如果是正常关闭服务器,session没有销毁,序列化到磁盘上)
* 调用void invalidate() 方法销毁session
3.访问JSP程序会创建session吗(会)?访问Servlet会吗(不一定)?访问HTML会吗(肯定不)?
----------
**ServletRequestListener监听器**
1.ServletRequest什么时候创建呢?什么销毁?
* 只要有请求,创建一个request对象,请求结束,request对象就销毁了。
2.方法
* void requestInitialized(ServletRequestEvent sre) -- 请求一创建,方法执行
* void requestDestroyed(ServletRequestEvent sre) -- 请求结束了,方法执行
3.编写一个类,实现ServletRequestListener,重写2个方法。在web.xml中进行配置。
----------
### 第二类:监听三个域对象中的属性状态的改变 ###
----------
**ServletContextAttributeListener监听器**
1.监听ServletContext域对象中的属性的状态的改变
2.方法
* void attributeAdded(ServletContextAttributeEvent scab) -- 向ServletContext对象存入值,方法执行
* void attributeRemoved(ServletContextAttributeEvent scab) -- 从ServletContext对象移除值,方法执行
* void attributeReplaced(ServletContextAttributeEvent scab) -- 向ServletContext对象覆盖值,方法执行
----------
**HttpSessionAttributeListener监听器**
1.监听HttpSession域对象中是属性的状态的改变
2.方法
* void attributeAdded(HttpSessionBindingEvent se) -- 向session中存入值,方法执行。
* void attributeRemoved(HttpSessionBindingEvent se) -- 向session中移除值,方法执行。
* void attributeReplaced(HttpSessionBindingEvent se) -- 向session中覆盖值,方法执行。
----------
**ServletRequestAttributeListener监听器**
1..监听ServletRequest域对象中是属性的状态的改变
2.方法
* void attributeAdded(ServletRequestAttributeEvent srae) -- 向request中存入值,方法执行。
* void attributeRemoved(ServletRequestAttributeEvent srae) -- 向request中存入值,方法执行。
* void attributeReplaced(ServletRequestAttributeEvent srae) -- 向request中存入值,方法执行。
----------
### 第三类:监听HttpSession域对象中JavaBean状态的改变的 ### (XXXXXXXXXXXXXXXX未)
----------
**监听HttpSession中的JavaBean状态的改变**
1.监听器是监听HttpSession域对象的。
2.操作的都是JavaBean,以后如果使用第三类监听器,那么JavaBean需要实现对应的接口。
3.在web.xml不需要进行配置(编写JavaBean类的实现监听器的接口)
4.HttpSessionBindingListener
* void valueBound(HttpSessionBindingEvent event) -- 把JavaBean保存到session中(绑定)
* void valueUnbound(HttpSessionBindingEvent event) -- 把JavaBean从session中移除(解除绑定)
5.HttpSessionActivationListener(完成钝化(序列化到磁盘上)和活化(反序列化))
* void sessionDidActivate(HttpSessionEvent se) -- 活化
* void sessionWillPassivate(HttpSessionEvent se) -- 钝化
6.好处:对session机制的优化!!
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="itcast"/>
</Manager>
</Context>
7.配置文件中的属性信息
* maxIdleSwap="1" -- 1分钟如果不操作,把session进行钝化
* directory="itcast" -- 保存到哪个目录下。
Filter:
1.解决中文 乱码问题
login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>登录页面</h3>
<form action="${ pageContext.request.contextPath }/login" method="post">
用户名:<input type="text" name="username" />
<input type="submit" value="提交" />
</form>
</body>
</html>
LoginFilter:
public class LoginFilter implements Filter{
public void destroy() {
}
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
arg0.setCharacterEncoding("utf-8");
arg2.doFilter(arg0, arg1);
}
public void init(FilterConfig arg0) throws ServletException {
}
}
LoginServlet:
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//接收请求的参数
String username=request.getParameter("username");
System.out.println(username);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.自动登录问题:
login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>登录页面</h3>
<font color="red">${msg }</font>
<form action="${pageContext.request.contextPath }/user" method="post">
用户名:<input type="text" name="username"/></br>
密 码:<input type="password" name="password"/></br>
<input type="checkbox" name="auto_login" value="login_ok"/>自动登录</br>
<input type="submit" value="登录">
</form>
</body>
</html>
UserServlet:
public class UserServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收用户名和密码
String username=request.getParameter("username");
String password=request.getParameter("password");
UserDao dao=new UserDao();
//登录的功能
User existUser=dao.login(username, password);
//如果返回Null,说明输入错误,不匹配
if(existUser==null){
request.setAttribute("msg","用户名或者密码错误");
request.getRequestDispatcher("/demo2/login.jsp").forward(request, response);
}else{
//判断,用户是否勾选了自动登录的功能。如果勾选了,会写cookie
String auto_login=request.getParameter("auto_login");
if("login_ok".equals(auto_login)){
//说明勾选了
//cookie不能存中文
Cookie cookie=new Cookie("autoLogin",username+"-"+password);
//设置有效时间
cookie.setMaxAge(60*60);
//设置有效路径
cookie.setPath("/");
//回写cookie
response.addCookie(cookie);
}
//登陆成功,把用户信息保存到session中
request.getSession().setAttribute("existUser", existUser);
response.sendRedirect(request.getContextPath()+"/demo2/home.jsp");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
UserDao:
public class UserDao {
/**
* 登录
* @param username
* @param password
* @return
*/
public User login(String username,String password){
QueryRunner runner=new QueryRunner(MyJdbcUtils.getDataSource());
String sql="select * from t_user where username= ? and password = ? ";
try {
return runner.query(sql,new BeanHandler<User>(User.class),username,password);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
UserFilter:
public class UserFilter implements Filter{
/**
* 每次拦截,都会执行
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
/**
* 1.先获取session,从session中获取existUser
* 如果获取到existUser,说明现在就是登录状态
* 如果获取不到existUser,说明不是登录状态
* 2.获取指定cookie
* 如果获取不到cookie,说明用户根本没保存过cookie,不想做自动登录的功能,放行
* 如果获取到cookie,说明用户保存过cookie,想做自动登录的功能,就帮他做这个功能
* 3.获取cookie中的用户名和密码。根据用户名和密码查询数据库
* 没查询到用户,说明用户名或者密码错误,不能做自动登录。放行
* 查询到用户,说明用户名和密码是正确的。把查询到的用户存入session中,session.setAttribute("existUser",user),放行
*/
//1.先获取session
HttpServletRequest req=(HttpServletRequest) request;
HttpSession session = req.getSession();
//获取用户
User user=(User) session.getAttribute("existUser");
//如果用户不为空,登录状态
if(user!=null){
chain.doFilter(req, response);
}else{
//用户为空,不是登录状态,获取cookie
Cookie[] cookies=req.getCookies();
//根据指定的名称查找cookie
Cookie cookie=CookieUtil.getCookieByName(cookies, "autoLogin");
//没找到,用户没选自动登录
if(cookie==null){
chain.doFilter(req, response);
}else{
//找到cookie,用户点了自动登录
//获取cookie中保存的用户名和密码
String username=cookie.getValue().split("-")[0];
String password=cookie.getValue().split("-")[1];
//数据库中查询
UserDao dao=new UserDao();
//登录的功能
User existUser=dao.login(username, password);
if(existUser==null){
//说明用户名或者密码错误
chain.doFilter(req, response);
}else{
//找到了
session.setAttribute("existUser", existUser);
chain.doFilter(req, response);
}
session.setAttribute("existUser", existUser);
chain.doFilter(req, response);
}
}
}
public void destroy() {
}
public void init(FilterConfig arg0) throws ServletException {
}
}
CookieUtil:
public class CookieUtil {
/**
* 通过名称,从数组中查找cookie
* @param cookies
* @param cookieName
* @return
*/
public static Cookie getCookieByName(Cookie[] cookies,String cookieName){
//判断,如果cookies数组Null
if(cookies==null){
return null;
}else{
for(Cookie cookie:cookies){
//根据传入的名称和cookie的名称对比
if(cookie.getName().equals(cookieName)){
return cookie;
}
}
}
return null;
}
}
home.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>门户网站的LOGO</h3>
<h4>
<c:if test="${not empty existUser }">
<h4>欢迎您:${existUser.nickname }</h4>
</c:if>
<c:if test="${empty existUser }">
<h4>
<a href="${pageContext.request.contextPath}/demo2/login.jsp">请登录</a>
</h4>
</c:if>
</h4>
<h4>出轨了</h4>
<h4>进去了</h4>
</body>
</html>