基於servlet和ajax的聊天室


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

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

  關於怎么把自己的javaweb項目放到雲主機,有一個教程http://www.cnblogs.com/diyunfei/p/6826557.html,前提是得先在雲主機下載配置jkd,tomcat

  安裝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<KeyValuePair> list = new ArrayList<KeyValuePair>();// 創建一個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、當用戶輸入很快的時候有時候會丟失聊天數據

2、里面沒有把聊天數據保存到數據庫,而是單純保存在Arraylist中和txt中,一旦宕機重啟,后果很嚴重。。。關於mysql數據庫,以前用的都是解壓版,在windowserver2012好像不能用,反正我試了好多次都不行,到最后迫不得已下載了安裝版,才把mysql搞定。(雖然我里面沒用到數據庫。。。==)安裝版數據庫教程

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

4、不能查看聊天記錄

5、在學習sockets中。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM