记录 |
---|
websockt在作为即时通讯类的聊天方面有较多的应用,其主要的特点就是轻量,使用方便,容易快速上手,通过webscoket整合服务端,就可以实现简单的类似聊天的功能,下面说说springboot整合socketjs实现一个简易版的点对点聊天过程,
1、pom依赖:
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-websocket
org.webjars
webjars-locator
0.35
org.webjars
sockjs-client
1.1.2
org.webjars
stomp-websocket
2.3.3
org.webjars
bootstrap
4.3.0
org.webjars
jquery
3.3.0
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
2、下面是服务端的webscoket配置文件,这个配置文件相当于是说创建了一个类似于服务器基站的连接信息,也成为连接端点,熟悉消息中间件的同学应该知道topic这个概念,就相当于是创建一个中转的点,用于客户端和服务端交互,
/**
* webscoket服务端配置
* @author asus
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{
/**
* 注册端点,发布或者订阅消息的时候需要连接此端点
* setAllowedOrigins 非必须,*表示允许其他域进行连接
* withSockJS 表示开始sockejs支持
*/
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/endpoint-websocket").setAllowedOrigins("*").withSockJS();
}
/**
* 配置消息代理(中介)
* enableSimpleBroker 服务端推送给客户端的路径前缀 ,可以设置多个
* setApplicationDestinationPrefixes 客户端发送数据给服务器端的一个前缀
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/chat");
registry.setApplicationDestinationPrefixes("/app");
}
}
3、为了统一返回前端指定的数据格式,我们这里自定义两个实体对象,InMessage 表示服务端接收的格式,OutMessage表示服务端推送客户端时候的数据格式,
public class InMessage {
private String from;
private String to;
private String content;
private Date time;
public String getFrom() {
return from;
}
public InMessage(){}
public InMessage(String content) {
this.content = content;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}
public class OutMessage {
private String from;
private String content;
private Date time = new Date();
public OutMessage(){}
public OutMessage(String content){
this.content = content;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}
4、接着设置两个监听器,用于监听客户端与服务端建立连接时候的信息打印,也可以不用加这两个类,有点儿类似于spring中的监听器一样,实际业务中有了这样的监听器可以在建立连接或者传递消息时候做一定的业务逻辑前置处理工作,可酌情使用,
/**
* 连接事件监听器,建立连接时候触发
* @author asus
*/
@Component
public class ConnectEventListener implements ApplicationListener{
public void onApplicationEvent(SessionConnectEvent event) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
System.out.println("【ConnectEventListener监听器事件 类型】"+headerAccessor.getCommand().getMessageType());
}
}
/**
* 订阅事件监听器
* @author asus
*
*/
@Component
public class SubscribeEventListener implements ApplicationListener{
public void onApplicationEvent(SessionSubscribeEvent event) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
System.out.println("【SubscribeEventListener监听器事件 类型】"+headerAccessor.getCommand().getMessageType());
}
}
5、服务端controller,这里注意使用的@MessageMapping这个注解,这是和客户端进行路径映射的特殊注解,
/**
* 功能描述:简单版单人聊天
*/
@Controller
public class SingleChatRoomContoller {
@Autowired
private WebSocketService ws;
/**
* 单人聊天
* @param message
*/
@MessageMapping("/v3/single/chat")
public void singleChat(InMessage message) {
ws.sendChatMessage(message);
}
}
6、service,
/**
* 功能描述:简单消息模板,用来推送消息
*/
@Service
public class WebSocketService {
@Autowired
private SimpMessagingTemplate template;
/**
* 单人聊天
* @param message
*/
public void sendChatMessage(InMessage message) {
template.convertAndSend("/chat/single/"+message.getTo(),
new OutMessage(message.getFrom()+" 发送:"+ message.getContent()));
}
}
7、为了演示方便,简单做了一下前端的页面,主要是看js部分,
Hello WebSocket
记录
var stompClient = null;
function setConnected(connected) {
$("#connect").prop("disabled", connected);
$("#disconnect").prop("disabled", !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#notice").html("");
}
/**
* 客户端和服务端建立初始化连接
*/
function connect() {
var from = $("#from").val();
var socket = new SockJS('/endpoint-websocket'); // endpoint-websocket 连接服务端配置的端点,可以理解为服务器
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/chat/single/'+ from, function (result) { // chat/single 服务端推送给客户端的路径前缀 ,可以设置多个
showContent(JSON.parse(result.body));
});
});
}
/**
* 断开连接
*/
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
/**
* 发送消息
*/
function sendName() {
stompClient.send("/app/v3/single/chat", {}, JSON.stringify({'content': $("#content").val(), 'to':$("#to").val(), 'from':$("#from").val()}));
}
/**
* 显示消息内容
* @param body
*/
function showContent(body) {
$("#notice").append("" + body.content + " "+new Date(body.time).toLocaleString()+" ");
}
$(function () {
$("form").on('submit', function (e) {
e.preventDefault();
});
$( "#connect" ).click(function() { connect(); });
$( "#disconnect" ).click(function() { disconnect(); });
$( "#send" ).click(function() { sendName(); });
});
8、启动类:
//@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@ComponentScan(basePackages="com.congge")
@SpringBootApplication
//@EnableScheduling
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
运行main函数,服务端成功启动后,我们到浏览器试一下效果:
一个简单的聊天效果就实现了,我们再看看控制台,我们设置的监听器也生效了,
到此为止,springboot就完成了和websocket的简单整合,是不是挺简单,服务端主要的就是几项配置,然后就是socketJs的几个js的配置需要注意一下即可,我们还可以基于此整合完成诸如服务端实时推送或者定时推送消息给客户端等这样的功能,大家有兴趣可以深入探讨!谢谢观看!