您的位置:首頁>正文

基於servlet和ajax的聊天室

(手賤點了更新發佈時間, 發佈時間變成6-9。 。 。 )

2017-5-20, 在這個奇特的日子, 我不再滿足於在本地測試javaweb, 於是在上騰訊雲買了第一個雲伺服器, 由於是學生認證, 所以一個月只要10塊錢, 還是要搶的, 每天早上9點開搶(騰訊雲的學生優惠活動好像取消了, 所以我又選擇了阿裡雲)打開後, 發現其實是一個雲主機, 就是遠端主機, 只不過他可以給你一個公網ID, 就是在流覽器輸入公網ID的話, 全國所有人都可以訪問你的項目

安裝eclipse後先安裝servers, 在help中的安裝軟體, 輸入http://download.eclipse.org/releases/kepler, 選擇Web,XML, java EE and OSGi Enterprise Development

配置jdk

新建 JAVA_HOME 變數 。

變數值填寫jdk的安裝目錄

尋找 Path 變數

在變數值最後輸入 %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

(注意原來Path的變數值末尾有沒有;號, 如果沒有, 先輸入;號再輸入上面的代碼)

新建 CLASSPATH 變數

.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意最前面有一點)

檢驗是否配置成功 運行cmd 輸入 java -version (java 和 -version 之間有空格)

若如圖所示 顯示版本資訊 則說明安裝和配置成功。

配置tomcat

新建CATALINA_HOME, 變數值是tomcat的安裝路徑

找到PATH, 在最後增加tomcat的bin檔的絕對路徑(我的就是F:\eclipse\apache-tomcat-7.0.77\bin)

配置後可以在流覽器輸入localhost:8080, 試試看可以可以訪問tomcat的主頁, 如果可以即為配置成功

雲主機全部準備好了之後, 可以把在本機的eclipse中的maven項目匯出成一個war包, 複製這個war包到雲主機, 放到tomcat的webapp的目錄下, 打開tomcat/bin裡的start.bat,然後就可以在別的電腦通過“公網ID:埠號/專案名/”的方式訪問該專案

----------------------------------------------------------------------------------------------------------------------------------

下面開始說我這個專案, 是跟我室友合作的, 前端頁面是他做的,

這個是一個多人即時聊天室, 在此之前沒有接觸過怎麼實現即時聊天, 走了很多彎路, 不過幸好可以說是摸出點門道。

一、實現效果如下:

1、先進入登錄介面, 輸入呢稱和選擇頭像後進入

2、進入後的介面是這樣的:

3、然後就可以輸入聊天內容了

二、主要邏輯代碼

因為我現在只會後端, 就不把前端的代碼貼出來了, 主要邏輯是建立在servlet和ajax通信之上

1、我使用maven來構建這個項目, 不過我這裡並沒有用maven來導入包, 因為就幾個包, 我就手動導入專案結構如下

2、Control類用來接收用戶名, 頭像id, 聊天內容, 然後生成一個系統當前時間, 把這4個當成參數傳給Model, 這裡先說一下為什麼要生成一個系統當前時間, 這就說到我遇到的另一個問題了, 本來我們是商量說讓前臺把用戶名, 頭像id, 聊天內容, 使用者當前時間也傳過來, 但是發現效果並不好, 因為如果涉及到多人同時聊天,

各個用戶端的當前時間不一定會一樣, 會造成一些請求得不到正確的回應, 然後就想了個辦法, 用戶端在發送聊天記錄這條請求時, 只發送用戶名, 頭像id, 聊天內容, 然後由伺服器生成時間作為回應返回, 然後把4個屬性傳給Model

