会话
概述
HTTP协议是无状态协议(stateless)(不保存状态),HTTP协议自身不对请求和响应之间的通信状态[客户端的状态]进行保存,浏览器发送请求,服务器接收并响应,但是服务器不记录请求是否来自哪个浏览器,服务器没记录浏览器的特征,协议对于发送过的请求或者响应都不做持久化处理
cookie是在客户端保留少量数据的技术,主要通过响应头向客户端响应一些客户端要保留的信息
session是在服务端保留更多数据的技术,主要通过HttpSession对象保存一些和客户端相关的信息
cookie和session配合记录请求状态
张三第一次去某个银行办业务,银行会为张三开户(Session),并向张三发放一张银行卡(cookie)张三后面每次去银行,就可以携带之间的银行卡(cookie),银行根据银行卡找到之前张三的账户(session)

Cookie
概述
cookie是一种客户端会话技术,cookie由服务端产生,它是服务器存放在浏览器的一小份数据,浏览器以后每次访问该服务器的时候都会将这小份数据携带到服务器去。
服务端创建cookie,将cookie放入响应对象中,Tomcat容器将cookie转化为set-cookie响应头,响应给客户端
客户端在收到cookie的响应头时,在下次请求该服务的资源时,会以cookie请求头的形式携带之前收到的Cookie
cookie是存储于客户端的数据,比较容易暴露,一般不存储一些敏感或者影响安全的数据

Cookie的使用
servletA向响应中增加Cookie
java
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie
Cookie cookie1 =new Cookie("c1","c1_message");
Cookie cookie2 =new Cookie("c2","c2_message");
// 将cookie放入响应对象
resp.addCookie(cookie1);
resp.addCookie(cookie2);
}
}
servletB从请求中读取Cookie
java
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求中的cookie
Cookie[] cookies = req.getCookies();
//迭代cookies数组
if (null != cookies && cookies.length!= 0) {
for (Cookie cookie : cookies) {
System.out.println(cookie.getName()+":"+cookie.getValue());
}
}
}
}
Cookie的时效性
会话级Cookie
服务器端并没有明确指定Cookie的存在时间
在浏览器端,Cookie数据存在于内存中
只要浏览器还开着,Cookie数据就一直都在
浏览器关闭,内存中的Cookie数据就会被释放
持久化Cookie
服务器端明确设置了Cookie的存在时间
在浏览器端,Cookie数据会被保存到硬盘上
Cookie在硬盘上存在的时间根据服务器端限定的时间来管控,不受浏览器关闭的影响
持久化Cookie到达了预设的时间会被释放
注:cookie.setMaxAge(int expiry)参数单位是秒,表示cookie的持久化时间,如果设置参数为0,表示将浏览器中保存的该cookie删除
java
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie
Cookie cookie1 =new Cookie("c1","c1_message");
cookie1.setMaxAge(60);
Cookie cookie2 =new Cookie("c2","c2_message");
// 将cookie放入响应对象
resp.addCookie(cookie1);
resp.addCookie(cookie2);
}
}
java
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求中的cookie
Cookie[] cookies = req.getCookies();
//迭代cookies数组
if (null != cookies && cookies.length!= 0) {
for (Cookie cookie : cookies) {
System.out.println(cookie.getName()+":"+cookie.getValue());
}
}
}
}
Cookie的提交路径
不需要每次都需要把所有Cookie带上。访问不同的资源时,可以携带不同的cookie,我们可以通过cookie的setPath(String path) 对cookie的路径进行设置
java
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie
Cookie cookie1 =new Cookie("c1","c1_message");
// 设置cookie的提交路径
cookie1.setPath("/web03_war_exploded/servletB");
Cookie cookie2 =new Cookie("c2","c2_message");
// 将cookie放入响应对象
resp.addCookie(cookie1);
resp.addCookie(cookie2);
}
}
Session
概述
HttpSession是一种保留更多信息在服务端的一种技术,服务器会为每一个客户端开辟一块内存空间,即session对象. 客户端在发送请求时,都可以使用自己的session
服务端在为客户端创建session时,会同时将session对象的id,即JSESSIONID以cookie的形式放入响应对象
后端创建完session后,客户端会收到一个特殊的cookie,叫做JSESSIONID
客户端下一次请求时携带JSESSIONID,后端收到后,根据JSESSIONID找到对应的session对象
通过该机制,服务端通过session就可以存储一些专门针对某个客户端的信息了
session也是域对象

