最近由于项目需要实时显示数据库更新的数据变化情况,一开始想过在前端使用ajax异步轮询方法实现,但后面考虑到性能和流量等要求,就放弃该方法而选择使用websocket(毕竟现在springboot整合websocket的技术算是比较成熟了,哈哈),现在此小小记录下。
首先,在springboot项目创建并配置成功的基础上对websocket进行整合。
1、在pom文件中添加对websocket的依赖
1 23 org.springframework.boot 4spring-boot-starter-websocket 5
2、个人习惯是先从后端写到前端,先写websocket的配置类吧
1 import org.springframework.stereotype.Component; 2 3 import javax.websocket.*; 4 import javax.websocket.server.ServerEndpoint; 5 import java.io.IOException; 6 import java.util.concurrent.CopyOnWriteArraySet; 7 8 /** 9 * @Name:WebSocket 10 * @Description:WebSocket配置 11 * @Version:V1.0.0 12 * @Author:mYunYu 13 * @Create Date:2018/11/15 14:45 14 */ 15 @Component 16 @ServerEndpoint(value = "/ws/webSocket" , encoders = {EncoderClassVo.class}) 17 public class WebSocket { 18 //每个客户端都会有相应的session,服务端可以发送相关消息 19 private Session session; 20 21 //J.U.C包下线程安全的类,主要用来存放每个客户端对应的webSocket连接 22 private static CopyOnWriteArraySetcopyOnWriteArraySet = new CopyOnWriteArraySet (); 23 24 /** 25 * @Name:onOpen 26 * @Description:打开连接。进入页面后会自动发请求到此进行连接 27 * @Author:mYunYu 28 * @Create Date:14:46 2018/11/15 29 * @Parameters: 30 * @Return: 31 */ 32 @OnOpen 33 public void onOpen(Session session) { 34 this.session = session; 35 copyOnWriteArraySet.add(this); 36 System.out.println("websocket有新的连接, 总数:"+ copyOnWriteArraySet.size()); 37 38 } 39 40 /** 41 * @Name:onClose 42 * @Description:用户关闭页面,即关闭连接 43 * @Author:mYunYu 44 * @Create Date:14:46 2018/11/15 45 * @Parameters: 46 * @Return: 47 */ 48 @OnClose 49 public void onClose() { 50 copyOnWriteArraySet.remove(this); 51 System.out.println("websocket连接断开, 总数:"+ copyOnWriteArraySet.size()); 52 } 53 54 /** 55 * @Name:onMessage 56 * @Description:测试客户端发送消息,测试是否联通 57 * @Author:mYunYu 58 * @Create Date:14:46 2018/11/15 59 * @Parameters: 60 * @Return: 61 */ 62 @OnMessage 63 public void onMessage(String message) { 64 System.out.println("websocket收到客户端发来的消息:"+message); 65 } 66 67 /** 68 * @Name:onError 69 * @Description:出现错误 70 * @Author:mYunYu 71 * @Create Date:14:46 2018/11/15 72 * @Parameters: 73 * @Return: 74 */ 75 @OnError 76 public void onError(Session session, Throwable error) { 77 System.out.println("发生错误:" + error.getMessage() + "; sessionId:" + session.getId()); 78 error.printStackTrace(); 79 } 80 81 public void sendMessage(Object object){ 82 //遍历客户端 83 for (WebSocket webSocket : copyOnWriteArraySet) { 84 System.out.println("websocket广播消息:" + object.toString()); 85 try { 86 //服务器主动推送 87 webSocket.session.getBasicRemote().sendObject(object) ; 88 } catch (Exception e) { 89 e.printStackTrace(); 90 } 91 } 92 } 93 94 /** 95 * @Name:sendMessage 96 * @Description:用于发送给客户端消息(群发) 97 * @Author:mYunYu 98 * @Create Date:14:46 2018/11/15 99 * @Parameters:100 * @Return:101 */102 public void sendMessage(String message) {103 //遍历客户端104 for (WebSocket webSocket : copyOnWriteArraySet) {105 System.out.println("websocket广播消息:" + message);106 try {107 //服务器主动推送108 webSocket.session.getBasicRemote().sendText(message);109 } catch (Exception e) {110 e.printStackTrace();111 }112 }113 }114 115 /**116 * @Name:sendMessage117 * @Description:用于发送给指定客户端消息118 * @Author:mYunYu119 * @Create Date:14:47 2018/11/15120 * @Parameters:121 * @Return:122 */123 public void sendMessage(String sessionId, String message) throws IOException {124 Session session = null;125 WebSocket tempWebSocket = null;126 for (WebSocket webSocket : copyOnWriteArraySet) {127 if (webSocket.session.getId().equals(sessionId)) {128 tempWebSocket = webSocket;129 session = webSocket.session;130 break;131 }132 }133 if (session != null) {134 tempWebSocket.session.getBasicRemote().sendText(message);135 } else {136 System.out.println("没有找到你指定ID的会话:{}"+ "; sessionId:" + sessionId);137 }138 }139 140 /**141 * 如果使用springboot内置tomcat,需要配置,否则不需要142 *143 * @return144 */145 // @Bean146 // public ServerEndpointExporter serverEndpointExporter() {147 // return new ServerEndpointExporter();148 // }149 150 151 }
上面类中的红色注释的代码是只有当springboot项目使用内置tomcat时需要配置(即打成jar包),如果使用外置tomcat则不需要配置(即打成war包)
3、配置编码器,主要是需要后端向前端发送对象数据,如果只是发送普通的字符串数据的话,就不需要
1 import com.alibaba.fastjson.JSON; 2 import com.xxx.utils.MsgUtil; 3 4 import javax.websocket.EncodeException; 5 import javax.websocket.Encoder; 6 import javax.websocket.EndpointConfig; 7 8 /** 9 * @Name:EncoderClassVo10 * @Description:编码器,防止发送对象出错11 * @Version:V1.0.012 * @Author:mYunYu13 * @Create Date:2018/11/15 14:4314 */15 public class EncoderClassVo implements Encoder.Text{16 17 @Override18 public void init(EndpointConfig endpointConfig) {19 20 }21 22 @Override23 public void destroy() {24 25 }26 27 @Override28 public String encode(MsgUtil msgUtil) throws EncodeException {29 try{30 return JSON.toJSONString(msgUtil) ;31 }catch (Exception e){32 e.printStackTrace() ;33 return null;34 }35 }36 }
4、接下来就是写controller层了,我这边demo只是简单的发送一些随机的数据,具体信息还需要根据各个项目需要来写
1 import com.xxx.pojo.User; 2 import com.xxx.utils.MsgUtil; 3 import com.xxx.webSocket.WebSocket; 4 import org.springframework.web.bind.annotation.RequestMapping; 5 import org.springframework.web.bind.annotation.RestController; 6 7 import javax.annotation.Resource; 8 import java.io.IOException; 9 10 /**11 * @Name:SocketController12 * @Description:消息发送Controller13 * @Version:V1.0.014 * @Author:mYunYu15 * @Create Date:2018/11/15 16:4416 */17 @RestController18 public class SocketController {19 20 @Resource21 WebSocket webSocket;22 23 /**24 * @Name:helloManyWebSocket25 * @Description:群发消息26 * @Author:mYunYu27 * @Create Date:16:44 2018/11/1528 * @Parameters:29 * @Return:30 */31 @RequestMapping("many")32 public String helloManyWebSocket(){33 34 int i = 1 ;35 while(i > 0){36 i=1+(int)(Math.random()*600) ;37 User user = new User() ;38 user.setUserid(i+1) ;39 user.setUsername(String.valueOf(i) + String.valueOf(i+i)) ;40 41 //将对象转为json对象,并发送到前端42 MsgUtil msgUtil = MsgUtil.success().addMsg("map", user);43 webSocket.sendMessage(msgUtil);44 45 try{46 Thread.sleep(1000) ;47 }catch (Exception e){48 e.printStackTrace() ;49 }50 }51 52 return "发送成功";53 }54 55 /**56 * @Name:helloOneWebSocket57 * @Description:根据session单个发送消息58 * @Author:mYunYu59 * @Create Date:16:44 2018/11/1560 * @Parameters:61 * @Return:62 */63 @RequestMapping("one")64 public String helloOneWebSocket(String sessionId) throws IOException {65 //向某个人发送消息66 webSocket.sendMessage(sessionId,"你好~!,单个用户");67 68 return "发送成功";69 }70 71 72 }
5、接下来该在前端写配置了,我这里使用的是thymeleaf模板
1 2 3 4 5Title 6 7 8 9 自动连接websocket10 50 51 52 53
6、最后就是测试了,先右击项目,选择Run Mavan-->clear install进行项目打包
打包成功之后再启动外置tomcat来启动项目
启动项目成功,在浏览器中访问
按f12,如果出现”Socket已打开“字样,则表示客户端连接ok,现在需要使用服务端向客户端发送消息
再打开另一个浏览器,输入http://localhost:端口号/项目名/many进行访问,就可以观察到idea和浏览器中已经打印了发送的消息字样了
上图是客户端访问的浏览器所显示的消息,下图是服务器端所打印的消息
好了,实现的很成功,接下来就是对发送的数据进行替换就差不多了,哈哈~