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. 搭建父項目

在IDEA中新建一個SpringBoot工程

在這裡插入圖片描述

這裡我使用瞭阿裡雲的啟動服務,正常使用可以直接用原本的啟動服務

根據你的需求選擇Java版本,初始化類型並配置groupID和artifactId,我這裡配置成我的域名的反寫,並將artifactId定義成Study。配置完成後單擊Next

在這裡插入圖片描述

這一步選擇你需求的SpringBoot版本,我這裡選擇的是2.1.17.RELEASE,然後單擊NEXT。在這一步中不需要勾選任何依賴。

在這裡插入圖片描述

選擇保存的路徑,點擊Finish完成創建。

在這裡插入圖片描述

刪除不需要的文件。將目錄下的src/,HELP.md,mvnw,mvnw.cmd等文件全部刪除(不包括.gitigore

在這裡插入圖片描述

至此,父項目一級已經創建完成,最後項目目錄如下:

在這裡插入圖片描述

2. 搭建子項目

右鍵項目根目錄->新建->新模塊

在這裡插入圖片描述

選擇Maven,單擊Next

在這裡插入圖片描述

配置父項,項目名稱以及構建坐標,完成後單擊Finish。這裡以study-common模塊為例

在這裡插入圖片描述

以此類推創建整個項目,項目目錄如圖所示

在這裡插入圖片描述

至此,我們搭建完所有的子項目,接下來開始配置各個項目的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

到此這篇關於SpringBoot集成mqtt的多模塊項目配置詳解的文章就介紹到這瞭,更多相關SpringBoot mqtt多模塊內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!