HttpSession的使用

用户提交form表单到ServletA,携带用户名,ServletA获取session 将用户名存到Session,用户再请求其他任意Servlet,获取之前存储的用户
html
<form action="servletA" method="post">
用户名:
<input type="text" name="username">
<input type="submit" value="提交">
</form>
java
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求中的参数
String username = req.getParameter("username");
// 获取session对象
HttpSession session = req.getSession();
// 获取Session的ID
String jSessionId = session.getId();
System.out.println(jSessionId);
// 判断session是不是新创建的session
boolean isNew = session.isNew();
System.out.println(isNew);
// 向session对象中存入数据
session.setAttribute("username",username);
}
}
java
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取session对象
HttpSession session = req.getSession();
// 获取Session的ID
String jSessionId = session.getId();
System.out.println(jSessionId);
// 判断session是不是新创建的session
boolean isNew = session.isNew();
System.out.println(isNew);
// 从session中取出数据
String username = (String)session.getAttribute("username");
System.out.println(username);
}
}
HttpSession时效性
用户量很大之后,Session对象相应的也要创建很多。如果一味创建不释放,那么服务器端的内存迟早要被耗尽。默认的session最大闲置时间(两次使用同一个session中的间隔时间) 在tomcat/conf/web.xml配置为30分钟
可以通过HttpSession的API 对最大闲置时间进行设定
java
// 设置最大闲置时间
session.setMaxInactiveInterval(60);
可以直接让session失效
java
// 直接让session失效
session.invalidate();
三大域对象
概述
域对象: 一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同
请求域,会话域,应用域

请求域对象是HttpServletRequest ,传递数据的范围是一次请求之内及请求转发

会话域对象是HttpSession,传递数据的范围是一次会话之内,可以跨多个请求

应用域对象是ServletContext,传递数据的范围是本应用之内,可以跨多个会话

域对象的使用

ServletA向三大域中放入数据
java
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 向请求域中放入数据
req.setAttribute("request","request-message");
//req.getRequestDispatcher("servletB").forward(req,resp);
// 向会话域中放入数据
HttpSession session = req.getSession();
session.setAttribute("session","session-message");
// 向应用域中放入数据
ServletContext application = getServletContext();
application.setAttribute("application","application-message");
}
}
ServletB从三大域中取出数据
java
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 从请求域中获取数据
String reqMessage =(String)req.getAttribute("request");
System.out.println(reqMessage);
// 从会话域中获取数据
HttpSession session = req.getSession();
String sessionMessage =(String)session.getAttribute("session");
System.out.println(sessionMessage);
// 从应用域中获取数据
ServletContext application = getServletContext();
String applicationMessage =(String)application.getAttribute("application");
System.out.println(applicationMessage);
}
}
请求转发时,请求域可以传递数据`请求域内一般放本次请求业务有关的数据,如:查询到的所有的部门信息`
同一个会话内,不用请求转发,会话域可以传递数据`会话域内一般放本次会话的客户端有关的数据,如:当前客户端登录的用户`
同一个APP内,不同的客户端,应用域可以传递数据`应用域内一般放本程序应用有关的数据 如:Spring框架的IOC容器`
过滤器
Filter,即过滤器,是JAVAEE技术规范之一,作用目标资源的请求进行过滤的一套技术规范
Filter接口定义了过滤器的开发规范,所有的过滤器都要实现该接口
Filter的工作位置是项目中所有目标资源之前,容器在创建HttpServletRequest和HttpServletResponse对象后,会先调用Filter的doFilter方法
Filter的doFilter方法可以控制请求是否继续,如果放行,则请求继续,如果拒绝,则请求到此为止,由过滤器本身做出响应
Filter不仅可以对请求做出过滤,也可以在目标资源做出响应前,对响应再次进行处理
Filter是GOF中责任链模式的典型案例
Filter的常用应用包括但不限于:登录权限检查,解决网站乱码,过滤敏感字符,日志记录,性能分析......

