3

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

}
4

2 回答 2

6

这就是我一直在寻找的

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;
      }
于 2016-03-19T12:06:39.670 回答
0

由于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) {

    }
}

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

于 2016-03-18T13:36:42.703 回答