1. 程式人生 > 實用技巧 >原生websocket簡單實現即時通訊功能-註解方式

原生websocket簡單實現即時通訊功能-註解方式

原生的webscoket使用,最低要求tomcat7,並且查詢tomcat的lib下是否存在webscoket*.jar,務必保證(apache-tomcat-7.0.78\lib)存在這兩個jar包,否則不支援webscoket功能(也可能有其他實現思路,請賜教...):說明:我使用的tomcat7+jdk1.8;

122538_ydwZ_3027745.png

本說明,使用註解的方式實現的簡易及時聊天,其他功能,自行開發...

mavn依賴pom.xml:其中使用到了阿里的fastjson

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.38</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket -->
<dependency>
   <groupId>org.java-websocket</groupId>
   <artifactId>Java-WebSocket</artifactId>
   <version>1.3.0</version>
</dependency>

因為我自己的專案跑不起來,所以單獨配置了一下:

<build>
<plugins>
   <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
         <source>1.8</source>  <!--換個版本-->
         <target>1.8</target>  <!--換個版本-->
      </configuration>
   </plugin>
</plugins>
</build>

1、實現 ServerApplicationConfig

public class WebSocketConfig implements ServerApplicationConfig{
    /**
     * 配置實現
     * @Author wugong
     * @Date 2017/12/30 20:46
     * @Modify if true,please enter your name or update time
     * @param
     */
    @Override
    public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> set) {
        return null;
    }
    /**
     * 註解實現
     * @Author wugong
     * @Date 2017/12/30 20:45
     * @Modify if true,please enter your name or update time
     * @param
     */
    @Override
    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> set) {
        // 這裡是注入當前專案中的所有的websocket服務,可以進行過過濾操作
        return set;
    }
}

2、註解實現websocket類

@ServerEndpoint("/demoAnnotation")
public class DemoChat {
    private Session session;// 此session非servlet中的session,是獲取不到當前登入人的資訊的
    private String userName;
    private Long userId;
    private static Set<DemoChat> demoChatSet = new HashSet<DemoChat>();
    private static List<Session> onLineSession = new ArrayList<Session>();
//    private static List<User> onLineUserList = new ArrayList<>();
    private static List<String> onLineUserNameList = new ArrayList<String>();// 線上使用者名稱
    private static Map<Long,Session> onLineSessionMap = new HashMap<>();// 使用者(session)與管道的關係

    @OnOpen
    public void openTunnel(Session session){
        // 我上線啦,通知所有線上的使用者:只要是導致管道重新開啟就會走這個方法
        System.out.println("專用通道開啟,有人來了...");
        ChatMessage chatMessage = new ChatMessage();
        String  queryString = session.getQueryString();
        System.out.println(queryString);
        this.userId = Long.valueOf(new Random().nextInt(100));;
        this.userName = "遊客" + this.userId;
        this.session = session;
        demoChatSet.add(this);
        onLineSessionMap.put(this.userId,this.session);
        chatMessage.setFromUserName(this.userName);
        chatMessage.setFromUserId(this.userId);
        chatMessage.setToUserId(-1L);
        onLineUserNameList.add(this.userName);
        String msgText = "歡迎:"+this.userName+"進入房間,請開始你的表演...";
        chatMessage.setMsgText(msgText);
        // 通知所有人線上的人
        this.broadcast(this.demoChatSet,JSON.toJSONString(chatMessage));
    }

    @OnClose
    public void closeTunnel(Session session){
        // 我下線啦,通知所有線上使用者
        System.out.printf("管道關閉,有人退場.....");
        demoChatSet.remove(this);
        onLineSessionMap.remove(this.userId);
        onLineUserNameList.remove(this.userName);
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setFromUserName(this.userName);
        chatMessage.setFromUserId(this.userId);
        chatMessage.setToUserId(-1L);
        String msgText = "歡送:"+this.userName+"離開房間,大家繼續嗨...";
        chatMessage.setMsgText(msgText);
        onLineUserNameList.add(this.userName);
        // msgText 通知所有人線上的人
        this.broadcast(this.demoChatSet,JSON.toJSONString(chatMessage));
    }

