ServletConfig和ServletContext
在初步接触Java Servlet之后,会发现一个HTTPServlet
有这么两个附属对象:ServletConfig
和ServletContext
,两者长得很像,又有着不少相同的方法(getAttribute()
, getInitParameter()
, getServletName()
/getServletNames()
),在网上搜了一下,发现有讲述两者之间的区别的博客,但是我是在理解之后才看懂的。。
在此简述一下使用Tomcat运行Web服务的三大主要层次,我依次将其命名为Server, Application和Servlet。其中Server指的是Tomcat本身,可以理解为一台服务器上一般只会跑一个Tomcat,所有需要借助Tomcat实现的Web服务都会依赖于这一个Tomcat实例。其次就是Application了,这就是上面所说,需要借助Tomcat实现的服务。一个Web服务就是一个Web项目,内部可以有复杂的Java逻辑代码,可以包括与数据库交互,等等。一个Servlet指的是提供单一Web功能的程序单位。
Application举例说明的话就是登陆系统,从登陆到连接后台,查看数据,修改用户信息、密码等,算是一个完整的后台管理系统服务,仅靠单一的URL是很难(但是是可以)实现整个功能的,起码作为一个便于维护和扩展的项目来说,都会需要多个URL来实现不同的功能,因为这样至少光靠URL地址就能有效地组织整合不同的功能了。这是Application。而Servlet实现的是原子操作,比如说后台管理系统中的登陆,或是获取用户信息,或是修改密码这种单一而清晰的任务。
然后就可以说明了:ServletConfig
是Servlet层面的,每个Servlet都有自己独立的ServletConfig
;而ServletContext
是Application层面的,同一服务/项目下的所有Servlet可以通过ServletContext
共享数据。那为什么ServletContext
不是Server层面呢?ServletContext
中可以存放应用的重要数据,出于安全考虑,一是防止数据窃取,二是防止篡改,不论是无意还是有意。
再仔细看看ServletContext
的方法的话,会发现有一个方法名为getServletNames()
,返回的是一个Enumeration
,也就是说具有多个Servlet名称。相对地,ServletConfig
的方法名为getServletName()
,返回一个String
。这下就更加清晰了,显然一个Servlet只应该有一个名字,那么ServletContext
肯定就是Servlet层面之上的了。
此外有一个小坑:声明Application级别的初始变量是在web-app
建立context-param
子节点,使用ServletContext
的getInitParameter()
方法获取;Servlet级别的初始变量则需要在web-app
节点下先新建servlet
子节点,再在servlet
子节点下新建init-param
节点定义,使用ServletConfig
的getInitParameter()
方法获取。其中两个param的定义结构相同,使用param-name
子节点定义变量名,param-value
子节点定义变量值,而显然这个值只能定义为String
类型。
例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
...
<context-param>
<param-name>contextInitParam</param-name>
<param-value>someValue</param-value>
</context-param>
<servlet>
<servlet-name>demoServlet</servlet-name>
<servlet-class>tk.esperz.demoServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>servletInitParam</param-name>
<param-value>otherServletsCannotSeeMe</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>/demo.do</url-pattern>
</servlet-mapping>
</web-app>
其中为该Web项目定义了一个名为contextInitParam
的上下文初始化变量,值为someValue
,所有该项目中的Servlet都可以通过ServletContext.getInitParameter("contextInitParam")
获取;为名为demoServlet
的Servlet定义了一个名为servletInitParam
的初始化变量,值为otherServletsCannotSeeMe
,仅在该Servlet内可以通过ServletConfig.getInitParameter("servletInitParam")
获取。凡是用错了方法的都会返回null
哦