ServletContext对象
ServletContext对象官方也称servlet上下文。服务器会为每一个Web应用创建一个ServletContext对象,这个对象全局唯一,而且Web应用中所有的Servlet都共享这个对象。
ServletContext对象的作用
相对路径转绝对路径
servletContext.getRealPath("Path");
该方法可以将一个相对路径转成绝对路径,在文件的上传和下载时需要用到该方法作为路径的转换。
示例:
package com.test;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;public class FileServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//使用ServletContext对象将相对路径转成绝对路径String path="image\\girl.jpg";//获取ServletContext对象ServletContext servletContext = this.getServletContext();String realPath=servletContext.getRealPath(path);System.out.println(realPath);// 先上传文件File file = new File(realPath);//实现文件的下载resp.addHeader("Content-Disposition","attachment;filename="+new String(file.getName().getBytes("gbk"),"ISO-8859-1"));//思路是:先以windows系统的GBK编码将字符串转成字节,再以浏览器的ISO-8859-1编码将字节转成字符try(InputStream is = new FileInputStream(file);OutputStream os = resp.getOutputStream();){//创建缓冲数组byte[] buffer = new byte[1024];int temp;while ((temp=is.read(buffer))!=-1){os.write(buffer,0,temp);}os.flush();}}
}
获取容器的基本附加信息
ServletContext简用sc表示
sc.getServerInfo();返回Servlet容器的名称和版本号
sc.getMajorVersion();返回Servlet容器所支持Servlet的主版本号
sc.getMinorVersion();返回Servlet容器所支持的Servlet的副版本号
web.xml配置
<servlet><servlet-name>baseInfo</servlet-name><servlet-class>com.test.GetBaseInfoServlet</servlet-class></servlet><servlet-mapping><servlet-name>baseInfo</servlet-name><url-pattern>/baseInfo.do</url-pattern></servlet-mapping>
代码:
//设置响应编码resp.setContentType("text/plain;charset=utf-8");//获取ServletContext对象ServletContext sc = this.getServletContext();//回Servlet容器的名称和版本号String serverInfo = sc.getServerInfo();//返回Servlet容器所支持Servlet的主版本号int majorVersion = sc.getMajorVersion();//返回Servlet容器所支持的Servlet的副版本号int minorVersion = sc.getMinorVersion();try(PrintWriter pw = resp.getWriter();){pw.println("servlet容器:"+serverInfo);//servlet容器:Apache Tomcat/9.0.80pw.println("支持的Servlet版本:"+majorVersion+"."+minorVersion);//支持的Servlet版本:4.0pw.flush();}
获取web.xml文件中的信息
<context-param><param-name>name</param-name><param-value>张三</param-value></context-param><context-param><param-name>age</param-name><param-value>20</param-value></context-param>
param-name:相当于key,param-value:相当于value
sc.getInitParameter("key");
读取web.xml文件标签中的配置信息
sc.getInitParameterNames();
读取web.xml文件中所有的param-name标签中的值
代码示例:
//设置响应编码格式resp.setContentType("text/plain;charset=utf-8");//获取ServletContext对象ServletContext sc = this.getServletContext();//Enumeration<String> initParameterNames = sc.getInitParameterNames();try(PrintWriter pw =resp.getWriter()){while (initParameterNames.hasMoreElements()){String key = initParameterNames.nextElement();String value = sc.getInitParameter(key);pw.println("key = "+key+",value : "+value);}pw.flush();}
全局容器
即将数据放到全局容器后不同的servlet都可以进行访问获取。
sc.setAttribute("key","ObjectValue");向全局容器添加数据
sc.getAttribute("key");从全局容器获取数据
sc.removeAttribute("key");从全局容器移除数据
代码示例:
@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置响应编码格式resp.setContentType("text/plain;charset=utf-8");//获取ServletContext对象ServletContext sc = this.getServletContext();String username = (String) sc.getAttribute("username");String password = (String)sc.getAttribute("password");try(PrintWriter pw =resp.getWriter()){pw.println("username:"+username);pw.println("password:"+password);pw.flush();}}@Overridepublic void init() throws ServletException {//全局信息一般是在容器初始化的时候添加的ServletContext sc= this.getServletContext();sc.setAttribute("username","root");sc.setAttribute("password","123456");}
ServletContext生命周期
当容器启动时就会创建ServletContext对象,并一直缓存该对象,直到容器关闭后该对象生命周期才结束。
ServletContext的生命周期很长,使用全局容器时不建议存放业务数据。
ServletConfig对象
ServletConfig对象对应web.xml文件中的节点,当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封装到一个ServletConfig对象中,我们可以通过这个对象获取节点中的配置信息,只能获取当前Servlet中的配置信息
<servlet><servlet-name>servletConfig</servlet-name><servlet-class>com.test.GetServletConfig</servlet-class><init-param><param-name>username</param-name><param-value>张三</param-value></init-param><init-param><param-name>password</param-name><param-value>123456</param-value></init-param></servlet><servlet-mapping><servlet-name>servletConfig</servlet-name><url-pattern>/servletConfig.do</url-pattern></servlet-mapping>
init-param标签只能在servlet标签里,多个name-value是这样并列的。
代码:
//设置响应编码resp.setContentType("text/plain;charset=utf-8");ServletConfig servletConfig = this.getServletConfig();Enumeration<String> names = servletConfig.getInitParameterNames();try(PrintWriter pw = resp.getWriter()){while (names.hasMoreElements()){String name=names.nextElement();String value=servletConfig.getInitParameter(name);pw.println("name = "+name+",value = "+value);}pw.flush();}
Cookie对象
Cookie对象和HttpSession对象的作用都是维护客户端浏览器与服务段的会话状态的对象。
Cookie是通过客户端浏览器实现会话的维持,支持跨二级域名
HttpSession是通过服务端来实现会话状态的维持
特点
- 使用字符串存储数据
- 使用key与value结果存储数据
- 单个Cookie存储数据大小限制在4097个字节
- Cookie存储的数据不支持中文,Servlet4.0支持
- Cookie是与域名绑定所以不支持跨一级域名访问
- Cookie对象是保存在客户端浏览器或系统磁盘中的
- Cookie分为持久化Cookie和状态Cookie
- 浏览器在保存同一域名所返回的Cookie数量是有限的,不同浏览器所支持的数量不同,chrome浏览器为50个。
- 浏览器每次请求时都会把当前访问的域名相关的Cookies在请求中提交到服务端。
Cookie对象的创建
cookie默认会随浏览器的关闭而销毁
//创建Cookie
Cookie cookie = new Cookie("key","value");
//添加Cookie
resp.addCookie(cookie);
代码示例
//创建CookieCookie cookie = new Cookie("word","helloWorld");//将cookie对象写回给客户端浏览器resp.addCookie(cookie);resp.setContentType("text/plain;charset=utf-8");try(PrintWriter pw = resp.getWriter()){pw.println("name:"+cookie.getName());pw.println("value:"+cookie.getValue());pw.println("Cookie创建好了");pw.flush();}
获取Cookie中的数据
浏览器每次请求时都会把与当前域名相关的Cookie在请求中提交到服务端,通过HttpServletResponse对象获取Cookie,返回Cookie数组
Cookie[] cookies = request.getCookies()
代码示例:
resp.setContentType("text/plain;charset=utf-8");//获取CookieCookie[] cookies = req.getCookies();try(PrintWriter pw = resp.getWriter()) {for (int i = 0; i < cookies.length; i++) {String name = cookies[i].getName();String value = cookies[i].getValue();pw.println("name:"+name);pw.println("value:"+value);}pw.flush();}
解决Cookie不支持中文问题
在Servlet4.0版本后的Cookie中name不能使用中文,但是value可以使用中文。
如果存储的数据里面含有中文,代码会直接出现异常,我们可以对含有中文的数据进行重新编码来解决该问题。
ULREncoder.encode("content","code");
将内容按照指定的编码方式做URL编码处理。
URLDecoder.decode("content","code")
将内容按照执行的编码做URL解码处理
代码示例:
//创建CookieCookie cookie = new Cookie(URLEncoder.encode("姓名","utf-8"), URLEncoder.encode("张三","utf-8"));//设置cookie有效时间cookie.setMaxAge(60);
解码:
//进行解码处理pw.println("name:"+ URLDecoder.decode(name,"utf-8"));pw.println("value:"+URLDecoder.decode(value,"utf-8"));
编码和解码的编码格式必须是一样的。
状态Cookie和持久化Cookie
状态cookie:Cookie对象仅仅会被缓存在浏览器所在的内存中,当浏览器关闭后Cookie对象也就会被销毁。
持久化Cookie:浏览器对Cookie做持久化处理,基于文件形式保存Cookie在系统的执行目录中。
当Cookie创建后默认是状态Cookie,可以使用cookie.setMaxAge();方法设置失效时间,单位为秒
一旦设置了失效时间,该Cookie就变成了持久化Cookie.浏览器就会将该Cookie持久化到磁盘里,当失效时间到达后删除。
注意:Cookie对于存储内容是基于明文方式存储的,安全性低,不要存放敏感数据,
在servlet4.0虽然支持中文,建议对Cookie中存放的数据做编码处理,可提高安全性。
HttpSession对象
特点:
保存在服务端,使用key与value结构存储数据,key是字符串类型,value是Object类型
存储数据大小没有限制
HttpSession对象的创建
通过request.getSession()方法创建
客户端浏览器在请求服务端资源时,
如果请求中没有jsessionid,getSession()方法将会为这个客户端浏览器创建一个新的HttpSession对象,并为这个HttpSession对象生成jsessionid,在响应中通过状态Cookie写回给客户端浏览器,
如果在请求中包含了jsessionid,getSession()方法则是根据这个ID返回与这个客户端浏览器对应的HttpSession对象。
getSession()方法重载方法getSession(true|false);
当参数为true时与getSession()方法相同,
当参数为false时则只去根据jsessionid查找是否有与这个客户端浏览器对应的HttpSession对象,如果有则返回,如果没有则不会创建新的HttpSession对象。
HttpSession对象常用方法
方法 | 描述 |
setAttribute("key",value) | 将数据存储到HttpSession对象中 |
getAttribute("key") | 根据key获取HttpSession中的数据,返回Object |
getAttributeNames() | 获取HttpSession中所有的key,返回枚举类型 |
removeAttribute("key") | 根据key删除HttpSession中的数据 |
getId() | 获取当前HttpSession的SessuonID,返回字符串类型 |
通过HttpSession对象存数据
resp.setContentType("text/plain;charset=utf-8");//创建HttpSession对象HttpSession session = req.getSession();//添加数据session.setAttribute("name","jack");session.setAttribute("age",30);String sessionId = session.getId();System.out.println(sessionId);try(PrintWriter pw = resp.getWriter()){pw.println(sessionId);pw.println("存好数据了");pw.flush();}
通过HttpSession取数据
resp.setContentType("text/plain;charset=utf-8");//创建HttpSession对象HttpSession session = req.getSession();//获取所有的name
// Enumeration<String> attributeNames = session.getAttributeNames();try(PrintWriter pw = resp.getWriter()) {
// while (attributeNames.hasMoreElements()) {
// String name = attributeNames.nextElement();
// }//通过key获取数据pw.println(session.getAttribute("name"));pw.println(session.getAttribute("age"));pw.flush();}
HttpSession对象的销毁方式
- 通过web.xml文件指定销毁时间
- 通过HttpSession对象中的invalidate()方法销毁当前HttpSession对象
web.xml文件指定超时时间,当达到超时时间后容器就会销毁该HttpSession对象,单位为分钟
<session-config><session-timeout>1</session-timeout></session-config>
时间计算是根据最后一次访问请求时间作为起始时间的,只要用户继续访问,服务器就会更新HttpSession对象的最后访问时间。
如果是在Tomcat的web.xml配置了超时时间,相当于配置了全局的HttpSession超时时间,如果同时也在web项目中配置了超时时间,则会以web项目中的超时时间为准。
invalidate()是HttpSession对象中提供的用于销毁当前HttpSession的方法。
HttpSession对象的生命周期
HttpSession对象生命周期中没有个固定的创建时间和摧毁时间。什么时候创建取决于什么时候调
用getSession(),HttpSession对象的销毁时间取决于超时时间以及调用invalidate();
如果没有超过超时时间或者通过invalidate()摧毁,则会一直存在。
默认超时时间为30分钟。
HttpSession与Cookie的区别
- cookie数据存在浏览器或者系统的文件里,HttpSession中的数据存放在服务器中
- cookie是不安全的,而HttpSession是安全的
- 单个cookie存储数据不能超过4k,很多浏览器都限制一个域名保存cookie的数量,HttpSession没有容量以及数量的限制
使用建议:
HttpSession中的数据存放在服务端的,安全性比较高。我们可以在HttpSession对象中存储数据,但是由于它的生命周期不固定,不建议存放业务数据,一般用来存放用户登录信息。