    @OnMessage
    public void receiveMessage(Session session,String msg){
        try {
            ChatMessage chatMessage = JSON.parseObject(msg,ChatMessage.class);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String nowDateStr = simpleDateFormat.format(new Date());
            chatMessage.setMsgText(nowDateStr+":"+chatMessage.getMsgText()+" from "+this.userName);
            chatMessage.setFromUserName(this.userName);
            chatMessage.setToUserId(null==chatMessage.getToUserId()?-1:chatMessage.getToUserId());
            // 廣播
            if(-1 == chatMessage.getToUserId()){
                // 廣播給所有的人
                this.broadcast(this.demoChatSet,chatMessage);
                // 傳送給指定的人
            }else{
                // 獲取當前的指定使用者
                if(onLineSessionMap.containsKey(chatMessage.getToUserId())){
                    Session thisSession = onLineSessionMap.get(chatMessage.getToUserId());
                    thisSession.getBasicRemote().sendText(JSON.toJSONString(chatMessage));
                }else{
                    chatMessage.setMsgText(nowDateStr+"使用者已經下線");
                    this.session.getBasicRemote().sendText(JSON.toJSONString(chatMessage));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 進行廣播訊息
     * @Author wugong
     * @Date 2017/12/30 21:51
     * @Modify if true,please enter your name or update time
     * @param
     */
    public void broadcast(Set<DemoChat> demoChatSet , ChatMessage chatMessage){

        for (Iterator iterator = demoChatSet.iterator(); iterator.hasNext();) {
            DemoChat demoChat = (DemoChat) iterator.next();
            try {
                demoChat.session.getBasicRemote().sendText(JSON.toJSONString(chatMessage));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 進行廣播訊息
     * @Author wugong
     * @Date 2017/12/30 21:51
     * @Modify if true,please enter your name or update time
     * @param
     */
    public void broadcast(Set<DemoChat> demoChatSet , String msg){

        for (Iterator iterator = demoChatSet.iterator(); iterator.hasNext();) {
            DemoChat demoChat = (DemoChat) iterator.next();
            try {
                demoChat.session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

輔助類:

public class User {

    private Long userId;
    private String userName;
    private Session session;
public class ChatMessage {

    private String msgText;
    private Integer msgType;
    private Long toUserId;
    private Long fromUserId;
    private String toUserName;
    private String fromUserName;
    private Long groupId;// 組ID
    private Integer chatType;// 聊天型別 1:單聊 2:多聊

3、jsp頁面 webchat.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>websocket簡易聊天</title>
    <style type="text/css">
    input#chat {
        width: 410px
    }

    #console-container {
        width: 400px;
    }

    #console {
        border: 1px solid #CCCCCC;
        border-right-color: #999999;
        border-bottom-color: #999999;
        height: 170px;
        overflow-y: scroll;
        padding: 5px;
        width: 100%;
    }
    .user_list{
        border: 1px solid #CCCCCC;
        border-right-color: #999999;
        border-bottom-color: #999999;
        height: 170px;
        overflow-y: scroll;
        padding: 5px;
        width: 280px;
    }

    #console p {
        padding: 0;
        margin: 0;
    }</style>
</head>
<body>
<div class="noscript"><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable
    Javascript and reload this page!</h2></div>
<div style="width: 100%;">
    <p>
        <label>傳送給userId:</label><input id="toUserId" placeholder="請輸入遊客id">
        <input type="text" placeholder="type and press enter to chat" id="chat" />
    </p>
    <div id="console-container" style="float: left">
        <label>聊天區</label>
        <div id="console"></div>
    </div>
    <div style="float: left;margin-left: 12px;width: 300px;">
        <label>線上使用者</label>
        <div class="user_list">
            這裡顯示線上使用者
        </div>
    </div>
</div>
</body>
<script type="text/javascript" src="${ctx}/js/jquery/jquery.min.js"></script>
<script type="application/javascript">
var Chat = {};

Chat.socket = null;

Chat.connect = (function(host) {
    if ('WebSocket' in window) {
        Chat.socket = new WebSocket(host);
    } else if ('MozWebSocket' in window) {
        Chat.socket = new MozWebSocket(host);
    } else {
        Console.log('Error: WebSocket is not supported by this browser.');
        return;
    }
    // 管道開啟shi
    Chat.socket.onopen = function () {
        Console.log('Info: WebSocket connection opened.');
        document.getElementById('chat').onkeydown = function(event) {
            if (event.keyCode == 13) {
                Chat.sendMessage();
            }
        };
    };
    // 管道關閉時
    Chat.socket.onclose = function () {
        document.getElementById('chat').onkeydown = null;
        Console.log('Info: WebSocket closed.');
    };
    // 接收到訊息時,進行處理顯示
    Chat.socket.onmessage = function (message) {
        eval("var result="+event.data);
        Console.log(result.msgText);
    };
});

Chat.initialize = function() {
    if (window.location.protocol == 'http:') {
        Chat.connect('ws://' + window.location.host + '/demoAnnotation?userId=1');
    } else {
        Chat.connect('wss://' + window.location.host + '/demoAnnotation?userId=1');
    }
};

Chat.sendMessage = (function() {
    var message = document.getElementById('chat').value;
    if (message != '') {
        var toUserId = document.getElementById('toUserId').value;
        if(''==toUserId||null==toUserId||typeof(toUserId)==undefined){
            toUserId = -1;
        }
        var msgJson = {
            chatType: 1,
            toUserId: toUserId,
            msgText: message
        };
        message = JSON.stringify(msgJson);
        Chat.socket.send(message);
        document.getElementById('chat').value = '';
    }
});

var Console = {};

Console.log = (function(message) {
    var console = document.getElementById('console');
    var p = document.createElement('p');
    p.style.wordWrap = 'break-word';
    p.innerHTML = message;
    console.appendChild(p);
    while (console.childNodes.length > 25) {
        console.removeChild(console.firstChild);
    }
    console.scrollTop = console.scrollHeight;
});

Chat.initialize();


document.addEventListener("DOMContentLoaded", function() {
    // Remove elements with "noscript" class - <noscript> is not allowed in XHTML
    var noscripts = document.getElementsByClassName("noscript");
    for (var i = 0; i < noscripts.length; i++) {
        noscripts[i].parentNode.removeChild(noscripts[i]);
    }
}, false);

</script>
</html>

5、結果演示:(很多功能沒與完善,自行完善即可)

123835_vrRr_3027745.png

轉載於:https://my.oschina.net/wugong/blog/1601107