※synchronized
如果沒有同步,需要注意有可能用戶端同時傳的問題int i; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out = resp.getWriter(); synchronized (this) { this.i++; try { Thread.sleep(2500); } catch (InterruptedException e) { e.printStackTrace(); } out.println("a=" + i); } }
※先將synchronized註解,然後開啟兩個瀏覽器,因為設定停止2.5秒,所以假設瀏覽器1得到1,瀏覽器得到2,
然後按完瀏覽器1時,在2.5秒之內按下瀏覽器2,會發現3不見了,兩個都是4
※initial & Destroy
@Override public void init() throws ServletException { try (BufferedReader in = new BufferedReader(new FileReader("xxx"))) { i = Integer.parseInt(in.readLine()); } catch (RuntimeException | IOException e) { i = 0; } } @Override public void destroy() { try (PrintWriter out = new PrintWriter(new FileWriter("xxx"))) { out.println(i); } catch (IOException e) { e.printStackTrace(); } } int i; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out = resp.getWriter(); // synchronized (this) { this.i++; // try { // Thread.sleep(2500); // } catch (InterruptedException e) { // e.printStackTrace(); // } out.println("a=" + i); // } }
※doGet和synchronized一樣,多init()和destroy(),xxx檔案前面沒有c:\之類的路徑,預設會放在eclipse.exe的地方
※第一次進來因為還沒有xxx檔案,所以會exception,就給它0
※server關閉時,就會存起來,起動時才去抓
※注意Eclipse有兩個按鈕很像,如下:
正常關閉是按Servers的紅鈕(Stop the server),但如果是按Console的紅鈕(Terminate)或者是按Eclipse右上角的╳,那就不會執行destroy(),所以如果突然斷電也是一樣
預設destroy是沒有執行任何東西,所以如果都不覆寫,按哪個就沒有關係
※三種變數
HelloServlet.java
public class HelloServlet extends HttpServlet { static int classI = 0; int i = 0; static Map<HelloServlet, HelloServlet> mapInstances = new HashMap<>(); static List<HelloServlet> listInstances = new ArrayList<>(); static Set<HelloServlet> setInstances = new HashSet<>(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/plain; charset=UTF-8"); PrintWriter out = resp.getWriter(); i++; out.println("實體變數=" + i); mapInstances.put(this, this); out.println("Map實體=" + mapInstances.size()); setInstances.add(this); out.println("Set實體=" + setInstances.size()); listInstances.add(this); out.println("List實體=" + listInstances.size()); classI++; out.println("靜態變數=" + classI); } }
web.xml
<servlet> <servlet-name>ooo</servlet-name> <servlet-class>controller.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ooo</servlet-name> <url-pattern>/xxx</url-pattern> </servlet-mapping> <servlet> <servlet-name>aaa</servlet-name> <servlet-class>controller.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>aaa</servlet-name> <url-pattern>/ooo</url-pattern> </servlet-mapping>
※結果參考:
實體變數=34 Map實體=1 Set實體=1 List實體=34 靜態變數=34
※只開一個瀏覽器或者開多個瀏覽器,但url最後都給xxx,結果就是34那三行一直變,Map實體和Set實體永遠都是1,因為Map的key和Set不可重覆
※另開一個瀏覽器,這次url最後給ooo,就會發現Map實體和Set實體是2了,而實體變數會從1開始,List實體和靜態變數是xxx和ooo的加總
※這個測試可以了解有幾個實體在run(Map實體和Set實體),每一個實體run了幾次(實體變數),全部的實體run了幾次(List實體、靜態變數)
※注意:我用3.0的@WebServlet(urlPatterns = { "/xxx", "/ooo" }),發現我給ooo和xxx,但Map實體和Set實體永遠都是1,可能設計的人認為既然一樣,就都給同一個實體吧!
又或者是版本問題,我用的是tomcat8(Servlet 3.1)
沒有留言:
張貼留言