У меня есть работающее многопользовательское приложение Spring. Он использует знакомую конструкцию локальной переменной потока и веб-фильтра, а также использует имя хоста (субдомен), чтобы определить, какой арендатор активен.
Но браузер также открывает веб-сокет и отправляет сообщения. Каким-то образом мне нужно проделать там тот же трюк; Мне нужно сопоставить входящее сообщение с арендатором, то есть с именем хоста, которое использовалось для запуска веб-сокета. Не существует понятия фильтра для веб-сокетов.
Существует HandshakeInterceptor, в котором можно получить доступ к имени хоста, или, возможно, через WebSocketEventListener, поэтому там, вероятно, что-то можно создать. Но я не могу найти способ связать входящее сообщение (в методе @MessageMapping класса @Controller) с чем-либо разумным.
Есть идеи, как это сделать?
Покопаться пришлось немного, но у людей возник тот же вопрос. Поместите код, который определяет tenantId из HttpServletRequest, и код, который настраивает любое ведение журнала (например, MDC), уже присутствующее в TenantFilter, в повторно используемых статических методах. А потом:
.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) {
}
})
@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, ...);
}