监听器html
监听某一个事件的发生。 状态的改变。java
其实就是接口回调.web
A在执行循环,当循环到5的时候, 通知B。数据库
事先先把一个对象传递给 A , 当A 执行到5的时候,经过这个对象,来调用B中的方法。 可是注意,不是直接传递B的实例,而是传递一个接口的实例过去。apache
总共有8个 划分红三种类型浏览器
定义一个类,实现接口tomcat
注册 | 配置监听器服务器
request ---httpServletRequest session ---httpSession aapplication --- ServletContext 1. ServletContextListener servletcontext建立: 1. 启动服务器的时候 servletContext销毁: 2. 关闭服务器. 从服务器移除项目 2. ServletRequestListener request建立: 访问服务器上的任意资源都会有请求出现。 访问 html: 会 访问 jsp: 会 访问 servlet : 会 request销毁: 服务器已经对此次请求做出了响应。 public class MyRequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("servletrequest 销毁了"); } @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("servletrequest 初始化了"); } } <listener> <listener-class>com.itheima.listener.MyRequestListener</listener-class> </listener> 3. HttpSessionListener session的建立 只要调用getSession html: 不会 jsp: 会 getSession(); servlet: 会 session的销毁 超时 30分钟 非正常关闭 销毁 正常关闭服务器(序列化) public class MySessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("建立session了"); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("销毁session了"); } }
做用:cookie
ServletContextListener 利用它来,在servletcontext建立的时候, 1. 完成本身想要的初始化工做 2. 执行自定义任务调度。 执行某一个任务。 Timer HttpSessionListener 统计在线人数.
能够监听在做用域中值 添加 | 替换 | 移除的动做。session
servletContext --- ServletContextAttributeListener
request --- ServletRequestAttributeListener
session --- HttpSessionAttributeListener
这一类监听器不用注册。
监听对象与session 绑定和解除绑定 的动做
1. 让javaBean 实现该接口便可 @Override public void valueBound(HttpSessionBindingEvent event) { System.out.println("对象被绑定进来了"); } @Override public void valueUnbound(HttpSessionBindingEvent event) { System.out.println("对象被解除绑定"); }
用于监听如今session的值 是 钝化 (序列化)仍是活化 (反序列化)的动做
把内存中的数据 存储到硬盘上
把硬盘中的数据读取到内存中。
session中的值可能会不少, 而且咱们有很长一段时间不使用这个内存中的值, 那么能够考虑把session的值能够存储到硬盘上【钝化】,等下一次在使用的时候,在从硬盘上提取出来。 【活化】
作配置便可
1. 在tomcat里面 conf/context.xml 里面配置 对全部的运行在这个服务器的项目生效 2. 在conf/Catalina/localhost/context.xml 配置 对 localhost生效。 localhost:8080 3. 在本身的web工程项目中的 META-INF/context.xml 只对当前的工程生效。 maxIdleSwap : 1分钟不用就钝化 directory : 钝化后的那个文件存放的目录位置。 D:\tomcat\apache-tomcat-7.0.52\work\Catalina\localhost\ListenerDemo\itheima <Context> <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"> <Store className="org.apache.catalina.session.FileStore" directory="itheima"/> </Manager> </Context>
过滤器 , 其实就是对客户端发出来的请求进行过滤。 浏览器发出, 而后服务器派servlet处理。 在中间就能够过滤, 其实过滤器起到的是拦截的做用。
做用
...
定义一个类, 实现Filter
public class FilterDemo implements Filter { 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.itheima.filter.FilterDemo</filter-class> </filter> <filter-mapping> <filter-name>FilterDemo</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
在服务器启动的时候就建立。
服务器中止的时候。
客户端发出请求,先通过过滤器, 若是过滤器放行,那么才能到servlet
若是有多个过滤器, 那么他们会按照注册的映射顺序 来 排队。 只要有一个过滤器, 不放行,那么后面排队的过滤器以及我们的servlet都不会收到请求。
init方法的参数 FilterConfig , 能够用于获取filter在注册的名字 以及初始化参数。 其实这里的设计的初衷与ServletConfig是同样的。
若是想放行,那么在doFilter 方法里面操做,使用参数 chain
chain.doFilter(request, response); 放行, 让请求到达下一个目标。
<url-pattern>/*</url-pattern> 写法格式与servlet同样。
全路径匹配 以 / 开始
/LoginServlet
以目录匹配 以 / 开始 以 * 结束
/demo01/*
之后缀名匹配 以 * 开始 之后缀名结束
*.jsp *.html *.do
针对 dispatcher 设置
REQUEST : 只要是请求过来,都拦截,默认就是REQUEST FORWARD : 只要是转发都拦截。 ERROR : 页面出错发生跳转 INCLUDE : 包含页面的时候就拦截。
搭建数据库
搭建页面
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { String userName = request.getParameter("username"); String password = request.getParameter("password"); String autoLogin = request.getParameter("auto_login"); UserBean user = new UserBean(); user.setUsername(userName); user.setPassword(password); UserDao dao = new UserDaoImpl(); UserBean userBean = dao.login(user); if(userBean != null){ //成功了,进入首页 request.getSession().setAttribute("userBean", userBean); response.sendRedirect("index.jsp"); }else{ //不成功... request.getRequestDispatcher("login.jsp").forward(request, response); } } catch (SQLException e) { e.printStackTrace(); } }
过滤器的核心不是完成拦截不给 , 仍是放行显示。 它的核心是在放行以前,帮用户完成登陆的功能。
实现思路
先判断session是否有效, 若是有效,就不用取cookie了,直接放行。
若是session失效了,那么就取 cookie。
没有cookie 放行
有cookie
1. 取出来cookie的值,而后完成登陆 2. 把这个用户的值存储到session中 3. 放行。 /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { HttpServletRequest request = (HttpServletRequest) req; //先判断,如今session中还有没有那个userBean. UserBean userBean = (UserBean) request.getSession().getAttribute("userBean"); //还有,有效。 if(userBean != null){ chain.doFilter(request, response); }else{ //表明session失效了。 //2. 看cookie。 //1. 来请求的时候,先从请求里面取出cookie , 可是cookie有不少的key-value Cookie[] cookies = request.getCookies(); //2. 从一堆的cookie里面找出咱们之前给浏览器发的那个cookie Cookie cookie = CookieUtil.findCookie(cookies, "auto_login"); //第一次来 if(cookie == null){ chain.doFilter(request, response); }else{ //不是第一次。 String value = cookie.getValue(); String username = value.split("#itheima#")[0]; String password = value.split("#itheima#")[1]; //完成登陆 UserBean user = new UserBean(); user.setUsername(username); user.setPassword(password); UserDao dao = new UserDaoImpl(); userBean = dao.login(user); //使用session存这个值到域中,方便下一次未过时前还能够用。 request.getSession().setAttribute("userBean", userBean); chain.doFilter(request, response); } } } catch (Exception e) { e.printStackTrace(); chain.doFilter(req, response); } }
BeanUtils.populate(bean, map);
//注册本身的日期转换器 ConvertUtils.register(new MyDateConverter(), Date.class); //转化数据 Map map = request.getParameterMap(); UserBean bean = new UserBean(); 转化map中的数据,放置到bean对象身上 BeanUtils.populate(bean, map);
8个 三种类型 针对三个做用域的建立和销毁 针对三个做用域的值改变 【添加 | 替换 | 移除】 针对session中的值 【钝化 活化】 , 【绑定 解绑】 钝化 ( 序列化 ) 内存中的对象存储到硬盘 超时失效。 session销毁了。 非正常关闭服务器, 钝化 。 正常关闭服务器 销毁 设置了session,多久时间。 context.xml 活化 (反序列化) 从硬盘里面读取到内存
ServletContextListner : 应用被部署的时候, 服务器加载这个项目的时候,作一些初始化工做, 任务调度。 HttpSessionListener : 统计在线人数 HttpSessionActivationListener : 钝化活化处理
使用频率更高
定义一个类,实现接口 Filter
注册 . web.xml . 与servlet类似。
chain.doFilter(request, response);
过滤器生命周期
建立: 服务器加载这个项目的时候建立实例
销毁: 关闭服务器或者从服务器中移除项目的时候。
package com.itheima.test; /** * 1988年写 * @author xiaomi * */ public class A { public void print(B b){ for (int i = 0; i < 10; i++) { System.out.println("循环到了--"+i); if(i == 5){ System.out.println("循环到了5了,该通知B 了。"); B b = new B(); b.printFive(); } } } }
package com.itheima.test; public class B { public void printFive(){ System.out.println("A已经循环到了5, 因此B的这个方法将被调用"); } }
package com.itheima.test; public class Test { public static void main(String[] args) { A a = new A(); a.print(); } }
package com.itheima.test; /** * 1988年写的 * @author xiaomi * */ public class A { /** * 这是之前的java基础使用的代码。 * 可是假设这个A这个类是早在上个世纪80年 就写好的A类, 这个方法 内部是不能直接new B() * 1. 不能直接new B * * 2. 页不能传递B的实例进来。 * * 因此在定义这个方法的时候,无论将来写的是B 类, 仍是C类,仍是D类, 人家为了通用。 * 因此定义了一种接口,只要让将来的那些类,实现这个接口。 而后这个方法的参数写 接口类型便可。 */ /*public void print(){ for (int i = 0; i < 10; i++) { System.out.println("循环到了--"+i); if(i == 5){ System.out.println("循环到了5了,该通知B 了。"); B b = new B(); b.printFive(); } } }*/ public void print(PrintListener listener){ for (int i = 0; i < 10; i++) { System.out.println("我在1988年就开始打印这个语句了。。循环到了--"+i); if(i == 5){ System.out.println("循环到了5了,该通知B 了。"); listener.print(); /*B b = new B(); b.printFive();*/ } } } }
package com.itheima.test; /** * 2018 * @author xiaomi * */ public class B implements PrintListener{ /*public void printFive(){ System.out.println("A已经循环到了5, 因此B的这个方法将被调用"); }*/ @Override public void print() { System.out.println("2018年。。。A已经循环到了5, 因此B的这个方法将被调用"); } }
package com.itheima.test; /** * 1988年写 * 打印监听器 * @author xiaomi * */ public interface PrintListener { /** * 一旦出现了某一种事件, 达到了某一个状态,就调用这个方法。 */ void print(); }
package com.itheima.test; public class Test { public static void main(String[] args) { A a = new A(); //这是多态的体现, /* * 这个方法咋i1988年就定义了要收 printlistener 这个接口的类型。 * 在2018年的时候有一个类 B 实现了这个接口printlistener , * 因此如今能够传递B进来 */ a.print(new B()); } }