Javascript 如何使用事件更新Thymeleaf
我配置了一个Eventbus,它将使用监视器事件更新映射。因此,对于每个名称,映射将始终具有最新的监视事件。作为用户,您可以看到最近发生的事件,然后转到URL“/概述”,其中显示基本的HTML页面Javascript 如何使用事件更新Thymeleaf,javascript,spring,spring-boot,thymeleaf,guava,Javascript,Spring,Spring Boot,Thymeleaf,Guava,我配置了一个Eventbus,它将使用监视器事件更新映射。因此,对于每个名称,映射将始终具有最新的监视事件。作为用户,您可以看到最近发生的事件,然后转到URL“/概述”,其中显示基本的HTML页面 import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.C
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
@Controller
public class OverviewController {
private final Map<String, MonitorResponse> monitorEvents;
@Autowired
public OverviewController(EventBus eventBus) {
monitorEvents = new HashMap<>();
eventBus.register(this);
}
@RequestMapping("/overview")
public String overview(Model model) {
model.addAttribute("monitorResponseMap", monitorEvents);
return "overview";
}
@Subscribe
public void subscribe(MonitorEvent monitorEvent) {
monitorEvents.put(monitorEvent.getName(), monitorEvent.getMonitorResponse());
}
}
import java.util.HashMap;
导入java.util.Map;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.stereotype.Controller;
导入org.springframework.ui.Model;
导入org.springframework.web.bind.annotation.RequestMapping;
导入com.google.common.eventbus.eventbus;
导入com.google.common.eventbus.Subscribe;
@控制器
公共类概览控制器{
私人最终地图监控事件;
@自动连线
公共概览控制器(EventBus EventBus){
monitoreports=newhashmap();
eventBus.register(this);
}
@请求映射(“/overview”)
公共字符串概述(模型){
addAttribute(“monitorResponseMap”,monitorEvents);
返回“概述”;
}
@订阅
公共无效订阅(MonitorEvent MonitorEvent){
monitorEvent.put(monitorEvent.getName(),monitorEvent.getMonitorResponse());
}
}
HTML:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="/bootstrap-4.0.0/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/css/styles.css"/>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-"
th:each="monitorevent : ${monitorResponseMap}"
style="margin: 10px;padding:20px;border-radius: 10px;"
th:classappend="${monitorevent.value.getMonitorStatus().name()}">
<div class="card-title" style="font-weight: bolder" th:text="${monitorevent.key}"></div>
<p th:text="${monitorevent.value.getMessage()}"></p>
</div>
</div>
</div>
<script src="/jquery-3.3.1.min.js"></script>
<script src="/bootstrap-4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
入门:提供Web内容
当出现新事件时,在调用subscribe方法时,动态更新UI的最简单方法是什么?
现在我自动刷新页面的Javascript(使用标记meta(http equiv=refresh),但这对用户来说很烦人。使用websockets?Ajax?多亏了Venu Duggireddy,我了解了SSE,并跟随了 这很容易解决了我的问题: SSE控制器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@RestController
public class SseController {
private final SseService sseService;
@Autowired
public SseController(SseService sseService) {
this.sseService = sseService;
}
@RequestMapping(path = "/sse/infinite", method = RequestMethod.GET)
public SseEmitter getInfiniteMessages() {
return sseService.getInfiniteMessages();
}
}
当我想要更新前端时,我可以使用notifyListeners调用SseService:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@Component
public class SseService {
private final static Logger LOGGER = LoggerFactory.getLogger(SseService.class);
private final SseEmitter emitter;
@Autowired
public SseService() {
emitter = new SseEmitter();
}
SseEmitter getInfiniteMessages() {
return emitter;
}
public void notifyListeners(MonitorEvent monitorEvent) {
try {
emitter.send(monitorEvent);
} catch (IOException e) {
LOGGER.error("Sse message " + monitorEvent + "not send", e);
}
}
}
在HTML中:
<script type="application/javascript">
if (!!window.EventSource) {
var eventSource = new EventSource("/sse/infinite");
eventSource.onmessage = function (e) {
var message = JSON.parse(e.data);
console.log(message);
//updating my HTML here
};
eventSource.onerror = function (e) {
if (e.readyState === EventSource.CONNECTING) {
console.log('event: CONNECTING');
} else if (e.readyState === EventSource.OPEN) {
console.log('event: OPEN');
} else if (e.readyState === EventSource.CLOSING) {
console.log('event: CLOSING');
} else if (e.readyState === EventSource.CLOSED) {
console.log('event: CLOSED');
}
};
} else {
alert('The browser does not support Server-Sent Events');
}
</script>
如果(!!window.EventSource){
var eventSource=new eventSource(“/sse/infinite”);
eventSource.onmessage=函数(e){
var message=JSON.parse(e.data);
控制台日志(消息);
//在这里更新我的HTML
};
eventSource.onerror=函数(e){
if(e.readyState==EventSource.CONNECTING){
log('event:CONNECTING');
}else if(e.readyState==EventSource.OPEN){
日志('event:OPEN');
}else if(e.readyState==EventSource.CLOSING){
console.log('event:CLOSING');
}else if(e.readyState==EventSource.CLOSED){
console.log('event:CLOSED');
}
};
}否则{
警报(“浏览器不支持服务器发送的事件”);
}
服务器端事件可能是一个更好的选择,因为它是单向的(服务器到客户端),开销很小