用spring boot + redis + dubbo +rabbitmq + mybatis 搭建一个项目

  用spring boot + redis + dubbo +rabbitmq + mybatis 搭建一个项目。

 

  项目链接地址:

 

  1、创建项目,目录结构如下图。controller和server通过dubbo链接。在server中根据不同业务决定是否调用rabbitmq-publisher

    

  2、在主pom文件中加入常规所需要的依赖jar

    

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>
                <dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>23.3-jre</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.2</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>joda-time</groupId>
			<artifactId>joda-time</artifactId>
			<version>2.9.8</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.10</version>
		</dependency>

		<dependency>
			<groupId>com.rabbitmq</groupId>
			<artifactId>amqp-client</artifactId>
			<version>5.1.2</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba.boot</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<version>0.2.0</version>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>

		<!-- AOP -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>        

  3、配置依赖关系

    将rabbitmq-common配置成rabbitmq-consumer和rabbitmq-publisher依赖包

    将entity配置成controller和server依赖包

    将rabbitmq-publisher配置成server依赖包

       rabbitmq-consumer pom.xml

    

    rabbitmq-publisher pom.xml

    

    controller pom.xml

    

    server pom.xml文件

    

  4、配置application文件加载信息

    controller 下application.yml

    配置dubbo相关信息,端口,和数据库相关信息。

   

    server 下 application.yml

    配置dubbo,rabbitmq,端口,数据库 相关信息

   

    注:在配置dubbo 信息时候需要配置dubbo.scan.basePackages: 属性,指定需要扫面的包,本项目配置的是com.wan。否则在dubbo调用时会报找不到类,接口,或对应prodive服务。

      如下错误是没在application.yml时产生

    

   5、启动文件配置

    ControllerApplication.java

    

    由于在controller 项目userConsumer 中需要引用entity接口中 IUserServer 接口。所以需要在启动类中添加 scanBasePackages = "com.wan"。否则在install打包或者调用时会报找不到 IUserServer 类或接口

     ServerApplication.java 

    

    若不配置scanBasePackages=“com.wan" ,在server调用依赖包rabbitmq-publisher中对象时会报错。

     6、代码详解

      1.dubbo 消费者

      

      在调用dubbo服务时需要用注解@Reference 注解(alibaba包)。将其注入

      2. dubbo 提供者

      

      在提供dubbo服务时需要用@Service 注解(alibaba包)

      3. RabbitMQ 配置加载初始化

package com.wan.comm.common;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class RabbitMQConfig {

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

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

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

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

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

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

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

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

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

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

    /** 并发消费数量 */
    @Value("${spring.rabbitmq.concurrency}")
    private Integer consumeConcurrency;

    /** 队列超时时间 */
    @Value("${spring.rabbitmq.connection.timeout}")
    private Integer connectionTimeout;

    /** 设置线程核心线程数 **/
    @Value("${spring.rabbitmq.connection.min_threads}")
    private Integer connectionMinThreads;

    /** 设置线程最大线程数 **/
    @Value("${spring.rabbitmq.connection.max_threads}")
    private Integer connectionMaxThreads;

    /** 线程池所使用的缓冲队列 */
    @Value("${spring.rabbitmq.connection.max_queued}")
    private Integer connectionMaxQueued;

    @Value("${spring.rabbitmq.virtual-host}")
    private String virtualHost;

    /** 线程名称前缀 */
    private static final String CONNECTION_THREAD_PREFIX = "rabbitmq-connection-thread";

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    /**
     * rabbit 连接创建
     * @return
     */
    @Bean
    ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        connectionFactory.setConnectionTimeout(connectionTimeout);

        //线程池设置
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setThreadNamePrefix(CONNECTION_THREAD_PREFIX);
        executor.setCorePoolSize(connectionMinThreads);
        executor.setMaxPoolSize(connectionMaxThreads);
        executor.setQueueCapacity(connectionMaxQueued);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        connectionFactory.setExecutor(executor);
        return connectionFactory;
    }

    /**
     * 设置发送队列时的数据格式,默认编码为UTF-8
     * @return
     */
    @Bean
    MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 设置发送队列时的数据格式
     * @return
     */
    @Bean
    RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory,MessageConverter messageConverter) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(messageConverter);
        return rabbitTemplate;
    }

    /**
     * 工作交换器
     * @returns
     */
    @Bean
    DirectExchange workExchange(){
        return new DirectExchange(workExchange);
    }

    /**
     * 失败交换器
     * @return
     */
    @Bean
    DirectExchange errorExchange(){return new DirectExchange(errorExchange);}

    /**
     * 工作队列,默认正常情况下从该队列消费消息
     *
     * @return
     */
    @Bean
    Queue workQueue() {
        return QueueBuilder.durable(workQueueName).build();
    }

    /**
     * 失败队列,消息消费失败则入该队列
     *
     * @return
     */
    @Bean
    Queue errorQueue() {
        return QueueBuilder.durable(errorQueueName).build();
    }

    /**
     * 队列与交换器绑定
     * @param workQueue
     * @param workExchange
     * @return
     */
    @Bean
    Binding workQueuqBindingExchange(Queue workQueue,DirectExchange workExchange){
        return BindingBuilder.bind(workQueue).to(workExchange).with(workRoutingKey);
    }

    @Bean
    Binding errorQueuqBindingExchange(Queue errorQueue,DirectExchange errorExchange){
        return BindingBuilder.bind(errorQueue).to(errorExchange).with(errorRoutingKey);
    }

    @Bean
    MessageListenerContainer workMessageListenerContainer(ConnectionFactory connectionFactory, WorkRabbitMQConsumer workRabbitMQConsumer) {
        SimpleMessageListenerContainer messageListenerContainer = new SimpleMessageListenerContainer();
        messageListenerContainer.setConnectionFactory(connectionFactory);

        //设置队列名
        messageListenerContainer.setQueueNames(workQueueName);

        //设置监听类
        messageListenerContainer.setMessageListener(new MessageListenerAdapter(workRabbitMQConsumer));
        // 并发消费信息的数量
        messageListenerContainer.setConcurrentConsumers(consumeConcurrency);
        //设置ack
        messageListenerContainer.setAcknowledgeMode(AcknowledgeMode.MANUAL);

        //设置返回格式 在发送convertAndSend 中会将Obj转换成jsonString,默认编码为UTF-8
        //messageListenerContainer.setMessageConverter(new Jackson2JsonMessageConverter());
        return messageListenerContainer;
    }

}

    4.RabbitMQ 发送。

    

    若使用 rabbitTemplate.convertAndSend(routingKey,obj); 方法,在未指定交换器时,会根据传入的 routingKey 去匹配queueName 去查找队列。

    rabbitTemplate 在 RabbitMQConfig.java 初始化是已注入。并rabbitTemplate.setMessageConverter(messageConverter);设置了数据格式转换方式。如下

    

    Jackson2JsonMessageConverter 默认将数据转成jsonString 在封装成Message对象进行传输。具体代码如下:

    —— RabbitTemplate.class中send()

    

    —— AbstractMessageConverter.class 中 toMessage()

    

     找到createMessage(),进入初始化注入的 Jackson2JsonMessageConverter 中的实现

    

     ——  AbstractJackson2MessageConverter

    如下图,将我们传入的Object对象转换成jsonString ,并封装成Message对象。

    

     在RabbitMQ消费者取用时,只需直接从Message中获取

    String jsonString = new String(message.getBody(),"UTF-8");

    就能直接获取到json字符串。

     

     

 

posted on 2019-04-09 18:40  Best_Wishes  阅读(626)  评论(0编辑  收藏  举报

导航