• 用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字符串。

         

         

  • 相关阅读:
    JSP页面
    JSP简介
    常量与变量的声明与使用
    AJAX无刷新上传图片
    JSP连接MySql数据库
    运算符与表达式
    世界级的javascript ajax client端UI库 Ext学习笔记 menu组件 和 toolbar组件
    OOD/OOA基本原则
    Java字符编码转换过程说明
    正则表达式系统教程
  • 原文地址:https://www.cnblogs.com/BestWishesZJ/p/10678855.html
Copyright © 2020-2023  润新知