インターネットでたくさんのWebSocketブログを読んでみましたが、基本的には上記の操作で失敗しました。情報が不完全だったり、プロジェクト環境が異なっていたりするのが原因です。この問題を解決するために一生懸命探索してみて、ようやく自分のやりたいことに気づきました。望ましい効果。最初にプロジェクト環境についてお話します。プロジェクトではSSMフレームワークを使用し、次にアノテーションを使用して Bean を注入します。開発ツールはアイデアであり、tomcatのバージョンは7.0.84で、Jdkのバージョンは1.8.0_152です。tomcatは8以上である必要があるとインターネット上で言われていますが、使用したtomcat7.0.84でも目的の機能を実現できますが、tomcatの最小バージョンについては調べていません。次に、プログラムについて説明しましょう。
最初のステップ:HTMLページのプログラム。直接貼り付けて、対応するフィールドを変更できます。注意ブラウザのバージョンが低すぎるは、WebSocketをサポートされていないのを
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>测试websocket</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style type="text/css">
* {
margin: 0px;
padding: 0px;
}
</style>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
//建立连接,这里的/websocket ,是Servlet中注解中的那个值,一定对应哈
websocket = new WebSocket("ws://localhost:8086/项目名称/websocket");//这里的项目名称,有的人进行了设置,有的人没有进行设置,还是根据自己的项目情况来
}
else {
alert('当前浏览器不支持websocket');
}
//连接发生错误的回调方法
websocket.onerror = function () {
document.write("WebSocket连接发生错误<br>")
};
//连接成功建立的回调方法
websocket.onopen = function () {
document.write("WebSocket连接成功<br>");
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
//我在编写逻辑时,如果后端数据库发生变化,就给前端传送的数据设置为1,
if(event.data=="1"){
//这里就可以在前端进行相应的功能展示,我这里就只用打印一句话进行表示了
document.write("数据更新啦<br>");
}
}
//连接关闭的回调方法
websocket.onclose = function () {
document.write("WebSocket连接关闭<br>");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭WebSocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
}
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
</script>
</head>
<body>
</body>
</html>
ステップ2:pom.xmlを設定する
<!-- 下面的是websocket的依赖-开始处 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- 上面的是websocket的依赖-结尾处-->
ステップ3:Daoレイヤー
/**
* 下面的方法是测试websocket下数据库中商品总数的变化
* @return
*/
Integer WebsocketSumFood();
ステップ4:マッパー
<!-- websocket查询商品总数-->
<select id="WebsocketSumFood" resultType="Integer" >
select count(*) from t_product
</select>
ステップ5:サービス層
/**
* 测试食品修改下websocket的使用
* @return
*/
int WebsocketSumFood();
ステップ6:サービス実装レイヤー
/**
* websocket下测试食品总数修改的变化
* @return
*/
@Override
public int WebsocketSumFood() {
return foodDao.WebsocketSumFood();
}
ステップ7:WebSocketConfigクラスを作成する
import org.apache.catalina.session.StandardSessionFacade;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
/**
* @Author: Wxz
* @Date: 2020/9/1 11:49
*/
@Configuration
public class WebSocketConfig extends Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
/*如果没有监听器,那么这里获取到的HttpSession是null*/
StandardSessionFacade ssf = (StandardSessionFacade) request.getHttpSession();
if (ssf != null) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
//关键操作
sec.getUserProperties().put("sessionId", httpSession.getId());
}
}
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
8番目のステップ:モニタリングクラスの記述
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* @Author: Wxz
* @Date: 2020/9/1 14:59
*/
@Component
public class RequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent sre) {
//将所有request请求都携带上httpSession
HttpSession httpSession = ((HttpServletRequest) sre.getServletRequest()).getSession();
}
public RequestListener() {
}
@Override
public void requestDestroyed(ServletRequestEvent arg0) {
}
}
ステップ9:スレッドクラスMyThreadを記述する
package com.example.orderserver.foodwebsocket;
import com.example.orderserver.service.foodManage.FoodService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @Author: Wxz
* @Date: 2020/9/1 10:29
*/
@Component
public class MyThread implements Runnable{
//普通类获取service对象,否则会报空指针
@Autowired
private FoodService foodService;
public static MyThread testUtils;
//下面的注解一定要有哈
@PostConstruct
public void init() {
testUtils = this;
}
//原始数量
private int sum;
//数据库变化后的数量
private int new_sum;
//设置循环状态
private boolean stopMe = true;
public void stopMe() {
stopMe = false;
}
@Override
public void run() {
sum=testUtils.foodService.WebsocketSumFood();
WebSocketServlet wbs=new WebSocketServlet();
while(stopMe){
new_sum=testUtils.foodService.WebsocketSumFood();
if(sum!=new_sum){
sum=new_sum;
wbs.onMessage(sum);
}
try {
//每10秒检查一下数据库
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
10番目のステップ:WebSocketServletを作成する
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @Author: Wxz
* @Date: 2020/9/1 10:30
*/
@ServerEndpoint("/websocket")
@Component
public class WebSocketServlet {
MyThread thread1=new MyThread();
//开启线程
Thread thread=new Thread(thread1);
//用来存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocketServlet> webSocketSet = new CopyOnWriteArraySet<WebSocketServlet>();
private javax.websocket.Session session=null;
/**
* @ClassName: onOpen
* @Description: 开启连接的操作
*/
@OnOpen
public void onOpen(Session session, EndpointConfig config) throws IOException{
//获取WebsocketConfig.java中配置的“sessionId”信息值
String httpSessionId = (String) config.getUserProperties().get("sessionId");
this.session=session;
webSocketSet.add(this);
//开启一个线程对数据库中的数据进行轮询
thread.start();
}
/**
* @ClassName: onClose
* @Description: 连接关闭的操作
*/
@OnClose
public void onClose(){
thread1.stopMe();
webSocketSet.remove(this);
}
/**
* 告知前端数据库发生变化,调用sendMessage()方法
* @param count
*/
@OnMessage
public void onMessage(int count) {
System.out.println("发生变化"+count);
try {
sendMessage();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 出错操作
* @param error
*/
@OnError
public void onError(Throwable error){
error.printStackTrace();
}
/**
* 此方法是被调用的方法,所以没注解,这里才是真正处理逻辑的地方,可以给前台传输你想要传输的内容,我只是用1进行代替了。
* @throws IOException
* 发送自定义信号,“1”表示告诉前台,数据库发生改变了,需要刷新
*/
public void sendMessage() throws IOException{
//群发消息
for(WebSocketServlet item: webSocketSet){
item.session.getBasicRemote().sendText("1");
}
}
}
ステップ11:プロジェクトを開始し、データベースを変更します。
ステップ12:ブラウザーを確認します。
これまでのところ、欲しい効果は出ていますし、皆さんとコミュニケーションできてうれしいです!