1 public class Control extends HttpServlet { 2 3 @Override 4 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 5 6 doGet(req, resp); 7 } 8 9 @Override 10 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 11 throws ServletException, IOException { 12 13 // 接受聊天記錄不發送東西:1 14 req.setCharacterEncoding("utf-8"); 15 16 String username = req.getParameter("username");// 用戶名 17 String content = req.getParameter("content");// 內容 18 String pic = req.getParameter("picture"); 19 SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");// 設置日期格式 20 21 String time = df.format(new Date); 22 23 String callbackName = req.getParameter("jsoncallback");// 時間 24 // ------------------------------------------------------------------------- 25 26 try { 27 new Model; 28 Model.write(username, content, time, pic); 29 } catch (ClassNotFoundException e) { 30 e.printStackTrace; 31 } 32 String success = "success"; 33 String result = "{\"success\":\"" + success + "\",\"time\":\"" + time + "\"}"; 34 35 String renderStr = callbackName + "(" + result + ")"; 36 resp.setContentType("text/plain;charset=UTF-8"); 37 resp.getWriter.write(renderStr); 38 } 39 40 }

這裡的success只是為了給前臺做判斷。 。 裡面的time也是前臺用來給聊天內容打時間標籤用的, json資料是動態拼接的, 然後以callbackname作為函數名, 直接返回一個字串

2、Model類是做資料處理的, 就是把4個屬性存到keyvaluepair物件中, 然後在把物件存到Arraylist中, Model裡有3個方法:

(1)fileinit方法是初始化一個流, 打開txt檔的開口, (其實這裡我本來是想用mybatis, 但是時間倉促我就說先存在txt裡湊合吧, 以後找時間改一下)

(2)write是把4個屬性追加到檔案結尾,這裡遇到的問題是,寫到檔裡的中文變成了亂碼,所以我就把他處理了一下URLDecoder.decode(username, "UTF-8");

(3)getContent方法是用來提取資料用的,用的key就是時間

1 public class Model { 2 public static BasicDataSource ds = null; 3 4 public final static String JDBC_DRIVER = "com.mysql.jdbc.Driver"; 5 public final static String USER_NAME = "root"; 6 public final static String PASSWORD = "123456"; 7 public final static String DB_URL = "jdbc:mysql://localhost/shen_db?useUnicode=true&characterEncoding=utf-8&useSSL=false"; 8 9 public static FileWriter writer = null; 10 public static OutputStreamWriter osw = null; 11 public static FileOutputStream fos = null; 12 static List list = new ArrayList;// 創建一個arraylist,把鍵值物件保存在其中 13 14 public Model { 15 fileInit; 16 } 17 18 // public static void dbcpInit { 19 // ds = new BasicDataSource; 20 // ds.setUrl(DB_URL); 21 // ds.setDriverClassName(JDBC_DRIVER); 22 // ds.setUsername(USER_NAME); 23 // ds.setPassword(PASSWORD); 24 // 25 // } 26 public static void fileInit { 27 String fileName = "C:\\a.txt"; 28 try { 29 fos = new FileOutputStream(fileName, true); 30 } catch (FileNotFoundException e1) { 31 e1.printStackTrace; 32 } 33 try { 34 osw = new OutputStreamWriter(fos, "UTF-8"); 35 } catch (UnsupportedEncodingException e1) { 36 e1.printStackTrace; 37 } 38 } 39 40 public static void write(String username, String content, String time, String pic) 41 throws ClassNotFoundException { 42 // Connection connection = null; 43 // PreparedStatement preparedStatement = null; 44 String x = null; 45 String y = null; 46 try { 47 x = URLDecoder.decode(username, "UTF-8"); 48 y = URLDecoder.decode(content, "UTF-8"); 49 } catch (UnsupportedEncodingException e1) { 50 e1.printStackTrace; 51 } 52 String z = time; 53 String p = pic; 54 System.out.println("發送東西來的內容:" + y); 57 58 list.add(new KeyValuePair(z, x, y, p)); 59 try { 60 osw.write(KeyValuePair.getKey); 61 osw.write("---"); 62 osw.write(KeyValuePair.getPic(z)); 63 osw.write("---"); 64 osw.write(KeyValuePair.getName(z)); 65 osw.write("---"); 66 osw.write(KeyValuePair.getContent(z)); 67 osw.write("\r\n"); 68 } catch (IOException e) { 69 e.printStackTrace; 70 } finally { 71 try { 72 if (osw != null) { 73 osw.close; 74 } 75 } catch (IOException e) { 76 e.printStackTrace; 77 } 78 } 79 80 // try { 81 // connection = ds.getConnection; 82 // preparedStatement = connection.prepareStatement("insert into Chatlog 83 // (time,logs) values (?,?)"); 84 // preparedStatement.setString(1, currentTime); 85 // preparedStatement.setString(2, x); 86 // } catch (SQLException e) { 87 // 88 // e.printStackTrace; 89 // } 90 91 } 92 93 public static KeyValuePair getContent(String time) { 94 95 String time1 = time; 96 KeyValuePair kvp = null; 97 if (list.isEmpty) { 98 } else { 99 for (KeyValuePair ss : list) { 100 if (time1.equals(ss.getKey)) { 101 kvp = ss; 102 } else { 103 kvp = null; 104 } 105 } 106 } 107 return kvp; 108 } 109 110 public static void main(String[] args) { 111 112 new Model; 113 } 114 115 }

3、GetCurrentTime這個類就是用來返回當前時間的

public class GetCurrentTime extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String callbackName = req.getParameter("jsoncallback"); System.out.println("get current time"); String time = null; SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); time=df.format(new Date); String result=null; result="{\"time\":\""+time+"\"}"; String renderStr = callbackName + "(" + result + ")"; resp.setContentType("text/plain;charset=UTF-8"); resp.getWriter.write(renderStr); } }

