ServletContext对象
ServletContext对象官方也称servlet上下文。服务器会为每一个Web应用创建一个ServletContext对象,这个对象全局唯一,而且Web应用中所有的Servlet都共享这个对象。
ServletContext对象的作用
相对路径转绝对路径
servletContext.getRealPath("Path");
该方法可以将一个相对路径转成绝对路径,在文件的上传和下载时需要用到该方法作为路径的转换。
示例:
java
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 {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected 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配置
java
<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>
代码:
java
//设置响应编码
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.80
pw.println("支持的Servlet版本:"+majorVersion+"."+minorVersion);//支持的Servlet版本:4.0
pw.flush();
}
获取web.xml文件中的信息
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标签中的值
代码示例:
java
//设置响应编码格式
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");从全局容器移除数据
代码示例:
java
@Override
protected 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();
}
}
@Override
public 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中的配置信息
XML
<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是这样并列的。
代码:
java
//设置响应编码
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默认会随浏览器的关闭而销毁
java
//创建Cookie
Cookie cookie = new Cookie("key","value");
//添加Cookie
resp.addCookie(cookie);
代码示例
java
//创建Cookie
Cookie 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数组
java
Cookie[] cookies = request.getCookies()
代码示例:
java
resp.setContentType("text/plain;charset=utf-8");
//获取Cookie
Cookie[] 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解码处理
代码示例:
java
//创建Cookie
Cookie cookie = new Cookie(URLEncoder.encode("姓名","utf-8"), URLEncoder.encode("张三","utf-8"));
//设置cookie有效时间
cookie.setMaxAge(60);
解码:
java
//进行解码处理
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对象存数据
java
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取数据
java
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对象,单位为分钟
XML
<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对象中存储数据,但是由于它的生命周期不固定,不建议存放业务数据,一般用来存放用户登录信息。