Listener和Filter

Listener

监听器
  • 监听某一个时间,状态的改变。

  • 监听器的内部机制就是接口回调

接口回调
  • 需求
    案例:
//老程序
public class A {
	public void println(PrintListener listener) {//传递接口实例
		for(int i = 0; i < 10; i++) {
			System.out.println("老程序循环到了" + i);
			if(5 == i) {
				System.out.println("老程序可以通知调用者");
				listener.print();
			}
		}
	}
}

接口:

public interface PrintListener {
	void print();
}

新程序:

//谁调用老程序,谁实现这个接口
public class B implements PrintListener{
	public void printFive() {
		System.out.println("老的程序A已经循环到了5,B执行这个方法");
	}

	@Override
	public void print() {
		this.printFive();
	}
}

测试:

public static void main(String[] args) {
		A a = new A();
		a.println(new B());
}
web监听器
  • 总共有8个,分三种类型
监听三个作用域创建和销毁
	pageContext
	request	httpServletRequest
	session	httpSession
	application	servletContext

	(1)ServletContextListener	
		ServletContext的创建:
			启动Tomcat服务器的时候
			
		ServletContext的销毁
			关闭服务器,从服务器移除出去
			
		xml中的配置:
		<listener>
			 <listener-class>com.lxr.MyServletContextListener</listener-class>
	    </listener>
	    
		ServletContextListener	作用:
			在ServletContextListener创建的时候
			完成自己想要初始化的工作;
			执行自定义任务调度


	(2)ServletRequestListener
		request的创建:
			访问服务器上任何资源的时候都会有请求
			html、jsp、servlet
			
		request的销毁:
			服务器已经对该请求做出来响应


	(3)HttpSessionListener
		session的创建:
			只要调用getSession();
			HTML 不会
			jsp、servlet会
			
		session的销毁:
			超时(30min)
			正常关闭服务器序列化
			非正常关闭销毁
			
		HttpSessionListener作用:
			统计在线人数
监听三个作用域属性状态变更

request ServletRequestAttributeListener
session HttpSessionAttributeListener
servletContext ServletContextAttributeListener
监听作用域中属性的添加、移除、替换

<body>
	<%
	session.setAttribute("name", "zahngsan");//属性添加
	session.setAttribute("name", "lisi");//属性替换
	session.removeAttribute("name");//属性移除
	%>
</body>
监听HttpSession里面存值的状态变更

不用注册

  • HttpSessionBindingListener
    让Javabean实现该接口
public class Bean1 implements HttpSessionBindingListener{
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public void valueBound(HttpSessionBindingEvent arg0) {
		System.out.println("值被绑定");
	}
	@Override
	public void valueUnbound(HttpSessionBindingEvent arg0) {
		System.out.println("解除绑定");
	}
}

jsp部分:

Bean1 b = new Bean1();
b.setName("zhangsan");
session.setAttribute("bean", b);
session.removeAttribute("bean");

结果:

值被绑定
session属性被添加
解除绑定
session属性被移除
  • HttpSessionActivationListener

    用于监听session的值是钝化(序列化)还是活化(反序列化)

  1. 钝化(序列化)

    把内存中数据存放在硬盘上

  2. 活化(反序列化)

    把硬盘上的数据读取到内存里

  • session的钝化活化的意义:
    session中的值可能很多,有很长时间一直没用内存中这个值,内存有压力,我们考虑把session的值存放在硬盘上,等下一次再使用,再从硬盘提取出来(活化)
  • 让session值在一定时间内钝化:
    做配置:
  1. 在Tomcat里的conf/context.xml中做配置

    对所有运行在这个服务器的项目生效

  2. 在conf\Catalina\localhost中做配置

    对localhost生效

  3. 在web项目下的META-INF中context.xml配置

    只对当前工程生效

    <context>
    <!-- maxIdleSwap表示1分钟不用后就钝化, directory是钝化后的文件存放的目录位置-->
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
    	<Store className="org.apache.catalina.session.FileStore" directory="lxrContent"/>
    </Manager>
    
