目录
一.ServletContext对象介绍
ServletContext
官方叫
Servlet
上下文。服务器(eg:Tomcat)会为每一个
Web
应用创建一个
ServletContext
对象。这个对象全局唯一,而且
Web
应用
中的所有
Servlet
都共享这个对象。所以叫全局应用程序共享对象。
ServletContext
对象的作用
- 相对路径转绝对路径
- 获取容器的附加信息
- 读取配置信息
- 全局容器
二.ServletContext对象的使用
1.相对路径转绝对路径
context.getRealPath("path")
该方法可以将一个相对路径转换为绝对路径,在文件上传与下载时,需要用到该方法做路径的转换。
静态资源应该放到web目录下或 web子目录下,相对路径是指相对于项目的根目录而言的,比如本节在web下创建image,将heat.jpg放到image下,则此时heat.jpg的相对路径是
"image/heat.jpg"
之前已经讲过将项目自动部署到Tomcat的webapps目录下了,这里又新增了image文件夹,部署后如果发现webapps中的项目目录下仍没有image,则将项目目录散删除,然后冲重新部署。
如果不删除,我遇到了如下错误:
以上篇文章的文件下载案例进行稍加改造,
FileDownServlet.java:
package com.first.servlet;
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 FileDownServlet 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对象
ServletContext servletContext=this.getServletContext();
//路径转换
String realPath=servletContext.getRealPath("image/heat.jpg");
System.out.println("绝对路径:"+realPath);
//读取下载文件
File file=new File(realPath);
//用字节输入流将文件读入
InputStream is=new FileInputStream(file);
/*
is.available()返回is的大小,因为一般大太大的东西一次性读入就行,
大的话可以设置一次读1024B,2048B等
*/
//缓冲区
byte[] buff =new byte[is.available()];
//将文件读入buff中
is.read(buff);
//在响应中添加附加信息
resp.addHeader("Content-Disposition", "attachment; filename="
+new String(file.getName().getBytes("gbk"),"iso-8859-1"));
//产生响应
//字节输出流
OutputStream os=resp.getOutputStream();
os.write(buff);
os.flush();
os.close();
}
}
输出:
控制台输出绝对路径:
绝对路径:D:\Tomcat\apache-tomcat-9.0.34\webapps\ajaxDemo\image\heat.jpg
2.获取容器的附加信息
servletContext.getServerInfo()
返回
Servlet
容器的名称和版本号
servletContext.getMajorVersion()
返回
Servlet
容器所支持
Servlet
的主版本号。
servletContext.getMinorVersion()
返回
Servlet
容器所支持
Servlet
的副版本号。
GetBaseInfoServlet.java:
package com.first.servlet;
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.IOException;
import java.io.PrintWriter;
public class GetBaseInfoServlet 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对象
ServletContext servletContext=this.getServletContext();
//获取容器信息
String servletInfo=servletContext.getServerInfo();
//获取容器支持Servlet的主版本号
int majorVersion=servletContext.getMajorVersion();
//获取容器支持Servlet的副版本号
int minorVersion=servletContext.getMinorVersion();
//设置响应编码,消除浏览器显示中文乱码
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw=resp.getWriter();
pw.println("容器基本信息:"+servletInfo);
pw.println("容器支持Servlet的版本号:"+majorVersion+"."+minorVersion);
pw.flush();
pw.close();
}
}
web.xml配置:
<servlet>
<servlet-name>GetBaseInfoServlet</servlet-name>
<servlet-class>com.first.servlet.GetBaseInfoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetBaseInfoServlet</servlet-name>
<url-pattern>/getBaseInfo.do</url-pattern>
</servlet-mapping>
输出:
容器基本信息:Apache Tomcat/9.0.34
容器支持Servlet的版本号:4.0
3.获取web.xml文件中的信息
servletContext.getInitParameter("key")
该方法可以读取
web.xml
文件中标签中的配置信息。
servletContext.getInitParameterNames()
该方法可以读取
web.xml
文件中所有
param-name
标签中的值。
配置web.xml中的键值对:
注意键值对的位置,要放在最上面
ContextReadInfoServlet.java:
package com.first.servlet;
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.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
public class ContextReadInfoServlet 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对象
ServletContext servletContext=this.getServletContext();
//获取所有的<param-name>的值
Enumeration<String> initParameterNames=servletContext.getInitParameterNames();
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw=resp.getWriter();
while(initParameterNames.hasMoreElements()){
String name=initParameterNames.nextElement();
String value=servletContext.getInitParameter(name);
pw.println("Name:"+name+" = Value:"+value);
}
pw.flush();
pw.close();
}
}
在web.xml中配置servlet:
<servlet>
<servlet-name>ContextReadInfoServlet</servlet-name>
<servlet-class>com.first.servlet.ContextReadInfoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContextReadInfoServlet</servlet-name>
<url-pattern>/readInfo.do</url-pattern>
</servlet-mapping>
输出:
Name:key1 = Value:未来
Name:key2 = Value:怎么样
4.全局容器
servletContext.setAttribute("key",ObjectValue)
向全局容器中存放数据。
servletContext.getAttribute("key")
从全局容器中获取数据。
servletContext.removeAttribute("key")
根据
key
删除全局容器中的
value
。
可以把servletContext看做是全局容器对象。
当servlet被实例化以后,tomcat会立即调用一次init来完成一些初始化的动作。所以我们可以在init中向全局容器添加一些信息 。
GlobalContainerServlet.java:
package com.first.servlet;
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.IOException;
import java.io.PrintWriter;
public class GlobalContainerServlet 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对象
ServletContext servletContext =this.getServletContext();
//从全局容器中获取数据
String value1= (String) servletContext.getAttribute("key1");
String value2= (String) servletContext.getAttribute("key2");
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw=resp.getWriter();
pw.println(value1);
pw.println(value2);
pw.flush();
pw.close();
}
@Override
public void init() throws ServletException {
//获取ServletContext对象
ServletContext servletContext =this.getServletContext();
//向全局容器中存放数据
servletContext.setAttribute("key1","一片舟");
servletContext.setAttribute("key2","流浪");
}
}
配置web.xml:
<servlet>
<servlet-name>GlobalContainerServlet</servlet-name>
<servlet-class>com.first.servlet.GlobalContainerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GlobalContainerServlet</servlet-name>
<url-pattern>/global.do</url-pattern>
</servlet-mapping>
输出:
体现全局性,这个项目的其他servlet也可以访问全局容器
访问http://localhost:8888/ajaxDemo/global.do
再把从全局容器中获取数据的代码复制到其他servlet试试,如下
访问http://localhost:8888/ajaxDemo/readInfo.do
三.ServletContext对象生命周期
当容器启动时会创建
ServletContext
对象并一直缓存该对象,直到容器关闭后该对象生命周期结束。
ServletContext
对象的生命周期
非常长,所以在使用全局容器时不建议存放业务数据(而是放到数据库当中)。 一般在全局容器放置一些永远不变的配置信息。
四.ServletConfig对象
ServletConfig
对象对应
web.xml
文件中的节点。当
Tomcat
初始化一个
Servlet
时,会将该
Servlet
的配置信息,封装到一个
ServletConfig
对象中。我们可以通过该对象读取节点中的配置信息。
servletConfig.getInitParameter("key")
该方法可以读取
web.xml文件中
<servlet>
标签中
<init-param>
标签中的配置信息。
servletConfig.getInitParameterNames()
该方法可以读取
web.xml文件中当前
<servlet>
标签中所有
<init-param>
标签中的值。
使用上面两个函数时只能在当前servlet中去读取配置信息,因为一个servlet对象对应一个ServletConfig对象,这也是和ServletContext读取web.xml配置信息的区别之一。
配置web.xml:
<servlet>
<servlet-name>GetConfigServlet</servlet-name>
<servlet-class>com.first.servlet.GetConfigServlet</servlet-class>
<init-param>
<param-name>key1</param-name>
<param-value>嘻嘻</param-value>
</init-param>
<init-param>
<param-name>key2</param-name>
<param-value>吼吼</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>GetConfigServlet</servlet-name>
<url-pattern>/config.do</url-pattern>
</servlet-mapping>
GetConfigServlet.java:
package com.first.servlet;
import javax.servlet.ServletConfig;
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.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
public class GetConfigServlet 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对象
ServletConfig servletConfig=this.getServletConfig();
//读取web.xml文件中当前<servlet>标签中所有<init-param> 标签中的值,即key
Enumeration<String> initParameterNames=servletConfig.getInitParameterNames();
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw=resp.getWriter();
while (initParameterNames.hasMoreElements()){
String name=initParameterNames.nextElement();
//根据key得到value
String value=servletConfig.getInitParameter(name);
pw.println("name:"+name+"value:"+value);
}
pw.flush();
pw.close();
}
}
输出: