【问题标题】:Add STOMP header without recreating Message on ChannelInterceptorAdapter添加 STOMP 标头而不在 ChannelInterceptorAdapter 上重新创建 Message
【发布时间】:2016-03-18 13:21:24
【问题描述】:

我需要为 STOMP 消息添加标头,目前它的工作方式如下,但我正在重新创建消息,是否可以只添加本机标头而无需重新创建消息以提高性能。

public class MyChannelInterceptor extends ChannelInterceptorAdapter {


    @Override
      public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);

        StompCommand command = accessor.getCommand();
        if(command != null) {
            log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
            if(command == StompCommand.SEND) {
                log.debug("Adding expires header to  msg {} from {}",command,accessor.getUser().getName());
                String ttlString = accessor.getFirstNativeHeader("ttl");
                long ttl = 30000;
                try {
                    ttl = Long.parseLong(ttlString);
                } 
                catch(Exception ex) {
                    log.error("TTL header received but not in correct format {}",ttlString);
                }
                accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));

                return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
            }
        }
        return message;
      }

}

【问题讨论】:

    标签: spring-websocket spring-messaging


    【解决方案1】:

    这就是我要找的东西

    StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
    

    上面的代码将获取消息的实际 StompHeaderAccessor,因此如果您操作本机标头,它们会直接反映在消息上

    StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
    

    将获得一个标头的克隆,您必须使用新克隆的标头创建一条新消息

    下面的完整固定代码

    @Override
          public Message<?> preSend(Message<?> message, MessageChannel channel) {
    
            StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
           // StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
            if(accessor != null) {
                StompCommand command = accessor.getCommand();
                if(command != null) {
                    log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
                    if(command == StompCommand.SEND) {
    
                        log.debug("Adding expires header to  msg {} from {}",command,accessor.getUser().getName());
                        String ttlString = accessor.getFirstNativeHeader("ttl");
                        long ttl = 30000;
                        if(ttlString != null) {
                            try {
                                ttl = Long.parseLong(ttlString);
                            } 
                            catch(Exception ex) {
                                log.error("TTL header received but not in correct format {}",ttlString);
                            }
                        }
    
                        accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));
                         // I don't need any more to create a new message
                        //return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
                    }
                }
            }
            return message;
          }
    

    【讨论】:

    • 你拯救了我的一天。就我而言,我确实必须创建一条新消息。我在 beforeHandle() 方法中修改了 SUBSCRIBE 框架。
    【解决方案2】:

    由于addNativeHeader 成功,这表明消息仍然是可变的 - 请参阅addNativeHeader()

    在任何情况下,由于NATIVE_HEADERS 消息头是MultiValueMap-valued 头,您可以就地更新头内容。

    因此,无需创建新消息。

    如果您向消息本身添加新标头(而不是更新现有标头的可变内容),您必须创建新消息。

    编辑

    我刚刚进行了测试;只要消息仍然是可变的,你就可以改变它......

    @Test
    public void test() {
        Map<String, Object> map = new HashMap<String, Object>();
        MutableMessageHeaders headers = new MutableMessageHeaders(map);
        Message<String> message = MessageBuilder.createMessage("foo", headers);
        StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
        accessor.addNativeHeader("foo", "bar");
        System.out.println(message.getHeaders().get(NativeMessageHeaderAccessor.NATIVE_HEADERS));
        accessor.setImmutable();
        try {
            accessor.addNativeHeader("baz", "qux");
            fail("expected IllegalStateException");
        }
        catch (IllegalStateException e) {
    
        }
    }
    

    也就是说,您是否遇到了性能问题,或者这只是一个感知问题。创建消息并不昂贵。

    【讨论】:

    • 然后我将如何告诉消息使用新的访问器进行更新并且它没有添加新的标题
    • 我不确定你的意思;访问者只是简单地包装了消息;只要消息仍然是可变的,您就可以添加新的标头。如果它已经是不可变的,addNativeHeader 将会失败。
    • 我假设创建消息很重,我尝试的是注释掉 return MessageBuilder.createMessage ...,但结果是消息完全按照原样返回,没有添加过期标头
    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 2019-08-17
    相关资源
    最近更新 更多