SpringBoot集成mqtt的多模块项目配置

前言

近期为了准备毕设,准备使用SpringBoot搭建mqtt后端,本篇主要记录了在IDEA中搭建SpringBoot mqtt的多模块项目的过程

开发工具及系统环境

  • IDE:IntelliJ IDEA 2020.2
  • 操作系统:Windows 10 2004
  • Java Version:1.8
  • SpringBoot Version:2.1.17.RELEASE

项目路径

Study
    |----study-common        # 存放公共类
    |----study-mapper        # mapper层
    |----study-mqtt          # mqtt相关配置文件及接口
    |----study-service       # service层
    |----study-serviceimpl   # service的实现类
    |----study-web           # web层 
	|----pom.xml

配置过程

1. 搭建父项目

  1. 在IDEA中新建一个SpringBoot工程
    在这里插入图片描述

    这里我使用了阿里云的启动服务,正常使用可以直接用原本的启动服务

  2. 根据你的需求选择Java版本,初始化类型并配置groupID和artifactId,我这里配置成我的域名的反写,并将artifactId定义成Study。配置完成后单击Next

在这里插入图片描述

  1. 这一步选择你需求的SpringBoot版本,我这里选择的是2.1.17.RELEASE,然后单击NEXT。在这一步中不需要勾选任何依赖。

在这里插入图片描述

  1. 选择保存的路径,点击Finish完成创建。

