12.listener(了解)和filter(掌握)

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>

  

  

  

  

原文地址:https://www.cnblogs.com/syj1993/p/8472357.html

时间: 2024-10-19 10:55:01

12.listener(了解)和filter(掌握)的相关文章

java web.xml listener servlet 和filter的加载顺序

在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关.即不会因为 filter 写在 listener 的前面而会先加载 filter. 最终得出的结论是:listener -> filter -> servlet 同时还存在着这样一种配置节:context-param,它用于向 Servle

Listener监听器与Filter过滤器

1.Listener [1]监听器简介 > Listener是JavaWeb的三大组件之一,Servlet.Filter.Listener > Listener翻译过来就是监听器 > 现实生活中的监听器: - 监听谁:明星 - 监听器:朝阳群众 - 监听事件:干坏事 - 回调函数:报警 > JavaWeb中的监听器: - 监听谁:ServletContext.HttpSession.ServletRequest - 监听器:自己写 - 监听的事件:生命周期.属性的变化 - 回调函数

web.xml之context-param,listener,filter,servlet加载顺序及其周边

先以加载spring为例子看看加载顺序的作用: Spring加载可以利用ServletContextListener 实现,也可以采用load-on-startup Servlet 实现,但比如filter 需要用到 bean ,但加载顺序是: 先加载filter 后加载spring,则filter中初始化操作中的bean为null:所以,如果过滤器中要使用到 bean,此时就可以根据加载顺序listener>filter>servlet,将spring 的加载 改成 Listener的方式.

web.xml 之contextParam,listener,filter,servlet的加载顺序

先以加载spring为例子看看加载顺序的作用: Spring加载可以利用ServletContextListener 实现,也可以采用load-on-startup Servlet 实现,但比如filter 需要用到 bean ,但加载顺序是: 先加载filter 后加载spring,则filter中初始化操作中的bean为null:所以,如果过滤器中要使用到 bean,此时就可以根据加载顺序listener>filter>servlet,将spring 的加载 改成 Listener的方式.

Java web基础总结七之—— Filter与Listener

Java web基础总结七之-- Filter与Listener 一.Filter 1. Filter简介 Filter是Servlet体系中非常重要的一个技术.Filter的意思是过滤器,那么它过滤的是什么呢?就是web服务器管理的所有web资源.例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.它的代码逻辑执行在访问这些资源之前,从而进行一些特殊的操作.例如实现权限访问控制.编码和词汇的过滤等一些高级功能. Servlet API中提供了一

Spring Boot 学习系列(08)—自定义servlet、filter及listener

此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的filter及listener配置 在传统的Java web项目中,servlet.filter和listener的配置很简单,直接在web.xml中按顺序配置好即可,程序启动时,就会按照你配置的顺序依次加载(当然,web.xml中各配置信息总的加载顺序是context-param -> listener -> filter -> servlet),项目搭建完成后,估计一般新来的开发同学没啥

AngularJS 之 过滤器 Filter

一.内置过滤器 1.大小写转换: uppercase.lowercase {{"lower cap string"| uppercase }} {{"Tank Is GOOD"| lowercase}} 2.json格式化(将对象转换成json字符串),默认输出就是json字符串: {{ {name:'zhangsan',age:15} }} {{ {name:'zhangsan',age:15}|json }} 3.number格式化: {{1.2345|numb

[原创]java WEB学习笔记44:Filter 简介,模型,创建,工作原理,相关API,过滤器的部署及映射的方式,Demo

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

javaweb学习总结(四十二)——Filter(过滤器)学习

一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter.通过F