```

Filter

过滤器就是对客户端发来的请求过滤。浏览器发出,servlet处理,filter在这中间进行过滤拦截。

 作用:
	1. 对敏感词汇过滤
	2. 统一设置编码
	3. 自动登录等

如何使用Filter

  • 定义一个类实现Filter
public class FilterDemo implements Filter {
    public FilterDemo() {
    }
	public void destroy() {
	}
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("来到过滤器了");
		chain.doFilter(request, response);
	}
	public void init(FilterConfig fConfig) throws ServletException {
	}
}
  • 注册过滤器
    在web.xml中注册,方法与servlet类似
<filter>
  	<display-name>filterDemo</display-name>
  	<filter-name>filterDemo</filter-name>
  	<filter-class>com.lxr.FilterDemo</filter-class>
 </filter>
 <filter-mapping>
 	<filter-name>filterDemo</filter-name>
	<url-pattern>/*</url-pattern>
 </filter-mapping>

有关Filter的细节

  • <url-pattern>/*</url-pattern>类似servlet
  1. 全路径匹配,以/开始
    /login
  2. 以目录匹配 /开始,*结束
    /demo1/*
  3. 以后缀名匹配,*开始,后缀名结束
    *.jsp、*.html
  • init方法的参数FilterConfig获取Filter在注册时候的名字和初始化参数
public void init(FilterConfig fConfig) throws ServletException {
	System.out.println("过滤器创建");
	System.out.println("Filter在注册时的名字:" + fConfig.getFilterName());
	System.out.println("初始化的参数" + fConfig.getInitParameterNames());
}
  • 针对dispatcher的设置

      REQUEST	只要是请求过来都拦截,默认就是REQUEST
      FORWARD	只要是转发都拦截
      ERROR	页面出错发生跳转
      INCLUDE	包含页面的时候就跳转
    

Filter生命周期

  • Filter的创建

       在服务器启动时创建
    
  • Filter的销毁

Filter执行顺序

过滤器1:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("来到过滤器1了before");
	//如果想放行,就使用chain参数
	chain.doFilter(request, response);
	System.out.println("来到过滤器1了after");
}

过滤器2:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
	System.out.println("来到过滤器2 before");
	chain.doFilter(request, response);
	System.out.println("来到过滤器2了 after");
}

结果:

来到过滤器1了before
来到过滤器2 before
来到过滤器2了 after
来到过滤器1了after

自动登录范例

准备好JDBCUtils和c3p0-config.xml,以及必要的jar包

  • 搭建数据库
public class UserDaoImpl implements UserDao{
	@Override
	public UserBean login(UserBean user) throws SQLException{
		QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
		String sql = "select * from tb_user where username=? and password=?";
		return (UserBean) runner.query(sql, new BeanHandler<UserBean>(UserBean.class), user.getUsername(), user.getPassword());
	}
}
  • UserBean:
private String username;
private String password;
  • LoginServlet:
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		String autoLogin = req.getParameter("autoLogin");//自动登录是否勾选
		UserBean user = new UserBean();
		user.setPassword(password);
		user.setUsername(username);
		UserDao dao = new UserDaoImpl();
		try {
			UserBean userBean = dao.login(user);
			if(null != userBean) {//用户名密码正确
				//选择自动登录
				if("on".equals(autoLogin)) {//勾选了自动登录,需要让服务器生成cookie
					//发送cookie给客户端
					Cookie cookie = new Cookie("autoLogin", username + "#" + password);
					cookie.setMaxAge(60 * 60 * 24 * 7);//一周有效
					cookie.setPath(req.getContextPath());//针对当前这个项目有效
					resp.addCookie(cookie);
				}
				HttpSession session = req.getSession();
				session.setAttribute("userBean", user);
				req.getRequestDispatcher("index.jsp").forward(req, resp);
			}else {//用户名或密码错误重新登陆
				req.getRequestDispatcher("login.jsp").forward(req, resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}
  • CookieUtils:
public class CookieUtils {//从众多cookie中找到需要的cookie
	public static Cookie findCookie(Cookie[] cookies, String name) {
		if(null != cookies) {
			for (Cookie cookie : cookies) {
				if(name.equals(cookie.getName())) {
					return cookie;
				}
			}
		}
		return null;
	}
}
  • AutoLoginFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
	HttpServletRequest req = (HttpServletRequest) request;
	UserBean userBean = (UserBean) req.getSession().getAttribute("userBean");
	if(null != userBean) {//没有过期,直接放行,不考虑自动登录
		chain.doFilter(request, response);
	}else {//过期了
		Cookie[] cookies = req.getCookies();
		Cookie cookie = CookieUtils.findCookie(cookies, "autoLogin");
		if(null == cookie) {//第一次来,放行,让它去登录
			chain.doFilter(request, response);
		}else {//勾选了自动登录,且没有失效
			String value = cookie.getValue();
			String username = value.split("#")[0];
			String password = value.split("#")[1];
			UserBean user = new UserBean();
			user.setUsername(username);
			user.setPassword(password);
			UserDao dao = new UserDaoImpl();
			try {
				userBean = dao.login(user);
				req.getSession().setAttribute("userBean", userBean);
			} catch (Exception e) {
				e.printStackTrace();
			}
			chain.doFilter(request, response);
		}
	}
}
  • index.jsp:
<body>
	<c:if test="${not empty userBean }">
		<h1>这是首页,欢迎用户${userBean.username }登陆</h1>
	</c:if>
	<c:if test="${empty userBean }">
		<h1>你好,请先登录再访问</h1>
	</c:if>
</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值