添加STOMP标头而不在ChannelInterceptorAdapter上重新创建Message

时间:2016-03-18 13:21:25

标签: spring-websocket spring-messaging

我需要向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;
      }

}

2 个答案:

答案 0 :(得分:3)

这就是我要找的东西

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

答案 1 :(得分:0)

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

在任何情况下,由于NATIVE_HEADERS邮件标头是MultiValueMap值标头,您可以就地更新标头内容。

因此,无需创建新消息。

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

修改

我刚刚参加了考试;只要消息仍然可变,您就可以更改它......

@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) {

    }
}

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