Spring многопользовательское приложение с веб-сокетами?

У меня есть работающее многопользовательское приложение Spring. Он использует знакомую конструкцию локальной переменной потока и веб-фильтра, а также использует имя хоста (субдомен), чтобы определить, какой арендатор активен.

Но браузер также открывает веб-сокет и отправляет сообщения. Каким-то образом мне нужно проделать там тот же трюк; Мне нужно сопоставить входящее сообщение с арендатором, то есть с именем хоста, которое использовалось для запуска веб-сокета. Не существует понятия фильтра для веб-сокетов.

Существует HandshakeInterceptor, в котором можно получить доступ к имени хоста, или, возможно, через WebSocketEventListener, поэтому там, вероятно, что-то можно создать. Но я не могу найти способ связать входящее сообщение (в методе @MessageMapping класса @Controller) с чем-либо разумным.

Есть идеи, как это сделать?

0
0
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Покопаться пришлось немного, но у людей возник тот же вопрос. Поместите код, который определяет tenantId из HttpServletRequest, и код, который настраивает любое ведение журнала (например, MDC), уже присутствующее в TenantFilter, в повторно используемых статических методах. А потом:

  1. Определите и сохраните tenantId в HandshakeInterceptor.
.addInterceptors(new HandshakeInterceptor() {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {

        // Determine the tenantId (see TenantFilter)
        ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request;
        HttpServletRequest httpServletRequest = servletServerHttpRequest.getServletRequest();
        String tenantId = TenantFilter.determineTenantId(httpServletRequest, ...);
        attributes.put("tenantId", tenantId);
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
    }
})

  1. В методах обработки сообщений в классе WebsocketController используйте аннотацию заголовка, чтобы получить атрибуты и получить из них tenantId:
@MessageMapping("/SetNoteworthy")
public void browserToBackend(SetNoteworthy command, @Header("simpSessionId") String sessionId, @Header("simpSessionAttributes") Map<String, String> attributes) throws Exception {
    String tenantId = attributes.get("tenantId");

    if (LOG.isInfoEnabled()) LOG.info(BROWSER_TO_BACKEND + command);
    TenantFilter.setCurrentTenant(tenantId, ...);
}

Другие вопросы по теме