4、SendServlet這個類是用來提取聊天資料的,前臺在GetCurrentTime那個servlet中接收到我的系統時間後,把這個系統時間當成一個參數然後發送一個請求到SendServlet,然後我就去調用Model的getcontent,返回一個keyvaluepair物件,

利用這個物件調出所有資料,可以看到json資料都是動態拼接的方法做成的,甚是拙劣

1 public class SendServlet extends HttpServlet { 2 3 @Override 4 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 5 doPost(req, resp); 6 } 7 8 @Override 9 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 10 11 12 String time = req.getParameter("time"); 13 System.out.println("時間"+time); 14 KeyValuePair kvp = null; 15 String result = "{\"content\":\"" + null + "\",\"time\":\"" + null + "\",\"name\":\"" + null 16 + "\",\"picture\":\"" + null + "\"}"; 17 String callbackName4 = req.getParameter("jsoncallback"); 18 19 try { 20 kvp = Model.getContent(time); 21 System.out.println(kvp); 22 if (kvp != null) { 23 result = "{\"content\":\"" + kvp.getContent(time) + "\",\"time\":\"" + kvp.getKey + "\",\"name\":\"" 24 + kvp.getName(time) + "\",\"picture\":\""+kvp.getPic(time) +"\"}"; 25 } 26 kvp = null; 27 String renderStr = callbackName4 + "(" + result + ")"; 28 resp.setContentType("text/plain;charset=UTF-8"); 29 resp.getWriter.write(renderStr); 30 31 } catch (IOException e) { 32 e.printStackTrace; 33 } 34 } 35 36 }

5、keyvaluepair物件時用來保存那4個屬性的bean,就一個構造函數和4個get方法

public class KeyValuePair { public static String Key; public static String Name; public static String Content; public static String Pic; public KeyValuePair(String k, String n,String c,String p) { Key = k; Name = n; Content =c; Pic=p; } public static String getName(String k){ return Name; } public static String getPic(String k){ return Pic; } public static String getKey{ return Key; } public static String getContent(String k){ return Content; } public static void main(String[] args) { } }

三、還存在的問題

1、當用戶輸入很快的時候有時候會丟失聊天資料

3、servlet怎麼跟ajax異域通訊,那時候還沒有學spring,所以糾結了很久,查了資料到最後發現是通過一個很不“優雅”的方式進行通信的,就是強行拼接一個json資料類型,不知道還有沒有更好的方法

4、不能查看聊天記錄

5、在學習sockets中。。

(2)write是把4個屬性追加到檔案結尾,這裡遇到的問題是,寫到檔裡的中文變成了亂碼,所以我就把他處理了一下URLDecoder.decode(username, "UTF-8");

(3)getContent方法是用來提取資料用的,用的key就是時間

