简体   繁体   中英

How to pass locale from http request to websocket in spring boot?

How do I pass over the locale from http request to websocket in spring boot?

My locale is already set in LocaleContextHolder, but when I hand over to websocket, it's gone and it's default again. What's the right way to hand over the locale to websockets?

Ok, I found a solution. Since LocaleContextHolder is thread based and websockets are running asynchronously, things get lost from the request. But luckily there is HandshakeInterceptor to hand over certain things to websocket sessions.

My config:

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

    // ...

}

The interceptor:

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 is just a string constant. Call it whatever you like.

Then in your controller:

@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;
    }

}

Hope this helps others with the same issues.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM