Servlet3-Cookie、Session、ServletContext、ServletConfig
会话跟踪技术
会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。
会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。
HTTP协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现会话内数据共享。
实现方式:
Cookie技术:会话数据保存在浏览器客户端。
Session技术:会话数据保存在服务器端。(域对象)
Cookie技术
客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问
Cookie 基本使用
发送Cookie
创建Cookie对象,设置数据
Cookie cookie = new Cookie("key","value");
发送Cookie到客户端:使用response对象
response.addCookie(cookie);
1 @WebServlet("/aServlet") 2 public class AServlet extends HttpServlet { 3 @Override 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 //发送Cookie 6 //1. 创建Cookie对象 7 Cookie cookie = new Cookie("username","zs"); 8 //2. 发送Cookie,response 9 response.addCookie(cookie); 10 } 11 @Override 12 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 13 this.doGet(request, response); 14 } 15 }
获取Cookie
获取客户端携带的所有Cookie,使用request对象
Cookie[] cookies = request.getCookies();
遍历数组,获取每一个Cookie对象:for
使用Cookie对象方法获取数据
cookie.getName();
cookie.getValue();
1 @WebServlet("/bServlet") 2 public class BServlet extends HttpServlet { 3 @Override 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 //获取Cookie 6 //1. 获取Cookie数组 7 Cookie[] cookies = request.getCookies(); 8 //2. 遍历数组 9 for (Cookie cookie : cookies) { 10 //3. 获取数据 11 String name = cookie.getName(); 12 if("username".equals(name)){ 13 String value = cookie.getValue(); 14 System.out.println(name+":"+value); 15 break; 16 } 17 } 18 } 19 @Override 20 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 21 this.doGet(request, response); 22 } 23 }
Cookie 原理
Cookie的实现是基于HTTP协议的
响应头:set-cookie
请求头:cookie
Cookie 使用细节
Cookie 存活时间
默认情况下,Cookie 存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁。
setMaxAge(int seconds):设置Cookie存活时间(seconds单位为秒)
正数:将 Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则 Cookie被销毁
零:删除对应 Cookie
1 @WebServlet("/aServlet") 2 public class AServlet extends HttpServlet { 3 @Override 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 //发送Cookie 6 //1. 创建Cookie对象 7 Cookie cookie = new Cookie("username","zs"); 8 //设置存活时间,1周 7天 9 cookie.setMaxAge(60*60*24*7); //易阅读,需程序计算 10 //cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补),程序少进行一次计算 11 //2. 发送Cookie,response 12 response.addCookie(cookie); 13 } 14 @Override 15 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 16 this.doGet(request, response); 17 } 18 }
Cookie 存储中文
Cookie 不能直接存储中文
如需要存储,则需要进行转码:URL编码
对中文进行URL编码:
1 @WebServlet("/aServlet") 2 public class AServlet extends HttpServlet { 3 @Override 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 //发送Cookie 6 String value = "张三"; 7 //对中文进行URL编码 8 value = URLEncoder.encode(value, "UTF-8"); 9 System.out.println("存储数据:"+value); 10 //将编码后的值存入Cookie中 11 Cookie cookie = new Cookie("username",value); 12 //设置存活时间 ,1周 7天 13 cookie.setMaxAge(60*60*24*7); 14 //2. 发送Cookie,response 15 response.addCookie(cookie); 16 } 17 @Override 18 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 19 this.doGet(request, response); 20 } 21 }
对值进行解码:
1 @WebServlet("/bServlet") 2 public class BServlet extends HttpServlet { 3 @Override 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 //获取Cookie 6 //1. 获取Cookie数组 7 Cookie[] cookies = request.getCookies(); 8 //2. 遍历数组 9 for (Cookie cookie : cookies) { 10 //3. 获取数据 11 String name = cookie.getName(); 12 if("username".equals(name)){ 13 String value = cookie.getValue();//获取的是URL编码后的值 %E5%BC%A0%E4%B8%89 14 //URL解码 15 value = URLDecoder.decode(value,"UTF-8"); 16 System.out.println(name+":"+value);//value解码后为 张三 17 break; 18 } 19 } 20 } 21 @Override 22 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 23 this.doGet(request, response); 24 } 25 }
注意:
一个Cookie对象存储一条数据。多条数据,可以多创建几个Cookie对象进行存储。
特点
浏览器端的数据存储技术。
存储的数据声明在服务器端。
临时存储:存储在浏览器的运行内存中,浏览器关闭即失效。
定时存储:设置了Cookie的有效期,存储在客户端的硬盘中,在有效期内符合路径要求的请求都会附带该信息。
默认cookie信息存储好之后,每次请求都会附带,除非设置有效路径
Session技术
服务端会话跟踪技术:将数据保存到服务端。
Session是存储在服务端而Cookie是存储在客户端。
存储在客户端的数据容易被窃取和截获,存在很多不安全的因素。
存储在服务端的数据相比于客户端来说就更安全。
Session 基本使用
JavaEE 提供 HttpSession接口,来实现一次会话的多次请求间数据共享功能。
获取Session对象:
HttpSession session = request.getSession();
Session对象功能:
void setAttribute(String name, Object o):存储数据到 session 域中
Object getAttribute(String name):根据 key,获取值
void removeAttribute(String name):根据 key,删除该键值对
SessionDemo1:获取Session对象、存储数据
1 @WebServlet("/demo1") 2 public class SessionDemo1 extends HttpServlet { 3 @Override 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 //存储到Session中 6 //1. 获取Session对象 7 HttpSession session = request.getSession(); 8 //2. 存储数据 9 session.setAttribute("username","zs"); 10 } 11 @Override 12 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 13 this.doGet(request, response); 14 } 15 }
SessionDemo2:获取Session对象、获取数据
1 @WebServlet("/demo2") 2 public class SessionDemo2 extends HttpServlet { 3 @Override 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 //获取数据,从session中 6 //1. 获取Session对象 7 HttpSession session = request.getSession(); 8 //2. 获取数据 9 Object username = session.getAttribute("username"); 10 System.out.println(username); 11 } 12 @Override 13 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 14 this.doGet(request, response); 15 } 16 }
Session 原理
Session是基于Cookie实现的
用户第一次访问服务器,服务器会创建一个session对象给此用户,并将该session对象的JSESSIONID使用Cookie技术存储到浏览器中,保证用户的其他请求能够获取到同一个session对象,也保证了不同请求能够获取到共享的数据。
Session 使用细节
Session 钝化、活化
服务器是正常关闭和启动,Session中的数据是可以被保存下来的,原因为:
钝化:在服务器正常关闭后,Tomcat会自动将 Session数据写入硬盘的文件中。
钝化的数据路径为:项目目录\target\tomcat\work\Tomcat\localhost\项目名称\SESSIONS.ser。
活化:再次启动服务器后,从文件中加载数据到Session中。
数据加载到Session中后,路径中的 'SESSIONS.ser' 文件会被删除掉。
注:
session数据存储在服务端,服务器重启后,session数据会被保存。
浏览器被关闭启动后,重新建立的连接就已经是一个全新的会话,获取的session数据也是一个新的对象。
session的数据要想共享,浏览器不能关闭,所以session数据不能长期保存数据。
cookie是存储在客户端,是可以长期保存。
Seesion 销毁
1、默认情况下,无操作,30分钟自动销毁。
对于这个失效时间,是可以通过配置进行修改的:在项目的web.xml中配置
<session-config> <session-timeout>100</session-timeout> </session-config>
2、调用Session对象的invalidate()方法进行销毁。
session.invalidate();
该销毁方法一般会在用户退出的时候,需要将session销毁掉。
特点
存储在服务器端服务器进行创建
依赖Cookie技术
一次会话
默认存储时间是30分钟
小结
Cookie 和 Session 都是来完成一次会话内多次请求间数据共享的。
区别:
存储位置:Cookie 是将数据存储在客户端,Session 将数据存储在服务端。
安全性:Cookie 不安全,Session 安全。
数据大小:Cookie 最大3KB,Session 无大小限制。
存储时间:Cookie 可以长期存储,Session 默认30分钟。
服务器性能:Cookie 不占服务器资源,Session 占用服务器资源。
ServletContext对象(Servlet上下文对象)
问题:
不同的用户使用相同的数据
解决:
ServletContext对象
特点:
服务器创建
用户共享
一个项目只有一个
作用域:
整个项目内
生命周期:
服务器启动到服务器关闭
ServletContext配置方式
在<web-app>标签中,通过<context-param>标签来配置。有两个子标签。
<param-name>:代表全局初始化参数的 key。
<param-value>:代表全局初始化参数的value。
<!--配置ServletContext--> <context-param> <param-name>globalEncoding</param-name> <param-value>UTF-8</param-value> </context-param> <context-param> <param-name>globalDesc</param-name> <param-value>This is ServletContext</param-value> </context-param>
ServletContext使用
1、获取ServletContext对象
//第一种方式:
ServletContext sc=this.getServletContext();
//第二种方式:
ServletContext sc2=this.getServletConfig().getServletContext();
//第三种方式:
ServletContext sc3=req.getSession().getServletContext();
2、使用ServletContext对象完成数据共享
//向应用域对象中存储数据
sc.setAttribute(String name, Object value);
//通过名称获取应用域对象中的数据
sc.getAttribute("str") 返回的是Object类型
//通过名称移除应用域对象中的数据
sc.removeAttribute("str")
注意:
不同的用户可以给ServletContext对象进行数据的存取。
获取的数据不存在返回null。
3、获取项目中web.xml文件中的全局配置数据
sc.getInitParameter(String name); 根据键的名字返回web.xml中配置的全局数据的值,返回String类型。
如果数据不存在返回null。
sc.getInitParameterNames();返回键名的枚举
配置方式:注意一组<context-param>标签只能存储一组键值对数据,多组可以声明多个 <context-param>进行存储。
在<servlet>上,在<web-app>下:
<context-param>
<param-name>name</param-name>
<param-value>zhangsan</param-value>
</context-param>
作用:将静态数据和代码进行解耦。
4、获取web应用的上下文路径
String path=sc.getContextPath();
获取web应用上下路径。也就是部署到tomcat服务器上运行的web应用名称。
例:重定向:resp.sendRedirect("/login/main"); 写成:resp.sendRedirect(sc.getContextPath()+"/main");
5、获取项目webroot下的资源的绝对路径。
String path=sc.getRealPath(String path);
获取的路径为项目根目录,path参数为项目根目录中的路径
6、获取webroot下的资源的流对象
InputStream is = sc.getResourceAsStream(String path);
注意:
此种方式只能获取项目根目录下的资源流对象,class文件的流对象需要使用类加载器获取。
path参数为项目根目录中的路径
7、获取webroot下的资源的URL
URL url = sc.getResource(String path);
能获取一个URL,不能构造输入流。
1 protected void service(HttpServletRequest req, HttpServletResponse resp) 2 throws ServletException, IOException { 3 //获取ServletContext对象 4 //第一种方式: 5 ServletContext sc=this.getServletContext(); 6 //第二种方式: 7 ServletContext sc2=this.getServletConfig().getServletContext(); 8 //第三种方式: 9 ServletContext sc3=req.getSession().getServletContext(); 10 System.out.println(sc==sc2); 11 System.out.println(sc==sc3); 12 //使用ServletContext对象完成数据共享 13 //数据存储 14 sc.setAttribute("str", "ServletContext对象学习"); 15 //获取项目web.xml的全局配置数据 16 String str = sc.getInitParameter("name2"); 17 System.out.println("全局配置参数:"+str); 18 //获取项目根目录下的资源的绝对路径 19 //String path="D:\\apache-tomcat-7.0.56\\webapps\\sc\\doc\\1.txt"; 20 String path=sc.getRealPath("/doc/1.txt"); 21 System.out.println(path); 22 //获取项目根目录下资源的流对象 23 InputStream is = sc.getResourceAsStream("/doc/1.txt"); 24 25 }
1 protected void service(HttpServletRequest req, HttpServletResponse resp) 2 throws ServletException, IOException { 3 //创建ServletContext对象 4 ServletContext sc=this.getServletContext(); 5 //获取数据 6 System.out.println("ServletContextServlet2.service()"+sc.getAttribute("str")); 7 }
ServletConfig对象
问题:
如何获取在web.xml中给每个servlet单独配置的数据呢?
解决:
使用ServletConfig对象
注意:ServletConfig对象是在创建完servlet对象之后,被创建出来。然后通过有参数的init方法传递到servlet中。 一个网站中存在多个ServletConfig对象,一个ServletConfig对象就封存了一个Servlet的配置信息。
使用:
获取ServletConfig对象
获取web.xml中的配置数据
在<servlet>中添加:
<init-param>
<param-name>config</param-name>
<param-value>utf-8</param-value>
</init-param>
1 protected void service(HttpServletRequest req, HttpServletResponse resp) 2 throws ServletException, IOException { 3 //获取ServletConfig对象 4 ServletConfig sc=this.getServletConfig(); 5 //获取web.xml中的配置数据 6 String code=sc.getInitParameter("config"); 7 System.out.println(code); 8 }
ServletConfig常用方法
String getlnitParameter(String name) 根据参数名称获取参数的值
Enumeration<String> getlnitParameterNames() 获取所有参数名称的枚举
String getServletName() 获取Servlet的名称
ServletContext getServletContext() 获取ServletContext对象
web.xml文件使用
作用:
存储项目相关的配置信息,保护 Servlet。解耦一些数据对程序的依赖。
使用位置:
每个 Web 项目中
Tomcat 服务器中(在服务器目录 conf 目录中)
区别:
Web 项目下的 web.xml 文件为局部配置,针对本项目的位置。
Tomcat 下的 web.xml 文件为全局配置,配置公共信息。
内容(核心组件):
全局上下文配置(全局配置参数)
Servlet 配置
过滤器配置
监听器配置
加载顺序:
Web 容器会按 ServletContext -> context-param -> listener ->filter-> servlet 这个顺序加载组件,这些元素可配置在 web.xml文件中的任意位置。
加载时机:
服务器启动时。
server.xml文件使用
Server.xml 文件核心组件:
<Server> <Service> <Connector/> <Connector/> <Engine> <Host> <Context/> </Host> </Engine> </Service> </Server>
热部署: <Context path="/Pet" reloadable="true" docBase="F:/PetWeb" />
path: 项目访问路径
docBase: 项目路径。/开头的是实际路径,没有/开头的为相对路径,相对于webapps
reloadable: 开启热更新,热部署