过滤器使用
java
public class LoggingFilter implements Filter {
private SimpleDateFormat dateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 参数父转子
HttpServletRequest request =(HttpServletRequest) servletRequest;
HttpServletResponse response =(HttpServletResponse) servletResponse;
// 拼接日志文本
String requestURI = request.getRequestURI();
String time = dateFormat.format(new Date());
String beforeLogging =requestURI+"在"+time+"被请求了";
// 打印日志
System.out.println(beforeLogging);
// 获取系统时间
long t1 = System.currentTimeMillis();
// 放行请求
filterChain.doFilter(request,response);
// 获取系统时间
long t2 = System.currentTimeMillis();
// 拼接日志文本
String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";
// 打印日志
System.out.println(afterLogging);
}
}
doFilter方法中的请求和响应对象是以父接口的形式声明的,实际传入的实参就是HttpServletRequest和HttpServletResponse子接口级别的,可以安全强转
filterChain.doFilter(request,response); 这行代码的功能是放行请求,如果没有这一行代码,则请求到此为止
filterChain.doFilter(request,response);在放行时需要传入request和response,意味着请求和响应对象要继续传递给后续的资源,这里没有产生新的request和response对象
ServletA
java
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 处理器请求
System.out.println("servletA处理请求的方法,耗时10毫秒");
// 模拟处理请求耗时
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
ServletB
java
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 处理器请求
System.out.println("servletB处理请求的方法,耗时15毫秒");
// 模拟处理请求耗时
try {
Thread.sleep(15);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
配置过滤器以及过滤器的过滤范围
XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<!--配置filter,并为filter起别名-->
<filter>
<filter-name>loggingFilter</filter-name>
<filter-class>com.atguigu.filters.LoggingFilter</filter-class>
</filter>
<!--为别名对应的filter配置要过滤的目标资源-->
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<!--通过映射路径确定过滤资源-->
<url-pattern>/servletA</url-pattern>
<!--通过后缀名确定过滤资源-->
<url-pattern>*.html</url-pattern>
<!--通过servlet别名确定过滤资源-->
<servlet-name>servletBName</servlet-name>
</filter-mapping>
</web-app>
filter-mapping标签中定义了过滤器对那些资源进行过滤
子标签url-pattern通过映射路径确定过滤范围
/servletA 精确匹配,表示对servletA资源的请求进行过滤
*.html 表示对以.html结尾的路径进行过滤
/* 表示对所有资源进行过滤
一个filter-mapping下可以配置多个url-pattern[资源唯一(clsss),多种方式访问]
子标签servlet-name通过servlet别名确定对那些servlet进行过滤
使用该标签确定目标资源的前提是servlet已经起了别名
一个filter-mapping下可以定义多个servlet-name[资源唯一(clsss),多种方式访问]
一个filter-mapping下,servlet-name和url-pattern子标签可以同时存在

过滤器生命周期

java
@WebServlet("/*")
public class LifeCycleFilter implements Filter {
public LifeCycleFilter(){
System.out.println("LifeCycleFilter constructor method invoked");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LifeCycleFilter init method invoked");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("LifeCycleFilter doFilter method invoked");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("LifeCycleFilter destory method invoked");
}
}
过滤器链的使用

一个web项目中,可以同时定义多个过滤器,多个过滤器对同一个资源进行过滤时,工作位置有先后,整体形成一个工作链,称之为过滤器链
过滤器链中的过滤器的顺序由filter-mapping顺序决定
每个过滤器过滤的范围不同,针对同一个资源来说,过滤器链中的过滤器个数可能是不同的
如果某个Filter是使用ServletName进行匹配规则的配置,那么这个Filter执行的优先级要更低

java
@WebServlet("/servletC")
public class ServletC extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servletC service method invoked");
}
}
三个过滤器代码
java
public class Filter1 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter1 before chain.doFilter code invoked");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("filter1 after chain.doFilter code invoked");
}
}
public class Filter2 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter2 before chain.doFilter code invoked");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("filter2 after chain.doFilter code invoked");
}
}
public class Filter3 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter3 before chain.doFilter code invoked");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("filter3 after chain.doFilter code invoked");
}
}
过滤器配置代码
XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.atguigu.filters.Filter1</filter-class>
</filter>
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.atguigu.filters.Filter2</filter-class>
</filter>
<filter>
<filter-name>filter3</filter-name>
<filter-class>com.atguigu.filters.Filter3</filter-class>
</filter>
<!--filter-mapping的顺序决定了过滤器的工作顺序-->
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/servletC</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/servletC</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filter3</filter-name>
<url-pattern>/servletC</url-pattern>
</filter-mapping>
</web-app>
注解方式配置过滤器
优先级取决于类名
XML
<filter>
<filter-name>loggingFilter</filter-name>
<filter-class>com.atguigu.filters.LoggingFilter</filter-class>
<!--配置filter的初始参数-->
<init-param>
<param-name>dateTimePattern</param-name>
<param-value>yyyy-MM-dd HH:mm:ss</param-value>
</init-param>
</filter>
<!--为别名对应的filter配置要过滤的目标资源-->
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<!--通过映射路径确定过滤资源-->
<url-pattern>/servletA</url-pattern>
<!--通过后缀名确定过滤资源-->
<url-pattern>*.html</url-pattern>
<!--通过servlet别名确定过滤资源-->
<servlet-name>servletBName</servlet-name>
</filter-mapping>
java
@WebFilter(
filterName = "loggingFilter",
initParams = {@WebInitParam(name="dateTimePattern",value="yyyy-MM-dd HH:mm:ss")},
urlPatterns = {"/servletA","*.html"},
servletNames = {"servletBName"}
)
public class LoggingFilter implements Filter {
private SimpleDateFormat dateFormat ;
/*init初始化方法,通过filterConfig获取初始化参数
* init方法中,可以用于定义一些其他初始化功能代码
* */
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 获取初始参数
String dateTimePattern = filterConfig.getInitParameter("dateTimePattern");
// 初始化成员变量
dateFormat=new SimpleDateFormat(dateTimePattern);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 参数父转子
HttpServletRequest request =(HttpServletRequest) servletRequest;
HttpServletResponse response =(HttpServletResponse) servletResponse;
// 拼接日志文本
String requestURI = request.getRequestURI();
String time = dateFormat.format(new Date());
String beforeLogging =requestURI+"在"+time+"被请求了";
// 打印日志
System.out.println(beforeLogging);
// 获取系统时间
long t1 = System.currentTimeMillis();
// 放行请求
filterChain.doFilter(request,response);
// 获取系统时间
long t2 = System.currentTimeMillis();
String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";
// 打印日志
System.out.println(afterLogging);
}
}
监听器
概述
专门用于对域对象身上发生的事件或状态改变进行监听和相应处理的对象
监听器使用的感受类似JS中的事件,被观察的对象发生某些情况时,自动触发代码的执行
监听器并不监听web项目中的所有组件,仅仅是对三大域对象做相关的事件监听
按监听的对象划分
application[应用]域监听器:ServletContextListener、ServletContextAttributeListener
session[会话]域监听器:HttpSessionListener、HttpSessionAttributeListener、HttpSessionBindingListener、HttpSessionActivationListener
request[请求]域监听器:ServletRequestListener、ServletRequestAttributeListener
按监听的事件分
域对象的创建和销毁监听器:ServletContextListener、HttpSessionListener、ServletRequestListener
域对象数据增删改事件监听器:ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener
其他监听器:HttpSessionBindingListener、HttpSessionActivationListener
监听器的六个主要接口
application域监听器
监听ServletContext对象的创建与销毁

监听ServletContext中属性的添加、移除和修改

ServletContextAttributeEvent对象代表属性变化事件

定义监听器
java
@WebListener
public class ApplicationListener implements ServletContextListener , ServletContextAttributeListener {
// 监听初始化
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext application = sce.getServletContext();
System.out.println("application"+application.hashCode()+" initialized");
}
// 监听销毁
@Override
public void contextDestroyed(ServletContextEvent sce) {
ServletContext application = sce.getServletContext();
System.out.println("application"+application.hashCode()+" destroyed");
}
// 监听数据增加
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
String name = scae.getName();
Object value = scae.getValue();
ServletContext application = scae.getServletContext();
System.out.println("application"+application.hashCode()+" add:"+name+"="+value);
}
// 监听数据移除
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
String name = scae.getName();
Object value = scae.getValue();
ServletContext application = scae.getServletContext();
System.out.println("application"+application.hashCode()+" remove:"+name+"="+value);
}
// 监听数据修改
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
String name = scae.getName();
Object value = scae.getValue();
ServletContext application = scae.getServletContext();
Object newValue = application.getAttribute(name);
System.out.println("application"+application.hashCode()+" change:"+name+"="+value+" to "+newValue);
}
}
定义触发监听器的代码
java
// ServletA用于向application域中放入数据
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 向application域中放入数据
ServletContext application = this.getServletContext();
application.setAttribute("k1","v1");
application.setAttribute("k2","v2");
}
}
// ServletB用于向application域中修改和移除数据
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext appliation = getServletContext();
// 修改application域中的数据
appliation.setAttribute("k1","value1");
// 删除application域中的数据
appliation.removeAttribute("k2");
}
}
session域监听器
监听HttpSession对象的创建与销毁

监听HttpSession中属性的添加、移除和修改

HttpSessionBindingEvent对象代表属性变化事件

定义监听器
java
@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {
// 监听session创建
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("session"+session.hashCode()+" created");
}
// 监听session销毁
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
System.out.println("session"+session.hashCode()+" destroyed");
}
// 监听数据增加
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
String name = se.getName();
Object value = se.getValue();
HttpSession session = se.getSession();
System.out.println("session"+session.hashCode()+" add:"+name+"="+value);
}
// 监听数据移除
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
String name = se.getName();
Object value = se.getValue();
HttpSession session = se.getSession();
System.out.println("session"+session.hashCode()+" remove:"+name+"="+value);
}
// 监听数据修改
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
String name = se.getName();
Object value = se.getValue();
HttpSession session = se.getSession();
Object newValue = session.getAttribute(name);
System.out.println("session"+session.hashCode()+" change:"+name+"="+value+" to "+newValue);
}
}
定义触发监听器的代码
java
// servletA用于创建session并向session中放数据
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建session,并向session中放入数据
HttpSession session = req.getSession();
session.setAttribute("k1","v1");
session.setAttribute("k2","v2");
}
}
// servletB用于修改删除session中的数据并手动让session不可用
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
// 修改session域中的数据
session.setAttribute("k1","value1");
// 删除session域中的数据
session.removeAttribute("k2");
// 手动让session不可用
session.invalidate();
}
}
request域监听器
监听ServletRequest对象的创建与销毁

监听ServletRequest中属性的添加、移除和修改

ServletRequestAttributeEvent对象代表属性变化事件

