标签:
配置一个Servlet时,一般要在自己项目中的web.xml配置<servlet>与<servlet-mapping>两个元素,但con/web.xml中为我们提供了一个名叫 invoker 的Servlet(5.5.30中已被注释掉,我们需要去掉),如下:
<servlet>
<servlet-name>invoker</servlet-name>
<servlet-class>
org.apache.catalina.servlets.InvokerServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
它可以根据URL中提供的Servlet类信息而自动激活这个Servlet,而不需要我们再在自己的应用中的web.xmlj里另外配置一<servlet>,只需要配置 <servlet-mapping>即可,配置如下:
<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
如现在有这样一个Servlet:mypak.HelloWorldServlet,则这样可以访问http://localhost:8080/myapp/servlet/mypak.HelloWorldServlet。注意,每个Web应用程序中为Servlet激活器所映射的访问路径可以各不相同,但必须以“/*”结尾(比如这里去掉前面的 /servlet 也可以)。经过这样的设置以后,即使某个Servlet程序没有在web.xml文件中进行注册,我们只需要将Servlet激活器所映射的访问路径中的通配符(*)替换为这个Servlet的完整类名,就可以通过Servlet激活器来调用这个Servlet程序。
如果某个Servlet的映射路径(<servlet-mapping>元素中的<url-pattern>元素的值)仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlete。凡是在web.xml文件中找不到匹配的<servlet-mapping>元索的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为缺省Servlet。由于<tomcat的安装目录>\conf\web.xml文件的设置信息对该服务器上的所有Web应用程序都起作用,所以,服务器上的所有Web应用程序的缺省Setvlet都是org.apacbe.catalina.servlets.DefaultServlet。
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
…
</servlet>
当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Setvlet,而这个缺省Servlet的处理方式通常是把静态资源中的内容按字节原封不动地读出来,然后再按字节流原封不动传递给客户端,并且生成一些响应消息头字段,例如,根据静态资源的扩展名所映射的MIME类型生成Content-Type头字段,根据静态资源的大小生成Content-Length头字段。
如果将conf/web.xml 下的默认Servlet注释掉,则非Servlet与Jsp资源将不能访问:
<!--servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping-->
注意,缺省Servlet在输出静态页面内容后,会将静态页面内容暂时在服务器上的缓存中保存5秒中,也就是在这5秒中内如果又来访问这个静态的页面(根据你请求的URL来分辨,如果与上次相同则认为是请求的同一资源),将会得到相同的静态页面内容,即使你立即修改了这个静态页面的内容。但这会有个问题:如果静态页面是在服务上动态生成的,虽然它是静态页面,但里面的内容却是动态的,这就会使浏览器在5秒内不会看到最新的内容。另外,当请求一个静态页面时,缺少Servlet会自动在响应头上加上 Last-Modified 头,如果静态页面不修改,缺少Servlet会回应 304 状态码,表示没有修改,浏览器可以从缓存中读取。
1、 Bootstrap类装载器负责加载Java核心名中的类<java_home>\jre\lib\rt.jar。
2、 ExtClassLoader负责加载存在<JAVA_HOME>/jre/lib/ext上当下的Java名中的类。
3、 AppClassLoader负责加载应用程序中的类,即CLASSPAH环境变量设置的目录中的类。但Tomcat的启动脚本catalina.bat 已将CLASSPATH环境变量原来的设置值完全清除,也就是说,Tomcat不会继承操作系统上原来设置好的CLASSPATH环境变量的内容,而是将CLASSPATH一半变量重新设置成了如下两个jar包:<CATALINA_HOME>/bin/bootstrap.jar、<JAVA_HOME>/lib/tools.jar。
4、 Common类装载器负责从<CATALINA_HOME>/common/classes中的.class 类文件和<CATALINA_HOME>/common/lib中的jar包加载类。Common类装载器加载的类对Tomcat服务器内核和每个Web应用程序都可见,例如,servlet.jar中包含的类既要被Tomcat服务器内核使用,又要被每个Web应用程序便用,所以,它需耍放置在CATALINA_HOME/common/lib中。
5、 Catalina类装载器负<CATALINA_HOME>/server/classes中的 .class 类文件和<CATALINA_HOME>/server/lib中的jar包加载类。Catalina类装载器加载的类只对Tomcat服务器内核可见,对每个Web应用程序完全不可见,所以,只想让Tomcat服务器内核使用而不想让Web应用程序便用的类应放置在Catalina类装载器的搜索目录中。对于运行Tomcat内核的线程,它的上下文类装载器就是Catalina类装载器。
6、 Shared类装载器负责从<CATALINA_HOME>/share/claases中的 .class 类文件和<CATALINA_HOME>/share/lib中的jar包加载类。Catalina类装载器加载的类只对所有的Web应用程序可见,对Tomcat服务器内核完全不可见。
7、 WebappX类装载器负责从当前Web应用程序的/WEB-INF/classes中的.class类文件/WEB-INF/lib中的Jar包加载类。WebappX类装载器加载的类只对当前Web应用程序可见,对其他wb应用程序不可见。对于运行每个节Web应用程序的线程,它们的上下文类装载器就是它们各自的WebappX类装载器。San公司在Servlet规范中建议WebappX类装载器不应按照标准委托模式来设计,而是应该由WebappX类装载器自己先加载某个类,只有自己加载不了时,才委托父级的类装载器进行加载,除了WebappX类装载器之外,Servlet引擎中的其他类装载器都遵循标准委托棋式。但是,许多Servlet引攀开发商认为这个建议没有什么意义,所以,他们并没有采纳Servlet规范的建议,而是仍然按照标准委托模式设计了他们的WebappX类装载器,例如,笔者通过实验发现Tomcat 4.中的WebappX类装载器采用的就是标准委托模式。
<servlet>
<servlet-name>test.Forward</servlet-name>
<servlet-class>test.Forward</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test.Forward</servlet-name>
<url-pattern>/demo/hello.html</url-pattern>
</servlet-mapping>
上面Servlet的url-pattern配置的是 /demo/hello.html ,注意,demo 不是应用目录(虚拟目录或Web站点),现假设应用目录为myapp,则访问的路径为 http://localhost:8080/myapp/demo/hello.html。另外,如果在应用目录下真存在 /demo/hello.html这样一个静态页面,这里也不会去调用它,除非这里没有配这个Servlet。
Servlet映射到URL中也可以使用 * 通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,在 * 前面不能有目录分隔符“/”,例如“*.do”表示匹配以“.do”结尾的所有URL;另一种是以“/”开头,并以“/*”结尾,例如“/*”表示匹配当前Web应用程序下的所有URL,“/action/*”表示匹配当前Web应用程序下的“/action”子路径下的所有URL。另外,在匹配时,如果与多个路径都匹配,则优先使用最精确的那个Servlet。
Sevlet引擎将代表Servlet容器的对象和Servlet的配置参数信息(web.xml中所配置的)一并封装到一个称为ServletConfig的对象中,并在初始化Servlet实例对象时传递给该Servlet。Servlet引擎装载并创建一个Servlet的实例对象后,接着调用该实例对象的init(ServletConfig config)方法将ServletConfig对象传递给Servlet。
GenericServlet实现了ServletConfig接口。这里我们不必要这样 getServletConfig().getServletName()来获取Servlet的名称,而是直接通过 getServletName() 方法即可获取。
getServletContext方法返回某个Web应用程序的ServletContext对象。
getServletName方法用于返回Servlet在web.xml文件中的注册名称,如下面的的Servlet配置将返回“default”。对于没有在web.xml文件中注册的Servlet,将返回Servlet的类名。
在web.xml文件中可以为Servlet设置很多个初始化参数,getInitParameterNames()方法用于返回一个Enumeration的集合对象,该对象包含了在web.xml文件中为当前Servlet设置的所有初始化参数的名称。
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
servletConfig.getInitParameter("debug") = "0"
GenericServlet是一个实现了Servlet的基本我笑和功能的基类,其完整的名称为javax.servlet.GenericServlet。HttpServlet是GenericServlet的子类。其完整名称为javax.servlet.http.HttpServlet,它提供了处理HTTP协议的基本架构。如果一个Servlet要充分利用HTTP协议的功能,就应该继承HttpServlet。
在Servlet接口中定义了一个带参的init方法:
public void init(ServletConfig config) throws ServletException
在GenericServlet中还定义了一个无参数的init方法:
public void init() throws ServletException
GenericServlet类中带参数init与不带参数init的实现如下:
public void init() throws ServletException {}
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
所以我们在创建自己的Servlet时,一般只重写不带参数的init方法即可。如果重写带参数的init,你还得要在该方法的第一行调用一下super.init(config)语句,否则会有问题。
只有带参数的init方法才是Servlet接口定义的标准方法,也是Servler引擎才会调用的方法。
Servlet接口中定义的 service 方法如下:
public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
GenericServlet类没有对这个方法进行实现,HttpServlet类实现了这个方法,实现如下:
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);//调用了另外一重载形式的service方法
}
针对HttpServlet的实现,为了简化这一转换过程,HttpServlet类实现的service方法内部调用了另外一重载形式的service方法,重载的service方法的定义语法为:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
注,Servlet引擎或容器只会去调用在Servlet接口中定义的 service方法,即service(ServletRequest req, ServletResponse res)方法,还不是在HttpServlet中重载的service(HttpServletRequest req, HttpServletResponse resp)方法。所以我们在创建自己的Servlet类时,我们可以去重写service(HttpServletRequest req, HttpServletResponse resp)方法,Servlet引擎会通过调用Servlet接口上中的那个service方法来调用我们重写过的service方法。
返回Servlet的描述信息,GenericServlet实现返回的为空字符串,如有必要,可以重写这个方法,以便返回Servlet的作者、版本等信息
不管客户端以哪种请求主方式访问Servlet,Servlet引擎都将调用Servlet接口中定义的那个service方法,它是所有请求方式的总入口;然后再调用HttpServlet中重载的那个service方法;最后由重载的那个service方法分派到不同的doXxx方法。HttpServlet重载的service方法实现如下:
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);//默认为-1,即不支持Last-Modified头
if (lastModified == -1) {//不支持Last-Modified头
// servlet doesn‘t support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {//支持Last-Modified头
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < (lastModified / 1000 * 1000)) {//如果已更新
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
//在响应头中设置文档最后更新时间头Last-Modified头
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
//如果没有更改,则返回304状态码,表示GET请求的资源可用并且没有修改,
//浏览器会从缓存中读取
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
//doHead的目的就是看服务器是否已更新文档
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
在一般情况下,Servlet只需处理GET和POST两种请求方式,也就是在继承HttpServlet时只需重写doGet和doPost这两个方法即可。
如果自己编写的Servlet程序要对客户端的所有请求方式进行相同的处理,可以重写HttpServlet的service方法。这时Servlet引擎将不会再调用父类HttpServlet中的service方法(除非在重写的service方法中使用super.service()进行显示的调用),所以,doXxx方法也将不再被调用。
另外,虽然HttpServlet中的doXxx方法都有默认实现,但doGet、doPost、doPut、doDelete方法的实现都是违例实现,即它们在没有重写的情况下,就表示没有实现,再直接调用时会返回给浏览器相应错误状态码与信息,以下是doGet、doPost、doPut、doDelete各自默认实现所抛出的错误信息:
http.method_get_not_supported=HTTP method GET is not supported by this URL
http.method_post_not_supported=HTTP method POST is not supported by this URL
http.method_put_not_supported=HTTP method PUT is not supported by this URL
http.method_delete_not_supported=Http method DELETE is not supported by this URL
当然,在重写doGet或doPost时,如果这两个方法实现都一样,我们也只需要实现其中一个,再实现另一个时去直接调用它即可。
getLastModified()方法返回Servlet当前输出的响应内容的修改时间,单位为毫秒数。它由HttpServlet类的service方法调用,HttpServlet类的service方法可以根据这个返回值决定是否在响应消息中自动生成Last-Modified头。默认返回-1,表示不生成,则浏览器将页面缓存在本地时不会有
注意,HttpServet中的doGet支持Last-Modified头缓存功能,但doPost不支持。如果我们要实现Last-Modified头与If-Modified-Since头的功能,对于doGet,我们只需要实现HttpServlet中的getLastModified方法;但如果是doPost,则还要自己让doPost支持缓存功能。
public class CacheServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println(new Date());
}
// @Override
// protected long getLastModified(HttpServletRequest req) {
// //返回当前毫秒数,默认返回为-1
// return System.currentTimeMillis();
// }
}
http://localhost:8080/myapp/cacheservlet
去掉getLastModified的注释再访问
如果将getLastModified方法返回值改成很小的毫秒数,如1,则刷新页面时,页中的时间内容不会再变化。
如果getLastModified方法返回的不是-1,则响应头会有Last-Modified字段:
linux-7qez /home/fpcsmp> telnet 192.168.1.94 8080
Trying 192.168.1.94...
Connected to 192.168.1.94.
Escape character is ‘^]‘.
GET /myapp/cacheservlet HTTP/1.1
Host:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT
Content-Length: 30
Date: Mon, 12 Jul 2010 08:34:52 GMT
Mon Jul 12 16:34:52 CST 2010
如果请求头的 if-modified-since 头字段值比服务器新或等时,返回304状态码:
linux-7qez /home/fpcsmp> telnet 192.168.1.94 8080
Trying 192.168.1.94...
Connected to 192.168.1.94.
Escape character is ‘^]‘.
GET /myapp/cacheservlet HTTP/1.1
if-modified-since: Thu, 01 Jan 1970 00:00:00 GMT
Host:
HTTP/1.1 304 Not Modified
Server: Apache-Coyote/1.1
Date: Mon, 12 Jul 2010 08:38:12 GMT
Servlet引擎为每个Web应用程序都创建一个对应的ServletContext对象,ServletContext对像被包含在ServletConfig对象中。调用ServletConfig.getServletcontext法可以返回ServletContext对象的引用。在Servlet容器初始化Servlet对象时,ServletContext对象随着ServletConfig对象提供给Servlet。与Servlet API中的其他接口一样,ServletContext接口的实现类也是由Servlet引擎提供的。
如果要在server.xml文件中为某个web应用程序设置初始化参数,需要在该web应用所对应的<Context>元素增加<Parameter>子元素,更改conf\Catalina\localhost\myapp.xml 文件,添加 <Parameter>:
<Context path= "/myapp" docBase="Z:\eclipse_workspace\servlet_jsp_exercise\myapp" debug="0" reloadable="true">
<Parameter name="companyName1" value="XX" override="false"/>
<Parameter name="companyName2" value="YY" override="true"/>
</Context>
其中voerride属性用于指定在web应用程序的web.xml文件中设置的同名初始化参数是否覆盖这里的设置,当该属性值为false时表示不允许覆盖,默认值为true,即允许覆盖。
如果要在web应用程序中web.xml文件设置初始化参数,则需要在根元素的<Web-app>中增加<context-param>子元素,如下:
<context-param>
<param-name>companyName1</param-name>
<param-value>XXX</param-value>
</context-param>
<context-param>
<param-name>companyName2</param-name>
<param-value>YYY</param-value>
</context-param>
public class ContextParmServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
System.out.println(servletContext.getInitParameterNames().nextElement());
//companyName1 = XX
System.out.println("companyName1 = " + servletContext.getInitParameter("companyName1"));
//companyName2 = YYY
System.out.println("companyName2 = " + servletContext.getInitParameter("companyName2"));
}
}
ServletContext类中定义了以下两个记录日志方法:
log(java.lang.String msg)
log(java.lang.String message, java.lang.Throwable throwable)
GenericServlet类中也定义了两个log方法,不过它们是通过调用ServletContext相应的方法来实现的:
public void log(String msg) {
getServletContext().log(getServletName() + ": "+ msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
log方法记录的日志文件名称和存储路径因Web服务器不同而不同。Tomcat中的日志文件的存储路径和名称是在servlet.xml文件中进行设置的。每个Web应用程序都可以设置其单独的日志文件。在server.xml文件中,使用<logger>元素来设置日志文件的相关信息,如下所示:
<Logger className="org.apache.catalina.logger.FileLogger" directory="logs" prefix="catalina_log." suffix=".txt" timestamp="true"/>
directory如果是相对路径,则是相对于 $CATALINA_HOME 环境变量所设置的目录,directory的默认值为相对目录“logs”。
以上是针对 Tomcat 4.X的配置,Tomcat 5.x不一样了。
<logger>元素可以嵌套在<Engine> <Host> <Context>元素之中,如果里层元素中没有单独的设置<logger>元素,它将继承外层元素中的日志设置。
ServletContext接口中还定义了一些用于访问Web应用程序的内部资源文件的方法,比如WEB-INF目录中不能被外界访问的文件。
getResourcePaths(java.lang.String path):返回一个Set集合,包含某个资源目录中所有子目录和文件的路径名称,每个路径名名称相对于web应用程序的根目录(web应用目录或虚拟目录)的形式表示,如果是目录,则还以“/”结尾。如有某个应用目录下有以下这些资源:
/welcome.html
/catalog/index.html
/catalog/products.html
/catalog/offers/books.html
/catalog/offers/music.html
/customer/login.jsp
/WEB-INF/web.xml
/WEB-INF/classes/com.acme.OrderServlet.class,
则
getResourcePaths("/") returns {"/welcome.html", "/catalog/", "/customer/", "/WEB-INF/"}
getResourcePaths("/catalog/") returns {"/catalog/index.html", "/catalog/products.html", "/catalog/offers/"}
注,参数path一定要以“/”开头,且是相对于应用目录。
java.net.URL getResource(java.lang.String path):返回指定的某个资源的URL对象,path参数也必须以“/”开头,并且也是相对于应用根目录的。
java.io.InputStream getResourceAsStream(java.lang.String path):返回连接到某个资源上的InputStream对象,实际上是打开了getResource方法返回的URL对象上的输入流,它的参数传递规则与getResource方法完全一样。
一个Web应用程序在本地文件系统中的安装位里是可以变化的,不同的公司或个人可能将它安装在不同的位置上,所以ServIet程序不应使用绝对路径的形式来访问Web应用程序中的某个文件。
在某个java类中使用的相对路径是相对于当前的工作目录(比如在eclipse里运行一个Java类时,目录为项目所在的根目录;如果Tomcat是通过startup.bat启动的,那就是相对于startup.bat所在的目录而言的)而言的,这个工作目录通常是执行java命令的目录,而不是当前正在执行的java类所在的目录,这一特性导致在Java程序中很难直接使用相对目录。
针对在Java程序中使用FileInputStream类和相对路径访问资源文件时会出现的问题,JDK中的ClassLoader类专门提供了getResource等方法去装载资源文件,它们使用与查找Java类文件同样的方式去查找资源文件,即在类装载器所搜索的目录中查找。为了简化程序的编写,Class类中也定义了几个访问资源文件的方法,这些方法内部调用了ClassLoader类中的同名方法去完成相应的功能。为了防止外部使用浏览器访问到资源文件,Web应用程序中的资源文件通常应放置在WEB-INF目录或其子目录中。由于Web应用程序的类装载器会搜索WEB-INF/classes目录,所以,ClassLoader.getResourceAsStream方法也可以访问该目录中的资源文件,但是,ClassLoader.getResourceAsStream方法不能访问Web应用程序内的其他目录(比如应用目录或虚拟目录下的文件,或者是WEB-INF中的资源,而不是WEB-INF/classes或WEB-INF/lib下的资源)中的资源。ServletContext类中的访问资源的方法是通过Servlet容器来获得资源文件的,它使得Servlet程序可以访问Web应用程序内部的任意位置的文件。
ServletContext接口的getRealPath方法,用于返回某个虚拟路径所映射的本地文件系统路径。不管传递的路径参数是否以“/”开头,它们都应该是相对于应用目录的,因为在转换后它们前面都会带上应用目录。具体的细微差别请看:
// Z:\eclipse_workspace\servlet_jsp_exercise\myapp
System.out.println(servletContext.getRealPath(""));
// Z:\eclipse_workspace\servlet_jsp_exercise\myapp\
System.out.println(servletContext.getRealPath("/"));
// Z:\eclipse_workspace\servlet_jsp_exercise\myapp\WEB-INF
System.out.println(servletContext.getRealPath("WEB-INF"));
// Z:\eclipse_workspace\servlet_jsp_exercise\myapp\WEB-INF
System.out.println(servletContext.getRealPath("/WEB-INF"));
ServletContext.getRealPath只能获取当前应用下的资源路径,因为传给它的路径永远是相对于当前应用目录的。如果要获取其他Web应用的资源,怎么办?那就得先要获取到其他Web应用的ServletContext对象。
ServletContext接口中定义了一个getContext方法来获得某个URL所对应的ServletContext对象,传递给geContext方法的路径字符串必须以“/”作为起始字符,这个“/”代表的是整个Web服务器的根目录,而不是某个Web应用程序的根目录,这说明在一个Web应用程序中可以获得代表其他Web应用程序的ServletContext对象,如果要让某个Web应用程序内部能够使用ServletContext.getContext方法返回代表其他Web应用程序的ServletContext对象,必须将conf/server.xml文件中与该Web应用程序对应的<Context>元素的crossContext属性设置为true,只有为true时,它所对应的Web应用程序内部才能使用ServletContext.getContext方法返回代表其他Web应用程序的ServletContext对象。例如,如果想/myapp这个Web应用程序能够访问其他的Web应用程序,应将对应的<Context>元素的起始标签修改成如下形式:
<Context path= "/myapp" docBase="Z:\eclipse_workspace\servlet_jsp_exercise\myapp" crossContext="true" debug="0" reloadable="true">
//获取同一主机中Web应用目录为 / 的Web应用
ServletContext sc = servletContext.getContext("/");
// Z:\tomcat-5.5.30\webapps\ROOT
System.out.println(sc.getRealPath(""));
//获取同一主机中Web应用目录为 /myapp2 的Web应用
sc = servletContext.getContext("/myapp2");
// Z:\eclipse_workspace\myapp2\myapp2
System.out.println(sc.getRealPath(""));
crossContext的默认值为false。
//获取Servlet容器所支持的Servlet API的主次版本号
System.out.println(servletContext.getMajorVersion() + "."
+ servletContext.getMinorVersion());//2.4
//获取某个文件的MIME类型,这个类型是在conf/web.xml中配置的
System.out.println(servletContext.getMimeType("xx.html"));//text/html
//获取容器的名称和版本信息
System.out.println(servletContext.getServerInfo());//Apache Tomcat/5.5.30
标签:
原文地址:http://www.cnblogs.com/jiangzhengjun/p/4288968.html