介绍
WebSocket为浏览器和服务器提供了全双工异步通信的功能,即浏览器可以向服务段发送消息,服务端也可以向浏览器发送消息,WebSocket需要浏览器的支持,如IE10+、Chrome13+ 。。。等,同时Spring Boot为WebSocket提供了starter pom 。
广播式
广播式即服务端有消息时,会将消息发送给所有连接了当前endpoint的浏览器。
- 添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
- domain
//浏览器消息 @Data public class WiselyMessage { private String name; } //服务器端消息 @Data public class WiselyResponse { private String responseManage; public WiselyResponse(String s) { this.responseManage = s; } }
- WebSocket设置
@Configuration @EnableWebSocketMessageBroker//开启使用STOMP协议传输,基于代理message broker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { //配置一个/topic消息代理 config.enableSimpleBroker("/topic"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //注册STOMP协议的节点,并映射指定的URL registry.addEndpoint("/endpointWisely").withSockJS(); } }
- Controller
@Controller public class WsController { @MessageMapping("/welcome")//和RequestMapping作用相似 @SendTo("/topic/getResponse")//浏览器监听的地址 public WiselyResponse say(WiselyMessage message) throws InterruptedException { Thread.sleep(3000); return new WiselyResponse("Welcome, " + message.getName() + "!"); } }
- Config
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/ws").setViewName("/ws"); } }
- html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>Spring Boot + WebSocket +广播</title> </head> <body> <noscript><h2 style="color: #ff0000;">貌似你的浏览器不支持websocket</h2></noscript> <div> <div> <button id="connect" onclick="connect();">链接</button> <button id="disconnect" disabled="disabled" onclick="disconnect()">断开</button> </div> <div id="conversationDiv"> <label>输入你的名字</label><input type="text" id="name"/> <button id="sendName" onclick="sendName()">发送</button> <p id="response"></p> </div> </div> <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script> <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script> <script type="text/javascript"> var stompClient = null; function setConnected(connected) { document.getElementById("connect").disabled = connected; document.getElementById("disconnect").disabled = !connected; document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden'; $('#response').html(); } function connect() { var socket = new SockJS('/endpointWisely'); stompClient = Stomp.over(socket); stompClient.connect({}, function (fream) { setConnected(true); console.log("Conected" + fream); stompClient.subscribe("/topic/getResponse", function (response) { showResponse(JSON.parse(response.body).responseManage); }); }); } function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); } function sendName() { var name = $('#name').val(); stompClient.send("/welcome", {}, JSON.stringify({'name': name})) } function showResponse(message) { var response = $("#response"); response.html(message); } </script> </body> </html>
自此,发一个消息所有的链接都可以接受的到,广播式完成
点对点
- 添加依赖(身份校验)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
- 添加WebMvcConfig
registry.addViewController("/login").setViewName("/login"); registry.addViewController("/chat").setViewName("/chat");
- 添加WebSecurityConfig
@EnableWebSecurity @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/login").permitAll() .and() .formLogin().loginPage("/login") .defaultSuccessUrl("/chat") .permitAll() .and() .logout() .permitAll(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("hjx").password("hjx").roles("USER") .and() .withUser("zyt").password("zyt").roles("USER"); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/resources/static/**"); } }
- 添加俩个节点
@Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic", "/queue"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/endpointWisely").withSockJS(); registry.addEndpoint("/endpointChat").withSockJS(); }
- 添加访问路径
@Autowired private SimpMessagingTemplate messagingTemplate; @MessageMapping("/chat") public void handleChat(Principal principal, String msg) { if (principal.getName().equals("hjx")) { messagingTemplate .convertAndSendToUser("zyt", "/queue/notifications", principal.getName() + "-send:" + msg); } else { messagingTemplate .convertAndSendToUser("hjx", "/queue/notifications", principal.getName() + "-send:" + msg); } }
- 界面
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>Spring Boot + WebSocket +广播</title> <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script> <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script> </head> <body> <noscript><h2 style="color: #ff0000;">貌似你的浏览器不支持websocket</h2></noscript> <p>聊天室</p> <form id="wiselyForm"> <textarea rows="4" cols="60" name="text"></textarea> <input type="submit"/> </form> <script type="text/javascript"> $("#wiselyForm").submit(function (e) { e.preventDefault(); var text = $("#wiselyForm").find('textarea[name="text"]').val(); sendSpittler(text); }); var sock = new SockJS("/endpointChat"); var stomp = Stomp.over(sock); stomp.connect({}, function (frame) { stomp.subscribe("/user/queue/notifications", handleNotification) }) function handleNotification(message) { $('#output').append("<b>Received: " + message.body + "</b><br/>") } function sendSpittler(text) { stomp.send("/chat", {}, text) } $("#stop").click(function () { sock.close(); }) </script> <div id="output"> </div> </body> </html>
到这里,简单的WebSocket就演示完成了,如果有不懂的地方可以看源码
Demo源码
参考资料
- 《Java EE开发的颠覆者 Spring Boot实战》汪云飞编著
有想要电子书的小伙伴可以联系我