Как передать локаль из http-запроса в websocket при весенней загрузке? - PullRequest
1 голос
/ 04 июля 2019

Как передать языковой стандарт из запроса http в websocket при весенней загрузке?

Мой языковой стандарт уже задан в LocaleContextHolder, но когда я передаю его в websocket, он исчезает и снова используется по умолчанию.Как правильно передать локаль веб-сокетам?

1 Ответ

0 голосов
/ 04 июля 2019

Хорошо, я нашел решение. Поскольку 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;
    }

}

Надеюсь, это поможет другим с такими же проблемами.

...