一.MVC軟件設計模式
1:MVC簡介
MVC即model(模型)-view(視圖)-controller(控制器)的縮寫,一種軟件設計典范,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。
2.圖解
3.優點
耦合性低
視圖層和業務層分離,這樣就允許更改視圖層代碼而不用重新編譯模型和控制器代碼,同樣,一個應用的業務流程或者業務規則的改變只需要改動MVC的模型層即可。因為模型與控制器和視圖相分離,所以很容易改變應用程序的數據層和業務規則。
模型是自包含的,並且與控制器和視圖相分離,所以很容易改變應用程序的數據層和業務規則。如果把數據庫從MySQL移植到Oracle,或者改變基於RDBMS數據源到LDAP,只需改變模型即可。一旦正確的實現了模型,不管數據來自數據庫或是LDAP服務器,視圖將會正確的顯示它們。由於運用MVC的應用程序的三個部件是相互獨立,改變其中一個不會影響其它兩個,所以依據這種設計思想能構造良好的松耦合的構件
重用性高
隨着技術的不斷進步,需要用越來越多的方式來訪問應用程序。MVC模式允許使用各種不同樣式的視圖來訪問同一個服務器端的代碼,因為多個視圖能共享一個模型,它包括任何WEB(HTTP)瀏覽器或者無線瀏覽器(wap),比如,用戶可以通過電腦也可通過手機來訂購某樣產品,雖然訂購的方式不一樣,但處理訂購產品的方式是一樣的。由於模型返回的數據沒有進行格式化,所以同樣的構件能被不同的界面使用。例如,很多數據可能用HTML來表示,但是也有可能用WAP來表示,而這些表示所需要的命令是改變視圖層的實現方式,而控制層和模型層無需做任何改變。由於已經將數據和業務規則從表示層分開,所以可以最大化的重用代碼了。模型也有狀態管理和數據持久性處理的功能,例如,基於會話的購物車和電子商務過程也能被Flash網站或者無線聯網的應用程序所重用。
生命周期成本低
MVC使開發和維護用戶接口的技術含量降低。
部署快
使用MVC模式使開發時間得到相當大的縮減,它使程序員(Java開發人員)集中精力於業務邏輯,界面程序員(HTML和JSP開發人員)集中精力於表現形式上。
可維護性高
分離視圖層和業務邏輯層也使得WEB應用更易於維護和修改。
有利軟件工程化管理
由於不同的層各司其職,每一層不同的應用具有某些相同的特征,有利於通過工程化、工具化管理程序代碼。控制器也提供了一個好處,就是可以使用控制器來聯接不同的模型和視圖去完成用戶的需求,這樣控制器可以為構造應用程序提供強有力的手段。給定一些可重用的模型和視圖,控制器可以根據用戶的需求選擇模型進行處理,然后選擇視圖將處理結果顯示給用戶。
4.缺點
沒有明確的定義
完全理解MVC並不是很容易。使用MVC需要精心的計划,由於它的內部原理比較復雜,所以需要花費一些時間去思考。同時由於模型和視圖要嚴格的分離,這樣也給調試應用程序帶來了一定的困難。每個構件在使用之前都需要經過徹底的測試。
不適合小型,中等規模的應用程序
花費大量時間將MVC應用到規模並不是很大的應用程序通常會得不償失。
增加系統結構和實現的復雜性
對於簡單的界面,嚴格遵循MVC,使模型、視圖與控制器分離,會增加結構的復雜性,並可能產生過多的更新操作,降低運行效率。
視圖與控制器間的過於緊密的連接
視圖與控制器是相互分離,但卻是聯系緊密的部件,視圖沒有控制器的存在,其應用是很有限的,反之亦然,這樣就妨礙了他們的獨立重用。
視圖對模型數據的低效率訪問
依據模型操作接口的不同,視圖可能需要多次調用才能獲得足夠的顯示數據。對未變化數據的不必要的頻繁訪問,也將損害操作性能。
一般高級的界面工具或構造器不支持模式
改造這些工具以適應MVC需要和建立分離的部件的代價是很高的,會造成MVC使用的困難。
https://baike.baidu.com/item/MVC%E6%A1%86%E6%9E%B6/9241230?fr=aladdin&fromid=85990&fromtitle=MVC
二.html向Java發送數據
1.GET、POST方式
GET請求的數據會附在URL之后(就是把數據放置在HTTP協議頭中),以?分割URL和傳輸數據,參數之間以&相連,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果數據是英文字母/數字,原樣發送,如果是空格,轉換為+,如果是中文/其他字符,則直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX為該符號以16進制表示的ASCII.
POST請求一般是表單提交的請求,他具有一定的數據安全性,不會再地址欄中顯示提交數據,並且對編碼沒有要求.
注意:GET請求不得對數據進行增刪改查,敏感數據要用POST方式提交
2.獲得數據