在这里插入图片描述

  1. 删除不需要的文件。将目录下的src/,HELP.md,mvnw,mvnw.cmd等文件全部删除(不包括.gitigore

在这里插入图片描述

至此,父项目一级已经创建完成,最后项目目录如下:

在这里插入图片描述

2. 搭建子项目

  1. 右键项目根目录->新建->新模块

在这里插入图片描述

  1. 选择Maven,单击Next

在这里插入图片描述

  1. 配置父项,项目名称以及构建坐标,完成后单击Finish。这里以study-common模块为例

在这里插入图片描述

  1. 以此类推创建整个项目,项目目录如图所示

在这里插入图片描述

至此,我们搭建完所有的子项目,接下来开始配置各个项目的pom文件

3. 配置各个模块

1. 配置父项目
  • 配置父项目的pom.xml文件

    父项目的pom.xml主要是对子项目的引用起到一个约束作用,固在父项目的pom.xml需要使用dependencyManagement这一项来约束子项目中各个依赖的版本。在父项目中可以引用子项目都用得到的引用。父项目的pom.xml文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.itbu</groupId>
        <artifactId>study</artifactId>
        <packaging>pom</packaging>
        <version>1.0.0</version>
        <modules>
            <module>study-common</module>
            <module>study-service</module>
            <module>study-serviceimpl</module>
            <module>study-web</module>
            <module>study-mapper</module>
            <module>study-mqtt</module>
        </modules>
        <name>study</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <artifactId>spring-boot-starter-parent</artifactId>
            <groupId>org.springframework.boot</groupId>
            <version>2.1.17.RELEASE</version>
            <relativePath/>
        </parent>
    
        <properties>
            <java.version>1.8</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <spring-boot.version>2.1.17.RELEASE</spring-boot.version>
            <mybatis.boot.starter.version>2.1.4</mybatis.boot.starter.version>
            <mysql.connector.java.version>8.0.22</mysql.connector.java.version>
            <druid.version>1.2.0</druid.version>
            <integration.version>2.3.7.RELEASE</integration.version>
            <stream.integration.version>5.4.2</stream.integration.version>
            <mqtt.integration.version>5.4.2</mqtt.integration.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>${mybatis.boot.starter.version}</version>
                </dependency>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>${mysql.connector.java.version}</version>
                </dependency>
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                    <version>${druid.version}</version>
                </dependency>
    
    
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>2.1.17.RELEASE</version>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
2. 配置common模块
  • 配置pom.xml文件

    common模块主要包括一些通用的类和接口,固这里只需要配置下parent这一项指向父项目即可,common模块的pom.xml配置文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>study</artifactId>
            <groupId>com.itbu</groupId>
            <version>1.0.0</version>
        </parent>
        <groupId>com.itbu.study</groupId>
        <artifactId>common</artifactId>
        <version>1.0.0</version>
        <modelVersion>4.0.0</modelVersion>
        <packaging>jar</packaging>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
  • 创建所需要的类和接口

    配置完pom.xml后,就可以在目录下创建所需要的类以及接口。在本项目中我分别创建了作为pojo类的UserBean和作为json返回结果的JsonResult类作为通用类,项目结构如下:

    study-common
    	|----pom.xml
    	|----src
    		|----test
    		|----main
    			|----resources
    			|----java
    				|----com.itbu.study.common
    					|----bean
    						|----UserBean.java
    					|----result
    						|----JsonResult.java
    

    UserBean.java文件

    package com.itbu.study.common.bean;
    
    public class UserBean {
        private int id;
        private String username;
        private String password;
    
        public int getId() {
            return id;
        }
    
        public String getPassword() {
            return password;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public UserBean(){
    
        }
    
        public UserBean(String username, String password){
            this.username = username;
            this.password = password;
        }
    }
    

    JsonResult.java文件

    package com.itbu.study.common.result;
    
    public class JsonResult<T> {
        private int code;
        private String msg;
        private T data;
    
        public JsonResult(int Code,String msg){
            this.code = Code;
            this.msg = msg;
        }
    
        public JsonResult(T data) {
            this.data = data;
            this.code = 0;
            this.msg = "操作成功!";
        }
    
        public JsonResult(T data, String msg) {
            this.data = data;
            this.code = 0;
            this.msg = msg;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public int getCode() {
            return code;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    }
    
3. 配置mapper模块

mapper模块对应的是mapper层,也就是我们常说的DAO层,用于与数据库进行通信,读写操作。这里我们用的持久层框架是Mybatis,连接的数据库是mysql数据库。同时需要common模块中的各个pojo类,这里需要引入各个引用。操作步骤如下:

  • 配置pom.xml文件

    这里我们需要引入mybatis,druid和mysql支持,固配置文件编写如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.itbu.study</groupId>
        <artifactId>mapper</artifactId>
        <version>1.0.0</version>
        <name>mapper</name>
        <description>Demo project for Spring Boot</description>
        <packaging>jar</packaging>
    
        <parent>
            <artifactId>study</artifactId>
            <groupId>com.itbu</groupId>
            <version>1.0.0</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
    
        <properties>
            <java.version>1.8</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <spring-boot.version>2.1.17.RELEASE</spring-boot.version>
        </properties>
    
        <dependencies>
            <!-- 内部引用 -->
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>common</artifactId>
                <version>1.0.0</version>
            </dependency>
    
            <!-- 外部引用 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
  • 编写接口和映射文件

    和不分模块的操作一样,在resource文件夹下创建mapper目录,并编写用于映射的xml文件。同时创建对应的接口,本项目工程目录大致如下:

    study-mapper
    	|----pom.xml
    	|----src
    		|----test
    		|----main
    			|----java
    				|----com.itbu.study.mapper
    					|----UserMapper.java
    			|----resources
    				|----mapper
    					|----UserMapper.xml
    

    UserMapper.java文件

    package com.itbu.study.mapper;
    import com.itbu.study.common.bean.UserBean;
    import java.util.List;
    public interface UserMapper {
        List<UserBean> getAll();
    }
    

    UserMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.itbu.study.mapper.UserMapper">
        <select id="getAll" resultType="com.itbu.study.common.bean.UserBean">
            select * from mqtt.user_table
        </select>
    </mapper>
    
4. 配置service模块

service模块也就是service层,主要是一些服务接口方便给controller层调用。步骤如下:

  • 配置pom.xml文件

    service层需要用到common模块中的pojo类,这里需要对该模块添加依赖项

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>study</artifactId>
            <groupId>com.itbu</groupId>
            <version>1.0.0</version>
            <relativePath>../pom.xml</relativePath>
        </parent>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.itbu.study</groupId>
        <artifactId>service</artifactId>
        <version>1.0.0</version>
        <packaging>jar</packaging>
        <name>service</name>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>common</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
  • 编写service各个接口

    这里接口与mapper层类似,就不一一赘述,这里直接放代码

    UserService.java

    package com.itbu.study.service;
    
    import com.itbu.study.common.bean.UserBean;
    
    import java.util.List;
    
    public interface UserService {
        List<UserBean> getAll();
    }
    
    
5. 配置serviceimpl模块

serviceimpl即service接口的各个实现类,实现步骤如下:

  • 配置pom.xml文件

    serviceimpl需要mapper层的支持,需要实现service层的各个接口,也需要引用到common模块中的pojo类,我们直接加上这三项的依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.itbu.study</groupId>
        <artifactId>serviceimpl</artifactId>
        <version>1.0.0</version>
        <name>serviceimpl</name>
        <description>Demo project for Spring Boot</description>
        <packaging>jar</packaging>
        <parent>
            <artifactId>study</artifactId>
            <groupId>com.itbu</groupId>
            <version>1.0.0</version>
        </parent>
    
        <properties>
            <java.version>1.8</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <spring-boot.version>2.1.17.RELEASE</spring-boot.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>common</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>service</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>mapper</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
  • 根据service各个接口编写实现类

    UserServiceimpl.java 注意在实现类上要加上@Service标注以用于SpringBoot框架识别

    package com.itbu.study.serviceimpl;
    
    import com.itbu.study.common.bean.UserBean;
    import com.itbu.study.mapper.UserMapper;
    import com.itbu.study.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public List<UserBean> getAll() {
            return userMapper.getAll();
        }
    }
    
6. 配置web模块

接下来就到了核心部分,也就是与不分模块配置差异较大的部分。Web层需要配置启动类以及配置文件,内容较多,配置步骤如下:

  • 配置pom.xml文件

    Web层将直接引用Service层的各个接口,Common模块的各个类,这里我们直接加上依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.itbu.study</groupId>
        <artifactId>serviceimpl</artifactId>
        <version>1.0.0</version>
        <name>serviceimpl</name>
        <description>Demo project for Spring Boot</description>
        <packaging>jar</packaging>
        <parent>
            <artifactId>study</artifactId>
            <groupId>com.itbu</groupId>
            <version>1.0.0</version>
        </parent>
    
        <properties>
            <java.version>1.8</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <spring-boot.version>2.1.17.RELEASE</spring-boot.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>common</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>service</artifactId>
                <version>1.0.0</version>
            </dependency>
            <dependency>
                <groupId>com.itbu.study</groupId>
                <artifactId>mapper</artifactId>
                <version>1.0.0</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
    
  • 编写各个Controller以及配置文件

    先根据以下的项目结构创建对应的文件,项目结构如下:

    study-web
    	|----pom.xml
    	|----src
    		|----test
    			|----java
    				|----com.itbu.study.web
    					|----WebApplicationTests.java  #测试类
    		|----main
    			|----java
    				|----com.itbu.study.web
    					|----WebApplication.java
    					|----controller
    						|----ApiController.java
             	|----resources
             		|----config
             			|----application.yml
             			|----application-dev.yml
    

    编写启动类,记得加上MapperScan

    WebApplication.java

    package com.itbu.study.web;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    @SpringBootApplication(scanBasePackages = {"com.itbu.study.*"})
    @MapperScan("com.itbu.study.mapper")
    public class WebApplication {
        public static void main(String[] args) {
            SpringApplication.run(WebApplication.class, args);
        }
    }
    

    编写Controller层

    ApiController.java

    package com.itbu.study.web.controller;
    
    import com.itbu.study.common.bean.UserBean;
    import com.itbu.study.common.result.JsonResult;
    import com.itbu.study.service.UserService;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.xml.ws.RequestWrapper;
    import java.util.List;
    
    @RestController
    @RequestMapping("/api")
    public class ApiController {
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
        public ApiController(UserService userService){
            this.userService = userService;
        }
        private final UserService userService;
        @RequestMapping("/index")
        public List<UserBean> index(){
            return userService.getAll();
        }
    }
    

    在配置文件中设置数据源和mapper映射文件以及监听端口

    application-dev.xml

    server:
      port: 10000
    mybatis:
      mapper-locations: classpath*:mapper/*.xml  #注意此处与未分模块的区别
    spring:
      datasource:
        username: root
        password: 123456
        url: jdbc:mysql://192.168.28.88:10090/mqtt?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
        driver-class-name: com.mysql.cj.jdbc.Driver
    
7. 测试

至此,我们以及配置完了一个多模块的MQTT后端基本项目,接下来进行简单测试

运行项目并在浏览器中输入http://localhost:10000/api/index, 返回以下结果表明测试成功

在这里插入图片描述

4. 配置MQTT模块

前面我们完成了SpringBoot基础项目的配置,接下来我们将mqtt也做成模块,步骤如下:

  • 配置pom.xml文件

    我们集成mqtt功能主要使用了spring-integration-mqtt这个jar包,所以我们在pom中添加对这个包的依赖,pom.xml文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>study</artifactId>
            <groupId>com.itbu</groupId>
            <version>1.0.0</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.itbu.study</groupId>
        <artifactId>mqtt</artifactId>
        <packaging>jar</packaging>
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-integration</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-stream</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-mqtt</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    
    </project>
    
  • 在study-web的配置文件中添加如下配置:

    mqtt:
      enabled: true
      username: root
      password: 123456
      url: tcp://192.168.28.88:15005
      producer:
        clientId: server
        defaultTopic: default
      consumer:
        clientId: client
        defaultTopic: default
    
  • 编写MQTT各个配置类以及方法

    项目结构如下:

    study-mqtt
    	|----pom.xml
    	|----src
    		|----test
    		|----main
    			|----resources
    			|----java
    				|----com.itbu.study.mqtt
    					|----MqttBaseConfig.java
    					|----MqttInConfig.java
    					|----MqttOutConfig.java
    					|----MqttMessageReceiver.java
    					|----MqttMessageSender.java
    

    MqttBaseConfig.java

    package com.itbu.study.mqtt;
    
    import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
    import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
    
    @Configuration
    @ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
    public class MqttBaseConfig {
        @Value("${mqtt.url:#{null}}")
        private String[] url;
    
        @Value("${mqtt.username:}")
        private String username;
    
        @Value("${mqtt.password:}")
        private String password;
    
        @Bean
        public MqttPahoClientFactory factory(){
            DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
            MqttConnectOptions options = new MqttConnectOptions();
            if(username != null)
                options.setUserName(username);
            if(password != null)
                options.setPassword(password.toCharArray());
            options.setServerURIs(url);
            factory.setConnectionOptions(options);
            return factory;
        }
    }
    

    MqttInConfig.java

    package com.itbu.study.mqtt;
    
    import com.itbu.study.mqtt.MqttMessageReceiver;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.integration.annotation.ServiceActivator;
    import org.springframework.integration.channel.DirectChannel;
    import org.springframework.integration.core.MessageProducer;
    import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
    import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
    import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.MessageHandler;
    
    @Configuration
    @ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
    public class MqttInConfig {
    
        private final MqttMessageReceiver mqttMessageReceiver;
    
        public MqttInConfig(MqttMessageReceiver mqttMessageReceiver){
            this.mqttMessageReceiver = mqttMessageReceiver;
        }
    
        @Value("${mqtt.producer.clientId:")
        private String clientId;
    
        @Value("${mqtt.producer.defaultTopic}")
        private String topic;
    
        @Bean
        public MessageChannel mqttInputChannel(){
            return new DirectChannel();
        }
    
        @Bean
        public MessageProducer channelInbound(MessageChannel mqttInputChannel, MqttPahoClientFactory factory){
            MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, factory, topic);
            adapter.setCompletionTimeout(5000);
            adapter.setConverter(new DefaultPahoMessageConverter());
            adapter.setQos(2);
            adapter.setOutputChannel(mqttInputChannel);
            return adapter;
        }
    
        @Bean
        @ServiceActivator(inputChannel = "mqttInputChannel")
        public MessageHandler mqttMessageHandler(){
            return this.mqttMessageReceiver;
        }
    }
    
    

    MqttOutConfig.java

    package com.itbu.study.mqtt;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.integration.annotation.ServiceActivator;
    import org.springframework.integration.channel.DirectChannel;
    import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
    import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.MessageHandler;
    
    @Configuration
    @ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
    public class MqttOutConfig {
        @Value("${mqtt.consumer.clientId:}")
        private String clientId;
    
        @Value("${mqtt.consumer.defaultTopic}")
        private String topic;
    
        @Bean
        public MessageChannel mqttOutputChannel(){
            return new DirectChannel();
        }
    
        @Bean
        @ServiceActivator(inputChannel = "mqttOutputChannel")
        public MessageHandler mqttOutBound(MqttPahoClientFactory factory){
            MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, factory);
            messageHandler.setAsync(true);
            messageHandler.setDefaultQos(2);
            messageHandler.setDefaultTopic(topic);
            return messageHandler;
        }
    }
    

    MqttMessageReceiver.java

    package com.itbu.study.mqtt;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.integration.mqtt.support.MqttHeaders;
    import org.springframework.messaging.Message;
    import org.springframework.messaging.MessageHandler;
    import org.springframework.messaging.MessagingException;
    import org.springframework.stereotype.Component;
    
    @Component
    @ConditionalOnProperty(value = "mqtt.enabled",havingValue = "true")
    public class MqttMessageReceiver implements MessageHandler {
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @Override
        public void handleMessage(Message<?> message) throws MessagingException {
            String topic = String.valueOf(message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
            String payload = String.valueOf(message.getPayload());
            logger.info("接收到 mqtt消息, 主题:{} 消息:{}", topic, payload);
        }
    }
    
    

    MqttMessageSender.java

    package com.itbu.study.mqtt;
    
    import org.springframework.integration.annotation.MessagingGateway;
    import org.springframework.integration.mqtt.support.MqttHeaders;
    import org.springframework.messaging.handler.annotation.Header;
    import org.springframework.stereotype.Component;
    
    @MessagingGateway(defaultRequestChannel = "mqttOutputChannel")
    @Component
    public interface MqttMessageSender {
        void sendToMqtt(String data);
        void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);
        void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
    }
    
    
  • 在启动类中添加@IntegrationComponentScan注解

    package com.itbu.study.web;
    
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.integration.annotation.IntegrationComponentScan;
    
    @SpringBootApplication(scanBasePackages = {"com.itbu.study.*","com.itbu.study.mqtt"})
    @MapperScan("com.itbu.study.mapper")
    @IntegrationComponentScan(basePackages = "com.itbu.study.mqtt") //这里添加,不然无法自动注入
    public class WebApplication {
        public static void main(String[] args) {
            SpringApplication.run(WebApplication.class, args);
        }
    }
    
    
  • 编写对应Controller,我这里直接在ApiController上修改了

    package com.itbu.study.web.controller;
    
    import com.itbu.study.common.bean.UserBean;
    import com.itbu.study.common.result.JsonResult;
    import com.itbu.study.mqtt.MqttMessageSender;
    import com.itbu.study.service.UserService;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.xml.ws.RequestWrapper;
    import java.util.List;
    
    @RestController
    @RequestMapping("/api")
    public class ApiController {
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        private final MqttMessageSender mqttMessageSender;
    
        public ApiController(MqttMessageSender mqttMessageSender, UserService userService){
            this.mqttMessageSender = mqttMessageSender;
            this.userService = userService;
        }
    
        private final UserService userService;
    
        @RequestMapping("/index")
        public List<UserBean> index(){
            return userService.getAll();
        }
    
        @RequestMapping("/mqtt")
        public JsonResult<?> mqtt_sender(@RequestParam("msg")String msg){
            logger.info("Send mqtt msg: {}", msg);
            mqttMessageSender.sendToMqtt(msg);
            logger.info("Send successfully!");
            return new JsonResult<>(0,"Send Successfully");
        }
    
    }
    
    
  • 测试

    首先我们运行后端项目,可以看到日志打出以下输出,说明后端项目正常启动

在这里插入图片描述

然后我们使用mqtt.fx这个软件往订阅主题default发送helloworld

在这里插入图片描述

发现日志打印如下信息,表面输入通道正常:

在这里插入图片描述

然后我们在浏览器中输入http://localhost:10000/api/mqtt?msg=1234556 并按下回车,浏览器显示如下:

在这里插入图片描述

可以看到日志中打印了如下内容:

在这里插入图片描述

因为我们订阅的主题也是default,所以也收到了生产者发送的信息,我们打开mqtt.fx, 订阅default主题,可以收到如下信息:

在这里插入图片描述

测试成功

最后放上工程的源码:GitHub

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值