【发布时间】:2021-05-25 15:56:19
【问题描述】:
这是我的要求
- 在我的应用程序中,Spring-mvc 在内部访问其余 api 并从依赖系统获取数据(耗时操作)。我想从 JSP 页面监控这个服务器端事件
- 我想为 spring 触发的 rest-api 搜索设置计时器/进度条。
【问题讨论】:
标签: spring spring-mvc jsp
这是我的要求
【问题讨论】:
标签: spring spring-mvc jsp
在这种情况下,您可以使用 WebSocket 和 STOMP 协议来满足您的要求。
WebSocket
WebSocket 是用户浏览器和服务器之间的双向连接。 for more info about WebSocket.
STOMP 协议
STOMP 是一种简单(或流式)的面向文本的消息传递协议,用于与面向消息的中间件一起使用。 for more info about STOMP
WebSocket 和 STOMP 协议的区别,please refer Nitin Kamate answer。
在这个答案中,使用 SockJS 和 stopmjs 在 Spring 应用程序中创建 WebSocket 和通信协议。
SockJS
SockJS 是一个用于创建 WebSocket 的 java 脚本库。 for more info about SockJS 和 you can download sockjs.min.js file from here。
stompjs
stompjs 是一个 java 脚本库,用于为 Web 浏览器提供 STOMP over WebSocket 客户端。 for more info about stompjs 和 you can download stomp.min.js file from here。
你应该下载 sockjs.min.js 和 stomp.min.js 文件并将这些 java 脚本文件添加到你的项目中,并且需要添加 WebSocket 库依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>x.x.x</version>
</dependency>
首先在servlet.xml中配置WebSocket
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
https://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/portfolio"/>
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic"/>
</websocket:message-broker>
</beans>
application-destination-prefix 用作按摩映射的前缀path - 使用 http://localhost:8080/portfolio url 连接到 WebSocketprefix 用作 STOMP 目的地的前缀然后如下构建WebSocket客户端,
在这个例子中,我们将一些值从服务器端控制器发送到目的地
AppController.java
@Controller
public class AppController {
@Autowired
private SimpMessagingTemplate template; //provide methods for sending messages to a user
@RequestMapping(value = "/event")
public void getValue() throws InterruptedException{
for (int i = 0; i < 100; i++) { //in this example, used for loop to generate a value in iteration
this.template.convertAndSend("/topic/number", i); //send the value of i to destination through WebSocket
Thread.sleep(1000); //added a delay to every round in for loop
}
}
}
JavaScript (SockJS) 客户端,用于接收服务器端 (java) 事件发送的值。 (另外使用了 Angular 库来处理前端。tutorial for angular js)
app.js
var mainApp = angular.module("mainApp", []);
mainApp.controller('appController', function($scope, $http) {
$scope.progress = 0; // variable declared by angular for store the value return by java
var socket = new SockJS('/Your_Application_Name/portfolio'); //create a new SockJS WebSocket
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.subscribe('/topic/number', function (value) {
$scope.progress=value.body; //assigned value to progress variable
$scope.$apply();
});
$scope.startEvent = function() { // this function call the getValue() function in controller
$http.post('event').then(function(value) {
}, function(reason) {
}, function(value) {
})
}
}
});
下面的jsp文件包含在按钮和进度条中。使用按钮启动服务器端事件(在本例中,按钮通过 Angular js 在AppController.java 中调用getValue() 函数。另外使用引导框架来创建前端。tutorial for bootstrap)
index.jsp
<html>
<head>
<link rel="stylesheet" href="resources/css/bootstrap.min.css">
<script type="text/javascript" src="resources/js/jquery.min.js"></script>
<script type="text/javascript" src="resources/js/sockjs.min.js"></script>
<script type="text/javascript" src="resources/js/stomp.min.js"></script>
<script type="text/javascript" src="resources/js/bootstrap.min.js"></script>
<script type="text/javascript" src="resources/js/angular.min.js"></script>
<script type="text/javascript" src="resources/js/app.js"></script>
</head>
<body ng-app="mainApp" ng-controller="appController">
<div class="container">
<div class="progress mb-3">
<div class="progress-bar" role="progressbar" ng-style="{width: progress + '%'}" aria-valuenow="{{progress}}" aria-valuemin="0" aria-valuemax="100">{{progress}}%</div>
<!--progress variable used for set value to progress bar-->
</div>
<button type="button" class="btn btn-outline-secondary btn-sm" ng-click="startEvent()">Start Event</button>
<!--click event of above button call to startEvent() function in app.js file-->
</div>
</body>
</html>
有关 WebSocket 的更多详细信息,请参阅 Spring 文档,Spring WebSocket 来自here。
【讨论】: