HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器(Browser)和万维网服务器(WebServer)之间互相通信的规则.其主要特点可简单概括如下:
1) 简单快速 : 客户端向服务器请求服务时,只需传送请求方法和路径, 因此使得HTTP服务器的程序规模小,通信速度快;
2) 灵活 : HTTP允许传输任意类型的数据对象(传输类型由 Content-Type
控制);
3) 无连接 : 无连接的含义是限制每次连接只处理一个请求;
4) 无状态 : 无状态是指协议对于事务处理没有记忆能力(如果后续处理需要前面的信息,则必须重传.这样可能导致每次连接传送的数据量增大.但如果在服务器不需要先前信息时它的应答就会非常快快).
一个HTTP请求通常包含三部分(中间已空行隔开):
请求行: (方法 /统一资源标识符URI/协议/版本) 请求头: (Accept/Accept-Language等) 空行: (CRLF) 请求体: (携带的数据信息, GET请求没有)
HTTP请求可以使用HTTP标准中定义的所有请求类型, HTTP1.1支持7种请求类型, 但在互联网应用中最为常用的只有 GET 与 POST .
GET /WeChat/cc3200/get_status.do HTTP/1.1 Host: aliyun User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive
请求头 | 描述 |
---|---|
User-Agent | 浏览器与操作系统信息 |
Accept | 当前浏览器可以接收的文档类型 |
Accept-Language | 当前浏览器支持的语言 |
Accept-Encoding | 当前浏览器支持的压缩格式:服务器会把数据压缩后再发送到网络中传输 |
Accept-Charset | 当前浏览器支持的编码 |
Connection | 当前浏览器支持的连接方式( keep-alive 即保持一段时间的连接,默认为3000ms) |
Cookie | 如果不是第一次访问该网址,可能会在请求中把上次服务器响应的Cookie数据一并发送过去 |
POST /WeChat/cc3200/get_status.do HTTP/1.1 Content-Length: 36 Cache-Control: max-age=0 Origin: http://localhost:8080 Content-Type: application/x-www-form-urlencoded Referer: http://localhost:8080/test/ ... user_name=feiqing&user_password=pass
请求头 | 描述 |
---|---|
Referer | 表明请求来自哪个页面 |
Content-Type | application/x-www-form-urlencoded:表单数据类型,说明会使用URL编码来格式化数据 |
Content-Length | 请求体长度 |
user_name=feiqing&user_password=pass | 请求体: 请求携带的数据 |
一个HTTP响应通常也包含三部分(中间已空行隔开):
响应行: (协议/状态码/描述) 响应头: (Server/Content-Length/Set-Cookie等) 空行: (CRLF) 响应体: (携带的数据)
HTTP响应是由服务器发送给浏览器的数据,浏览器会根据HTTP响应来解析并显示内容:
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Length: 8 Date: Sun, 17 Apr 2016 12:39:11 GMT <html> ... </html>
响应头 | 描述 |
---|---|
Server | 服务器信息 |
Content-Length | 响应实体长度 |
Set-Cookie | 响应给客户端的Cookie |
Expires: -1; / Cache-Control: no-cache; / Pragma: no-cache; | 设置浏览器不要缓存数据 |
Refresh | 自动刷新页面 |
在HTML文件中可用 <meta/>
标签来设置响应头信息:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
状态码说明了响应的真正含义:
状态 | 描述 |
---|---|
200 | 请求成功 |
404 | 请求资源没找到 |
500 | 服务器内部错误 |
302 | 重定向: 表示服务器要求浏览器重新再发一个请求到服务器指定的一个 Location |
304 | 缓存未过期(服务器资源未曾修改), 详细可参考 理解HTTP/304响应 |
Tomcat是一个免费开源的Serlvet容器,它是Apache基金会的 Jakarta 项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成. 由于有了Sun的参与和支持, 因此最新的Servlet和Jsp规范总能在Tomcat中得到体现.主页: http://tomcat.apache.org/ .
<Server port="8005" shutdown="SHUTDOWN"> <Service name="Catalina"> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server>
元素 | 描述 |
---|---|
<Server/> | 根元素,整个Tomcat的配置信息 |
<Service/> | 服务(在 <Server/> 中只能有一个 <Service/> ) |
<Connector/> | 连接 |
<Engine/> | 引擎,是 <Service/> 组件核心 |
<Host/> | 每个 <Host/> 元素表示一台虚拟主机.每台虚拟主机都有自己的主机名和项目目录 |
<Context/> | 每个 <Context/> 元素表示一个应用.如果应用在 <Host/> 的appBase指定的目录下,那么可以不配置 <Context/> 元素,如果是外部应用,那么就必须配置 <Context/> |
编辑 %CATALANA_HOME%/conf/server.xml 文件中的 <Connector/>
元素
<!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL HTTP/1.1 Connector on port 8080 --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
配置外部应用之后, 项目就可以不用拷贝到webapps目录下,自定义项目存放位置,其配置方式有两种:
1: 修改server.xml
在 <Host/>
元素中添加 <Context/>
元素
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context path="/test/" docBase="/home/www/test"/> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host>
如果指定path为空(path=”“), 则默认访问的项目就是 /home/www/test , 而不再是webapps下的ROOT.
2: 编辑conf/catalana/localhost目录:
新增test.xml文件
<Context docBase="/home/www/test"/>
存放到 %CATALANA_HOME%/conf/catalana/localhost 目录下, 文件名即为应用名.
Servlet技术核心就是 Servlet
接口,所有Servlet实现类都必须实现 Servlet
接口,Servlet容器(如Tomcat)会把Servlet类加载到内存并生成唯一实例,当有请求到来时调用其方法.
javax.servlet.Servlet
接口 javax.servlet.GenericServlet
类 javax.servlet.http.HttpServlet
类 Servlet
接口定义如下
public interface Servlet { public void init(ServletConfig config) throws ServletException; public ServletConfig getServletConfig(); public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; public String getServletInfo(); public void destroy(); }
方法 | 描述 |
---|---|
init | 在第一次请求该Servlet(默认)或容器启动时, Servlet容器就会调用 init() , 且只调用一次 |
service | 每次请求Servlet都会调用该方法 |
destroy | 销毁Servlet时(卸载应用/关闭容器时), 调用该方法 |
/** * @author jifang. * @since 2016/4/17 8:32. */ public class HelloServlet implements Servlet { private ServletConfig config; public void init(ServletConfig config) throws ServletException { System.out.println("init()..."); this.config = config; System.out.println("config: <" + config + ">"); } public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("service()..."); System.out.println("req: <" + req + ">, res: <" + res + ">"); res.getWriter().print("<h1>HelloServlet</h1>"); } public void destroy() { System.out.println("destroy()..."); } public ServletConfig getServletConfig() { return this.config; } public String getServletInfo() { return null; } }
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <display-name>JavaWeb</display-name> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.fq.web.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello_servlet.do</url-pattern> </servlet-mapping> </web-app>
1.url-pattern
<url-pattern/>用来指定Servlet的访问路径,必须以/开头.
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.fq.web.servlet.HelloServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
<load-on-startup/>
元素可以让容器在启动时就创建该Servlet实例(调用 init()
方法),注意 <load-on-startup/>
元素的值必须是 >=0
的整数,它代表容器启动时创建Servlet实例的顺序.
GenericService
抽象类实现了 Servlet
接口并完成以下工作:
1. 将 init()
方法中的 ServletConfig
赋给一个实例变量, 使他可以通过 getServletConfig()
来获取.
2. 为Servlet接口的所有方法提供默认实现.
3. 提供方法来包装 ServletConfig
.
public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable { private transient ServletConfig config; public GenericServlet() { } public void destroy() { } public String getInitParameter(String name) { ServletConfig sc = getServletConfig(); if (sc == null) { throw new IllegalStateException( lStrings.getString("err.servlet_config_not_initialized")); } return sc.getInitParameter(name); } public Enumeration<String> getInitParameterNames() { ServletConfig sc = getServletConfig(); if (sc == null) { throw new IllegalStateException( lStrings.getString("err.servlet_config_not_initialized")); } return sc.getInitParameterNames(); } public ServletConfig getServletConfig() { return config; } public ServletContext getServletContext() { ServletConfig sc = getServletConfig(); if (sc == null) { throw new IllegalStateException( lStrings.getString("err.servlet_config_not_initialized")); } return sc.getServletContext(); } public String getServletInfo() { return ""; } public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } public void init() throws ServletException { } public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; public String getServletName() { ServletConfig sc = getServletConfig(); if (sc == null) { throw new IllegalStateException( lStrings.getString("err.servlet_config_not_initialized")); } return sc.getServletName(); } }
HttpServlet
是 GenericServlet
的子类,它提供了对HTTP协议的支持.覆盖了 GenericServlet
的 service()
方法,并新增了接受 HttpServletRequest
/ HttpServletResponse
参数的 service()
方法:
@Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; if (!(req instanceof HttpServletRequest && res instanceof HttpServletResponse)) { throw new ServletException("non-HTTP request or response"); } request = (HttpServletRequest) req; response = (HttpServletResponse) res; service(request, response); } protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // 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 maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { 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 { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // 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); } }
service()
将请求/响应向下转型为 HttpServletRequest
/ HttpServletResponse
, 并调用新的 service()
. 由于 HttpServlet
在新的 service()
方法中已经做了很多工作, 因此在继承 HttpServlet
实现自动以Servlet时, 则只需覆盖 doGet()
/ doPost()
等即可, 而没有必要覆盖 service()
(极少数情况需要覆盖 doHead()
等) 注意: Request/Response向下转型总会成功:因为在调用 service()
方法时,Servlet容器总会预计使用HTTP,从而直接创建并传递 HttpServletRequest
/ HttpServletResponse
实例.
/** * @author jifang. * @since 2016/4/20 19:48. */ @WebServlet(name = "HelloHttpServlet", urlPatterns = "/hello_http_servlet.do") public class HelloHttpServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doPost() ..."); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doGet() ..."); } }
对于每一个HTTP请求, Servlet容器会在调用 service()
方法时创建Request实例并传递给 service
形参, HttpServletRequest
是Request在HTTP环境下的实例,其封装了有关请求的信息:
方法 | 描述 |
---|---|
String getHeader(String name) | Returns the value of the specified request header as a String. |
Enumeration<String> getHeaderNames() | Returns an enumeration of all the header names this request contains. |
long getDateHeader(String name) | Returns the value of the specified request header as a long value that represents a Date object. |
Enumeration<String> getHeaders(String name) | Returns all the values of the specified request header as an Enumeration of String objects. |
int getIntHeader(String name) | Returns the value of the specified request header as an int. |
String getRemoteAddr() | Returns the Internet Protocol (IP) address of the client or last proxy that sent the request. |
String getMethod() | Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. |
String getContextPath() | Returns the portion of the request URI that indicates the context of the request. |
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String referer = request.getHeader("Referer"); String userAgent = request.getHeader("User-Agent"); composeResponse(referer, userAgent, response); } private void composeResponse(String referer, String userAgent, HttpServletResponse response) throws IOException { response.setHeader("Content-Type", "text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); if (!Strings.isNullOrEmpty(referer)) { writer.print("<h1>来源地址: " + referer + "</h1>"); } else { writer.print("<h1>来自浏览器地址栏</h1>"); } writer.print("<hr>"); writer.print("<h1>来源信息: " + userAgent + "</h1>"); }
方法 | 描述 |
---|---|
String getParameter(String name) | Returns the value of a request parameter as a String, or null if the parameter does not exist. |
Map<String,String[]> getParameterMap() | Returns a java.util.Map of the parameters of this request. |
Enumeration<String> getParameterNames() | Returns an Enumeration of String objects containing the names of the parameters contained in this request. |
String[] getParameterValues(String name) | Returns an array of String objects containing all of the values the given request parameter has, or null if the parameter does not exist. |
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Element root; String xml = request.getParameter("xml"); try { if (!Strings.isNullOrEmpty(xml)) { root = new SAXReader().read(new StringReader(xml)).getRootElement(); } else { String data = CharStreams.toString(new InputStreamReader(request.getInputStream())); root = new SAXReader().read(new StringReader(data)).getRootElement(); } } catch (DocumentException | IOException e) { LOGGER.error("parse wx xml error", e); throw new RuntimeException(); } // ... }
Request提供了 getRequestDispatcher()
来获取一个 RequestDispatcher
, 并由其提供请求转发/请求包含功能.
Request方法 | 描述 |
---|---|
RequestDispatcher getRequestDispatcher(String path) | Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path. |
请求转发/请求包含都是由多个Servlet协作完成一个请求, 因此需要从一个Servlet中跳到另一个Servlet中:
RequestDispatcher方法 | 描述 |
---|---|
void include(ServletRequest request, ServletResponse response) | Includes the content of a resource (servlet, JSP page, HTML file) in the response. |
void forward(ServletRequest request, ServletResponse response) | Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. |
注意: 请求转发时, 可能会因为原Servlet设置了过多的响应体内容导致抛出异常 java.lang.IllegalStateException: Cannot forward after response has been committed
由于请求转发/请求包含都只是一次请求, 因此在多个Servlet之间都是共用一个 Reqeust , 因此可以利用Request的在多个Servlet之间共享数据:
方法 | 描述 |
---|---|
Object getAttribute(String name) | Returns the value of the named attribute as an Object, or null if no attribute of the given name exists. |
Enumeration<String> getAttributeNames() | Returns an Enumeration containing the names of the attributes available to this request. |
void setAttribute(String name, Object o) | Stores an attribute in this request. |
void removeAttribute(String name) | Removes an attribute from this request. |
同Request, Servlet容器会在每次调用 service()
方法时创建Response实例并传递给 service()
形参, HttpServletResponse
是Response绑定在HTTP环境下的实例, 其隐藏了将响应发送给浏览器的复杂性:
方法 | 描述 |
---|---|
void setStatus(int sc) | Sets the status code for this response. |
void sendError(int sc) | Sends an error response to the client using the specified status code and clears the buffer. |
void sendError(int sc, String msg) | Sends an error response to the client using the specified status and clears the buffer. |
关于状态码的描述, 详见HTTP协议部分介绍, 在此就不再赘述.
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // response.sendError(404, "nothing!!"); response.setStatus(404); }
方法 | 描述 |
---|---|
void setHeader(String name, String value) | Sets a response header with the given name and value. |
void addHeader(String name, String value) | Adds a response header with the given name and value. |
void setIntHeader(String name, int value) | Sets a response header with the given name and integer value. |
void addIntHeader(String name, int value) | Adds a response header with the given name and integer value. |
void addDateHeader(String name, long date) | Adds a response header with the given name and date-value. |
void setDateHeader(String name, long date) | Sets a response header with the given name and date-value. |
void sendRedirect(String location) | Sends a temporary redirect response to the client using the specified redirect location URL and clears the buffer. |
关于HTTP响应头的描述, 详见HTTP协议部分介绍, 在此就不再赘述.
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Cache-Control", "no-cache"); response.setHeader("pragma", "no-cache"); response.setDateHeader("expires", -1); }
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); response.setHeader("Location", "http://www.baidu.com"); }
HttpServletResponse还提供了另外一种重定向的方式, 直接使用 sendRedirect()
方法, 避免了以上的步骤:
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendRedirect("http://www.baidu.com"); }
Response提供了如下两个方法来获取输出流对象以响应HTTP正文内容
方法 | 描述 |
---|---|
ServletOutputStream getOutputStream() | Returns a ServletOutputStream suitable for writing binary data in the response. |
PrintWriter getWriter() | Returns a PrintWriter object that can send character text to the client. |
OutputStream传输二进制数据流(字节数据), 常用作文件下载; Writer传输字符数据, 常用作响应HTTP正文内容(如HTML/XML等).
注意: 在一个请求中,不能同时使用这两个流, 否则会抛出 IllegalStateException
.
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter writer = response.getWriter(); writer.print("<html>"); writer.print("<h1>content</h1>"); writer.print("</html>"); }
缓冲区
PrintWriter
的默认缓冲区大小为8K, 因此当响应数据大小<8K时, 数据存放在缓冲区, 而不会立刻发送到浏览器, 直到Servlet执行结束,因此如果希望马上发送给浏览器, 需要调用Response的 flushBuffer()
方法手动刷新缓冲区.
在容器初始化Servlet时, 会将一个 ServletConfig
实例传给 init()
方法,其封装了 @WebServlet
/部署描述符传递给Servlet的配置信息:
方法 | 描述 |
---|---|
String getInitParameter(String name) | Gets the value of the initialization parameter with the given name. |
Enumeration<String> getInitParameterNames() | Returns the names of the servlet’s initialization parameters as an Enumeration of String objects. |
ServletContext getServletContext() | Returns a reference to the ServletContext in which the caller is executing. |
public void init(ServletConfig config) throws ServletException { this.config = config; Enumeration<String> names = config.getInitParameterNames(); while (names.hasMoreElements()) { String name = names.nextElement(); String value = config.getInitParameter(name); System.out.println(name + " -> " + value); } }
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.fq.web.servlet.HelloServlet</servlet-class> <init-param> <param-name>admin</param-name> <param-value>com.fq</param-value> </init-param> <init-param> <param-name>e-mail</param-name> <param-value>zhujifang666@163.com</param-value> </init-param> </servlet>
ServletConfig
中提供了获取 ServletContext
的方法 getServletContext()
, ServletContext
代表Servlet应用程序,且每个应用程序仅有一个 ServletContext
实例,其在容器启动时创建, 在容器关闭时销毁, 因此可以利用其在多个Servlet中传递数据.
所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,下面是ServletContext对象用来操作数据的方法:
方法 | 描述 |
---|---|
void setAttribute(String name, Object object) | Binds an object to a given attribute name in this ServletContext. |
Object getAttribute(String name) | Returns the servlet container attribute with the given name, or null if there is no attribute by that name. |
Enumeration<String> getAttributeNames() | Returns an Enumeration containing the attribute names available within this ServletContext. |
void removeAttribute(String name) | Removes the attribute with the given name from this ServletContext. |
前面看到 ServletConfig
可以获取针对本Servlet的初始化参数,而利用 ServletContext
可以获取针对本应用程序的公共初始化参数:
方法 | 描述 |
---|---|
String getInitParameter(String name) | Returns a String containing the value of the named context-wide initialization parameter, or null if the parameter does not exist. |
Enumeration<String> getInitParameterNames() | Returns the names of the context’s initialization parameters as an Enumeration of String objects, or an empty Enumeration if the context has no initialization parameters. |
<context-param> <param-name>admin</param-name> <param-value>feiqing</param-value> </context-param> <context-param> <param-name>e-mail</param-name> <param-value>zhujifang666@163.com</param-value> </context-param>
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = getServletContext(); String admin = context.getInitParameter("admin"); String email = context.getInitParameter("e-mail"); System.out.printf("admin: %s%n", admin); System.out.printf("e-mail: %s%n", email); }
可以使用 ServletContext
来获取Web应用下的资源路径/资源流等内容:
方法 | 描述 |
---|---|
String getRealPath(String path) | Gets the real path corresponding to the given virtual path. |
URL getResource(String path) | Returns a URL to the resource that is mapped to the given path. |
InputStream getResourceAsStream(String path)` | Returns the resource located at the named path as an InputStream object. |
Set<String> getResourcePaths(String path) | Returns a directory-like listing of all the paths to resources within the web application whose longest sub-path matches the supplied path argument. |