最近有个项目需要实现视频流的信息交换处理,但是之前一直都没有写过有关的代码,所以就想到了websocket接口。
java创建一个socket非常简单,繁琐的可能是日常的业务信息处理,下面看下一段代码:
import model.User; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; /** * Created by alan.luo on 2017/9/10. */ @ServerEndpoint(value = "/websocket2") public class TestWebSocket { @OnOpen public void onOpen(Session session, EndpointConfig endpointConfig) { sendMsg(session,"Welcome back."); //push list. User user = new User(); user.setId(Integer.parseInt(session.getId())); Map<String,List<String>> map = session.getRequestParameterMap(); user.setUserName(map.get("userName").get(0)); user.setSession(session); //has client come in,so server must be save the session to the application.class. Application.getInstance().putSession(user); } @OnMessage public void onMessage(Session session,String message){ System.out.println("++++++++++:"+message); //if has user push message to the server.then server will each all the client and send message too. for (User user:Application.getInstance().getUsers()){ sendMsg(user.getSession(),user.getUserName() + " say:"+message); } } @OnClose public void onClose(Session session, CloseReason closeReason){ List<User> list = Application.getInstance().getUsers(); //pop list. for (int i = 0;i<list.size();i++){ if (Integer.parseInt(session.getId()) == list.get(i).getId()){ list.remove(i); Application.getInstance().setUsers(list); break; } } } @OnError public void onError(Session session, Throwable thr) { System.out.println("+++++++++onError"+thr.getMessage()); } /** * send message to session. * @param session * @param message */ protected void sendMsg(Session session,String message){ System.out.println(message); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { session.getBasicRemote().sendText(message+" >"+sdf.format(new Date())); } catch (IOException e) { e.printStackTrace(); } } }
当有客户端进入,则把客户端保存到application这个实例中,application是自定义的一个类,实现了单例,所以保存进去是最合适的,当有消息进入时,server将从application读取session list 并且遍历全部session and send the message。
Application实例的代码:
import model.User; import java.util.ArrayList; import java.util.List; /** * Created by alan.luo on 2017/9/10. */ public class Application { private List<User> users; private static Application app; public Application(){ users = new ArrayList<>(); } public static Application getInstance(){ if (app == null){ app = new Application(); } return app; } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } public void putSession(User s){ this.users.add(s); } }
User实体类的代码:
package model; import javax.websocket.Session; /** * Created by alan.luo on 2017/9/6. */ public class User { private int id; private String userName; private String userPassword; private Session session; public Session getSession() { return session; } public void setSession(Session session) { this.session = session; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPassword() { return userPassword; } public void setUserPassword(String userPasswd) { this.userPassword = userPasswd; } @Override public String toString() { return "User{" + "id=" + id + ", userName='" + userName + '\'' + ", userPassword='" + userPassword + '\'' + '}'; } }
可能会有错误,那是因为需要配置一下web.xml
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/websocket2</url-pattern> </servlet-mapping>
剩下的就是javascript客户端的代码了:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <p><input type="text" id="userName" value="" placeholder="输入名字进入聊天室"></p> </div> <div> <textarea rows="16" cols="40" id="content"></textarea> </div> <div> <input type="text" id="message" value="" placeholder="输入内容"/> <button type="button" id="send">send</button> </div> <div> <button type="button" id="connect">connect</button> <button type="button" id="destroy">destroy</button> </div> <script> var connect = document.getElementById("connect"); var content = document.getElementById("content"); var message = document.getElementById("message"); var destroy = document.getElementById("destroy"); var send = document.getElementById("send"); var userName = document.getElementById("userName"); var socket = null; connect.addEventListener("click",function () { console.log("connect") if(userName.value.length <= 2){ return false; } socket = new WebSocket("ws://localhost:8080/websocket2?userName="+userName.value); socket.onopen = function (p1) { console.log("onopen",p1) } socket.onclose = function (p1) { console.log("onclose",p1) } socket.onerror = function (p1) { console.log("onerror",p1) } socket.onmessage = function (p1) { console.log("onmessage",p1) content.innerHTML = (content.innerHTML + p1.data + "\n") } }); destroy.addEventListener("click",function () { console.log("destroy") socket.close(); }); send.addEventListener("click",function () { console.log("send") socket.send(message.value); message.value = ""; }); </script> </body> </html>
最后上传一张效果图吧: