SSH实现的JAVA在线聊天室

最近在一次偶然的机会下接触到了EasyUI,里面有一个layout的demo和QQ聊天窗口超像,于是萌发了写一个在线聊天室的想法。
实现步骤也非常简单,首先是先创建两个存储数据的表,![图片描述][1]![图片描述][2],分别是保存用户姓名密码的user表,还有保存用户聊天记录的chat表.
建好表了,第一步就是创建对应的类。然后通过MyEclipse搭建一个最简单的SSH框架,![图片描述][3],UserAction主要实现用户的注册和登陆,ChatAction用于聊天数据的传输。

@Controller//用于标注控制层组件
@Namespace("/user")//url前缀
@Scope("prototype")//Action默认是单例,但实际开发中,一般是多例,因为一般一个Action可能会对应多个不同的请求
//@ParentPackage("struts-default")//继承特定的package,默认是“struts-default”,因此可以省略不写
@Results({
    @Result(name="loginSuccess",type="redirect",location="/Test/chat.jsp"),
    @Result(name="msg",location="/msg.jsp"),
    @Result(name="tologin",location="/index.jsp")
})
public class UserAction extends ActionSupport implements ModelDriven<User>{

    @Autowired//自动注入
    private UserService service ;
    private User user=new User();

    //struts默认拦截“.action以及不加任何后缀”
    @Action(value="login")//访问:/user/regist.action 或  /user/regist
    public String login(){
      //获取request
      HttpServletRequest request = ServletActionContext.getRequest();      
      //调用service层的方法,向数据库查询
      List<User> u =service.loginUser(user);
      System.out.println(u+u.toString());
      if(u.isEmpty()){
          System.out.println("登陆失败");
          request.setAttribute("msg", "登陆失败");
            return "msg";
      }
      request.getSession().setAttribute("user", u.get(0));
      return "loginSuccess";

      //将提示信息存入request域中,用以前台显示

    }

    @Action(value="regist")
    public String regist(){
        List<User> u = service.findUserByName(user.getUsername());
         HttpServletRequest request = ServletActionContext.getRequest();
        if(u.isEmpty()){
            service.addUser(user);
            request.setAttribute("msg", "注册成功");              
            return "msg";
        }
          request.setAttribute("msg", "用户名已被注册");
          return "msg";

    }

    @Override
    public User getModel() {
        // TODO Auto-generated method stub
        return user;
    }

}

这里没有对用户名为空等等各种情况的判断,只简单的实现注册和登陆。

@Controller
@Namespace("/chat")
@Scope("prototype")
@Results({
    @Result(name="msg",location="/msg.jsp"),
    @Result(name="success",location="/Test/chat.jsp",type="redirect")
})
public class ChatAction extends ActionSupport implements ModelDriven<Chat>{
    @Autowired
    private ChatService chatService;
    @Autowired//自动注入
    private UserService userService ;
    private Chat chat= new Chat();
    private int chatnum;

    @Action(value="chatAdd")
    public void chatAdd(){  
        chat.setChattime(new Date());
        chatService.addChat(chat);
    }

    //第一次更新
    @Action(value="chatUpate")
    public String chatUpdate(){
    List<Chat> chats=chatService.getChat();
        String json = JSONArray.fromObject(chats).toString();
        //将json发送给浏览器
        try {
            ServletActionContext.getResponse().setContentType("application/json;charset=utf-8");
            ServletActionContext.getResponse().getWriter().write(json);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            System.out.println("出错了");
            e.printStackTrace();
        }
        return null;//告诉struts2不需要进行结果处理

    }
    //ajax轮询更新
    @Action(value="chatFlash")
    public String chatFlash(){

        // TODO Auto-generated method stub
        try {
            while(true){
                List<Chat> chatf=chatService.getChatById(chatnum);

                if(chatf.isEmpty()){
                    //睡觉1秒
                    Thread.sleep(1000);
                }else{
                    String json = JSONArray.fromObject(chatf).toString();   
                    ServletActionContext.getResponse().setContentType("application/json;charset=utf-8");
                    ServletActionContext.getResponse().getWriter().write(json);
                    return null;
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            System.out.println("出错了");
            e.printStackTrace();
        }
        return null;//告诉struts2不需要进行结果处理
    }

    public int getChatnum() {
        return chatnum;
    }
    public void setChatnum(int chatnum) {
        this.chatnum = chatnum;
    }
    @Override
    public Chat getModel() {
        // TODO Auto-generated method stub
        return chat;
    }

}

chatAction主要分三块,插入聊天记录,用户第一次进入聊天室时把记录追加到“聊天记录”的div中,然后通过ajax的方式更新聊天信息到主面板。聊天页面没有才有表单提交的方式,全部通过ajax实现。因为感觉每提交一次,又要从服务器查询一次,追加一次,感觉很费劲。
然后其实最关键的,是冠以聊天记录刷新如何实现,最初的思路是,ajax每隔1S发送一次请求,把查询到的新信息追加到主面板上,虽然这种方式很简单实现,但是感觉很不合理。我的解决方案是,只发送一次ajax请求,服务器接收到请求后死循环,每隔1S查询一次数据库,一旦发现有新的聊天记录(这里是通过判断最新的聊天记录id和网页现存的记录id进行比较),跳出死循环,把新记录返回,把新记录data追加到面板后,又一次发送ajax请求,其实就相当于无限递归。网页源代码如下:


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Border Layout on Panel - jQuery EasyUI Demo</title>
    <link rel="stylesheet" type="text/css" href="../themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="../themes/icon.css">
    <link rel="stylesheet" type="text/css" href="demo.css">
    <script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../jquery-1.7.2.min.js"></script>
    <script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../jquery.easyui.min.js"></script>
<style>
p{ 
    margin:0 auto;
color:red;

font-size:10px;
}
</style>
<script type="text/javascript">
    $(function(){
        //发送ajax请求
        chatUpdate();
        var id=setTimeout(flash,1000);

    });
        function addChat(){
        var chatnum=$("#chatnum").val();    
        var chattext=$("#chattext").val();  
        $("#chattext").val("");
        var username="${sessionScope.user.username}";
            $.post("${pageContext.request.contextPath}/chat/chatAdd",{"chattext":chattext,"username":username},function(){});
        }

        function flash(){
        var chatnum=$("#chatnum").val();    

        var username="${sessionScope.user.username}";

        $.post("${pageContext.request.contextPath}/chat/chatFlash?chatnum="+chatnum,function(data){ 

            $(data).each(function(){
                if(username==this.username){
                        $("#main").append("<p align='right' style='color:green;'>"+this.chattimes+"</p>");
                        $("#main").append("<p align='right' style='color:green;''>   "+this.chattext+"</p>");
                    }else{
                        $("#main").append("<p>"+this.username+"  "+this.chattimes+"</p>");
                        $("#main").append("<p>   "+this.chattext+"</p>");
                    }
                    chatnum=this.id;
            });
        $("#chatnum").val(chatnum);
        flash();                
        },"json");
    }
        function chatUpdate(){

        var username="${sessionScope.user.username}";
        var num=0;
        $.post("${pageContext.request.contextPath}/chat/chatUpate",function(data){  

            $(data).each(function(){
                if(username==this.username){
                        $("#east").append("<p align='right' style='color:green;'>"+this.chattimes+"</p>");
                        $("#east").append("<p align='right' style='color:green;''>   "+this.chattext+"</p>");
                    }else{
                        $("#east").append("<p>"+this.username+"  "+this.chattimes+"</p>");
                        $("#east").append("<p>   "+this.chattext+"</p>");
                    }
                num=this.id;
            }); 
            $("#chatnum").val(num); 
        },"json");

    }
</script>
</head>
<body>
    <h2>欢迎<s:property value="#session.user.username"/>加入聊天室</h2>
    <div class="demo-info" style="margin-bottom:10px">
        <div class="demo-tip icon-tip"></div>
        <div>This is a chat-room.</div>
    </div>

    <div class="easyui-layout" style="width:700px;height:400px;">
        <div region="north" style="overflow:hidden;height:60px;padding:10px">
            <h2>JAVA 聊天室</h2>
        </div>
        <div region="south" split="true" style="height:120px;background:#fafafa;overflow:hidden;">
            <form action="${pageContext.request.contextPath}/chat/chat" method="post" style="width:100%;height:100%;">
                <textarea name ="chattext" id="chattext" style="width:99%;height:99%;overflow:hidden;">

重点是 flash()的无限调用,看懂就明白了。
于是乎,java在线聊天1.0版本就上线了,有没有同学有兴趣进行2.0版本的升级呢,增加在线私聊的功能,左侧的面板正好可以用作显示在线人数,问题是如何实现弹窗。可恶刚才写的没了,又写一遍。

点赞