commet-java服务端

/**标准的一个发送消息类*/
public class MessageSender implements Runnable {

    private String msg;
    //private HttpServletResponse connect;
    private Map<String,HttpServletResponse> cons=
            new HashMap<String,HttpServletResponse>();
    private boolean running=true;
    private boolean hasMsg=false;
    //private Object key=new Object();
    private boolean isPoll=true;
    
    @Override
    public void run() {
        while(running){
            if(!hasMsg){
                try {
                    synchronized (this) {
                        //没有消息就等着
                        this.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            String sendMessage=msg;
            hasMsg=false;
            msg=null;
            try {
                /*如果没有connect,同样让其挂起等待*/
                if(cons.size()<=0){
                    synchronized(cons){
                        cons.wait();
                    }
                }
                //创建一个新的对象来处理请求
                List<HttpServletResponse> tcons=
                        new ArrayList<HttpServletResponse>();
                for(String key:cons.keySet()){
                    tcons.add(cons.get(key));
                }
                for(HttpServletResponse connect:tcons){
                    PrintWriter out=connect.getWriter();
                    out.print(sendMessage);
                    out.flush();
                    /*如果是长轮询,需要关闭资源*/
                    if(isPoll){
                        out.close();
                        connect=null;
                    }
                }
                if(isPoll){
                    cons.clear();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /*设置是否是长轮询的方式,默认true*/
    public void setPoll(boolean isPoll){
        this.isPoll=isPoll;
    }
    
    public void setConnect(String sessionId,HttpServletResponse connect){
        synchronized(cons){
            //this.connect=connect;
            cons.put(sessionId, connect);
            cons.notify();
        }
    }
    /*synchronized方法默认就是通过this做钥匙*/
    public synchronized void sendMsg(String msg){
        this.msg=msg;
        hasMsg=true;
        this.notify();
    }
    
    public void close(){
        running=false;
    }

}

///////////////////////////////////////////////////
public class ChatServlet extends HttpServlet implements CometProcessor {
    private static final long serialVersionUID = 1L;
    private MessageSender sender;
    private TalkHandler th=null;
    public static Map<String,String> users=new HashMap<String,String>();
    
    
    @Override
    public void init() throws ServletException {
        //启动线程
        sender=new MessageSender();
        Thread ts=new Thread(sender);
        ts.setDaemon(true);
        ts.start();
        th=new TalkHandler();
        Thread ths=new Thread(th);
        ths.setDaemon(true);
        ths.start();
        super.init();
    }

    public void event(CometEvent event) throws IOException {
        /*event方法用来处理各种请求,可以根据状态的不同得到各种响应
         * 同时可以不断根据自己的需求向客户端发送信息*/
        HttpServletResponse response=event.getHttpServletResponse();
        HttpServletRequest request=event.getHttpServletRequest();
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/json;charset=utf-8");
        String loginUser=(String) request.getSession().getAttribute("loginUser");
        if(loginUser==null||"".equals(loginUser.trim())){
            response.sendRedirect("ajax05_comet/login.jsp");
            return;
        }
        String sessionId=request.getSession().getId();
        boolean newUser=checkUser(sessionId);
        ChatMessage cm=null;
        if(newUser){
            users.put(sessionId, loginUser);
            cm=new ChatMessage(getUsers(),loginUser+"加入聊天");
        }
        /*对于event而言,会存在多种状态,在begin的时候可以开始获取数据*/
        if(event.getEventType()==CometEvent.EventType.BEGIN){
            //在begin的状态下进行数据写操作
            log(sessionId+"成功建立连接");
            sender.setConnect(sessionId,response);
            if(newUser){
                //sender.sendMsg(JacksonUtil.getInstance().obj2json(cm));
                th.prepareMsg(JacksonUtil.getInstance().obj2json(cm));
            }else{
                String talk=request.getParameter("talk");
                if(talk!=null&&!"".equals(talk.trim())){
                    cm=new ChatMessage(users.get(sessionId)+":"+talk);
                    //sender.sendMsg(JacksonUtil.getInstance().obj2json(cm));
                    th.prepareMsg(JacksonUtil.getInstance().obj2json(cm));
                }
            }
        }else if(event.getEventType()==CometEvent.EventType.END){
            //请求结束的时候执行
            log(sessionId+"已经结束");
            event.close();
        }else if(event.getEventType()==CometEvent.EventType.ERROR){
            //发生错误的时候处理
            log(sessionId+"发送错误");
            //event.close();
        }else if(event.getEventType()==CometEvent.EventType.READ){
            //正在读取数据的状态
            throw new RuntimeException("该状态无法操作异常");
        }
        
    }
    private List<String> getUsers(){
        List<String> us=new ArrayList<String>();
        for(String k:users.keySet()){
            us.add(users.get(k));
        }
        return us;
    }
    
    /**判断是否是新登录用户*/
    public boolean checkUser(String sessionId){
        if(!users.containsKey(sessionId)) return true;
        
        return false;
    }

    @Override
    public void destroy() {
        sender.close();
        th.close();
        super.destroy();
    }
    private class TalkHandler implements Runnable{
        private String msg;
        private boolean ready;
        private boolean running=true;
        
        public void prepareMsg(String msg){
            synchronized (users) {
                this.msg = msg;
                ready = true;
                users.notify();
            }
        }
        public void close(){
            running=false;
        }
        @Override
        public void run() {
            while(running){
                if(!ready){
                    try {
                        synchronized (users) {
                            users.wait();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                String pm=msg;
                ready=false;
                sender.sendMsg(pm);
            }
        }
    }
}
/////////////////////////////////////////
public class CometServlet extends HttpServlet implements CometProcessor {
    private static final long serialVersionUID = 1L;
    private MessageSender sender;
    private static Random ran=new Random();
    public CometServlet() {
        super();
    }
    @Override
    public void init() throws ServletException {
        //启动线程
        sender=new MessageSender();
        Thread ts=new Thread(sender);
        ts.setDaemon(true);
        ts.start();
        new Thread(new RandomTestThread()).start();
        super.init();
    }

    public void event(CometEvent event) throws IOException {
        /*event方法用来处理各种请求,可以根据状态的不同得到各种响应
         * 同时可以不断根据自己的需求向客户端发送信息*/
        HttpServletResponse response=event.getHttpServletResponse();
        HttpServletRequest request=event.getHttpServletRequest();
        String sessionId=request.getSession().getId();
        /*对于event而言,会存在多种状态,在begin的时候可以开始获取数据*/
        if(event.getEventType()==CometEvent.EventType.BEGIN){
            //在begin的状态下进行数据写操作
            log(sessionId+"成功建立连接");
            sender.setConnect(sessionId,response);
        }else if(event.getEventType()==CometEvent.EventType.END){
            //请求结束的时候执行
            log(sessionId+"已经结束");
            event.close();
        }else if(event.getEventType()==CometEvent.EventType.ERROR){
            //发生错误的时候处理
            log(sessionId+"发送错误");
            event.close();
        }else if(event.getEventType()==CometEvent.EventType.READ){
            //正在读取数据的状态
            throw new RuntimeException("该状态无法操作异常");
        }
        
    }

    @Override
    public void destroy() {
        sender.close();
        super.destroy();
    }
    
    private class RandomTestThread implements Runnable{
        @Override
        public void run() {
            while(true){
                try {
                    Thread.sleep(5000);
                    int num=ran.nextInt(1000);
                    System.out.println("ready:"+num);
                    sender.sendMsg(String.valueOf(num));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
/////////////////////////////////////////////
public class RandomThread implements Runnable {

    private static final Random ran=new Random();
    private boolean running=true;
    private HttpServletResponse connect;
    
    public RandomThread(HttpServletResponse connect){
        this.connect=connect;
    }
    
    @Override
    public void run() {
        while(running){
            try {
                Thread.sleep(5000);
                PrintWriter out=connect.getWriter();
                int num=ran.nextInt(100);
                /*基于流的方式由于整个过程仅仅用一个连接,所以全部使用同一个response
                 * 来传递数据,所以不能关闭流*/
                out.print(num+"");
                System.out.println("send:"+num);
                //必须刷新
                out.flush();
                /*基于长轮询的方式,每一次发送完信息,都会建立一个新的请求,
                 * 当建立了新请求之后,原有response就没有意义了,必须关闭*/
                out.close();
                connect=null;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
///////////////////////////////////////
public class SecondServlet extends HttpServlet implements CometProcessor {
    private static final long serialVersionUID = 1L;
       
    public SecondServlet() {
        super();
    }
    @Override
    public void init() throws ServletException {
        super.init();
    }

    public void event(CometEvent event) throws IOException {
        /*event方法用来处理各种请求,可以根据状态的不同得到各种响应
         * 同时可以不断根据自己的需求向客户端发送信息*/
        HttpServletResponse response=event.getHttpServletResponse();
        HttpServletRequest request=event.getHttpServletRequest();
        /*对于event而言,会存在多种状态,在begin的时候可以开始获取数据*/
        if(event.getEventType()==CometEvent.EventType.BEGIN){
            //在begin的状态下进行数据写操作
            log(request.getSession().getId()+"成功建立连接");
            new Thread(new RandomThread(response)).start();
        }else if(event.getEventType()==CometEvent.EventType.END){
            //请求结束的时候执行
            log(request.getSession().getId()+"已经结束");
            event.close();
        }else if(event.getEventType()==CometEvent.EventType.ERROR){
            //发生错误的时候处理
            log(request.getSession().getId()+"发送错误");
            event.close();
        }else if(event.getEventType()==CometEvent.EventType.READ){
            //正在读取数据的状态
            throw new RuntimeException("该状态无法操作异常");
        }
        
    }

}


你可能感兴趣的:(commet-java服务端)