Servlet超详解+流程图
1.servlet处理用户请求的完整流程针对Servlet的每次请求,Web 服务器在调用 service() 方法之前,都会创建 HttpServletRequest 和 HttpServletResponse 对象。其中,HttpServletRequest 对象用于封装 HTTP 请求消息,简称 request 对象。HttpServletResponse 对象用于封装 HTTP 响应消息,
1.servlet处理用户请求的完整流程
针对Servlet的每次请求,Web 服务器在调用 service() 方法之前,都会创建 HttpServletRequest 和 HttpServletResponse 对象。其中,HttpServletRequest 对象用于封装 HTTP 请求消息,简称 request 对象。HttpServletResponse 对象用于封装 HTTP 响应消息,简称 response 对象。浏览器访问 Servlet 的交互过程如图 1 所示。
图 1 浏览器访问Servlet过程
在图 1 中,首先浏览器向 Web 服务器发送了一个 HTTP 请求,Web 服务器根据收到的请求,会先 创建一个 HttpServletRequest 和 HttpServletResponse 对象,然后再调用相应的 Servlet 程序。
在 Servlet 程序运行时,它首先会从 HttpServletRequest 对象中读取数据信息,然后通过 service() 方法处理请求消息,并将处理后的响应数据写入到 HttpServletResponse 对象中。最后,Web 服务器会从 HttpServletResponse 对象中读取到响应数据,并发送给浏览器。
需要注意的是,在 Web 服务器运行阶段,每个 Servlet 都只会创建一个实例对象,针对每次 HTTP 请求,Web 服务器都会调用所请求 Servlet 实例的 service(HttpServletRequest request,HttpServletResponse response)方法,并重新创建一个 request 对象和一个 response 对象。
2.什么是 Servlet 容器?
1、什么是 Web 服务器?
想要了解什么是 Servlet 容器,首先需要知道什么是 Web 服务器。
Web 服务器使用 HTTP 协议传输数据。在一般情况下,用户在浏览器(客户端)中键入 URL(例如www.baidu.com/static.html),并获取要读取的网页。所以服务器所做的就是向客户机发送一个网页。信息的交换采用指定请求和响应消息的格式的 HTTP 协议。
2、什么是 Servlet 容器?
正如我们看到的,用户/客户端只能从服务器请求静态网页。如果用户希望根据自己的输入阅读网页,那么这还不够好。Servlet 容器的基本思想是使用 Java 动态生成服务器端的网页。所以 Servlet 容器本质上是与 Servlet 交互的 Web 服务器的一部分。
“Servlet 容器”是一个装载一堆 Servlet 对象的“器具”(容器),并且具备管理这些对象的功能。
3、什么是 Servlet?
Servlet 是 javax.servlet 包中定义的接口。它声明了 Servlet 生命周期的三个基本方法:init()、service() 和 destroy()。它们由每个 Servlet Class(在 SDK 中定义或自定义)实现,并由服务器在特定时机调用。
- init() 方法在 Servlet 生命周期的初始化阶段调用。它被传递一个实现 javax.servlet.ServletConfig 接口的对象,该接口允许 Servlet 从 Web 应用程序访问初始化参数。
- service() 方法在初始化后对每个请求进行调用。每个请求都在自己的独立线程中提供服务。Web容器为每个请求调用 Servlet 的 service() 方法。service() 方法确认请求的类型,并将其分派给适当的方法来处理该请求。
- destroy() 方法在销毁 Servlet 对象时调用,用来释放所持有的资源。
从 Servlet 对象的生命周期中,我们可以看到 Servlet 类是由类加载器动态加载到容器中的。每个请求都在自己的线程中,Servlet 对象可以同时服务多个线程(线程不安全的)。当它不再被使用时,会被 JVM 垃圾收集。
像任何Java程序一样,Servlet 在 JVM 中运行。为了处理复杂的 HTTP 请求,Servlet 容器出现了。Servlet 容器负责 Servlet 的创建、执行和销毁。
4、Servlet 容器和 Web 服务器如何处理一个请求的?
- Web 服务器接收 HTTP 请求。
- Web 服务器将请求转发到 Servlet 容器。
- 如果对应的 Servlet 不在容器中,那么将被动态检索并加载到容器的地址空间中。
- 容器调用 init() 方法进行初始化(仅在第一次加载 Servlet 时调用一次)。
- 容器调用 Servlet 的 service() 方法来处理 HTTP 请求,即读取请求中的数据并构建响应。Servlet 将暂时保留在容器的地址空间中,可以继续处理其它 HTTP 请求。
- Web 服务器将动态生成的结果返回到浏览器/客户端。
5、JVM 的作用
Servlet 允许 JVM 在处理每个请求时使用单独的 Java 线程,这是 Servlet 容器的一个主要优点。每个 Servlet 是一个 Java 类,具有响应 HTTP 请求的特殊元素。
Servlet 容器的主要功能是将请求转发到正确的 Servlet 进行处理,并在 JVM 处理完后将动态生成的结果返回到正确的位置。
在大多数情况下, Servlet 容器在单个 JVM 中运行,但是当容器需要多个 JVM 时,会有一些其它的解决方案。
3.JavaWeb工程中web.xml基本配置
1..理论准备
xml规则,必须有且只有一个根节点,大小写敏感,标签不嵌套,必须配对。
web.xml是不是必须的呢?
不是的,只要你不用到里面的配置信息就好了,不过在大型web工程下使用该文件是很方便的,若是没有也会很复杂。
那么web.xml能做的所有事情都有那些?
其实,web.xml的模式(Schema)文件中定义了多少种标签元素,web.xml中就可以出现它的模式文件所定义的标签元素,它就能拥有定义出来的那些功能。web.xml的模式文件是由Sun公司定义的,每个web.xml文件的根元素<web-app>中,都必须标明这个web.xml使用的是哪个模式文件。
来看个例子:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>db</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
二.标签元素
- 指定欢迎页面
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index1.jsp</welcome-file>
</welcome-file-list>
上面的例子指定了2个欢迎页面,显示时按顺序从第一个找起,如果第一个存在,就显示第一个,后面的不起作用。如果第一个不存在,就找第二个,以此类推。
关于欢迎页面:访问一个网站时,默认看到的第一个页面就叫欢迎页,一般情况下是由首页来充当欢迎页的。一般情况下,我们会在web.xml中指定欢迎页。但web.xml并不是一个Web的必要文件,没有web.xml,网站仍然是可以正常工作的。只不过网站的功能复杂起来后,web.xml的确有非常大用处,所以,默认创建的动态web工程在WEB-INF文件夹下面都有一个web.xml文件。
对于tomcat来说,当你只指定一个web的根名,没有指定具体页面,去访问时一个web时,如果web.xml文件中配置了欢迎页,那么就返回指定的那个页面作为欢迎页,而在文中没有web.xml文件,或虽然有web.xml,但web.xml也没指定欢迎页的情况下,它默认先查找index.html文件,如果找到了,就把index.html作为欢迎页还回给浏览器。如果没找到index.html,tomcat就去找index.jsp。找到index.jsp就把它作为欢迎页面返回。而如果index.html和index.jsp都没找到,又没有用web.xml文件指定欢迎页面,那此时tomcat就不知道该返回哪个文件了,它就显示The requested resource (/XXX) is not available(我就出现过这个问题)的页面。其中XXX表示web的根名。但如果你指定了具体页面,是可以正常访问的。
- 命名与定制URL
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>net.test.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
url-pattern的意思是所有的.do文件都会经过TestServlet处理。
- 定制初始化参数
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>net.test.TestServlet</servlet-class>
<init-param>
<param-name>userName</param-name>
<param-value>Tommy</param-value>
</init-param>
<init-param>
<param-name>E-mail</param-name>
<param-value>Tommy@163.com</param-value>
</init-param>
</servlet>
经过上面的配置,在servlet中能够调用getServletConfig().getInitParameter("param1")获得参数名对应的值。
//上下文参数:声明应用范围内的初始化参数。
<context-param>
<param-name>ContextParameter</para-name>
<param-value>test</param-value>
<description>It is a test parameter.</description>
</context-param>
//在servlet里面可以通过getServletContext().getInitParameter("context/param")
得到
- 指定错误处理页面,可以通过“异常类型”或“错误码”来指定错误处理页面。
<error-page>
<error-code>404</error-code>
<location>/error404.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception<exception-type>
<location>/exception.jsp<location>
</error-page>
<error-page>
<exception-type>java.lang.NullException</exception-type>
<location>/error.jsp</location>
</error-page>
- 设置过滤器:比如设置一个编码过滤器,过滤所有资源
<filter>
<filter-name>XXXCharaSetFilter</filter-name>
<filter-class>net.test.CharSetFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XXXCharaSetFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6.设置监听器
web.xml中的<listener></listener>有什么用? 没别的用处!就是配置监听类的~,它能捕捉到服务器的启动和停止! 在启动和停止触发里面的方法做相应的操作! 它必须在web.xml 中配置才能使用! web.xml 中listener元素不是只能有一个,有多个时按顺序执行。
如何在web.xml向listener中传参数 ?
<listener>
<listener-class>监听器类的完整路径</listener-class>
</listener>
监听器中不能够写初始化参数; 可通过另个的途径达到初始化参数的效果: 1.写一个properties文件,在文件里写好初始化参数值, 2.在监听器中可以通得到properties文件中的值(写在静态块中)。
- 设置会话(Session)过期时间,其中时间以分钟为单位
<session-config>
<session-timeout>60</session-timeout>
</session-config>
除了这些标签元素之外,还可以往web.xml中添加那些标签元素呢,那些标签元素都能起什么作用呢?我们只要去查看web.xml的模式文件就能知道。直接看模式文件看不懂,可以找一些中文教程来看看。
三.遗留问题
- 在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资 料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只 是略加点了自己的修饰。 首先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关。即不会 因为 filter 写在 listener 的前面而会先加载 filter。最终得出的结论是:listener -> filter -> servlet 。<session-config></session-config> 如果某个会话在一定时间内未被访问,服务器可 以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对 象的超时值,或者可利用session-config元素制定缺省超时值。
- <welcome-file-list></welcome-file-list> 指示服务器在收到引用一个目录名而不是 文件名的URL时,使用哪个文件。
- web.xml中怎么配置url-pattern? 首先要知道 web.xml 中url-pattern的作用,他是给外部提供的一个访问DoGetDemo类的接口,你可以自己随意定义,然后在IE里面写入这个配置内容。 可以看我给你写的一个例子图片,应该一下就看懂的,用 SimpleHello.java 为例,看图片,访问的时候,可以输入下面的网址 http://192.168.0.67:8888/book/hello 这样,服务器就可以通过 <url-pattern>/hello</url-pattern> 找到ch06.SimpleHello类,因此你的<url-pattern></url-pattern> 里面的内容可以自己定义。然后在应用目录下访问这个servlet 。
- web.xml中既然有url-pattern为什么还需要servlet-class呢?url-pattern是表明什么格式的的url进入这个servlet ,servlet-class 是表明哪个java类来处理这个请求 ,一个请求过来,先到servlet-mapping中去根据请求的url寻找这个url所对应的url-pattern,找到url-pattern后找到了servlet-name, 然后根据servlet-name和servlet中的servlet-name对应找到其所对应的servlet-class,具体的业务逻辑就写在来servlet-class对应的java类中了!
4.Servlet虚拟路径映射配置详解
Servlet虚拟路径映射
在web.xml文件中,一个<servlet-mapping>元素用于映射一个Servlet的对外访问路径,该路径也称为虚拟路径。例如<url-pattern>/TestServlet</url-pattern>,其中“/TestServlet”就是一个虚拟路径。
1.配置多个映射路径
在上一文中,我们说到@WebServlet中的urlPatterns属性,其可以是一组匹配规则,也就是说一个Servlet是可以配置多个虚拟路径的,也就是Servlet和虚拟路径可以是一对多的一个关系(并不是多对多,一个虚拟路径只能映射一个Servlet),其具体实现如下,并修改doPost处的代码:
@WebServlet(
description = "My First Servlet",
urlPatterns = { "/HelloServlet", "/StillMe" },
initParams = {
@WebInitParam(name = "name", value = "lizishu")
})
public class HelloServlet extends HttpServlet {
//具体逻辑参看上篇文章
//...
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置返回客户端的contentType
//text/plain :纯文本格式 设置为text/html println的换行会失效
response.setContentType("text/plain;charset=utf-8");
//response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
out.println("Served at: " + request.getContextPath());
String name = this.getInitParameter("name");
out.println("name: " + name);
out.println("访问的Servle名为:" + HelloServlet.class);
}
}
可以看到,增加一个虚拟路径映射非常方便,只需在urlPatterns中新增一项即可(注意'/'不可省略),启动项目,在浏览器上输入url,可以看到,无论是输入http://localhost:8080/FirstProject/HelloServlet、还是http://localhost:8080/FirstProject/StillMe页面上得到的输出内容均一致。
urlPatterns在Servlet 3.0版本之前,都是配置在web.xml中的,每个Servlet会有一个对应的<servlet-mapping>标签,其中可以配置多个<url-pattern>。
2.urlPatterns匹配规则
说到Servlet虚拟路劲的匹配规则,还需要说到urlPatterns的几种匹配规则,主要有以下四种:
- 精确匹配:也就是我们在上面配置的匹配规则,需要完全相等才能匹配成功,这也是我们经常发生错误的地方,请求Servlet时的大小写拼写错误导致404;
- 路径匹配:比如想匹配以rest开头的所有请求,可以写成"/rest/*",其格式为以'/‘字符开头,并以'/*'结尾;
- 扩展名匹配:比如想匹配所有以.do结尾的请求,可以写成"*.do",其格式为以'*.',后面跟上扩展名;
- 缺省匹配:映射路径为"/",那么这个Servlet就是当前应用的缺省Servlet,默认处理无法匹配到虚拟路径的请求。
需要注意的是,路径匹配和扩展匹配无法混合使用,即urlPattern无法写成"/rest/*.do";这也是让部分同学感到困惑的地方,Servlet的虚拟路径匹配并不是完全的按照正则来匹配的,虽然路径匹配和扩展匹配是按照正则中的通配符(*)来匹配的,这也是部分同学可以会写出特定的正则,但是却不是一个合法的虚拟路径;Servlet容器收到请求后,会将请求从上下文路径(通过request.getContextPath()获取的)处截断,使用剩余的部分来进行路径匹配,比如请求url为http://localhost:8080/FirstProject/HelloServlet,那么Servlet容器就会使用"/HelloServlet"来匹配Servlet。
最后需要注意的是,我们说了上面四种匹配规则,尤其是缺省匹配,可以匹配到任意请求,那么一个请求如果可以匹配多个Servlet的虚拟路径,那么该执行哪个Servlet?其实啊,这些匹配规则是有优先级的,具体的优先级为:精确匹配>路径匹配>扩展名匹配>缺省匹配,Servlet容器会从优先级高的虚拟路径开始匹配,匹配到后就会立刻将请求交给对应的Servlet来处理,不会再关心其他Servlet的虚拟路径是否会匹配成功。
下面我们来一组Servlet及其对应的虚拟路径:
urlPatterns | Servlet Name |
/abc/* | Servlet1 |
/ | Servlet2 |
/abc | Servlet3 |
*.do | Servlet4 |
当请求去除上下文路径后路径为:"/abc/a.html"时,根据上述规则,会调用Servlet1;
请求为:"/abc",根据匹配优先级,会调用Servlet3;
请求为:"/abc/a.do",会匹配到'/abc/*'、'*.do',但根据匹配优先级,会调用Servlet1;
请求为:"/a.do",会匹配到'/'、'*.do',但根据匹配优先级,会调用Servlet4;
3.Tomcat提供的缺省Servlet
为了测试缺省Servlet,我们来进行一个测试。我们新建个SelfDefaultServlet,其urlPatterns我们配置为"/",其中的方法我们不做任何修改。
@WebServlet(
description = "Self create default Servlet",
urlPatterns = { "/" }
)
public class SelfDefaultServlet extends HttpServlet {
//...
}
我们启动项目后,在浏览器上输入http://localhost:8080/FirstProject/hahaha或者其他任意无法匹配到HelloServlet虚拟路径的请求,发现页面上的结果都如下所示,是不是这样也不错,不会报404错误了。
但是,此时我们想访问WebContent目录下的静态页面(新建的一个welcome.html文件),浏览器上输入http://localhost:8080/FirstProject/welcome.html,猜猜会发生什么?我们来一起看下结果,如图所示,请求结果并没有按照我们的想法,根据请求路径找到welcome.htm页面,而是调用了SelfDefaultServlet,是不是很懵?
其实,客户端的每个请求,都是由Servlet容器根据虚拟路径的匹配规则来进行处理的,包括静态资源。并且,如果路径输入错误(去除了自己配置的缺省Servlet后),我们常见的下面的错误,也是Servlet返回给我们,哈哈,还是很意外?
我们能通过servlet方便简单的开发网站,是因为我们站在了巨人的肩膀上,下面我们一起来看下Sun公司都为我们开发者提前做了些什么工作。Tomcat会为项目配置一个缺省的Servlet(如果项目中自行配置,则不会生效),配置文件在tomcat安装目录下conf目录中的web.xml文件中,具体内容如下,缺省的Servlet名为DefaultServlet。
<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>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
客户端请求静态资源文件时,也是由缺省的Servlet处理的(自己单独配置Servlet除外),如果请求文件能找到,就会将页面通过HttpServletResponse对象以流的方式返回给客户端,否则报404错误。
不过讲到这里,大家可以自己试一试配置了缺省Servelt时,访问welcome.html的情况(会调用SelfDefaultServlet),但是,如果我们在浏览器中输入http://localhost:8080/FirstProject/index.jsp(index.jsp是创建的第一个jsp页面)呢?会是什么样一个结果?也是调用缺省的Servlet么?真是的运行结果如下:
这是什么原因?为什么不是调用缺省的servlet了?这是因为tomcat除了缺省Serlvet外,还给我们提供一个处理jsp文件的Servlet,配置如下,因为后缀匹配的优先级高于缺省的Servlet,所以访问JSP的时候需要交由JspServlet来处理(JSP因为可能包含Java代码,所以第一次执行的时候需要先编译,这个工作由JspServlet完成)
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param> <param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
4.总结
本文具体讨论了urlPatterns属性的匹配规则,主要为四种,其优先级也各不相同,我们在使用时,也需要根据自己的需求自己设定urlPatterns,不过知道了匹配规则,使用起来也会方便很多,也能帮我们快速的定位错误。
到此这篇关于Servlet虚拟路径映射配置详解的文章就介绍到这了,更多相关Servlet 虚拟路径映射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
5.ServletConfig和ServletContext)
ServletConfig接口
在运行 Servlet 程序时,可能需要一些辅助信息,例如,文件使用的编码、使用 Servlet 程序的共享信息等,这些信息可以在 web.xml 文件中使用一个或多个 <init-param> 元素进行配置。当 Tomcat 初始化一个 Servlet 时,会将该 Servlet 的配置信息封装到 ServletConfig 对象中,此时可以通过调用 init(ServletConfig config)方法将 ServletConfig 对象传递给 Servlet。
ServletConfig 接口中定义了一系列获取配置信息的方法,如表 1 所示。
表 1 ServletConfig接口的常用方法 | |
方法说明 | 功能描述 |
String getInitParameter(String name) | 根据初始化参数名返回对应的初始化参数值 |
Enumeration getInitParameterNames() | 返回一个 Enumeration 对象,其中包含了所有的初始化参数名 |
ServletContext getServletContext() | 返回一个代表当前 Web 应用的 ServletContext 对象 |
String getServletName() | 返回 Servlet 的名字,即 web.xml 中 <servlet-name>元素的值 |
2)配置参数信息
在 web.xml 文件中为 Servlet 配置一些参数信息,具体的配置代码如下所示:
<servlet>
<servlet-name>TestServlet02</servlet-name>
<servlet-class>com.mengma.servlet.TestServlet02</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet02</servlet-name> <url-pattern>/TestServlet02</url-pattern>
</servlet-mapping>
在上面的参数信息中,<init-param> 节点表示要设置的参数,该节点中的 <param-name> 表示参数的名称,<param-value> 表示参数的值,在 <init-param> 节点中为 TestServlet02 配置了一个名为 encoding 的参数,并设置其参数的值为 UTF-8。
3)运行项目并查看结果
启动 Tomcat 服务器,在浏览器的地址栏中输入地址 http://localhost:8080/servletDemo01/TestServlet02 访问 TestServlet02,结果如图 1 所示。
图 1 运行结果
从图 1 中可以看出,web.xml 文件中为 TestServlet02 配置的编码信息被读取了出来。由此可见,通过 ServletConfig 对象可以获得 web.xml 文件中的参数信息。
ServletContext接口
当 Tomcat 启动时,Tomcat 会为每个 Web 应用创建一个唯一的 ServletContext 对象代表当前的 Web 应用,该对象封装了当前 Web 应用的所有信息。可以利用该对象获取 Web 应用程序的初始化信息、读取资源文件等。下面对 ServletContext 接口的不同作用分别进行讲解。
1. 获取 Web 应用程序的初始化参数
在 web.xml 文件中,不仅可以配置 Servlet 的映射信息,还可以配置整个 Web 应用的初始化信息。Web 应用初始化参数的配置方式具体如下所示:
<context-param>
<param-name>XXX</param-name>
<param-value>xxx</param-value>
</context-param>
<context-param>
<param-name>AAA</param-name>
<param-value>aaa</param-value>
</context-param>
在上面的示例中,<context-param> 元素位于根元素 <web-app> 中,它的子元素 <param-name> 和 <param-value> 分别用于指定参数的名字和参数值。要想获取这些参数名和参数值的信息,可以使用 ServletContext 接口中定义的 getInitParameterNames() 和 getInitParameter(String name)方法分别获取。
下面通过案例演示如何使用 ServletContext 接口获取 Web 应用程序的初始化参数。
1)在 servletDemo01 项目的 web.xml 文件中配置初始化参数信息和 Servlet 信息,其代码如下所示:
<context-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>1234</param-value>
</context-param>
<servlet>
<servlet-name>TestServlet03</servlet-name>
<servlet-class>com.mengma.servlet.TestServlet03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet03</servlet-name>
<url-pattern>/TestServlet03</url-pattern>
</servlet-mapping>
2)在项目的 com.mengma.servlet 包中创建一个名称为 TestServlet03 的类,该类中使用 ServletContext 接口获取 web.xml 中的配置信息,如下所示。
package com.mengma.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet03 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 得到ServletContext对象
ServletContext context = this.getServletContext(); // 得到包含所有初始化参数名的Enumeration对象
Enumeration<String> paramNames = context.getInitParameterNames();
// 遍历所有的初始化参数名,得到相应的参数值并打印
while (paramNames.hasMoreElements()) {
String name = paramNames.nextElement();
String value = context.getInitParameter(name);
out.println(name + ":" + value);
out.println("<br/>");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
上述代码中,当通过 this.getServletContext() 方法获取到 ServletContext 对象后,首先调用 getInitParameterNames() 方法,获取到包含所有初始化参数名的 Enumeration 对象,然后遍历 Enumeration 对象,根据获取到的参数名,通过 getInitParamter(String name)方法得到对应的参数值。
3)启动 Tomcat 服务器,在浏览器的地址栏中输入地址 http://localhost:8080/servletDemo01/TestServlet03 访问 TestServlet03,浏览器的显示结果如图 2 所示。
图 2 运行结果
从图 2 中可以看出,web.xml 文件中配置的信息被读取了出来。由此可见,通过 ServletContext 对象可以获取 Web 应用的初始化参数。
2. 读取 Web 应用下的资源文件
在实际开发中,有时会需要读取 Web 应用中的一些资源文件,如配置文件和日志文件等。为此,在 ServletContext 接口中定义了一些读取 Web 资源的方法,这些方法是依靠 Servlet 容器实现的。Servlet 容器根据资源文件相对于 Web 应用的路径,返回关联资源文件的 I/O 流或资源文件在系统的绝对路径等。
表 2 中列举了 ServletContext 接口中用于获取资源路径的相关方法。
表 2 ServletContext接口的常用方法 | |
方法说明 | 功能描述 |
Set getResourcePaths(String path) |
|
String getRealPath(String path) | 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)。参数 path 代表资源文件的虚拟路径,它应该以正斜线(/)开始,/ 表示当前 Web 应用的根目录,如果 Servlet 容器不能将虚拟路径转换为文 件系统的真实路径,则返回 null |
| 返回映射到某个资源文件的 URL 对象。参数 path 必须以正斜线(/)开始,/ 表示当前 Web 应用的根目录 |
InputStream getResourceAsStream(String path) | 返回映射到某个资源文件的 InputStream 输入流对象。参数 path 的传递规则和 getResource() 方法完全一致 |
了解了 ServletContext 接口中用于获得 Web 资源路径的方法后,下面通过案例分步骤演示如何使用 ServletContext 对象读取资源文件。
案例分步骤演示如何使用 ServletContext 对象读取资源文件。
1)在 servletDemo01 项目的 src 目录中创建一个名称为 itcast.properties 的文件,在创建好的文件中输入如下所示的配置信息:
username=admin
password=1234
2)在 com.mengma.servlet 包中创建一个名称为 TestServlet04 的 Servlet 类,使用该类读取 itcast.properties 资源文件的内容,其实现代码如下所示。
package com.mengma.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet04 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
ServletContext context = this.getServletContext();
PrintWriter out = response.getWriter(); // 获取相对路径中的输入流对象
InputStream in = context .getResourceAsStream("/WEB-INF/classes/itcast.properties");
Properties pros = new Properties();
pros.load(in);
out.println("username=" + pros.getProperty("username") + "<br/>");
out.println("password=" + pros.getProperty("password") + "<br/>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response); }
}
在上述代码中,使用 ServletContext 的 getResourceAsStream(String path)方法获得了关联 itcast.properties 资源文件的输入流对象,其中的 path 参数必须以正斜线(/)开始,表示 itcast.properties 文件相对于 Web 应用的相对路径。
3)启动 Tomcat 服务器,在浏览器的地址栏中输入地址 http://localhost:8080/servletDemo01/TestServlet04 访问 TestServlet04,浏览器的显示结果如图 3 所示。
图 3 运行结果
从图 3 中可以看出,itcast.properties 资源文件中的内容已经被读取了出来。由此可见,使用 ServletContext 可以读取 Web 应用中的资源文件。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)