Как обновить Thymeleaf с событиями - PullRequest
0 голосов
/ 05 июня 2018

У меня настроен Eventbus, который будет обновлять карту с событиями монитора.Таким образом, карта всегда будет иметь самые последние события монитора для каждого имени.Как пользователь, вы видите самые последние события, которые вы переходите по URL-адресу "/ Overview", который отображает основную страницу HTML.

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());
    }
}

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>

Что такоеСамый простой способ динамического обновления пользовательского интерфейса, когда появляются новые события, например, когда вызывается метод подписки?Сейчас я делаю автоматическое обновление страницы Javascript (используя мета-тег (http-equ = refresh), но это раздражает пользователя. Использование websockets? Ajax?

1 Ответ

0 голосов
/ 06 июня 2018

Благодаря Вену Дуггиредди я познакомился с SSE и последовал демонстрации https://github.com/aliakh/demo-spring-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();
    }
}

Когда я хочу обновить интерфейс, я могу просто вызвать SseService с notifyListeners:

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...