Spring Boot - 数据对接总结

业务场景:

需要从某集团服务器SqlServer数据库中获取数据进行转换,并插入到我司开发服务器Mysql数据库中。过渡期项目使用Spring Boot 与MyBatis整合进行数据抓取、转换与创建。

Spring Boot 版本:2.1.3.RELEASE

MyBatis-Spring Boot整合包版本:1.3.2

mysql驱动包版本:5.1.43

sqlserver驱动包版本:3.0

连接池:HicariCP

maven (阿里):

        <!-- spring boot 启动引导包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- spring boot jdbc支持包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- mybatis-spring boot整合包 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.spring.boot.version}</version>
        </dependency>

        <!-- sqlserver 数据库驱动包 -->
        <dependency>
            <groupId>com.microsoft</groupId>
            <artifactId>sqljdbc4</artifactId>
            <version>${sqlserver.driver.version}</version>
        </dependency>

        <!-- mysql 数据库驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

application.yml配置文件(或application.properties)

注:使用自定义数据源取代默认配置的数据源时,yml(properties)中的默认url一项需要改变为jdbc-url

spring:
 datasource:
  mysql:
   type: com.zaxxer.hikari.HikariDataSource
   driver-class-name: com.mysql.jdbc.Driver
   jdbc-url: jdbc:mysql://xxx.xxx.xxx.xxx:xxxx/xxx?useUnicode=true&characterEncoding=utf8&useSSL=false&autoReconnect=true
   username: xxxxx
   password: xxxxx
  sqlserver:
   type: com.zaxxer.hikari.HikariDataSource
   driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
   jdbc-url: jdbc:sqlserver://xxx.xxx.xxx.xxx:xxxx;Database=
   username: xxxxx
   password: xxxxx

config:

1.MysqlDataSourceConfigurer

@Configuration
@MapperScan(basePackages = "com.logwsd.delsync.dao.mysql",sqlSessionTemplateRef = "mysqlSqlSessionTemplate")
public class MysqlDataSourceConfigurer {

