Servlet - 基础
Servlet
标签 : Java与Web
HTTP协议
HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器(Browser)和万维网服务器(WebServer)之间互相通信的规则.其主要特点可简单概括如下:
1) 简单快速: 客户端向服务器请求服务时,只需传送请求方法和路径, 因此使得HTTP服务器的程序规模小,通信速度快;
2) 灵活: HTTP允许传输任意类型的数据对象(传输类型由Content-Type
控制);
3) 无连接: 无连接的含义是限制每次连接只处理一个请求;
4) 无状态: 无状态是指协议对于事务处理没有记忆能力(如果后续处理需要前面的信息,则必须重传.这样可能导致每次连接传送的数据量增大.但如果在服务器不需要先前信息时它的应答就会非常快快).
HTTP请求
一个HTTP请求通常包含三部分(中间已空行隔开):
请求行: (方法 /统一资源标识符URI/协议/版本)
请求头: (Accept/Accept-Language等)
空行: (CRLF)
请求体: (携带的数据信息, GET请求没有)
HTTP请求可以使用HTTP标准中定义的所有请求类型, HTTP1.1支持7种请求类型, 但在互联网应用中最为常用的只有GET与POST.
HTTP-GET
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数据一并发送过去 |
HTTP-POST
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响应
一个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
Tomcat是一个免费开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成. 由于有了Sun的参与和支持, 因此最新的Servlet和Jsp规范总能在Tomcat中得到体现.主页:http://tomcat.apache.org/.
Tomcat目录结构
- bin: 存放可执行脚本文件(如startup.bat/startup.sh等)
- conf: 存放Tomcat相关配置文件:
- server.xml: 整个Tomcat运行环境配置(如端口号/虚拟主机等)
- web.xml: 部署描述符文件(定义了默认JSP/Servlet处理规则,是所有web项目中WEB-INF/web.xml的父文件)
- context.xml: 对所有应用的统一配置.
- lib:Tomcat类库, 该目录中的jar包所有项目共享.
- logs : Tomcat日志目录.
- webapps:存放WEB应用,其每个子目录都是一个项目;
- work:运行时生成的文件.
server.xml
<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/> |
Tomcat配置
1. 配置端口号
编辑%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" />
2. 配置外部应用
配置外部应用之后, 项目就可以不用拷贝到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
接口,Servlet容器(如Tomcat)会把Servlet类加载到内存并生成唯一实例,当有请求到来时调用其方法.
- 实现Servlet方式有三种:
- 实现
javax.servlet.Servlet
接口 - 继承
javax.servlet.GenericServlet
类 - 继承
javax.servlet.http.HttpServlet
类
- 实现
Servlet
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时(卸载应用/关闭容器时), 调用该方法 |
- HelloServlet
/**
* @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.xml
<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>
url-pattern
<url-pattern/>
用来指定Servlet的访问路径,必须以/
开头.
- 可以在
<servlet-mapping/>
配置多个<url-pattern/>
, 此时一个Servlet实例就绑定多个URL.- 可以在
<url-pattern/>
中使用通配符*
,可以使一个Servlet绑定一组URL, 但*
不能出现在中间位置,也不能只有*
通配符, 另外, 通配符只是一种模糊匹配URL的方式,如果存在更具体的<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
GenericService
抽象类实现了Servlet
接口并完成以下工作:
1. 将init()
方法中的ServletConfig
赋给一个实例变量, 使他可以通过getServletConfig()
来获取.
2. 为Servlet接口的所有方法提供默认实现.
3. 提供方法来包装ServletConfig
.
- Generic部分代码
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
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
实例.
- HelloHttpServlet
/**
* @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() ...");
}
}
HttpServletRequest
对于每一个HTTP请求, Servlet容器会在调用service()
方法时创建Request实例并传递给service
形参, HttpServletRequest
是Request在HTTP环境下的实例,其封装了有关请求的信息:
- 封装请求头信息;
- 封装请求正文数据(GET没有正文);
- 提供请求转发/包含功能;
- 作为域对象, 可以传递数据.
获取请求头
方法 | 描述 |
---|---|
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只会保留设置的响应头信息.
- 请求包含: 原Servlet既会保留响应头, 还会保留响应体内容.
注意: 请求转发时, 可能会因为原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. |
HttpServletResponse
同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协议部分介绍, 在此就不再赘述.
- 响应404
@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协议部分介绍, 在此就不再赘述.
- 设置禁用浏览器缓存(Cache-Control, pragma, expires)
@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);
}
- 设置重定向(302, Location)
@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()
方法手动刷新缓冲区.
ServletConfig
在容器初始化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. |
- java
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);
}
}
- web.xml
<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>
ServletContext
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. |
- web.xml
<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>
- java
@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. |
Servlet - 基础的更多相关文章
- JSP数据交互(二)和Servlet基础
01.Application原理与应用 01.application对象的作用域范围是整个应用服务,而它在应用中所承担的责任就类似于一个全局变量.只要服务启动,则application对象就会存在. ...
- Servlet基础(三) Servlet的多线程同步问题
Servlet基础(三) Servlet的多线程同步问题 Servlet/JSP技术和ASP.PHP等相比,由于其多线程运行而具有很高的执行效率. 由于Servlet/JSP默认是以多线程模式执行的, ...
- Servlet基础(二) Servlet的生命周期
Servlet基础(二) Servlet的生命周期 Servlet的生命周期可以分为三个阶段: 1.初始化阶段 2.响应客户请求阶段 3.终止阶段 Servlet的初始化阶段 在下列时刻Servlet ...
- Servlet基础(一) Servlet简介 关键API介绍及结合源码讲解
Servlet基础(一) Servlet基础和关键的API介绍 Servlet简介 Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中. Servlet容器负责Servl ...
- JSP/Servlet基础语法
相关学习资料 http://my.oschina.net/chape/blog/170247 http://docs.oracle.com/cd/E13222_01/wls/docs81/webapp ...
- Servlet基础简单总结(上)
Servlet基础一些简单总结(上): 1.Java Servlet是运行在Web服务器上的Java程序2.Java平台给Servlet开发者提供了强大的API/面向对象编程平台无关/强类型/垃圾回收 ...
- servlet总结:Servlet基础
Servlet基础 1.手工编写第一个Servlet ⑴继承HttpServlet ⑵重写doGet()或者doPost()方法 ⑶在web.xml中注册Servlet 2.使用eclipse编写第一 ...
- servlet基础(组成与生命周期)
servlet基础作用:servlet是运行在Web服务器或应用服务器上的程序:担当web浏览器或其他HTTP客户程序发出的请求与HTTP服务器上的数据库或应用程序之间的中间层.1.读取客户程序发送的 ...
- Unit01: Servlet基础 、 HTTP协议
Unit01: Servlet基础 . HTTP协议 在页面上输出当前时间 package web; import java.io.IOException; import java.io.PrintW ...
- Servlet基础教程:tutorialspoint-servlet
来自turorialspoint的Servlet基础教程(英文),官网:https://www.tutorialspoint.com/servlets/index.htm 这个教程在国内已经被翻译成中 ...
随机推荐
- 再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结
这篇是对angularJS的一些疑点回顾,是对目前angularJS开发的各种常见问题的整理汇总.如果对文中的题目全部了然于胸,觉得对整个angular框架应该掌握的七七八八了.希望志同道合的通知补充 ...
- [LeetCode] Minimum Factorization 最小因数分解
Given a positive integer a, find the smallest positive integer b whose multiplication of each digit ...
- 使用redis,zookeeper实现分布式锁
1.分布式锁 分布式锁一般用在分布式系统或者多个应用中,用来控制同一任务是否执行或者任务的执行顺序.在项目中,部署了多个tomcat应用,在执行定时任务时就会遇到同一任务可能执行多次的情况,我们可以借 ...
- Python super使用
一 基础使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: #!/usr ...
- 【BZOJ1059】【ZJOI2007】矩阵游戏
Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏.矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两 ...
- ●洛谷P3168 [CQOI2015]任务查询系统
题链: https://www.luogu.org/problemnew/show/P3168题解: 主席树 强制在线? 那就直接对每一个前缀时间建一个线段树(可持久化线段树),线段树维护优先度权值. ...
- Unix系统的文件目录项的内容是什么,这样处理的好处是什么?
(Unix系统采用树型目录结构,而且目录中带有交叉勾链.每个目录表称为一个目录文件.一个目录文件是由目录项组成的.) 每个目录项包含16个字节,一个辅存磁盘块(512B)包含32个目录项.在目录项中, ...
- Hash算法入门指南(聊点不一样的算法人生)
前言 很多人到现在为止都总是问我算法该怎么学啊,数据结构好难啊怎么的,学习难度被莫名的夸大了,其实不然.对于一个学计算机相关专业的人都知道,数据结构是大学的一门必修课,数据结构与算法是基础,却常常容易 ...
- avalon,xmp
- python实现编写windows服务
使用python编写windows服务 最近测试服务器上经常发生磁盘空间不足,每次手动清除比较麻烦,所以写个windows服务定时清理下.中间也遇到过几个坑,一起记录下来. 1.python实现win ...