You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决WebSphere JMS中带连字符Header的CWSIA0112E警告?

解决WebSphere JMS下带连字符Header的映射警告问题

这个问题我之前在类似的Spring Integration + WebSphere环境里碰到过,根源很明确:WebSphere的默认JMS提供者对属性名称有严格要求,必须符合合法Java标识符规则(只能包含字母、数字、下划线,不能以数字开头,也不能有连字符这类特殊符号)。而Spring Integration自带的DefaultJmsHeaderMapper默认会直接把原Header名称作为JMS属性名,这就导致带连字符的Header无法正常映射,抛出CWSIA0112E警告/错误。

自定义Header Mapper是完美的解决方案

当然可以通过自定义JmsHeaderMapper来解决,核心思路是:在将Header映射为JMS属性时,把带连字符的名称转换成合法格式(比如替换成下划线,或者转成驼峰命名);在反向映射(从JMS属性转回Header)时,再把名称转换回去,保证消息的完整性。

下面给你具体的实现示例:

1. 自定义HeaderMapper类

继承DefaultJmsHeaderMapper,重写映射逻辑:

import org.springframework.integration.jms.DefaultJmsHeaderMapper;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;

import javax.jms.JMSException;
import javax.jms.Message;
import java.util.Enumeration;
import java.util.Map;

public class WebSphereJmsHeaderMapper extends DefaultJmsHeaderMapper {

    // 处理从MessageHeaders到JMS属性的正向映射:把连字符替换为下划线
    @Override
    protected void fromHeaders(MessageHeaders headers, Message jmsMessage) {
        Map<String, Object> filteredHeaders = filterHeaders(headers);
        for (Map.Entry<String, Object> entry : filteredHeaders.entrySet()) {
            String originalHeaderName = entry.getKey();
            // 替换连字符为下划线,生成合法的JMS属性名
            String validPropertyName = originalHeaderName.replace("-", "_");
            if (isJmsProperty(validPropertyName)) {
                setJmsProperty(jmsMessage, validPropertyName, entry.getValue());
            }
        }
    }

    // 处理从JMS属性到MessageHeaders的反向映射:把下划线转回连字符
    @Override
    protected void populateStandardHeaders(Map<String, Object> headers, Message jmsMessage) {
        super.populateStandardHeaders(headers, jmsMessage);
        try {
            Enumeration<?> propertyNames = jmsMessage.getPropertyNames();
            while (propertyNames.hasMoreElements()) {
                String propertyName = (String) propertyNames.nextElement();
                // 跳过JMS保留属性,避免重复处理
                if (!isJmsReservedProperty(propertyName)) {
                    // 将下划线转回连字符,还原原始Header名称
                    String originalHeaderName = propertyName.replace("_", "-");
                    headers.put(originalHeaderName, jmsMessage.getObjectProperty(propertyName));
                }
            }
        } catch (JMSException e) {
            throw new MessagingException("读取JMS属性失败", e);
        }
    }
}

2. 在Spring配置中启用自定义Mapper

如果用JavaConfig,配置如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.jms.JmsMessageDrivenChannelAdapter;
import org.springframework.integration.jms.JmsSendingMessageHandler;

import javax.jms.ConnectionFactory;

@Configuration
public class JmsIntegrationConfig {

    // 注册自定义HeaderMapper
    @Bean
    public WebSphereJmsHeaderMapper webSphereJmsHeaderMapper() {
        WebSphereJmsHeaderMapper mapper = new WebSphereJmsHeaderMapper();
        // 允许所有Header参与映射(你也可以指定具体的Header列表)
        mapper.setOutboundHeaderNames("*");
        return mapper;
    }

    // 配置JMS消息发送处理器
    @Bean
    public JmsSendingMessageHandler jmsSendingHandler(ConnectionFactory connectionFactory) {
        JmsSendingMessageHandler handler = new JmsSendingMessageHandler(connectionFactory);
        handler.setHeaderMapper(webSphereJmsHeaderMapper());
        return handler;
    }

    // 配置JMS消息驱动适配器(消费端)
    @Bean
    public JmsMessageDrivenChannelAdapter jmsMessageDrivenAdapter(ConnectionFactory connectionFactory) {
        JmsMessageDrivenChannelAdapter adapter = new JmsMessageDrivenChannelAdapter(connectionFactory, "your-target-queue");
        adapter.setHeaderMapper(webSphereJmsHeaderMapper());
        return adapter;
    }
}

备选方案:直接排除不需要的Header

如果你不需要保留这些带连字符的Header,也可以通过配置默认的DefaultJmsHeaderMapper来排除它们,避免警告:

@Bean
public DefaultJmsHeaderMapper defaultJmsHeaderMapper() {
    DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
    // 指定要排除的Header名称
    mapper.setExcludedHeaders("Keep-Alive", "Transfer-Encoding");
    return mapper;
}

不过这种方式会丢失这些Header的信息,所以更推荐前面的自定义映射方案,既能符合WebSphere的要求,又能保留Header内容。

内容的提问来源于stack exchange,提问作者Kris Swat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:22:08