1、ServletContext类详解
Web容器在启动时,会为每一个Web
项目创建一个对应的ServletContext
对象。它是当前项目中所有Servlet
实例之间信息交互的“中间商”。(参见“Servlet的运行原理”)
注:一个Web项目对应一个ServletContext
。(即:同一个Web项目中的所有servlet
实例共用同一个ServletContext
对象。)
2、常见应用
ServletContext
的常见应用场景主要包括:
-
数据共享:在一个
Servlet
中保存的数据,可以在另一个Servlet
中使用。 -
获取初始化参数
-
请求转发
-
读取资源文件
3、使用ServletContext实现:数据共享
(1)在上述父项目下再使用Maven模板新建一个MavenWeb子项目:servlet-02
。
(2)同样地,为了避免以后出现兼容性问题,建议我们先将该子项目中的web.xml
文件替换成“web-app_4_0”
版本。
(3)同样地,在该子项目的main
文件夹下新建一个java
文件夹和一个resource
文件夹,并将它们分别标记为“源码根目录”和“资源根目录”。
(4)编译父项目或子项目,此时父项目与子项目的目录结构如下图所示。
(5)配置Tomcat服务器,deploy(发布)servlet-02:war
包,并为该子项目添加虚拟路径映射:/s2
。
注:如果只发布某一子项目,那么其它子项目的war
包和虚拟路径映射可以删除。若不删除,则一起发布。
(6)在该子项目的java目录下新建一个com.atangbiji.servlet
包,并在该包下新建一个Servlet1
类,用于将数据以“键-值“对的形式保存在ServlContex对象中。同样地,让Servlet1
类继承(extends)HttpServlet
类,以实现Servlet
接口。然后,在Servlet1
类中重写doGet
和doPost
方法。
Servlet1.java
文件:
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();//获取ServlContex对象
String usernameVal = "阿汤笔迹";
servletContext.setAttribute("username",usernameVal);//将数据以“键-值“对的形式保存在ServlContex对象中
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp); //因为`get`和`post`只是不同的Http请求方式,所以它们之间可以相互调用。
}
}
(7)同样地,com.atangbiji.servlet
包下再新建一个Servlet2
类,用于获取ServlContex对象中保存的“键-值“对。
Servlet2.java
文件:
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();//获取ServlContex对象
String usernameVal = (String)servletContext.getAttribute("username");//从ServletContext中获取username的值
resp.setHeader("Content-Type", "text/html; charset=utf-8");
resp.getWriter().print("Servlet2从ServletContext中获取到username的值为:" + usernameVal);//在页面上输出响应
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp); //因为`get`和`post`只是不同的Http请求方式,所以它们之间可以相互调用。
}
}
(8)同样地,在该子项目的Web
配置文件(web.xml)中注册(映射)我们自己编写的两个Servlet
,并为它们分别提供一个浏览器可以访问的路径。
web.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<servlet>
<servlet-name>SetServletContext</servlet-name>
<servlet-class>com.atangbiji.servlet.Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SetServletContext</servlet-name>
<url-pattern>/setVal</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>GetServletContext</servlet-name>
<servlet-class>com.atangbiji.servlet.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetServletContext</servlet-name>
<url-pattern>/getVal</url-pattern>
</servlet-mapping>
</web-app>
(9)在IDEA中启动Tomcat。在浏览器中先输入http://localhost:8080/s2/setVal
加载Servlet1
,然后再输入http://localhost:8080/s2/getVal
,访问结果如下:
注:我们可以通过IDEA为我们提供的Web
窗口来查看Web项目的结构。

