简单的多人在线聊天系统----------简单基础的项目

以下是该聊天系统代码的思路和解释,详细的报告和代码可见:

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;

       


版权声明:本文为weixin_40789841原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。