1 public class Model { 2 public static BasicDataSource ds = null; 3 4 public final static String JDBC_DRIVER = "com.mysql.jdbc.Driver"; 5 public final static String USER_NAME = "root"; 6 public final static String PASSWORD = "123456"; 7 public final static String DB_URL = "jdbc:mysql://localhost/shen_db?useUnicode=true&characterEncoding=utf-8&useSSL=false"; 8 9 public static FileWriter writer = null; 10 public static OutputStreamWriter osw = null; 11 public static FileOutputStream fos = null; 12 static List list = new ArrayList;// 創建一個arraylist,把鍵值物件保存在其中 13 14 public Model { 15 fileInit; 16 } 17 18 // public static void dbcpInit { 19 // ds = new BasicDataSource; 20 // ds.setUrl(DB_URL); 21 // ds.setDriverClassName(JDBC_DRIVER); 22 // ds.setUsername(USER_NAME); 23 // ds.setPassword(PASSWORD); 24 // 25 // } 26 public static void fileInit { 27 String fileName = "C:\\a.txt"; 28 try { 29 fos = new FileOutputStream(fileName, true); 30 } catch (FileNotFoundException e1) { 31 e1.printStackTrace; 32 } 33 try { 34 osw = new OutputStreamWriter(fos, "UTF-8"); 35 } catch (UnsupportedEncodingException e1) { 36 e1.printStackTrace; 37 } 38 } 39 40 public static void write(String username, String content, String time, String pic) 41 throws ClassNotFoundException { 42 // Connection connection = null; 43 // PreparedStatement preparedStatement = null; 44 String x = null; 45 String y = null; 46 try { 47 x = URLDecoder.decode(username, "UTF-8"); 48 y = URLDecoder.decode(content, "UTF-8"); 49 } catch (UnsupportedEncodingException e1) { 50 e1.printStackTrace; 51 } 52 String z = time; 53 String p = pic; 54 System.out.println("發送東西來的內容:" + y); 57 58 list.add(new KeyValuePair(z, x, y, p)); 59 try { 60 osw.write(KeyValuePair.getKey); 61 osw.write("---"); 62 osw.write(KeyValuePair.getPic(z)); 63 osw.write("---"); 64 osw.write(KeyValuePair.getName(z)); 65 osw.write("---"); 66 osw.write(KeyValuePair.getContent(z)); 67 osw.write("\r\n"); 68 } catch (IOException e) { 69 e.printStackTrace; 70 } finally { 71 try { 72 if (osw != null) { 73 osw.close; 74 } 75 } catch (IOException e) { 76 e.printStackTrace; 77 } 78 } 79 80 // try { 81 // connection = ds.getConnection; 82 // preparedStatement = connection.prepareStatement("insert into Chatlog 83 // (time,logs) values (?,?)"); 84 // preparedStatement.setString(1, currentTime); 85 // preparedStatement.setString(2, x); 86 // } catch (SQLException e) { 87 // 88 // e.printStackTrace; 89 // } 90 91 } 92 93 public static KeyValuePair getContent(String time) { 94 95 String time1 = time; 96 KeyValuePair kvp = null; 97 if (list.isEmpty) { 98 } else { 99 for (KeyValuePair ss : list) { 100 if (time1.equals(ss.getKey)) { 101 kvp = ss; 102 } else { 103 kvp = null; 104 } 105 } 106 } 107 return kvp; 108 } 109 110 public static void main(String[] args) { 111 112 new Model; 113 } 114 115 }

3、GetCurrentTime這個類就是用來返回當前時間的

public class GetCurrentTime extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String callbackName = req.getParameter("jsoncallback"); System.out.println("get current time"); String time = null; SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); time=df.format(new Date); String result=null; result="{\"time\":\""+time+"\"}"; String renderStr = callbackName + "(" + result + ")"; resp.setContentType("text/plain;charset=UTF-8"); resp.getWriter.write(renderStr); } }

4、SendServlet這個類是用來提取聊天資料的,前臺在GetCurrentTime那個servlet中接收到我的系統時間後,把這個系統時間當成一個參數然後發送一個請求到SendServlet,然後我就去調用Model的getcontent,返回一個keyvaluepair物件,

利用這個物件調出所有資料,可以看到json資料都是動態拼接的方法做成的,甚是拙劣

1 public class SendServlet extends HttpServlet { 2 3 @Override 4 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 5 doPost(req, resp); 6 } 7 8 @Override 9 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 10 11 12 String time = req.getParameter("time"); 13 System.out.println("時間"+time); 14 KeyValuePair kvp = null; 15 String result = "{\"content\":\"" + null + "\",\"time\":\"" + null + "\",\"name\":\"" + null 16 + "\",\"picture\":\"" + null + "\"}"; 17 String callbackName4 = req.getParameter("jsoncallback"); 18 19 try { 20 kvp = Model.getContent(time); 21 System.out.println(kvp); 22 if (kvp != null) { 23 result = "{\"content\":\"" + kvp.getContent(time) + "\",\"time\":\"" + kvp.getKey + "\",\"name\":\"" 24 + kvp.getName(time) + "\",\"picture\":\""+kvp.getPic(time) +"\"}"; 25 } 26 kvp = null; 27 String renderStr = callbackName4 + "(" + result + ")"; 28 resp.setContentType("text/plain;charset=UTF-8"); 29 resp.getWriter.write(renderStr); 30 31 } catch (IOException e) { 32 e.printStackTrace; 33 } 34 } 35 36 }

5、keyvaluepair物件時用來保存那4個屬性的bean,就一個構造函數和4個get方法

public class KeyValuePair { public static String Key; public static String Name; public static String Content; public static String Pic; public KeyValuePair(String k, String n,String c,String p) { Key = k; Name = n; Content =c; Pic=p; } public static String getName(String k){ return Name; } public static String getPic(String k){ return Pic; } public static String getKey{ return Key; } public static String getContent(String k){ return Content; } public static void main(String[] args) { } }

三、還存在的問題

1、當用戶輸入很快的時候有時候會丟失聊天資料

3、servlet怎麼跟ajax異域通訊,那時候還沒有學spring,所以糾結了很久,查了資料到最後發現是通過一個很不“優雅”的方式進行通信的,就是強行拼接一個json資料類型,不知道還有沒有更好的方法

4、不能查看聊天記錄

5、在學習sockets中。。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示