1.1,servlet的基本結構html
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class ServletTemplate extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Use "request" to read incoming HTTP headers // (e.g., cookies) and query data from HTML forms. // Use "response" to specify the HTTP response status // code and headers (e.g., the content type, cookies). PrintWriter out = response.getWriter(); // Use "out" to send content to browser } }
這是一個基本的servlet,servlet通常擴展自HttpServlet,依據數據發送方式的不一樣(GET或POST),覆蓋doGet或doPost方法,若是但願servlet對GET和POST採起一樣的行動,只須要讓doGet調用doPost便可,反之亦然。java
doGet和doPost都接受2個參數,HttpServletRequest和HttpServletResponse,經過HttpServletRequest能夠得到全部的輸入數據:表單數據,HTTP請求報頭,客戶主機名等。HttpServletResponse能夠指定輸出信息,如HTTP狀態碼和響應報頭,最重要的是,經過它能夠得到PrintWriter,用它將文檔內容發給用戶。數據庫
1.2,生成純文本的servlet瀏覽器
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); out.println("Hello World"); } }
直接用out輸出文本形式的頁面服務器
1.3 生成HTML的servlet
1)告知瀏覽器,要生成HTMLcookie
2)修改println,輸出html格式的內容多線程
3)用形式語法驗證器檢查生成的hmtl(後面講述)併發
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">\n"; out.println(docType + "<HTML>\n" + "<HEAD><TITLE>Hello</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>Hello111</H1>\n" + "</BODY></HTML>"); } }
1.4 簡單的html構建工具工具
把html的DOCTYPE和HRAD部分放在一個使用工具中,避免每次重複性能
package coreservlets; import javax.servlet.*; import javax.servlet.http.*; public class ServletUtilities { //單獨寫在一個類裏,之後直接引用 public static final String DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">"; public static String headWithTitle(String title) { return(DOCTYPE + "\n" + "<HTML>\n" + "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n"); } ......... }
package coreservlets; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloServlet3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Hello (3)"; out.println(ServletUtilities.headWithTitle(title) + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>" + title + "</H1>\n" + "</BODY></HTML>"); } }
1.5 理解servlet的生命週期
服務器只建立每一個servlet的單一實例,每一個用戶請求都會引起新的線程,將用戶請求交付給doGet或者doPost處理。
生命週期::首次建立servlet時,它的init對象獲得調用,所以init是放置一次性設置代碼的地方。在這以後,針對每一個用戶請求都會建立一個線程,該線程調用前面建立的實例的service方法,多個併發請求通常會致使多個線程同時調用service(能夠實現特殊的接口SingleThreadModel實現單線程運行),以後由service方法依據接收到的http請求類型,調用doGet,doPost或者其餘doXxx方法,最後若是服務器決定卸載某個servlet,調用servlet的destroy方法。
1,service方法
服務器每次收到對servlet的請求,都會產生一個新的線程,調用service方法檢查HTTP請求類型(GET,POST,PUT,DELETE等),從而調用相應的方法。
2,doGet,doPost,doXxx方法
servlet的主體。
3,init方法
能夠在servlet開始時,完成初始化:
在一個servlet裏寫一個
public void init() thorws ServletException{
//init code
}
來實現初始化。
4,destroy方法
服務器移除servlet以前能夠調用destroy方法來完成一些工做,例如使得servlet有機會關閉數據庫鏈接,停滯後臺進程,將cookie列表和點擊數寫入磁盤等收尾工做。
1.6 SingleThreadModel接口
一般狀況下,系統只生成servlet的單一實例,以後爲每一個用戶請求建立新的線程,這意味着,若是新的請求到來,而前面的請求還在執行,那麼可能會出現多個線程併發執行的狀況,所以doGet和doPost必須當心的同步對共享數據的訪問(注意doGet和doPost內部的局部變量並不擔憂這一點)。,原則上能夠這麼作:
public class YourServlet extends HttpServlet implements SingleThreadModel { ... }
阻止多線程訪問servlet,一般這不是一個好的解決方案。缺點:同步對servlet的訪問對性能形成極大影響。
下例試圖爲每一個user指定一個惟一的id,
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class UserIDs extends HttpServlet { private int nextID = 0; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Your ID"; String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">\n"; out.println(docType + "<HTML>\n" + "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n" + "<CENTER>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>" + title + "</H1>\n"); //關鍵代碼,在多請求狀況下並不能正常運行 String id = "User-ID-" + nextID; out.println("<H2>" + id + "</H2>"); nextID = nextID + 1; out.println("</BODY></HTML>"); } }
三種解決方案:
1,減小競爭 並不能徹底解決
String id = "User-ID-" + nextID++;
2,使用SingleThreadModel,上面已說,不推薦
3,明確對代碼塊的同步訪問。推薦
synchronized(this) {
String id = "User-ID-" + nextID;
out.println("<H2>" + id + "</H2>");
nextID = nextID + 1; }