最近要去参加一个程序设计比赛,听说比赛期间只能使用Eclipse和Tomcat,组委会不提供Spring之类的框架,故温习了一下Servlet。
What's a Servet?
A servlet is a small Java program that runs within a Web server.
Servlet就是一个运行在一个Web Server(如Tomcat)中的Java程序,可以收到客户端通过HTTP发来的请求(request),并提供返回值(response)。
Servlet Interface
init
public void init(ServletConfig config) throws ServletException
当一个ServletContainer(如Tomcat)初始化了一个servlet,它会调用这个servlet的init方法, 来告诉这个servlet它正在被放进这个container对外提供的服务中。只有在调用了init方法之后,这个servlet才可以收到客户端发来的请求。
当执行init方法时,若发生以下任何情况, container装载servlet的过程就会失败:
- 抛出ServletException
- 超时(时限由WebServer决定)
service
public void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException
在一个servlet的init方法被成功执行后,它就可以收到客户端发来的请求,当有请求发来,container会调用service方法, 针对这次请求服务段的响应会在这里进行,请注意servlet应为它的每次响应设置相应代码(500,404, 200...)。
另外一点需要注意的是, 在container中,servlets通常是并发运行的, 开发者们需要单例化一些资源的访问代码,比如文件、数据库、网络连接等等,以防死锁的发生。
destroy
当一个servlet并发执行的所有service方法全部结束后,container可以调用destroy方法来告诉一个servlet它正在被移出container提供的服务中。
调用这个方法后,一个servlet可以清理因为它被占用的所有资源。
getServletConfig
public ServletConfig getServletConfig()
返回container调用init时传入的ServeltConfig对象,这个对象包含这个servlet的初始化和启动参数
getServletInfo
public java.lang.String getServletInfo
返回诸如作者、版本、版权等信息
GenericServlet
GenericServlet implements Servlet, 它实现了Service接口定义的所有方法,因此我们介绍一下它自定义的方法
getServletName
ServletConfig.getServletName()
返回servlet实例的名字
log
- log(java.lang.String msg)
往servlet日志文件中插入日志信息, 由servlet的名字打头 - log(java.lang.String msg, java.lang.Throwable t)
往servlet日志文件中插入日志信息, 包含给定的字符串,以及给定异常的报错信息, 由servlet的名字打头
getInitParameter
从ServletConfig对象中获得指定的参数值
getInitParameterNames
获得ServletConfig对象中包含的参数名称的枚举
getServletContext
从ServletConfig对象中获得servlet运行的上下文对象(ServletContext)
init
提供无参的方式调用GenericServlet.init(ServletConfig config)
HttpServlet
service
protected void service (HttpServletRequest req, HttpServletResponse, res) throws ServletException, java.io.IOException
将共有service方法传来的请求分发给不同的方法(doXXX),通过以下代码可以看出,service方法首先获得客户端方来请求的方法,然后将其分发给doXXX方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals("GET")) {
long lastModified = getLastModified(req);
if (lastModified == -1L)
{
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException iae) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L)
{
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(304);
}
}
}
else if (method.equals("HEAD")) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
}
else if (method.equals("POST")) {
doPost(req, resp);
}
else if (method.equals("PUT")) {
doPut(req, resp);
}
else if (method.equals("DELETE")) {
doDelete(req, resp);
}
else if (method.equals("OPTIONS")) {
doOptions(req, resp);
}
else if (method.equals("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(501, errMsg);
}
}
doGet
protected void doGet(HttpServletRequest req, HttpServletResponse, res) throws ServletException, java.io.IOException
处理GET请求
重写这个方法可以自动地支持HTTP HEAD请求。HEAD请求相当于没有body的GET请求。
重写这个方法时, 首先读取请求数据,写响应头数据(必须写,会先于response body 发送), 然后写入响应输出流,最好包含content type和encoding,当使用PrintWriter对象响应请求时,就得在获得PrintWriter对象前设置content type。
如果可能,可以设置Content-Length头来使container开辟一个持久的连接来响应某一个客户端的请求,来优化性能。
GET方法应该是安全的,尤其是并发安全。
doHead
当用户只想获得响应头数据时,会像服务器发送HEAD请求。
doPost
HTTP POST 方法可以使客户端发送不限长度的数据给服务器。如何重写参照doGet
doPut
PUT操作可以帮助客户端服务器上传文件
重写这个方法时
doDelete
DELETE操作可以帮助客户端移出服务器上的文件或者网页
doOptions
OPTIONS请求可以使客户端知道servlet支持那些HTTP方法。
HTTP Request
HTTP Request | Description |
---|---|
GET | Asks to get the resource at the requested URL. |
POST | Asks the server to accept the body info attached. It is like GET request with extra info sent with the request. |
HEAD | Asks for only the header part of whatever a GET would return. Just like GET but with no body. |
TRACE | Asks for the loopback of the request message, for testing or troubleshooting. |
PUT | Says to put the enclosed info (the body) at the requested URL. |
DELETE | Says to delete the resource at the requested URL. |
OPTIONS | Asks for a list of the HTTP methods to which the thing at the request URL can respond |