Хорошо, я нашел решение.
Поскольку LocaleContextHolder основан на потоках, а веб-сокеты работают асинхронно, из-за запроса все теряется.
Но, к счастью, есть HandshakeInterceptor для передачи определенных вещей в сеансы websocket.
Моя конфигурация:
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketBrokerConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<Session> {
// ...
@Override
protected void configureStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("*")
.addInterceptors(new HttpWebsocketHandshakeInterceptor()) // <-- The interceptor
.withSockJS();
}
// ...
}
Перехватчик:
public class HttpWebsocketHandshakeInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
Locale locale = LocaleContextHolder.getLocale();
attributes.put(WSConstants.HEADER_HTTP_LOCALE, locale);
// hand over more stuff, if needed ...
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
}
}
WSConstants.HEADER_HTTP_LOCALE
это просто строковая константа. Называй как хочешь.
Тогда в вашем контроллере:
@Controller
public class WSController {
@MessageMapping("/somewhere/")
public void message(
SimpMessageHeaderAccessor headerAccessor,
Principal principal,
WSMessage frame) {
// update locale to keep it up to date
Map<String, Object> sessionHeaders = headerAccessor.getSessionAttributes();
Locale locale = (Locale) sessionHeaders.get(WSConstants.HEADER_HTTP_LOCALE);
if (locale != null) {
LocaleContextHolder.setLocale(locale);
}
// use your localized stuff as you used to
}
@SubscribeMapping("/somewhereelse/")
public ChannelPayload bubble(
SimpMessageHeaderAccessor headerAccessor,
Principal principal
) {
// update locale to keep it up to date
Map<String, Object> sessionHeaders = headerAccessor.getSessionAttributes();
Locale locale = (Locale) sessionHeaders.get(WSConstants.HEADER_HTTP_LOCALE);
if (locale != null) {
LocaleContextHolder.setLocale(locale);
}
// use your localized stuff as you used to
return null;
}
}
Надеюсь, это поможет другим с такими же проблемами.