Tomcat源码分析 - HttpServlet的源码分析

从官网下载Tomcat源码:Source Code Distributions,关联到Eclipse中。

1、查看HttpServlet中的service(ServletRequest req, ServletResponse res)方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
}

可以发现,这里把相应的request和response转换为了基于HTTP协议的相应对象。

Servlet接口中定义了一个service方法,HttpServlet对该方法进行了实现,将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse。

2、继续查看HttpServlet中的service(HttpServletRequest req, HttpServletResponse resp)方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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 / 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
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方法时,先获取提交的方法名,根据方法名调用相应的具体方法。

如果重写了该方法,那么就不会根据方法名调用其他具体的方法了。

3、接下来找个相关的具体方法doGet看看:

1
2
3
4
5
6
7
8
9
10
11
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method\_get\_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC\_METHOD\_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC\_BAD\_REQUEST, msg);
}
}

发现该方法只是判断协议类型,然后抛出相应的异常,其他什么都没做。

所以,在实现自己的Servlet时,需要重写这些方法,以符合自己的需求。一般不需要重写service方法。

arthinking wechat
欢迎关注itzhai公众号