4、使用ServletContext实现:获取初始化参数
(1)在Web.xml
文件中配置Web
应用的初始化参数(如:连接mybatis
的url
)。
Web.xml
文件:
<!-- 配置Web应用初始化参数(连接mybatis的url) -->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
(2)在该子项目com.atangbiji.servlet
包下新建一个Servlet3
类,用于获取Web
应用的初始化参数。同样地,让Servlet3
类继承HttpServlet
类,以实现Servlet
接口。然后,在Servlet3
类中重写doGet
和doPost
方法。
Servlet3.java
文件:
public class Servlet3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();//获取ServlContex对象
String url = servletContext.getInitParameter("url");//获取连接mybatis的url
resp.getWriter().print(url);//在页面上输出响应
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp); //因为`get`和`post`只是不同的Http请求方式,所以它们之间可以相互调用。
}
}
(3)同样地,在该子项目的Web
配置文件(web.xml)中注册(映射)我们自己编写的Servlet
,并为它提供一个浏览器可以访问的路径。
web.xml
文件:
<servlet>
<servlet-name>GetInitParameter</servlet-name>
<servlet-class>com.atangbiji.servlet.Servlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetInitParameter</servlet-name>
<url-pattern>/getInitParameter</url-pattern>
</servlet-mapping>
(4)在IDEA中启动Tomcat。在浏览器中输入http://localhost:8080/s2/getInitParameter
,访问结果如下:
5、使用ServletContext实现:请求转发
5.1、什么是请求转发
请求转发(RequestDispatcher)指的是:一个web资源(Servlet1
)接受到客户端的请求后,通知服务器去调用另外一个web资源(Servlet2
)进行处理。
5.2、请求转发的工作原理
在 Servlet
中,通常使用 forward()
方法将当前请求转发给其他的Web
资源进行处理。请求转发的工作原理如下图所示:
5.3、请求转发的特点
-
请求转发是服务器端的行为,浏览器不知道在服务器内部发生了转发行为,更无法得知转发的次数。
-
请求转发之后,浏览器地址栏中的 URL 不会发生变化。
-
请求转发不支持跨域访问,只能跳转到当前应用中的资源。
-
参与请求转发的
Web
资源之间共享同一request
对象和response
对象。 -
只有转发到最后一个
Web
资源时,生成的响应才会被发送到客户端。
5.4、请求转发的实现
(1)在该子项目com.atangbiji.servlet
包下新建一个Servlet4
类,用于将访问Servlet4的请求转发到Servlet3的请求路径上来。同样地,让Servlet4
类继承HttpServlet
类,以实现Servlet
接口。然后,在Servlet4
类中重写doGet
和doPost
方法。
Servlet4.java
文件:
public class Servlet4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();//获取ServlContex对象
//获取访问该Servlet的请求将要转发的路径
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/getInitParameter");
//调用forward方法实现请求转发
requestDispatcher.forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp); //因为`get`和`post`只是不同的Http请求方式,所以它们之间可以相互调用。
}
}
(2)同样地,在该子项目的Web
配置文件(web.xml)中注册(映射)我们自己编写的Servlet
,并为它提供一个浏览器可以访问的路径。
web.xml
文件:
<servlet>
<servlet-name>RequestDispatcher</servlet-name>
<servlet-class>com.atangbiji.servlet.Servlet4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestDispatcher</servlet-name>
<url-pattern>/requestDispatcher</url-pattern>
</servlet-mapping>
(3)在IDEA中启动Tomcat。在浏览器中输入http://localhost:8080/s2/requestDispatcher
,此时服务器会将我们的请求转发到/getInitParameter
路径上来。访问结果如下:
注:请注意请求转发与请求重定向的区别,我们将在介绍重定向是对比说明。
6、ServletContext应用示例:读取资源文件
(1)在该子项目的resources
文件夹下新建一个db.properties
文件。
db.properties
文件:
username = root
password = 123456789
(2)在该子项目com.atangbiji.servlet
包下新建一个propertiesServlet
类,用于读取db.properties
资源文件。同样地,让propertiesServlet
类继承HttpServlet
类,以实现Servlet
接口。然后,在propertiesServlet
类中重写doGet
和doPost
方法。
propertiesServlet.java
文件:
public class propertiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();//获取ServlContex对象
//以数据流的方式获取资源
InputStream stream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");//项目打包后的相对路径
Properties prop = new Properties();
//加载数据流
prop.load(stream);
//获取属性值
String username = prop.getProperty("username");
String password = prop.getProperty("password");
//在页面上输出响应
resp.getWriter().print(username + ":" + password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp); //因为`get`和`post`只是不同的Http请求方式,所以它们之间可以相互调用。
}
}
(3)同样地,在该子项目的Web
配置文件(web.xml)中注册(映射)我们自己编写的Servlet
,并为它提供一个浏览器可以访问的路径。
web.xml
文件:
<servlet>
<servlet-name>PropertiesServlet</servlet-name>
<servlet-class>com.atangbiji.servlet.propertiesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PropertiesServlet</servlet-name>
<url-pattern>/propertiesServlet</url-pattern>
</servlet-mapping>
(4)在IDEA中启动Tomcat。在浏览器中输入http://localhost:8080/s2/propertiesServlet
,访问结果如下:
注:由于Maven的“约定大于配置”思想,我们以后可能会遇到我们自己写的配置文件(如:我们配置文件*.xml
写在了项目中的Java
目录下)无法被导出或者无法生效的问题。该问题的解决方法是:在pom.xml
的<build>……</build>
中配置resources
,修改Maven约定的过滤条件,来防止我们的资源导出失败。
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<!--选择需要导出资源的路径,可以选择多个-->
<resource>
<directory>src/main/resources</directory>
<!--写入需要导出的什么类型的文件-->
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--不去过滤这些文件-->
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--不去过滤这些文件-->
<filtering>false</filtering>
</resource>
</resources>
</build>
(本讲完,系列博文持续更新中…… )
关注 “阿汤笔迹” 微信公众号,获取更多学习笔记。
原文始发于微信公众号(阿汤笔迹):ServletContext 的 4 个常见应用!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/248964.html