定义监听器
java
@WebListener
public class RequestListener implements ServletRequestListener , ServletRequestAttributeListener {
// 监听初始化
@Override
public void requestInitialized(ServletRequestEvent sre) {
ServletRequest request = sre.getServletRequest();
System.out.println("request"+request.hashCode()+" initialized");
}
// 监听销毁
@Override
public void requestDestroyed(ServletRequestEvent sre) {
ServletRequest request = sre.getServletRequest();
System.out.println("request"+request.hashCode()+" destoryed");
}
// 监听数据增加
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
String name = srae.getName();
Object value = srae.getValue();
ServletRequest request = srae.getServletRequest();
System.out.println("request"+request.hashCode()+" add:"+name+"="+value);
}
// 监听数据移除
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
String name = srae.getName();
Object value = srae.getValue();
ServletRequest request = srae.getServletRequest();
System.out.println("request"+request.hashCode()+" remove:"+name+"="+value);
}
// 监听数据修改
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
String name = srae.getName();
Object value = srae.getValue();
ServletRequest request = srae.getServletRequest();
Object newValue = request.getAttribute(name);
System.out.println("request"+request.hashCode()+" change:"+name+"="+value+" to "+newValue);
}
}
定义触发监听器的代码
java
// servletA向请求域中放数据
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 向request中增加数据
req.setAttribute("k1","v1");
req.setAttribute("k2","v2");
// 请求转发
req.getRequestDispatcher("servletB").forward(req,resp);
}
}
// servletB修改删除域中的数据
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 修改request域中的数据
req.setAttribute("k1","value1");
// 删除session域中的数据
req.removeAttribute("k2");
}
}
session域的两个特殊监听器
session绑定监听器
监听当前监听器对象在Session域中的增加与移除

HttpSessionBindingEvent对象代表属性变化事件

定义监听器
java
public class MySessionBindingListener implements HttpSessionBindingListener {
// 监听绑定
@Override
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
String name = event.getName();
System.out.println("MySessionBindingListener"+this.hashCode()+" binding into session"+session.hashCode()+" with name "+name);
}
// 监听解除绑定
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
HttpSession session = event.getSession();
String name = event.getName();
System.out.println("MySessionBindingListener"+this.hashCode()+" unbond outof session"+session.hashCode()+" with name "+name);
}
}
定义触发监听器的代码
java
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
// 绑定监听器
session.setAttribute("bindingListener",new MySessionBindingListener());
// 解除绑定监听器
session.removeAttribute("bindingListener");
}
}
钝化活化监听器
监听某个对象在Session中的序列化与反序列化

在关闭服务器前或者到达了设定时间时,对session进行序列化到磁盘,这种情况叫做session的钝化
在服务器启动后或者再次获取某个session时,将磁盘上的session进行反序列化到内存,这种情况叫做session的活化
Ajax
概述
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容,我们通过事件触发JS代码运行发送请求,响应后我们可以通过js代码动态处理是否要跳转页面还是要将响应的信息通过DOM编程显示在dom树中。需要用户允许 JavaScript 在浏览器上执行。[XMLHttpRequest]

通过运行JS代码发送的请求浏览器可以不用跳转页面 ,我们可以在JS代码中决定是否要跳转页面
通过运行JS代码发送的请求,接收到返回结果后,我们可以将结果通过dom编程渲染到页面的某些元素上,实现局部更新
实现ajax请求
原生javascript方式进行ajax
readystate有[1,2,3,4]中状态,最终一定会回到"4"状态
javascript
<script>
function loadXMLDoc(){
//实例化一个XMLHttpRequest对象
var xmlhttp=new XMLHttpRequest();
// 设置回调函数 处理响应结果
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
// 设置请求方式和请求的资源路径
xmlhttp.open("GET","/try/ajax/ajax_info.txt",true);
// 发送请求
xmlhttp.send();
}
</script>