簡單的多人在線聊天系統----------簡單基礎的項目

以下是該聊天系統代碼的思路和解釋,詳細的報告和代碼可見:

https://download.csdn.net/download/weixin_40789841/12496057

3 系統實現

3.1 表示層

       3.1.1 登錄界面(loginForm.jsp):

(1)初始化application,採用以下代碼:

ArrayList customers = (ArrayList)application.getAttribute("customers");       //初始化customers         

           if(customers==null)        {

                  customers = new ArrayList();

                  application.setAttribute("customers",customers);

           }

          

           ArrayList msgs = (ArrayList)application.getAttribute("msgs");//初始化msgs

           if(msgs==null)        {

                          msgs = new ArrayList();

                          application.setAttribute("msgs",msgs);

           }

        (2)使用javascript實現驗證碼的點擊刷新功能,代碼如下:

       <script type="text/javascript">

               function refresh(){

                      loginForm.imgValidate.src = "validate.jsp?id=" + Math.random();//驗證碼點擊刷新

               }

       </script>

        (3)添加登錄界面表單,並用<p style="text-align:center">,實現表單居中顯示,代碼如下:

               <p style="text-align:center">

     ★★歡迎登錄在線交流系統★★<br>

    <form action="login.action" name="loginForm" method="post">

           輸入賬號:<input name="account" type="text"><BR>

           輸入密碼:<input name="password" type="password"><br> 

           請輸入驗證碼: <input type="text" name="code" size="10">

               <img name="imgValidate" src="validate.jsp" οnclick="refresh()"><BR>

           <input type="submit" value="登錄" ><br>

           <a href = "logininsert.jsp">還沒賬號,點擊這裏註冊</a>

</form>   </p>

  1. 在<body>裏面加bgcolor="#fffff",實現界面顏色的更換。
  2. 實現效果如圖2

 

圖 2  登錄界面

       3.1.2 註冊界面(logininsert.jsp):

       (1)添加註冊的表單,,並用<p style="text-align:center">,實現表單居中顯示,代碼如下:

       <p style="text-align:center">

               ---歡迎來到註冊頁面---<br>

               <form action="insert.action" name="form1" method="post">

           輸入賬號:<input name="account" type="text"><BR>

           輸入密碼:<input name="password" type="password">   <br>     

           輸入名字:<input name="cname" type="text">   <br>

           請輸入驗證碼: <input type="text" name="code" size="10">

               <img name="imgValidate" src="validate.jsp" οnclick="refresh()"><BR>

           <input type="submit" value="註冊" >

           </p>

</form>

(2)使用javascript實現驗證碼的點擊刷新功能,代碼如下:

<script type="text/javascript">

               function refresh(){

                      form1.imgValidate.src = "validate.jsp?id=" + Math.random();//驗證碼點擊刷新

               }

       </script>

(3)在<body>裏面加bgcolor="#fffff",實現界面顏色的更換。

 

圖 3  註冊界面