    @Bean(name="mysqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.mysql")
    @Primary
    public DataSource mysqlDataSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "mysqlSqlSessionFactory")
    public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("mysqlDataSource")DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:**mapper/*.xml"));
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name="mysqlSqlSessionTemplate")
    public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory")SqlSessionFactory factory){
        return new SqlSessionTemplate(factory);
    }

}

2.SqlServerDataSourceConfigurer

@Configuration
@MapperScan(basePackages = "com.logwsd.delsync.dao.sqlserver",sqlSessionTemplateRef = "sqlServerSqlSessionTemplate")
public class SqlServerDataSourceConfigurer {

    @Bean("sqlServerDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.sqlserver")
    public DataSource sqlServerDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean("sqlServerSqlSessionFactory")
    public SqlSessionFactory sqlserverSqlSessionFactory(@Qualifier("sqlServerDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(sqlServerDataSource());
        return sqlSessionFactoryBean.getObject();
    }

    @Bean("sqlServerSqlSessionTemplate")
    public SqlSessionTemplate sqlserverSqlSessionTemplate(@Qualifier("sqlServerSqlSessionFactory") SqlSessionFactory factory){
        return new SqlSessionTemplate(factory);
    }

}

注:此处Mysql数据源使用的是*Mapper.xml形式的mapper,SqlServer使用的是注解式mapper。配置类的区别在于

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();  

sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:**mapper/*.xml"));

两句,并且在配置多数据源的场景下必须给某数据源设置@Primary注解。

包路径:

关于数据迁移:

过度阶段使用该种形式,在向mq生产消费模式转型,有考虑使用阿里cannel框架进行伪装的主从复制,相关内容后续更新。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2019-06-06:

该项目进行重构,进行重构总结。

数据源由先前的SqlServer改为IBM-MQ(基于JMS消息协议),队列中传递河北厂与华北厂的SAP数据消息,消息体为JMSByteMessage。通过获取bytes组装成String,String内容为XML,后将XML解析为JSON再供给后续进行处理。

XML解析工具类是借用编写好的工具类,非本人编写,后续会贴出代码。

根据工厂代码识别并对消息进行分发,采用RabbitMQ进行消息传递,根据不同的场景选用不同的RabbitTemplate发送消息,供下一级消费。

代码设计采用二级生产者与消费者的线程模型,IBM-MQ生产出的消息由我方接收,接受后进行消息解析与消息组装,组装后的消息加入到阻塞队列中,由消费线程进行消费处理。消费线程负责将,消息进行工厂级别的区分,进行实体的匹配与组装,再按照工厂进行消息派发。

多数据源:

    本项目设计到两种多数据源场景,一种为上一版本的程序中涉及到多个不同种、不同表的数据源,另一种为本次重构中涉及到的同种类型、分库分表或主从集群的数据源。后者实现思路:首先向Spring 容器中注入多个数据源(DataSource),然后使用AbstractRoutingDataSource(后作ARDS)的实现类进行多个数据源的集成,ARDS中封装有Map<Object,Object>。key为查找数据源的键,可以用常量或枚举或其他手段进行区分;value为数据源对象,在调用数据库操作前可以通过ARDS的determineCurrentLookupKey方法返回值以确定使用特定数据源。在整合MyBatis时将ARDS的实现类作为DataSource设置入SqlSessionFactoryBean,后续操作与MyBatis配置类无异。

代码如下:

 继承了ARDS的动态数据源类:

public class LogwsdDynamicRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return LogwsdOrderGenerateHandler.get();
    }

}

 数据源-Mybatis配置类

@Configuration
@MapperScan(basePackages = "com.logwsd.ibmmqreceiver.dao.logwsd",sqlSessionTemplateRef = "logwsdSqlSessionTemplate")
public class LogwsdDataSourceConfigurer {

    @Bean("hebeiMysqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.mysql.hebei")
    public DataSource hebeiMysqlDataSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean("huabeiMysqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.mysql.huabei")
    public DataSource huabeiMysqlDataSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean("logwsdDynamicDataSource")
    public LogwsdDynamicRoutingDataSource logwsdDynamicRoutingDataSource(@Qualifier("hebeiMysqlDataSource") DataSource hebeiDataSource ,@Qualifier("huabeiMysqlDataSource") DataSource huabeiDataSource){
        LogwsdDynamicRoutingDataSource dynamicRoutingDataSource = new LogwsdDynamicRoutingDataSource();
        Map<Object,Object> dataSources = new HashMap<>();
        //设置默认的数据源
        dynamicRoutingDataSource.setDefaultTargetDataSource(hebeiDataSource);

        //添加河北和华北厂的数据源
        dataSources.put(DataSourceKey.HEBEI_DATASOURCE,hebeiDataSource);
        dataSources.put(DataSourceKey.HUABEI_DATASOURCE,huabeiDataSource);

        dynamicRoutingDataSource.setTargetDataSources(dataSources);
        return dynamicRoutingDataSource;
    }

    @Bean("logwsdSqlSessionFactory")
    public SqlSessionFactory logwsdDynamicDataSourceSqlSessionFactoryBean(@Qualifier("logwsdDynamicDataSource")LogwsdDynamicRoutingDataSource dynamicRoutingDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicRoutingDataSource);
        PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = pathMatchingResourcePatternResolver.getResources("classpath:mapper/*Mapper.xml");
        sqlSessionFactoryBean.setMapperLocations(resources);
        return sqlSessionFactoryBean.getObject();
    }

    @Bean("logwsdSqlSessionTemplate")
    public SqlSessionTemplate logwsdSqlSessionTemplate(@Qualifier("logwsdSqlSessionFactory")SqlSessionFactory factory){
        return new SqlSessionTemplate(factory);
    }

    @Bean("transactionManager")
    public PlatformTransactionManager platformTransactionManager(@Qualifier("logwsdDynamicDataSource") LogwsdDynamicRoutingDataSource dynamicRoutingDataSource){
        return new DataSourceTransactionManager(dynamicRoutingDataSource);
    }
}

 选择数据源:

public void handle(SourceMessageWrapper mw) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {

        ZssdhAnalyzerJSONImpl zssdhAnalyzer = new ZssdhAnalyzerJSONImpl(mw);
        ZssdiAnalyzerJSONImpl zssdiAnalyzer = new ZssdiAnalyzerJSONImpl(mw);
        ZvttkAnalyzerJSONImpl zvttkAnalyzer = new ZvttkAnalyzerJSONImpl(mw);

        List<Zssdh> zssdhList = zssdhAnalyzer.analy();
        boolean flag = false;
        if (zssdhList != null && zssdhList.size() > 0 && (MappingConstant.HEBEI_DOC_SYMBOL.equals(zssdhList.get(0).getVkorg()) || MappingConstant.HUABEI_DOC_SYMBOL.equals(zssdhList.get(0).getVkorg()))) {
            //选用河北厂数据源
            if(MappingConstant.HEBEI_DOC_SYMBOL.equals(zssdhList.get(0).getVkorg())) {
                LogwsdOrderGenerateHandler.setRouter(DataSourceKey.HEBEI_DATASOURCE);
                flag = true;
            }
            //选用华北厂数据源
            if(MappingConstant.HUABEI_DOC_SYMBOL.equals(zssdhList.get(0).getVkorg())){
                LogwsdOrderGenerateHandler.setRouter(DataSourceKey.HUABEI_DATASOURCE);
                flag = true;
            }
            if(flag) {
                List<Zssdi> zssdiList = zssdiAnalyzer.analy();
                List<Zvttk> zvttkList = zvttkAnalyzer.analy();
                try {
                    logwsdOrderGenerateHandler.handle(zvttkList, zssdhList, zssdiList);
                } finally {
                    //清除设置的数据源标识
                    LogwsdOrderGenerateHandler.clear();
                }
            }
        }
        if(!flag){
            throw new UnknownOrganizationException();
        }
    }

设置/取出数据源标识:

    public static ThreadLocal<DataSourceKey> router = new ThreadLocal();

    public static void setRouter(DataSourceKey key){
        router.set(key);
    }

    public static DataSourceKey get(){
        return router.get();
    }

    public static void clear(){
         router.remove();
    }

数据源标识:

public enum DataSourceKey {
    HEBEI_DATASOURCE,
    HUABEI_DATASOURCE
}

数据分析:

XML -> JSON 转换工具类:该工具核心部分来源自网络,感谢原作者。

第三方jar涉及到fastjson与DOM4J

   private Logger logger = LoggerFactory.getLogger(this.getClass());

    public Document parseStringToXMlObject(String xmlContent) throws DocumentException {
        return DocumentHelper.parseText(xmlContent);
    }

    public JSONObject xmltoJson(String xml) throws DocumentException {
        JSONObject jsonObject = new JSONObject();
        Document document = this.parseStringToXMlObject(xml);
        //获取根节点元素对象
        Element root = document.getRootElement();
        iterateNodes(root, jsonObject);
        return jsonObject;
    }

    private void iterateNodes(Element node,JSONObject json){
        //获取当前元素的名称
        String nodeName = node.getName();
        //判断已遍历的JSON中是否已经有了该元素的名称
        if(json.containsKey(nodeName)){
            //该元素在同级下有多个
            Object Object = json.get(nodeName);
            JSONArray array = null;
            if(Object instanceof JSONArray){
                array = (JSONArray) Object;
            }else {
                array = new JSONArray();
                array.add(Object);
            }
            //获取该元素下所有子元素
            List<Element> listElement = node.elements();
            if(listElement.isEmpty()){
                //该元素无子元素,获取元素的值
                String nodeValue = node.getTextTrim();
                array.add(nodeValue);
                json.put(nodeName, array);
                return ;
            }
            //有子元素
            JSONObject newJson = new JSONObject();
            //遍历所有子元素
            for(Element e:listElement){
                //递归
                iterateNodes(e,newJson);
            }
            array.add(newJson);
            json.put(nodeName, array);
            return ;
        }
        //该元素同级下第一次遍历
        //获取该元素下所有子元素
        List<Element> listElement = node.elements();
        if(listElement.isEmpty()){
            //该元素无子元素,获取元素的值
            String nodeValue = node.getTextTrim();
            json.put(nodeName, nodeValue);
            return ;
        }
        //有子节点,新建一个JSONObject来存储该节点下子节点的值
        JSONObject object = new JSONObject();
        //遍历所有一级子节点
        for(Element e:listElement){
            //递归
            iterateNodes(e,object);
        }
        json.put(nodeName, object);
        return ;
    }

实体映射处理

JSONAnalyzer

abtract class JSONAnalyzarImpl

private Logger logger = LoggerFactory.getLogger(this.getClass());

    private FileOutputUtil fileOutputUtil = new FileOutputUtil("jsonAnalyzerErr.log");

    protected JSONObject jsonObject;

    public JSONAnalyzerImpl(SourceMessageWrapper sourceMessageWrapper){
        super(sourceMessageWrapper);
        this.jsonObject = sourceMessageWrapper.getJsonObject();
    }

    public JSONAnalyzerImpl(){}

    //获取特定节点数据,该数据可能为JSONArray也可能为JSONObject,统一转化为JSONArray
    protected JSONArray getJsonArrayByKey(String key){
        SourceMessageWrapper mw = this.sourceMessageWrapper;
        JSONObject jsonObject = mw.getJsonObject();
        String[] prefixs = MappingConstant.SAP_SOURCE_MESSAGE_PREFIX.split("\\.");
        for(String prefix : prefixs){
            jsonObject = (JSONObject)jsonObject.get(prefix);
        }
        JSON json = (JSON) jsonObject.get(key);
        if(json instanceof JSONObject){
            List list = new LinkedList();
            list.add(json);
            JSONArray array = new JSONArray(list);
            return array;
        }

        return (JSONArray) json;
    }
    //使用反射处理字段映射,此处字段名与JSON节点名内容一致,大小写不同
    protected List<Object> analy(String nodeName,Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        JSONArray array = getJsonArrayByKey(nodeName);

        if (array == null || array.size() == 0) {
            throw this.throwException();
        }
        List<Object> objectList = new LinkedList<>();
        Iterator itr = array.iterator();
        while (itr.hasNext()) {
            JSONObject jsonObject = new JSONObject((Map<String, Object>) itr.next());

            Object obj = clazz.getDeclaredConstructor().newInstance();

            Field[] fields = clazz.getDeclaredFields();

            for (Field field : fields) {
                field.setAccessible(true);

                try {
                    if(BigDecimal.class.getName().equals(field.getType().getName())){
                        field.set(obj,new BigDecimal(jsonObject.getString(field.getName().toUpperCase())));
                        continue;
                    }

                    if(Timestamp.class.getName().equals(field.getType().getName())){
                        String t = jsonObject.getString(jsonObject.getString(field.getName().toUpperCase()));
                        if("0000-00-00".equals(t)){
                            t = "1970-01-01 00:00:00";
                        }
                        field.set(obj,Timestamp.valueOf(t));
                        continue;
                    }

                    if(Date.class.getName().equals(field.getType().getName())){
                        String t = jsonObject.getString(jsonObject.getString(field.getName().toUpperCase()));
                        if("0000-00-00".equals(t)){
                            t = "1970-01-01";
                        }
                        field.set(obj,Date.valueOf(t));
                        continue;
                    }

                    if(Integer.class.getName().equals(field.getType().getName())){
                        String content = (String)jsonObject.get(field.getName());
                        if(content != null) {
                            field.set(obj, Integer.valueOf(content));
                        }
                        continue;
                    }

                    field.set(obj, jsonObject.get(field.getName().toUpperCase()));
                } catch (IllegalAccessException e) {
                    // e.printStackTrace();
                    logger.error("while["+field.getName()+"] value setting process throws Exception,value should be"+jsonObject.get(field.getName())+"\nerror message => "+e.getMessage());
                    logger.error("now start persistence");
                    try{
                        fileOutputUtil.fileOutput((String) jsonObject.get(field.getName()),array.toString());
                    }catch(Exception e1){
                        logger.error("persist failed");
                    }
                }

                field.setAccessible(false);
            }

            objectList.add(obj);

        }

        return objectList;
    }

    //此处为模板方法,子类实现后抛出特定异常
    protected abstract SourceMessagePartInfoNullException throwException();

 class ZssdhAnalyzer (另外两中实体分析转换类同下)

public class ZssdhAnalyzerJSONImpl extends JSONAnalyzerImpl {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public ZssdhAnalyzerJSONImpl(SourceMessageWrapper sourceMessageWrapper) {
        super(sourceMessageWrapper);
    }

    @Override
    protected SourceMessagePartInfoNullException throwException() {
        throw new ZssdhInfoNullException();
    }
    //转换返回值范型类型
    public List<Zssdh> analy() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        List<Object> sapZssdh = super.analy("SapZssdh", Zssdh.class);
        List<Zssdh> zssdhList = new LinkedList<>();
        for(Object object : sapZssdh){
            zssdhList.add((Zssdh)object);
        }
        return zssdhList;
    }

}

消息接收与进一步的生产消费

JMS的消息接收,自定义接收类,继承MessageListenerAdapter夫类,

重写void onMessage(Message message,@Notnull Session session) 方法


@Component
public class SourceMessageRecevierImpl extends MessageListenerAdapter implements ISourceMessageReceiver{

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private AtomicInteger counter = new AtomicInteger(0);

    @Autowired
    private MessageManager messageManager;

    @Autowired
    private XMLUtil xmlUtil;

    @Override
    @JmsListener(destination = "×××××××××××")
    public void onMessage(Message message, @NotNull Session session) throws JMSException{
        logger.info("accept message " + counter.incrementAndGet());

        JMSBytesMessage sourceMessage = (JMSBytesMessage) message;

        byte[] container = new byte[(int) sourceMessage.getBodyLength()];
        sourceMessage.readBytes(container);
        String messageBody = new String(container);

        SourceMessageWrapper mw = null;
        boolean flag = false;
        try {
            JSONObject object = xmlUtil.xmltoJson(messageBody);
            mw = new SourceMessageWrapper(MappingConstant.JSON_TYPE_MESSAGE,object);
        } catch (Exception e) {
            logger.error("error : {} , {}",e.getMessage(),e.getStackTrace());
            logger.error("XML -> JSON process failed , trying attempt to process XML");
            flag = !flag;
        }

        if(flag){
            try {
                //Document document = xmlUtil.parseStringToXMlObject(messageBody);
                //mw = new SourceMessageWrapper(MappingConstant.XML_TYPE_MESSAGE,document);

                throw new DocumentException("xml producer developing");
            } catch (DocumentException e) {
                logger.error("parsing XML process failed , persist source message");
                flag = !flag;
            }

            if(flag){
                //process strategy failed : persist sourceMessage
                logger.error("--------persist message--------");
                logger.error("message body => \n" + messageBody + "\n");
                logger.error("--------persist finished-------");

                return ;
            }
        }

        messageManager.addMessage(mw);
    }

}

注:因赶项目进度JSON处理失败的XML适配并没有完成,后续进行完善

消息载体 SourceMessageWrapper

public class SourceMessageWrapper {

    private String type;

    private JSONObject jsonObject;

    private Document xmlObject;

}

MessageManager 该管理器持有消息的阻塞队列,长度规定为200

onMessage包装出的消息将添加进阻塞队列,规定消费线程进行消费

@Component
public class MessageManager {

    public MessageManager(){}

    private BlockingQueue<SourceMessageWrapper> queue = new LinkedBlockingQueue<>(200);

    public void addMessage(SourceMessageWrapper message){
        queue.add(message);
    }

    public SourceMessageWrapper getMessage() throws InterruptedException {
        return this.queue.take();
    }

}

消费线程进行消费,若获取不到消息则进行阻塞,当队列添加消息时会队列会唤醒线程

线程任务为内部类

public class MessageConsumerHolder implements InitializingBean {

    private ExecutorService executorService = null;

    @Autowired
    private MessageManager messageManager;

    @Autowired
    private DBPersistHandler dbPersistHandler;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public MessageConsumerHolder(){
        executorService = new ThreadPoolExecutor(MappingConstant.CORE_THREAD_SIZE,MappingConstant.MAX_THREAD_SIZE,100, TimeUnit.MILLISECONDS,new SynchronousQueue<>(true));
    }

    public void init(){
        for(int i = 0 ; i < MappingConstant.MAX_THREAD_SIZE ; ++i){
            executorService.submit(new MessageConsumer(messageManager));
        }
    }
    
    //根据配置进行消费者线程池任务的初始化
    @Override
    public void afterPropertiesSet() throws Exception {
        init();
    }

    private class MessageConsumer implements Runnable {
        private MessageManager messageManager;

        private Logger logger = LoggerFactory.getLogger(this.getClass());

        MessageConsumer(MessageManager messageManager){
            this.messageManager = messageManager;
        }

        @Override
        public void run() {
            while(true){
                SourceMessageWrapper mw = null;
                try {
                    mw = messageManager.getMessage();
                } catch (InterruptedException e) {
                    logger.error("interruptedException {} \n {}",e.getMessage(),e.getStackTrace());
                    continue;
                }catch(Exception e){
                    logger.error("msg" + e.getMessage());
                }
                try {
                    dbPersistHandler.handle(mw);
                } catch (Exception e){
                    logger.error(e.getMessage());
                }
            }
        }
    }
}

MQ配置(IBM-MQ、RabbitMQ)


@Configuration
public class HebeiIBMMQConnectorConfigurer {

    @Value("${hb.ibm.mq.host}")
    private String host;
    @Value("${hb.ibm.mq.port}")
    private Integer port;
    @Value("${hb.ibm.mq.queue-manager}")
    private String queueManager;
    @Value("${hb.ibm.mq.channel}")
    private String channel;
    @Value("${hb.ibm.mq.username}")
    private String username;
    @Value("${hb.ibm.mq.password}")
    private String password;
    @Value("${hb.ibm.mq.receive-timeout}")
    private long receiveTimeout;

    @Bean
    public MQQueueConnectionFactory mqQueueConnectionFactory() {
        MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
        mqQueueConnectionFactory.setHostName(host);
        try {
            mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
            mqQueueConnectionFactory.setCCSID(1208);
            mqQueueConnectionFactory.setChannel(channel);
            mqQueueConnectionFactory.setPort(port);
            mqQueueConnectionFactory.setQueueManager(queueManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mqQueueConnectionFactory;
    }

    @Bean
    UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter(MQQueueConnectionFactory mqQueueConnectionFactory) {
        UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter = new UserCredentialsConnectionFactoryAdapter();
        userCredentialsConnectionFactoryAdapter.setUsername(username);
        userCredentialsConnectionFactoryAdapter.setPassword(password);
        userCredentialsConnectionFactoryAdapter.setTargetConnectionFactory(mqQueueConnectionFactory);
        return userCredentialsConnectionFactoryAdapter;
    }

    @Bean
    @Primary
    public CachingConnectionFactory cachingConnectionFactory(UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter) {
        CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
        cachingConnectionFactory.setTargetConnectionFactory(userCredentialsConnectionFactoryAdapter);
        cachingConnectionFactory.setSessionCacheSize(500);
        cachingConnectionFactory.setReconnectOnException(true);
        return cachingConnectionFactory;
    }

    @Bean
    public PlatformTransactionManager jmsTransactionManager(CachingConnectionFactory cachingConnectionFactory) {
        JmsTransactionManager jmsTransactionManager = new JmsTransactionManager();
        jmsTransactionManager.setConnectionFactory(cachingConnectionFactory);
        return jmsTransactionManager;
    }

    @Bean
    public JmsOperations jmsOperations(CachingConnectionFactory cachingConnectionFactory) {
        JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
        jmsTemplate.setReceiveTimeout(receiveTimeout);
        return jmsTemplate;
    }
}

RabbitMQ

@Configuration
public class LogwsdHuabeiRabbitMQConfigurer {

    @Value("${spring.rabbitmq.huabei.host}")
    private String host;

    @Value("${spring.rabbitmq.huabei.port}")
    private int port;

    @Value("${spring.rabbitmq.huabei.username}")
    private String username;

    @Value("${spring.rabbitmq.huabei.password}")
    private String password;

    public static final String EXCHANGE_A = "my-mq-exchange_A";

    public static final String QUEUE_A = "QUEUE_A";

    public static final String ROUTINGKEY_A = "spring-boot-routingKey_A";

    @Bean("huabeiMQConnectionFactory")
    public ConnectionFactory huabeiMQConnectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host,port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setPublisherConfirms(true);
        return connectionFactory;
    }

    @Bean("huabeiRabbitTemplate")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    //必须是prototype类型
    public RabbitTemplate huabeiRabbitTemplate(@Qualifier("huabeiMQConnectionFactory") ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        return template;
    }

    @Bean("huabeiMQdefaultExchange")
    public DirectExchange defaultExchange() {
        return new DirectExchange(EXCHANGE_A);
    }

    @Bean("huabeiMQqueueA")
    public Queue queueA() {
        //队列持久
        return new Queue(QUEUE_A, true);
    }

    @Bean("huabeiMQbinding")
    public Binding binding(@Qualifier("huabeiMQdefaultExchange") DirectExchange defaultExchange ,@Qualifier("huabeiMQqueueA") Queue queueA) {
        return BindingBuilder.bind(queueA).to(defaultExchange).with(ROUTINGKEY_A);
    }

}

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值