这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。
ServletContext 的讲解
// 例如一篇文章的上下连接。上下文语境
ServletContext servletContext = this.getServletContext();
Web 容器在启动的时候,一个Web 容器肯定可以和多个Servlet 交互。
比如说我在京东登陆了,这个登陆信息肯定会被带到多个页面,跳到其他页面也会发现自己也是登陆状态的。这个肯定不是自己做的,需要一个“中间商”去做。这个ServletContext 就可以理解为这个“中间商”。
所以在Web 容器在启动的时候,它会为每个Web 程序都创建一个对应的ServletContext 对象,它代表了当前的Web 应用。
参考上面的代码,那个网站,就是由servletContext 这个对象来管理的。因为这个对象,就代表了这个Web 应用。
ServletContext 的应用场景
- 共享数据。在某个Servlet 中保存的数据,可以在另外一个Servlet 中拿到。
比如说注册了三个Servlet,Servlet1,Servlet2,Servlet3 对应的url 分别为/s1,/s2,/s3。如果Servlet2 想读取Servlet1 中的某个数据,就可以使用ServletContext。
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 例如一篇文章的上下连接。上下文语境
ServletContext servletContext = this.getServletContext();
String userName = "abc";
// 将一个数据保存到ServletContext 中
servletContext.setAttribute("userName", userName);
}
}
在Servlet1 中,将userName 设置进入了ServletContext。
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 例如一篇文章的上下连接。上下文语境
ServletContext servletContext = this.getServletContext();
// 从ServletContext 中取数据
String userName = (String) servletContext.getAttribute("userName");
resp.getWriter().println(userName);
}
}
这样,在访问第一个Servlet 之后,再访问第二个Servlet,就可以取出对应的userName 并展示了。
- 利用ServletContext 读取web.xml 全局初始化参数。我们可以在web.xml 中写入一些web 应用初始化参数配置,如连接db 的url配置。
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/abc</param-value>
</context-param>
上面代码在写入web.xml 之后,可以在下述java 代码中拿到。
public class ServletParaTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 例如一篇文章的上下连接。上下文语境
ServletContext servletContext = this.getServletContext();
// 从ServletContext 中取数据
String userName = (String) servletContext.getInitParameter("url");
resp.getWriter().println(userName);
}
}
- 请求转发。
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入此页面");
// 例如一篇文章的上下连接。上下文语境
ServletContext servletContext = this.getServletContext();
// 转发的请求路径,也即此请求会被转发到哪个页面
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/testDispatcher");
// requestDispatcher 只是在这里做了转发的作用,然后把req & resp 写入
requestDispatcher.forward(req, resp);
}
}
- 读取资源文件。比如在resource 文件中新建的配置文件“db.properties”中写入如下数据。
username=root
pwd=123456
正常java 代码读取properties 文件的时候,写如下代码:
可以选择load 的两个方法,区别就是一个是流,一个是Reader。正常的时候都是用流,流都是按照File 地址生成的,根据文件绝对地址来就可以。
但是现在是web 应用,没有办法保证绝对地址。
我们观察properties 文件会生成到web 的哪个地方。
运行之后,我们发现properties 文件存在于:
即:WEB-INF 文件夹下的classes 文件夹内。所以可以得出结论,resource 文件默认路径是calsses 文件,也即classpath(类路径)。
同时我们也可以观察到,源代码main 文件夹下的java 文件和resource 文件中的内容,最终都生成到target 的classes 文件夹中。所以对于classpath 就比较好理解了。(类路径)
回归正题,如何通过ServletContext 读取配置文件内容。
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 例如一篇文章的上下连接。上下文语境
ServletContext servletContext = this.getServletContext();
// 转发的请求路径,只是在这里做了转发的作用
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/testDispatcher");
InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(is);
String username = properties.getProperty("username");
String pwd = properties.getProperty("pwd");
resp.getWriter().println(userName + " " + pwd);
}
}
在之后,获取共享数据,一般都用Session,Cookie 这些;初始化参数也不会使用到标签;请求转发一般用request 去做;读取资源文件,之后会用到类加载或者反射的方法。
即几乎不太会用到ServletContext。这里主要是讲一个ServletContext web 应用的思路。上述内容在之后会讲到。