3.1.3 驗證碼實現(validate.jsp

(1)在內存中創建圖象,代碼如下:

int width = 60, height = 20;

       BufferedImage image = new BufferedImage(width, height,

               BufferedImage.TYPE_INT_RGB);

(2)獲取畫筆,代碼如下:

Graphics g = image.getGraphics();

(3)設定背景色,代碼如下:

g.setColor(new Color(200, 200, 200));

       g.fillRect(0, 0, width, height);

(4)取隨機產生的驗證碼(4位數字),代碼如下:

Random rnd = new Random();

       int randNum = rnd.nextInt(8999) + 1000;

       String randStr = String.valueOf(randNum);

(5)將驗證碼存入session,實現代碼如下

       session.setAttribute("randStr", randStr);

(6)將驗證碼顯示到圖象中,代碼如下:

g.setColor(Color.black);

       g.setFont(new Font("", Font.PLAIN, 20));

       g.drawString(randStr, 10, 17);

(7)隨機產生100個干擾點,使圖象中的驗證碼不易被其他程序探測到,代碼如下:

for (int i = 0; i < 100; i++){

               int x = rnd.nextInt(width);

               int y = rnd.nextInt(height);

               g.drawOval(x, y, 1, 1);

       }

(8)輸出圖象到頁面,代碼如下:

ImageIO.write(image, "JPEG", response.getOutputStream());

       out.clear();

       out = pageContext.pushBody();

(9)驗證碼實現截圖,如圖4:

 

圖 4  驗證碼實現

       3.1.4 登錄失敗頁面、註冊失敗頁面:基本原理都一樣,至於登錄成功的話,將跳轉到聊天界面,註冊成功將跳轉到登錄界面。以登錄失敗爲例:

       (1)輸出文字,以及返回相應界面的連接。代碼如下:

       <p style="text-align:center">

   ----- 密碼或賬號錯誤,登錄失敗  -----<br>

   <a href = "loginForm.jsp">---點擊這裏,重新登錄---</a>.

   </p>

       (2)使用轉向語句,實現3秒未操作返回上一個界面。代碼如下:

       response.setHeader("Refresh", "3;URL=javascript:history.back(-1)");

(3)在<body>裏面加bgcolor="#fffff",實現界面顏色的更換。

       (4)頁面實現如圖5:

      

圖 5  登錄失敗

       3.1.5 驗證碼錯誤頁面(vfail.jsp:跟3.1.4的代碼差不多,不同的是用了javascript:history.back(-1)來返回到上一頁。頁面如圖6:

      

3.2  業務邏輯層

       3.2.1 登錄驗證(loginAction.java、strurs2.xml、loginsuccess.jsp):

       (1)用javabean獲取account、password及code(驗證碼)。代碼如下:

       public String getAccount() {

               return account;

       }

       public void setAccount(String account) {

               this.account = account;

       }

       public String getPassword() {

               return password;

       }

       public void setPassword(String password) {

               this.password = password;

       }

       public void setCode(String code) {

               this.code = code;

       }

       public String getCode() {

               return code;

       }

       (2)編寫execute(),先用HttpSession類的API接口獲得存在session中的源驗證碼randStr,讓code與源驗證碼進行對比,如果不同,則return “fail1”;如果相同,則進入賬號密碼驗證。賬號密碼驗證:通過輸入的賬號,查詢數據庫中該賬號的密碼,將查詢得到的密碼與輸入的密碼進行對比,如果相同,則return“success”,否則return “fail”。代碼如下:

       public String execute()throws Exception{

               CustomerDao cdao = new CustomerDao();

               HttpSession session = ServletActionContext.getRequest().getSession();   //用HttpSession類的API接口獲得存在session中的源驗證碼randStr

           String checkcode = (String)session.getAttribute("randStr");

               if(!code.equals(checkcode))   //讓code與源驗證碼進行對比

               {

                      return "fail1";

               }

               else{

               Customer customer = cdao.getCustomerByAccount(account);// 通過輸入的賬號,查詢數據庫中該賬號的密碼。

               if(customer==null || !customer.getPassword().equals(password)){// 將查詢得到的密碼與輸入的密碼進行對比

                      return "fail";

              }

               return "success";

               }

               }

(3)編寫strurs2.xml。先寫入相應action的跳轉界面,實現從表單跳轉到loginAction.java,然後編寫loginAction.java中execute()返回的字符串所要跳轉的相應JSP網頁。代碼如下:

       <action name = "login" class="login.loginAction">

                      <result name="success">/loginsuccess.jsp</result>

                      <result name="fail">/loginfail.jsp</result>

                      <result name="fail1">/vfail.jsp</result>

               </action>

 

(4)編寫loginsuccess.jsp。如果只有以上的代碼,會出現一個賬戶同時在線多個。因此需要一個判斷機制,來判斷一個賬戶是否已經登錄。該系統將在線的賬號添加到application類的customers中,該jsp通過輸入的賬號,與customers中的所有的賬號進行對比,如果相同,讓temp這個標誌變量爲1,直接進入聊天界面,不在讓其加入到customers中,如果不相同,則temp爲0,將該customer加入到session中和application類的customers中。不過只有以上判斷還不夠,這缺少第一次登錄時customers爲空的判斷,所以要添加改判斷。代碼如下:

int temp = 0;

            request.setCharacterEncoding("gb2312");

           String account = request.getParameter("account");

           String password = request.getParameter("password");

           CustomerDao cdao = new CustomerDao();

           Customer customer = cdao.getCustomerByAccount(account);

           ArrayList cuss = (ArrayList)application.getAttribute("customers");

           if(cuss.size()>0)    //判斷是否時該系統第一次啓動

           {

                   for(int i=cuss.size()-1;i>=0;i--)

                   {

                          Customer cus = (Customer)cuss.get(i);

                          if(cus.getAccount().equals(account))//判斷customers的account是否與輸入的account相同

                          {

                                 temp=1;

                                 break;

                          }

                   }

                   if(temp==1)            //如果相同則跳轉到聊天界面

                   {

                          response.sendRedirect("chatForm.jsp");  

                         

                   }

                   else{              //不同則將該customer加入到session中和application類的customers中。

                          session.setAttribute("customer",customer);

               ArrayList customers = (ArrayList)application.getAttribute("customers");

               ArrayList msgs = (ArrayList)application.getAttribute("msgs");

               customers.add(customer);              //將customer添加到customers中

               msgs.add(customer.getCname() + "上線啦!");                

            response.sendRedirect("chatForm.jsp");

                   }    

           }

           else if(cuss.size()==0){          //如果爲第一次登錄,直接將該customer加入到session中和application類的customers中。

               session.setAttribute("customer",customer);

               ArrayList customers = (ArrayList)application.getAttribute("customers");

               ArrayList msgs = (ArrayList)application.getAttribute("msgs");

               customers.add(customer);

               msgs.add(customer.getCname() + "上線啦!");                

            response.sendRedirect("chatForm.jsp");   }

(5)相關實現截圖如圖6:

 

圖 6 登錄成功跳轉至聊天界面

3.2.2  註冊驗證(loginAction.java、strurs2.xml)

(1)用javabean獲取account、password、cname及code(驗證碼)。代碼如下:

       public String getAccount() {

               return account;

       }

       public void setAccount(String account) {

               this.account = account;

       }

       public String getPassword() {

               return password;

       }

       public void setPassword(String password) {

               this.password = password;

       }

       public String getCname() {

               return cname;

       }

       public void setCname(String cname) {

               this.cname = cname;

       }

       public void setCode(String code) {

               this.code = code;

       }

       public String getCode() {

               return code;

       }

       (2)編寫execute(),先用HttpSession類的API接口獲得存在session中的源驗證碼randStr,讓code與源驗證碼進行對比,如果不同,則return “fail1”;如果相同,則驗證新加入的賬號是否數據庫中已經存在。驗證新加入的賬號是否數據庫中已經存在:通過輸入的賬號,查詢數據庫中是否存在該賬號如果存在則return  “fail”,並判斷賬號、密碼、用戶名是否有沒輸入的,如果沒有輸入,也return “fail”,否則將其插入數據庫,並return “success”,代碼如下:

           public  String execute()throws Exception{

               HttpSession session = ServletActionContext.getRequest().getSession(); // 用HttpSession類的API接口獲得存在session中的源驗證碼randStr   

           String checkcode = (String)session.getAttribute("randStr");

           if(!code.equals(checkcode))// 讓code與源驗證碼進行對比

               {

                      return "fail1";

               }

               else{

               CustomerDao cdao = new CustomerDao();

               Customer customer = cdao.getCustomerByAccount(account);

               System.out.println(account);

               if(customer != null||account.equals("")||password.equals("")||cname.equals(""))//驗證新加入的賬號是否數據庫中已經存在:通過輸入的賬號,查詢數據庫中是否存在該賬號

               {

                      return "fail";

               }

               else{

           int i = cdao.insertCustomer(account,password,cname);

               if(i>0)

               {

                      System.out.println("註冊成功 ");

                      return "success";

               }

               return "fail";

               }

               }

           }

(3)編寫strurs2.xml。先寫入相應action的跳轉界面,實現從表單跳轉到insertAction.java,然後編寫insertAction.java中execute()返回的字符串所要跳轉的相應JSP網頁。代碼如下:

               <action name = "insert" class="login.insertAction">

                      <result name="success">/loginForm.jsp</result>  //當返回success時跳轉到登錄界面,以方便剛註冊的賬號進行登錄

                      <result name="fail">/insertfail.jsp</result>//返回fail時跳轉到insertfail.jsp

                      <result name="fail1">/vfail.jsp</result>//返回fail1時跳轉到vfail.jsp

               </action>

(4)相關實現截圖如圖7、圖8:

 

圖 7  註冊

              

圖 8  註冊失敗

       3.2.3 聊天消息及相關功能(msgs.jsp、chatAction.jsp):

       (1)編寫chatAction.jsp。使用request對象獲取用戶發送的信息,然後將發送信息的用戶名和信息內容加入到application的msgs對象中。

       <%

             Customer customer = (Customer)session.getAttribute("customer");

     %>

    <%

           request.setCharacterEncoding("UTF-8");

           String msg = request.getParameter("msg");//使用request對象獲取用戶發送的信息

           ArrayList msgs = (ArrayList)application.getAttribute("msgs");

           if(msg!=null && !msg.equals("")){

                  msgs.add(customer.getCname() + "說:" + msg); //將發送信息的用戶名和信息內容加入到application的msgs對象中  

                  response.sendRedirect("chatForm.jsp");              

           }

%>

(2)編寫msgs.jsp。將application中的msgs對象輸出、顯示,然後從application中的customers中將所有用戶賬戶和用戶名顯示在當前在線列,並加入response.setHeader("Refresh","3")進行3秒一次的刷新,以保證信息的實時顯示。代碼如下:

<%

             response.setHeader("Refresh","3");  //進行3秒一次的刷新,以保證信息的實時顯示

       %>

      <table width="80%"  border="0" align="center">

        <tr bgcolor="orange" align="center">

        <td width="75%">消息</td>

        <td width="25%">當前在線</td>

        </tr>

      <tr bgcolor="yellow">

        <td><%       

           ArrayList msgs = (ArrayList)application.getAttribute("msgs");

           for(int i=msgs.size()-1;i>=0;i--){           //將application中的msgs對象輸出、顯示

                   out.println(msgs.get(i) + "<BR>");

           }

    %></td>

        <td valign="top"><%        

           ArrayList customers = (ArrayList)application.getAttribute("customers");

           for(int i=customers.size()-1;i>=0;i--){  

                   Customer customer = (Customer)customers.get(i);

                   out.println(customer.getAccount() + "(" + customer.getCname() + ")" + "<BR>");        從application中的customers中將所有用戶賬戶和用戶名顯示在當前在線列   

           }

    %></td>

      </tr>

    </table>

(3)相關截圖如圖9:

 

圖 9  聊天功能

3.3數據訪問層

       3.3.1 編寫Customer.java,將用戶信息用VO封裝,將輸入的數據進行封裝。代碼如下:

       package vo;

public class Customer {

       private String account;

       private String password;

       private String cname;

       public String getAccount() {

               return account;

       }

       public void setAccount(String account) {

               this.account = account;

       }

       public String getPassword() {

               return password;

       }

       public void setPassword(String password) {

               this.password = password;

       }

       public String getCname() {

               return cname;

       }

       public void setCname(String cname) {

               this.cname = cname;

       }

}

3.3.2 編寫CustomerDao.java。該類主要進行對數據庫的訪問和操作。

(1)編寫一個連接數據庫的函數,同時要將相應的驅動程序導入本系統中。因爲本系統採用的時sqlserver2008,所以驅動包爲sqljdbc4.jar,連接數據庫函數爲:

public void initConnection() throws Exception {

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");       

conn=  DriverManager.getConnection("jdbc:sqlserver://192.168.11.128:1433;DatabaseName=SalesDB;user=123;password=12345");

       }

(2)編寫查詢函數getCustomerByAccount()。首先,調用上一步的函數連接數據庫,然後設置sql語句,並使用PreparedStatement方法對sql語句設置,以防止sql語句因組織依賴變量導致的出錯發生。接着,用executeQuery()運行sql語句,實現數據的查詢,並使用ResultSet對查詢所得數據進行存儲。然後將這些數據添加進customer中,關閉數據庫連接。代碼如下:

public Customer getCustomerByAccount(String account) throws Exception {

               Customer cus = null;

               initConnection();                   //連接數據庫

               String sql =

"SELECT ACCOUNT,PASSWORD,CNAME FROM T_CUSTOMER WHERE ACCOUNT=?";             //sql語句

               PreparedStatement ps = conn.prepareStatement(sql);//sql語句設置

               ps.setString(1, account);

               ResultSet rs = ps.executeQuery();         //運行sql語句

               if(rs.next()){

                      cus = new Customer();

                      cus.setAccount(rs.getString("ACCOUNT"));        //將查詢的數據添加到customer中

                      cus.setPassword(rs.getString("PASSWORD"));

                      cus.setCname(rs.getString("CNAME"));

               }

               closeConnection();         //關閉數據庫連接

               return cus;             

       }

(3)編寫查詢函數insertCustomer()。首先,調用第一步的函數連接數據庫,然後設置sql語句,並使用PreparedStatement方法對sql語句設置,以防止sql語句因組織依賴變量導致的出錯發生。接着,用executeUpdate ()運行sql語句,實現數據的插入,最後關閉數據庫連接。代碼如下:

public int insertCustomer(String account,String password,String cname) throws Exception {

               initConnection();//連接數據庫

               String sql =

"insert into T_CUSTOMER(ACCOUNT,PASSWORD,CNAME) values(?,?,?)";//插入的sql語句

               PreparedStatement ps = conn.prepareStatement(sql);//設置sql語句

               ps.setString(1, account);

               ps.setString(2, password);

               ps.setString(3, cname);

               int i= ps.executeUpdate();//運行sql語句

               closeConnection();//關閉數據庫連接

               return i;

       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章