一,Listener 监听器
Javaweb 开发中的监听器,是用于监听 web 常见对象 HttpServletRequest HttpSession ServletContext
监听它们的创建与销毁
,
属性变化
以及 session
绑定
javaBean
1,监听机制
事件 就是一个事情
事件源 产生这个事情的源头
监听器 用于监听指定的事件的对象
注册监听 要想让监听器可以监听到事件产生,必须对其进行注册.
2,Javaweb 开发中常见监听器
2.1,监听域对象的创建与销毁
监听 ServletContext 创建与销毁ServletContextListener
监听 HttpSession 创建与销毁HttpSessionListener
监听 HttpServletRequest 创建与销毁ServletRequestListener
2.2,监听域对象的属性变化
监听 ServletContext 属性变化ServletContextAttributeListener
监听 HttpSession 属性变化HttpSessionAttributeListener
监听 HttpServletRequest 属性变化ServletRequestAttributeListener
2.3,监听 session 绑定 javaBean
它是用于监听
javaBean
对象是否绑定到了
session
域
HttpSessionBindingListener
它是用于监听 javaBean 对象的活化与钝化 HttpSessionActivationListener
3,监听器的快速入门
关于创建一个监听器的步骤
创建一个类,实现指定的监听器接口
重写接口中的方法
在 web.xml 文件中对监听器进行注册.
ServletContext 对象的创建与销毁
3.1,关于域对象创建与销毁的演示
这个对象是在服务器启动时创建的,在服务器关闭时销毁的.
HttpSession 对象的创建与销毁
HttpSession session=request.getSession();
Session 销毁 的方法
默认超时30 分钟
关闭服务器
invalidate() 方法
setMaxInactiveInterval(int interval) 可以设置超时时间
问题
:
直接访问一个
jsp
页面时,是否会创建
session
会创建,因为我们默认情况下是可以在
jsp
页面中直接使用
session
内置对象的.
HttpServletRequest 创建与销毁
Request 对象是发送请求服务器就会创建它,当响应产生时,request 对象就会销毁.
3.2,演示了 Request 域对象中属性变化
在 java 的监听机制中,它的监听器中的方法都是有参数的,参数就是事件对象,而我们可以通过事件对象直接获取事件源.
3.3,演示 session 绑定 javaBean
1,javaBean 对象自动感知被绑定到 session 中.
HttpSessionBindingListener
这个接口是由
javaBean
实现的,并且不需要在
web.xml
文件中注册
.
2,javabean 对象可以活化或钝化到 session 中.
HttpSessionActivationListener 如果 javaBean 实现了这个接口,那么当我们正常关闭服务器时,session 中的 javaBean 对象就会被钝化到我们指定的文件中.
当下一次在启动服务器,因为我们已经将对象写入到文件中,这时就会自动将
javaBean
对象活化到
session
中.
我们还需要个 context.xml 文件来配置钝化时存储的文件
在
meta-inf
目录下创建一个
context.xml
文件
案例 - 定时销毁 session
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="it315"/>
</Manager>
</Context>
1,怎样可以将每一个创建的 session 全都保存起来?
我们可以做一个
HttpSessionListener
,当
session
对象创建时,就将这个
session
对象装入到一个集合中
.
将集合 List 保存到 ServletContext 域中.
2,怎样可以判断 session 过期了
在 HttpSession 中有一个方法 public long getLastAccessedTime()
它可以得到 session 对象最后使用的时间,可以使用 invalidate 方法销毁.
ps(我们上面的操作需要使用任务调度功能.) 在
java
中有一个
Timer
定时器类
关于三个域对象获取
package com.timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TestTimer {
public static void main(String[] args) {
Timer t = new Timer();
t.schedule(new TimerTask() {@Override public void run() {
System.out.println(new Date().toLocaleString());
}
},
2000, 1000);
}
}
如果在
Servlet
中要获取
request
,
在方法上就有,request.getSession() getServletContext();
如果我们有 request 对象了, request.getSession() request.getSession().getServletCotnext();
程序在使用时,需要考虑并发问题, 因为我们在 web 中,它一定是一个多线程的,那么我们的程序对集合进行了添加,还有移除操作.具体在 MyServletContextListener 的方法中如下
public class MySessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent arg0) {
HttpSession session = arg0.getSession();
//得到application中的list集合
ServletContext application = session.getServletContext();
//得到session对象,并放入list集合
List < HttpSession > list = (List < HttpSession > ) application.getAttribute("sessions");
list.add(session);
System.out.println("添加了" + session.getId());
}
public void sessionDestroyed(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}
}
二,Filter
public class MyServletContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {}
public void contextInitialized(ServletContextEvent arg0) {
//通過事件原對象得到事件源
ServletContext application = arg0.getServletContext();
//创建一个集合 存储所有session对象
final List < HttpSession > list = Collections.synchronizedList(new ArrayList < HttpSession > ());
application.setAttribute("sessions", list);
//创建一个计时器对象
Timer t = new Timer();
t.schedule(new TimerTask() {@Override public void run() {
System.out.println("开始扫描");
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
HttpSession session = (HttpSession) iterator.next();
long l = System.currentTimeMillis() - session.getLastAccessedTime();
if (l > 5000) {
System.out.println("session移除了" + session.getId());
session.invalidate();
iterator.remove();
}
}
}
},
2000, 5000);
}
}
二,Filter 过滤器 (重要)
Javaweb 中的过滤器可以拦截所有访问 web 资源的请求或响应操作.
1.1,步骤:
创建一个类实现 Filter 接口
重写接口中方法 doFilter 方法是真正过滤的.
在 web.xml 文件中配置
注意: 在 Filter 的 doFilter 方法内如果没有执行 chain.doFilter(request,response),那么资源是不会被访问到的.
1.2,FilterChain
FilterChain 是 servlet 容器为开发人员提供的对象,它提供了对某一资源的已过滤请求调用链的视图.过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源.
问题: 怎样可以形成一个 Filter 链?
只要多个 Filter 对同一个资源进行拦截就可以形成 Filter 链
问题: 怎样确定 Filter 的执行顺序?
由来确定
1.3,Filter 生命周期
Servlet 生命周期:
实例化 --》 初始化 --》 服务 --》 销毁
1 当服务器启动,会创建 Filter 对象,并调用 init 方法,只调用一次.
2 当访问资源时,路径与 Filter 的拦截路径匹配,会执行 Filter 中的 doFilter 方法,这个方法是真正拦截操作的方法.
3 当服务器关闭时,会调用 Filter 的 destroy 方法来进行销毁操作.
1.4,FilterConfig
在 Filter 的 init 方法上有一个参数,类型就是 FilterConfig.
FilterConfig 它是 Filter 的配置对象,它可以完成下列功能
获取 Filtr 名称
获取 Filter 初始化参数
获取 ServletContext 对象.
问题: 怎样在 Filter 中获取一个 FIlterConfig 对象?
如下 web.xml配置
package com.itheima.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilterConfigTest implements Filter {
private FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
//通过FilterConfig对象获取到配置文件中的初始化信息
String encoding = filterConfig.getInitParameter("encoding");
System.out.println(encoding);
request.setCharacterEncoding(encoding);
//放行
chain.doFilter(request, response);
}
public void destroy() {
// TODO Auto-generated method stub
}
}
1.5,Filter 配置
<filter>
<filter-name>MyFilterConfigTest</filter-name>
<filter-class>com.itheima.filter.MyFilterConfigTest</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFilterConfigTest</filter-name>
<servlet-name>ServletDemo2</servlet-name>
</filter-mapping>
基本配置
<filter>
<filter-name>filter名称</filter-name>
<filter-class>Filter类的包名.类名</filter-class>
<filter-name>filter名称</filter-name>
</filter>
<filter-mapping>
<url-pattern>路径</url-pattern>
</filter-mapping>
关于其它配置
1.<url-pattern>
完全匹配 以 "/demo1" 开始,不包含通配符 *
目录匹配 以 "/" 开始 以 * 结束
扩展名匹配 *.xxx 不能写成 /*.xxx
2.<servlet-name>
它是对指定的 servlet 名称的 servlet 进行拦截的.
3.<dispatcher>
可以取的值有 REQUEST FORWARD ERROR INCLUDE根据跳转方式拦截
它的作用是:当以什么方式去访问 web 资源时,进行拦截操作.
1.REQUEST 当是从浏览器直接访问资源,或是重定向到某个资源时进行拦截方式配置的 它也是默认值
2.FORWARD 它描述的是请求转发的拦截方式配置
3.ERROR 如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用.除此之外,过滤器不会被调用.
4.INCLUDE 如果目标资源是通过 RequestDispatcher 的 include() 方法访问时,那么该过滤器将被调用.除此之外,该过滤器不会被调用
三,自动登录(PS bean 的属性名和数据库里的字段名千万要一样哦 不然会 emmm 很惨)
当用户登陆成功后,判断是否勾选了自动登陆,如果勾选了,就将用户名与密码持久化存储到 cookie
做一个 Filter,对需要自动登陆的资源进行拦截
首写要在登录 Servlet 中登录成功时把登录的信息保存在 cookie 里,并设置存活时间
然后设置好 filter 类 记住要在 web.xml 里面配置如下 为 doFilter 代码
if (null != user) {
String autologin = request.getParameter("autologin");
Cookie cookie = new Cookie("user", user.getUsername() + "&" + user.getPassword());
cookie.setPath("/");
if (autologin != null) { // on / null
cookie.setMaxAge(60 * 60 * 24 * 7);
} else {
cookie.setMaxAge(0);
}
response.addCookie(cookie);
request.getSession().setAttribute("user", user);
request.getRequestDispatcher("/home.jsp").forward(request, response);
}
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException,
ServletException {
//1,转换对象
HttpServletRequest req = (HttpServletRequest) arg0;
//2,处理业务
Cookie[] cookies = req.getCookies();
String username = "";
String password = "";
for (int i = 0; cookies != null && i < cookies.length; i++) {
if ("user".equals(cookies[i].getName())) {
String value = cookies[i].getValue();
String[] values = value.split("&");
username = values[0];
password = values[1];
}
}
UserService us = new UserService();
User user = us.findUser(username, password);
if (user != null) {
req.getSession().setAttribute("user", user);
}
//3,放行
arg2.doFilter(arg0, arg1);
}
来源: https://www.cnblogs.com/lzhh/p/javaweb_0.html