描述:基于websocket+sock.js(在线程中或前台自己)发送消息给前台
项目结构
1.导入pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.导入三个js文件到静态文件下
链接:https://pan.baidu.com/s/17W2K2fAB8p7QEgOyZZfS8Q
提取码:0axi
3.application.yml配置
spring:
thymeleaf:
cache: false
encoding: UTF-8
mode: LEGACYHTML5
prefix: classpath:/templates/
suffix: .html
4.websocket配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{
//添加服务端点,接受客户端连接
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//webSocket添加跨域和SocketJs支持
registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//客户端接受服务端消息的地址的前缀信息(前台被动接受消息 也就是前台的前缀要和他对应上)
registry.enableSimpleBroker("/topic");
//客户端发给服务端消息的地址前缀信息(前台发送消息 也就是前台的前缀要和他对应上)
registry.setApplicationDestinationPrefixes("/app");
}
}
4.优雅配置发送请求
//RestTemplate发送请求的配置
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);
factory.setConnectTimeout(5000);
return factory;
}
}
5.这个类是我另测的在线程中发送消息给前台
//这个类是模拟一下在线程中持续给前台更新即时数据
@Component
public class ContineSendMesage implements CommandLineRunner{
//使用RestTemplate转发给前台
@Autowired
private RestTemplate restTemplate;
//该方法为项目加载后自定加载 模拟在线程中持续给前台发数据
@Override
public void run(String... strings) throws Exception {
Runnable runnable=new Runnable() {
@Override
public void run() {
while (true){
Map<String,String> map=new HashMap<>();
Date date=new Date();
map.put("message","WebSocket发送当前时间为"+date.toString());
//发送到controller中test方法中
restTemplate.getForObject("http://localhost:8080/test?message={message}",Object.class,map);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread=new Thread(runnable);
thread.start();
}
}
6.WebSocketController
@Controller
public class WebSocketController {
@Autowired
public SimpMessagingTemplate simpMessagingTemplate;//websocket发送请求到前台
//访问html页面
@GetMapping("/socket")
public String socketHtml() {
return "socket";
}
/**
* 发送方法1
*
* @Description:这个方法是接收客户端发送功公告的WebSocket请求,使用的是@MessageMapping
* @SendTo 是将接收的消息发给 /topic/notice
*/
@ResponseBody
@MessageMapping("/change-notice")//客户端访问服务端的时候config中配置的服务端接收前缀也要加上 例:/app/change-notice
@SendTo("/topic/notice")//config中配置的订阅前缀记得要加上
public String greeting(String message) {
System.out.println("服务端接收到消息:" + message);
return message;
}
@ResponseBody
@RequestMapping(value = "/test",method = RequestMethod.GET)//客户端访问服务端的时候config中配置的服务端接收前缀也要加上 例:/app/change-notice
public void message(String message) {
Map<String,String> map=new HashMap<>();
map.put("message",message);
//这个方法是websocket给前台发送即时数据的
simpMessagingTemplate.convertAndSend("/topic/notice", JSONObject.toJSON(map));
}
}
7.socket.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>SpirngBoot 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>
</div>
<div>
<h3 id="response"></h3>
</div>
</div>
<script th:src="@{/js/sockjs.min.js}"></script>
<script th:src="@{/js/stomp.min.js}"></script>
<script th:src="@{/js/jquery-1.9.1.js}"></script>
<script type="text/javascript">
let 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() {
let socket = new SockJS('http://127.0.0.1:8080/socket'); //1
stompClient = Stomp.over(socket);//2
stompClient.connect({}, function (frame) {//3
setConnected(true);
console.log('开始进行连接Connected: ' + frame);
stompClient.subscribe('/topic/notice', function (response) { //4 接收信息
showResponse(JSON.parse(response.body).name);
});
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendName() {
let name = $('#name').val();
stompClient.send("/app/change-notice", {}, JSON.stringify({'name': name}));//5 发送信息
}
function showResponse(message) {
let response = $("#response");
response.html(message);
}
</script>
</body>
</html>
8.测试结果
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- dcrkj.com 版权所有 赣ICP备2024042791号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务