一:Session管理:
必要性:
http 是无状态的,在默认的情况下Web服务器是不知道一个Http请求是来自初次用户,还是来自之前已经访问过的用户。所以就当用户登入后是没必要再次登入。应用程序需要记住哪些用户是登入过的。
保持状态的4种方法:
1、URL重写:Session的追踪技术,需要将一个或者多个的token作为一个查询字符串添加到一个URL中。
2、隐藏域:将值保存在HTML页面的隐藏域中当用户提交表单时,隐藏域中的值也传送到服务器中。
3、cookie:cookie是作为Http标头嵌入的,所以传输过程是Http协议处理的当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中。服务端通过这种方式来获取用户的信息。但是用户可以通过修改浏览器设置来拒绝接受Cookie。
4、HttpSession:HttpSession 保存的值不发送到客户端,Servelt容器会为它创建一个唯一的表识符,并将这个表识符作为token发送给浏览器,一般是作为一个JSESSIONID的cookie,或者作为一个jsessionid参数添加到URL后面。后续请求浏览器会将这个token发送回服务器。
二:Servlet的监听器
三个不同级别的监听对象:ServletContext、HttpSession、ServletRequest
ServletContext的监听器:
1、ServletContextListener:能监听ServletContext一生中的两个关键事件:初始化(创建)和撤销;
public interface ServletContextListener extends EventListener {
//ServletContext初始化时调用
public void contextInitialized(ServletContextEvent sce);
//ServletContext被撤销时调用
public void contextDestroyed(ServletContextEvent sce);
}
//事件
public class ServletContextEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;
public ServletContextEvent(ServletContext source) {
super(source);
}
public ServletContext getServletContext() {
return (ServletContext) super.getSource();
}
}
2、ServletContextAttributeListener:当ServletContext范围内的属性被添加删除,替换时,这些对应的监听器将会被触发。
public interface ServletContextAttributeListener extends EventListener {
//添加
public void attributeAdded(ServletContextAttributeEvent scae);
//删除
public void attributeRemoved(ServletContextAttributeEvent scae);
//替换
public void attributeReplaced(ServletContextAttributeEvent scae);
}
//事件
public interface ServletContextAttributeListener extends EventListener {
public void attributeAdded(ServletContextAttributeEvent scae);
public void attributeRemoved(ServletContextAttributeEvent scae);
public void attributeReplaced(ServletContextAttributeEvent scae);
}
Session监听器
HttpSessionListener:用来监听HttpSession对象的创建和销毁。
public interface HttpSessionListener extends EventListener {
//创建时调用
public void sessionCreated(HttpSessionEvent se);
//销毁时调用
public void sessionDestroyed(HttpSessionEvent se);
}
//事件
public class HttpSessionEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;
public HttpSessionEvent(HttpSession source) {
super(source);
}
public HttpSession getSession() {
return (HttpSession) super.getSource();
}
}
2、HttpSessionAttributeListener:当Session中的属性被添加删除,替换时,这些对应的监听器将会被触发。
public interface HttpSessionAttributeListener extends EventListener {
//添加
public void attributeAdded(HttpSessionBindingEvent se);
//移除
public void attributeRemoved(HttpSessionBindingEvent se);
//替换
public void attributeReplaced(HttpSessionBindingEvent se);
}
//事件
public class HttpSessionBindingEvent extends HttpSessionEvent {
private static final long serialVersionUID = 1L;
private final String name;
private final Object value;
public HttpSessionBindingEvent(HttpSession session, String name) {
super(session);
this.name = name;
this.value = null;
}
public HttpSessionBindingEvent(HttpSession session, String name,
Object value) {
super(session);
this.name = name;
this.value = value;
}
@Override
public HttpSession getSession() {
return super.getSession();
}
public String getName() {
return name;
}
public Object getValue() {
return this.value;
}
}
3、HttpSessionActivationListener:实现此接口的JavaBean,可以感知自己被活化(从硬盘到内存)和钝化(从内存到硬盘)的过程。
案例:
public class Person implements Serializable, HttpSessionActivationListener {
private String name;
public Person(String name) {
super();
this.name = name;
}
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println(this + "保存到硬盘了...");
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println(this + "从硬盘读取并活化了...");
}
@Override
public String toString() {
return "Perosn [name=" + name + "]---"+super.toString();
}
}
4、HttpSessionBindingListener对象实现了HttpSessionBindingListener接口,当这个对象被绑定到Session中或者从session中被删除时,Servlet容器会通知这个对象;
案例:
public class UsersOnlineCountListener implements HttpSessionBindingListener {
int uid;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
@Override
public void valueBound(HttpSessionBindingEvent arg0) {
System.out.println(uid+"登录了"+new Date());
}
@Override
public void valueUnbound(HttpSessionBindingEvent arg0) {
System.out.println(uid+"下线了"+new Date());
}
}
ServletRequest的监听器:
ServletReqeustListener:用来监听ServletReqeust对象的创建和销毁。在Servlet容器中是通过池来重用ServletRequest的,创建ServletRequest花费的时间是从池中获取ServletRequest的时间,ServletRequest销毁相当于把ServletRequest还回池中的时间。
public interface ServletRequestListener extends EventListener {
//销毁
public void requestDestroyed (ServletRequestEvent sre);
//初始化
public void requestInitialized (ServletRequestEvent sre);
}
//事件
public class ServletRequestEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;
private final transient ServletRequest request;
public ServletRequestEvent(ServletContext sc, ServletRequest request) {
super(sc);
this.request = request;
}
public ServletRequest getServletRequest() {
return this.request;
}
public ServletContext getServletContext() {
return (ServletContext) super.getSource();
}
}
ServletRequestAttributeListener:当ServletRequest中的属性被添加删除,替换时,这些对应的监听器将会被触发。
public interface ServletRequestAttributeListener extends EventListener {
//添加
public void attributeAdded(ServletRequestAttributeEvent srae);
//移除
public void attributeRemoved(ServletRequestAttributeEvent srae);
//替换
public void attributeReplaced(ServletRequestAttributeEvent srae);
}
三:过滤器Filter
过滤器主要接口: Filter、FilterConfig、FilterChain
Filter
public interface Filter {
//Servlet启动服务时,Servlet容器会调用初始化代码
public void init(FilterConfig filterConfig) throws ServletException;
//每次http请求,filter进行拦截都会执行
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
//过滤器终止服务
public void destroy();
}
过滤器拦截流程:
1、当客户端发生请求后,在HttpServletRequest 到达Servlet 之前,过滤器拦截客户的HttpServletRequest 。
2、根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
3、在过滤器中调用doFilter方法,对请求放行。请求到达Servlet后,对请求进行处理并产生HttpServletResponse发送给客户端。
4、在HttpServletResponse 到达客户端之前,过滤器拦截HttpServletResponse 。
5、根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。
6、最后,HttpServletResponse到达客户端。
FilterConfig(过滤器的配置)
四、FilterChain
在一个Web应用程序中可以注册多个Filter程序,每个Filter程序都可以对一个或一组Servlet程序进行拦截。FilterChain其实就是一条过滤器链
Servlet容器的初始化
容器的初始化的核心是javax.servlet.ServletContainerInitializer接口,
package javax.servlet;
import java.util.Set;
/**
* 目的:Servlet容器初始化(ServletContainerInitializer初始化器)
*
* <p>web容器启动时,调用该接口的实现(初始化器),
* 初始化已被注册的servlets、filters、listeners。
*
* <p>{@link javax.servlet.annotation.HandlesTypes HandlesTypes}注解
* 来实现该接口,注解的类作为onStartup()方法的参数传入。
*
* <p>没有@HandlesTypes注解或没有指定应用程序类匹配的注解时,容器{@link #onStartup}必须是个null集合
*
* <p>实现该接口就必须在对应的jar包的META-INF/services
* 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,
* 该文件内容指定该接口的具体实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。
*
* 实现机制:
* Tomcat容器的ServletContainerInitializer机制的实现,主要交由Context容器
* 和ContextConfig监听器共同实现,ContextConfig监听器负责在容器启动时读取每个web
* 应用的WEB-INF/lib目录下包含的jar包的META-INF/services/javax.servlet.
* ServletContainerInitializer,以及web根目录下的META-INF/services/
* javax.servlet.ServletContainerInitializer,通过反射完成这些
* ServletContainerInitializer的实例化,然后再设置到Context容器中,最后
* Context容器启动时就会分别调用每个ServletContainerInitializer的onStartup方法,
* 并将感兴趣的类作为参数传入。
* 参考资料:http://blog.csdn.net/wangyangzhizhou/article/details/52013779
*
* @author TCM
* @create 2017年10月24日上午9:55:01
* @see javax.servlet.annotation.HandlesTypes
* @since Servlet 3.0
*/
public interface ServletContainerInitializer {
/**
* 启动ServletContainerInitializer具体实例后,并设置到ServletContext中
* @param c 实现该接口的具体实现类
* @param ctx ServletContext
* @throws ServletException if an error has occurred
*/
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}
1、Servlet容器启动会扫描,当前应用里面每一个jar包的
ServletContainerInitializer的实现
2、提供ServletContainerInitializer的实现类;
必须绑定在,META-INF/services/javax.servlet.ServletContainerInitializer
文件的内容就是ServletContainerInitializer实现类的全类名;
3、可以给ServletContainerInitializer 的实现类添加@HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializerde的onStartup方法作为参数传入。
网友评论