1 @Override 2 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 3 System.out.println("進入GET請求"); 4 String strG = req.getQueryString(); 5 System.out.println(strG); 6 }
如果URL傳遞中文后台得到的是類似%E4%BD%A0%E5的數據

1 @Override 2 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 3 System.out.println("進入POST請求"); 4 req.setCharacterEncoding("utf-8"); // 設置中文編碼 5 String strP = req.getParameter("strP"); 6 System.out.println("strP = " + strP); 7 }
req.getParameter("str")方法中name要和需要提取數據的<input>標簽中name="str"屬性一樣,並且返回String類型
如果參數值是文中就要使用req.setCharaEncoding("UTF-8")方法設置中文編碼來防止亂碼.
三.后台目錄搭建
1.系統文件放置
WEB-INF目錄只有服務器可以訪問到,未必避免用戶通過URL直接訪問系統頁面,將后台頁面放置在WEB-INF目錄下.
2.通過轉發訪問WEB-INF后台頁面

1 @Override 2 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 3 System.out.println("進入POST請求"); 4 req.setCharacterEncoding("utf-8"); // 設置中文編碼 5 String strP = req.getParameter("strP"); 6 System.out.println("strP = " + strP); 7 8 // 通過轉發的方式跳轉頁面,如果刷新會重復之前的操作 9 req.getRequestDispatcher("/WEB-INF/jsp/Jsp.jsp").forward(req, resp); 10 }
通過req.getRequsetDispatcher("路徑").forward(req.resp).
刷新轉發后的頁面,會重復之前的操作.轉發后的URL地址是隱藏的所以它的安全性很好,且速度較快
3.通過重定向訪問其他服務器上的文件

1 @Override 2 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 3 System.out.println("進入GET請求"); 4 String strG = req.getQueryString(); 5 System.out.println(strG); 6 resp.sendRedirect("http://www.runoob.com/python/python-for-loop.html"); 7 }
重定向由於是通過servlet1重定向到servlet2,servlet2對服務器的請求響應做出響應.所以速度較慢,且URL地址會顯示在地址欄.
重定向無法直接訪問WEB-INF目錄下的文件,但可以由Servlet2轉發訪問WEB-INF目錄下的文件

1 @Override 2 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 3 System.out.println("進入GET請求"); 4 String strG = req.getQueryString(); 5 System.out.println(strG); 6 resp.sendRedirect("Servlet2"); 7 }

1 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException ,IOException { 2 System.out.println("進入Servler2程序的GET請求"); 3 // 網頁轉發到WEB-INF后台頁面 4 req.getRequestDispatcher("/WEB-INF/jsp/Jsp.jsp").forward(req,resp); 5 } 6
四.數據持久化
1.JDBC簡介
JDBC(Java DataBase Connectivity,java數據庫連接)是一種用於執行SQL語句的Java API,可以為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC提供了一種基准,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序,同時,JDBC也是個商標名。
https://baike.baidu.com/item/jdbc/485214
2.JDBC配置
下載相應數據庫的鏈接文件,把jar文件放置在WEB-INF/lib目錄下
3.查看數據庫名稱和版本號

1 import java.sql.Connection; 2 import java.sql.DatabaseMetaData; 3 import java.sql.DriverManager; 4 import java.sql.SQLException; 5 6 import org.junit.Test; 7 8 public class UserDao { 9 10 // 驅動信息 11 String username = "root"; 12 String password = "123456"; 13 String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false"; 14 String driver = "com.mysql.cj.jdbc.Driver"; 15 16 17 // 加載驅動 18 { 19 try { 20 Class.forName(driver); 21 } catch (ClassNotFoundException e) { 22 // TODO Auto-generated catch block 23 e.printStackTrace(); 24 } 25 } 26 27 // 查看連接數據庫名稱和版本號 28 @Test 29 public void m01() throws SQLException { 30 Connection conn = DriverManager.getConnection(url,username,password); 31 DatabaseMetaData dmd = conn.getMetaData(); 32 String name = dmd.getDatabaseProductName(); 33 String version = dmd.getDatabaseProductVersion(); 34 System.out.println(name + " " + version); 35 } 36 37 }
-MySQL 警告WARN: Establishing SSL connection without server's identity verification is not recommended.
首先恭喜,出現這個的時候MySQL說明已經安裝成功了,這是警告不是錯誤,以后使用是不影響的。大概的意思就是說建立ssl連接,但是服務器沒有身份認證,這種方式不推薦使用。
解決辦法:
原來的連接url:Connection connect = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "letmein");
現在的連接url:Connection connect = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false","root", "letmein");
-java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized...
這是在使用MySQL 8.0以上版本(MySQL連接驅動和版本都是8.0以上)的時候出現的問題錯誤,我們需要在訪問數據庫的Url后面加上以下的語句即可:
?serverTimezone=GMT%2B8
比如,我原來的url是:
"jdbc:mysql://localhost:3306/shiro_test"
應該修改為:
"jdbc:mysql://localhost:3306/shiro_test?serverTimezone=GMT%2B8"
從錯誤上看應該是時區的錯誤,所以我們只需要設置完畢系統的時區即可。這里的GMT%2B8
代表東八區。
還有一種解決辦法就是設置整個數據庫的時區,可以執行下面的語句來完成:
show variables like '%time_zone%'
set global time_zone='+8:00';
參考:
https://blog.csdn.net/qq_15581405/article/details/52403576?locationNum=13
https://blog.csdn.net/github_35186068/article/details/80919528
4.簡單的增刪改查

1 // 添加 2 @Test 3 public void m02() throws SQLException{ 4 Connection conn = DriverManager.getConnection(url,username,password); 5 String sql = "insert into user1 values(?,?)"; 6 PreparedStatement ps = conn.prepareStatement(sql); // 對即將執行的SQL語句進行預編譯,安全快速 7 ps.setInt(1,1); // 替換sql中第一個?為1 8 ps.setString(2,"小明"); // 替換sql中第二個?為"小明" 9 int i = ps.executeUpdate(); 10 conn.close(); // 關閉連接,連接占用很大資源 11 System.out.println( "i == " + i); 12 }

1 // 刪除 2 @Test 3 public void m03() throws SQLException{ 4 Connection conn = DriverManager.getConnection(url,username,password); 5 String sql = "delete from user1 where user_id = ?"; 6 PreparedStatement ps = conn.prepareStatement(sql); 7 ps.setInt(1, 1); 8 int i = ps.executeUpdate(); 9 conn.close(); 10 System.out.println("i == " + i); 11 }

1 // 更改 2 @Test 3 public void m05() throws SQLException{ 4 Connection conn = DriverManager.getConnection(url,username,password); 5 String sql = "update user1 set user_name = '鑫鑫' where user_id = 3"; 6 PreparedStatement ps = conn.prepareStatement(sql); 7 int i = ps.executeUpdate(); 8 conn.close(); 9 System.out.println(i); 10 }

1 /** 2 * 查詢 3 * Java數據類型 VS 數據庫數據類型 4 * int VS int 5 * int VS decimal 6 * String VS varchar 7 * Date VS timestamp 8 * Date VS datetime 9 * @throws SQLException 10 */ 11 @Test 12 public void m04() throws SQLException{ 13 Connection conn = DriverManager.getConnection(url,username,password); 14 String sql = "select * from user1 "; 15 PreparedStatement ps = conn.prepareStatement(sql); 16 ResultSet rs = ps.executeQuery(); 17 while(rs.next()) { // 循環往下移動,同時rs.next()返回布爾類型,只有布爾類型才能用到循環條件里面 18 int user_id = rs.getInt(1); 19 String user_name = rs.getString("user_name"); 20 System.out.println(user_id + " " + user_name); 21 } 22 conn.close(); 23 }
sql語句最好使用preparedStatement(sql)方法預編譯,這樣做可以提高速度,防止sql注入提高安全性.
數據庫連接占用很大資源,使用完就要關閉連接.
五.Java建立model
1.model簡介
一般一個Java類對應model中的一個實體,model只關心數據模型,不關心數據獲取。
2.建立一個user模型

1 public class UserModel { 2 3 protected int user_id = -1; 4 protected String user_name = null; 5 protected String user_password = null; 6 7 protected int getUser_id() { 8 return user_id; 9 } 10 protected void setUser_id(int user_id) { 11 this.user_id = user_id; 12 } 13 protected String getUser_name() { 14 return user_name; 15 } 16 protected void setUser_name(String user_name) { 17 this.user_name = user_name; 18 } 19 protected String getUser_password() { 20 return user_password; 21 } 22 protected void setUser_password(String user_password) { 23 this.user_password = user_password; 24 } 25 26 27 public void prin(){ 28 System.out.println(user_id + " " + user_name + " " + user_password); 29 } 30 31 32 }
Model中一個成員代表表中的一個字段。
Model要有Get和Set接口。
六.從數據庫提取數據存放到model中
1.DAO簡介
2.編寫一個UserDAO

1 import java.sql.Connection; 2 import java.sql.DriverManager; 3 import java.sql.PreparedStatement; 4 import java.sql.ResultSet; 5 import java.sql.SQLException; 6 7 import org.junit.Test; 8 9 public class UserDao2 { 10 // 驅動信息 11 String username = "root"; 12 String password = "123456"; 13 String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false"; 14 String driver = "com.mysql.cj.jdbc.Driver"; 15 16 //加載驅動 17 { 18 try { 19 Class.forName(driver); 20 } catch (ClassNotFoundException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } 24 } 25 26 27 // 獲得數據並將數據存儲到UserModel中 28 @Test 29 public void m01() throws SQLException{ 30 UserModel user = new UserModel(); // 實例化一個UserModel類 31 Connection conn = DriverManager.getConnection(url,username,password); 32 String sql = "select * from user1 where user_id = 3"; 33 PreparedStatement ps = conn.prepareStatement(sql); 34 ResultSet rs = ps.executeQuery(); 35 while(rs.next()){ 36 user.setUser_id(rs.getInt(1)); 37 user.setUser_name(rs.getString(2)); 38 user.setUser_password(rs.getString(3)); 39 } 40 conn.close(); 41 user.prin(); 42 } 43 }
因為DAO層只關注數據訪問,所以需要Model來提供數據存儲。
如果需要多個相同的Model,請使用集合框架。
七.返回數據到html
1.Ajax簡介

2.編寫一個Service來實現業務邏輯

1 import java.io.IOException; 2 import java.io.PrintWriter; 3 import java.sql.SQLException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import com.google.gson.Gson; 12 13 14 15 @WebServlet("/UserService") 16 public class UserService extends HttpServlet{ 17 18 UserDao2 ud = new UserDao2(); 19 20 @Override 21 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 22 System.out.println("進入GET方法"); 23 // 創建用戶表模型 24 UserModel user = new UserModel(); 25 user.setUser_id(4); 26 user.setUser_name("小徐"); 27 user.setUser_password("123456"); 28 29 // 將user對象轉換成JSON文本(數據) 30 Gson gson = new Gson(); 31 String json = gson.toJson(user); // 轉換數據格式 32 33 // 使用HttpServletResponse接口完成數據的響應處理 34 // 關鍵點:中文編碼處理,數據響應格式的處理,輸出數據到前端界面 35 resp.setCharacterEncoding("utf-8"); 36 resp.setContentType("test/plain"); 37 PrintWriter out = resp.getWriter(); 38 out.println(json); 39 out.flush(); 40 out.close(); 41 } 42 43 @Override 44 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 45 // TODO Auto-generated method stub 46 super.doPost(req, resp); 47 } 48 49 50 }
Gson.toJson(Model)可以將Model轉化成Json對象
resp.setCharacterEncoding("UTF-8")方法設置中文編碼
3.編寫一段AJAX來響應數據

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>MyHtml.html</title> 5 <meta charset="UTF-8"> 6 <script src="../jquery-1.11.0.min.js"></script> 7 <script> 8 $(function(){ 9 $("#btn").click(function(){ 10 $.ajax({ 11 url: "../UserService", 12 type: "GET", 13 success: function(data){ 14 console.log("發送成功"); 15 var div = document.getElementById("div"); 16 div.innerHTML += data.user_id + " " + data.user_name + " " + data.user_password; 17 }, 18 dataType: "json" 19 }); 20 }); 21 }); 22 </script> 23 </head> 24 <body> 25 This is my HTML page. 26 <br> 27 <a href="../servlet?strp=中文">連接</a> 28 <br> 29 <form action="../servlet" method="POST"> 30 <input type="text" name="strP"> <input type="submit"> 31 </form> 32 <button id="btn">點擊</button> 33 <div id="div"></div> 34 </body> 35 </html>

1 import java.io.IOException; 2 import java.io.PrintWriter; 3 import java.sql.SQLException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import com.google.gson.Gson; 12 13 14 15 @WebServlet("/UserService") 16 public class UserService extends HttpServlet{ 17 18 UserDao2 ud = new UserDao2(); 19 20 @Override 21 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 22 System.out.println("進入GET方法"); 23 // 創建用戶表模型 24 UserModel user = new UserModel(); 25 user.setUser_id(4); 26 user.setUser_name("小徐"); 27 user.setUser_password("123456"); 28 29 // 將user對象轉換成JSON文本(數據) 30 Gson gson = new Gson(); 31 String json = gson.toJson(user); // 轉換數據格式 32 33 // 使用HttpServletResponse接口完成數據的響應處理 34 // 關鍵點:中文編碼處理,數據響應格式的處理,輸出數據到前端界面 35 resp.setCharacterEncoding("utf-8"); 36 resp.setContentType("test/plain"); 37 PrintWriter out = resp.getWriter(); 38 out.println(json); 39 out.flush(); 40 out.close(); 41 } 42 43 44 }
url: Java服務程序地址
type: 請求方式
success: function(data){ } 回調函數
dataType: 返回的數據格式
4.編寫一段Ajax來發送數據

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>MyHtml.html</title> 5 <meta charset="UTF-8"> 6 <script src="../jquery-1.11.0.min.js"></script> 7 <script> 8 $(function(){ 9 $("#btn").click(function(){ 10 user_id = document.getElementById("a1").innerHTML; 11 user_name = document.getElementById("a2").innerHTML; 12 $.ajax({ 13 url: "../UserService", 14 type: "post", 15 dataType: "json", 16 data: {"user_id":user_id , "user_name":user_name } 17 }); 18 }); 19 }); 20 </script> 21 </head> 22 <body> 23 This is my HTML page. 24 <br> 25 <a href="../servlet?strp=中文">連接</a> 26 <br> 27 <form action="../servlet" method="POST"> 28 <input type="text" name="strP"> <input type="submit"> 29 </form> 30 <button id="btn">點擊</button> 31 <div id="div"></div> 32 <div id="a1">5</div> 33 <div id="a2">小紅</div> 34 </body> 35 </html>

1 import java.io.IOException; 2 import java.io.PrintWriter; 3 import java.sql.SQLException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import com.google.gson.Gson; 12 13 14 15 @WebServlet("/UserService") 16 public class UserService extends HttpServlet{ 17 18 19 @Override 20 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 21 // 設置中文編碼 22 req.setCharacterEncoding("UTF-8"); 23 String user_id = req.getParameter("user_id"); 24 String user_name = req.getParameter("user_name"); 25 System.out.println(user_id + " " + user_name); 26 } 27 28 29 }
如果data:中傳入dom對象會報 Maximum call stack size exceeded
8.會話
1.什么是會話
Web程序中常用的技術,用來跟蹤用戶的整個會話。常用的會話跟蹤技術是Cookie與Session。Cookie通過在客戶端記錄信息確定用戶身份,Session通過在服務器端記錄信息確定用戶身份。
一次會話指的是:就好比打電話,A給B打電話,接通之后,會話開始,直到掛斷電話,該次會話就結束了,而瀏覽器訪問服務器,就跟打電話一樣,瀏覽器A給服務器發送請求,訪問web程序,該次會話就已經接通,其中不管瀏覽器發送多少請求(就相當於接通電話后說話一樣),都視為一次會話,直到瀏覽器關閉,本次會話結束。其中注意,一個瀏覽器就相當於一部電話,如果使用火狐瀏覽器,訪問服務器,就是一次會話了,然后打開google瀏覽器,訪問服務器,這是另一個會話,雖然是在同一台電腦,同一個用戶在訪問,但是,這是兩次不同的會話。
2.會話解決了什么問題
知道了什么是會話后,思考一個問題,一個瀏覽器訪問一個服務器就能建立一個會話,如果別的電腦,都同時訪問該服務器,就會創建很多會話,就拿一些購物網站來說,我們訪問一個購物網站的服務器,會話就被創建了,然后就點擊瀏覽商品,對感興趣的商品就先加入購物車,等待一起付賬,這看起來是很普通的操作,但是想一下,如果有很多別的電腦上的瀏覽器同時也在訪問該購物網站的服務器,跟我們做類似的操作呢?服務器又是怎么記住用戶,怎么知道用戶A購買的任何商品都應該放在A的購物車內,不論是用戶A什么時間購買的,不能放入用戶B或用戶C的購物車內的呢?所以就有了cookie和session這兩個技術,就像第一行說的那樣,cookie和session用來跟蹤用戶的整個會話,
3.Cookie和Session之間的區別和聯系
假如一個咖啡店有喝5杯咖啡免費贈一杯咖啡的優惠,然而一次性消費5杯咖啡的機會微乎其微,這時就需要某種方式來紀錄某位顧客的消費數量。想象一下其實也無外乎下面的幾種方案:
1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎么對待了。這種做法就是協議本身支持狀態。但是http協議本身是無狀態的
2、發給顧客一張卡片,上面記錄着消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以后的消費相聯系起來。這種做法就是在客戶端保持狀態。也就是cookie。 顧客就相當於瀏覽器,cookie如何工作,下面會詳細講解
3、發給顧客一張會員卡,除了卡號之外什么信息也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店里的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種做法就是在服務器端保持狀態。
由於HTTP協議是無狀態的,而出於種種考慮也不希望使之成為有狀態的,因此,后面兩種方案就成為現實的選擇。具體來說cookie機制采用的是在客戶端保持狀態的方案,而session機制采用的是在服務器端保持狀態的方案。同時我們也看到,由於采用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要借助於cookie機制來達到保存標識的目的,但實際上它還有其他選擇
原文:https://blog.csdn.net/android_bar/article/details/70570216
2018-9-4