1.HttpServlet的用法
提供了建立Http Servlet的抽象類,通過實作此類定義自己的Servlet
2.HttpServlet是否是線程安全
先說結論:HttpServlet不是線程安全
tomcat在隻在第一次有請求的時候加載Servlet,加載之後調用init方法進行初始化,容器中隻會儲存一個Servlet對象,當有Http請求的時候會調用service方法對請求進行處理。是以Servlet不是線程安全的,當我們在Servlet中定義類變量或者處理共享資源時,要注意線程安全問題。簡單的了解就是:單例多線程。
以下是對Servlet的測試代碼:
private static int staticCount = 0;
private int count = 0;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("count = " + count++ + "staticCount = " + staticCount++);
}
@Override
public void init() throws ServletException {
super.init();
System.out.println("init servlet!");
}
複制
運作tomcat,在浏覽器中第一次發送http請求的時候控制台會輸出
init servlet!
複制
浏覽器中多次發送請求後會輸出:
count = 14staticCount = 14
複制
由此驗證以上結論:單例多線程,Servlet不是線程安全的。
3.關鍵方法分析:service()
當接收到Http請求的時候會有一個public的service方法,此方法中隻是對參數類型進行判斷和強制轉換,然後調用此protected方法處理:
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);
}
}
複制
此方法中比較關鍵的地方是對get請求的處理:在處理get請求的時候會對所請求中的資源上次修改時間和實際修改時間比較,根據比較結果傳回狀态碼或者繼續請求資源。此方式需要Servlet實作getLastModified方法。其他請求都是直接調用相應方法。