springboot整合websocket实现简易版单人聊天

websockt在作为即时通讯类的聊天方面有较多的应用,其主要的特点就是轻量,使用方便,容易快速上手,通过webscoket整合服务端,就可以实现简单的类似聊天的功能,下面说说springboot整合socketjs实现一个简易版的点对点聊天过程,

1、pom依赖:

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.webjars/webjars-locator -->
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>webjars-locator</artifactId>
			<version>0.35</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.webjars/sockjs-client -->
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>sockjs-client</artifactId>
			<version>1.1.2</version>
		</dependency>

		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>stomp-websocket</artifactId>
			<version>2.3.3</version>
		</dependency>
		
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>bootstrap</artifactId>
			<version>4.3.0</version>
		</dependency>
		
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>jquery</artifactId>
			<version>3.3.0</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

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<SessionConnectEvent>{

	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<SessionSubscribeEvent>{

	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部分,

  • 7.1html 页面
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<head>
    <title>Hello WebSocket</title>
    <link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <link href="/v3/main.css" rel="stylesheet">
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
    <script src="/v3/app.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being
    enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div id="main-content" class="container">
    <div class="row">
        <div class="col-md-6">
            <form class="form-inline">
                <div class="form-group">
                    <label for="connect">建立连接通道:</label>
                    <button id="connect" class="btn btn-default" type="submit">Connect</button>
                    <button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect
                    </button>
                </div>
            </form>
        </div>
        <div class="col-md-6">
            <form class="form-inline">
                <div class="form-group">
                    <input type="text" id="from" class="form-control" placeholder="我是">
                    <input type="text" id="to" class="form-control" placeholder="发送给谁">
                    
                    <input type="text" id="content" class="form-control" placeholder="请输入...">
                    
                    
                </div>
                <button id="send" class="btn btn-default" type="submit">发送</button>
            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <table id="conversation" class="table table-striped">
                <thead>
                <tr>
                    <th>记录</th>
                </tr>
                </thead>
                <tbody id="notice">
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

  • 7.2 JS部分
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("<tr><td>" + body.content + "</td> <td>"+new Date(body.time).toLocaleString()+"</td></tr>");
}

$(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的配置需要注意一下即可,我们还可以基于此整合完成诸如服务端实时推送或者定时推送消息给客户端等这样的功能,大家有兴趣可以深入探讨!谢谢观看!

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小码农叔叔

谢谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值