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工程

SpringBoot集成mqtt的多模块项目配置详解_第1张图片

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

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

SpringBoot集成mqtt的多模块项目配置详解_第2张图片

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

SpringBoot集成mqtt的多模块项目配置详解_第3张图片

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

SpringBoot集成mqtt的多模块项目配置详解_第4张图片

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

SpringBoot集成mqtt的多模块项目配置详解_第5张图片

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

SpringBoot集成mqtt的多模块项目配置详解_第6张图片

2. 搭建子项目

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

SpringBoot集成mqtt的多模块项目配置详解_第7张图片

选择Maven,单击Next

SpringBoot集成mqtt的多模块项目配置详解_第8张图片

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

SpringBoot集成mqtt的多模块项目配置详解_第9张图片

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

SpringBoot集成mqtt的多模块项目配置详解_第10张图片

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

3. 配置各个模块

 1. 配置父项目

配置父项目的pom.xml文件

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



    4.0.0
    com.itbu
    study
    pom
    1.0.0
    
        study-common
        study-service
        study-serviceimpl
        study-web
        study-mapper
        study-mqtt
    
    study
    Demo project for Spring Boot

    
        spring-boot-starter-parent
        org.springframework.boot
        2.1.17.RELEASE
        
    

    
        1.8
        UTF-8
        UTF-8
        2.1.17.RELEASE
        2.1.4
        8.0.22
        1.2.0
        2.3.7.RELEASE
        5.4.2
        5.4.2
    

    
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-dependencies
                ${spring-boot.version}
                pom
                import
            
            
                org.mybatis.spring.boot
                mybatis-spring-boot-starter
                ${mybatis.boot.starter.version}
            
            
                mysql
                mysql-connector-java
                ${mysql.connector.java.version}
            
            
                com.alibaba
                druid
                ${druid.version}
            


        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                2.1.17.RELEASE
            
        
    


2. 配置common模块

配置pom.xml文件

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



    
        study
        com.itbu
        1.0.0
    
    com.itbu.study
    common
    1.0.0
    4.0.0
    jar
    
        1.8
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

创建所需要的类和接口

配置完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 {
    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支持,固配置文件编写如下:



    4.0.0
    com.itbu.study
    mapper
    1.0.0
    mapper
    Demo project for Spring Boot
    jar

    
        study
        com.itbu
        1.0.0
        ../pom.xml
    

    
        1.8
        UTF-8
        UTF-8
        2.1.17.RELEASE
    

    
        
        
            com.itbu.study
            common
            1.0.0
        

        
        
            com.alibaba
            druid
        

        
            mysql
            mysql-connector-java
        

        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

编写接口和映射文件

和不分模块的操作一样,在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 getAll();
}

UserMapper.xml




    

4. 配置service模块

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

配置pom.xml文件

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



    
        study
        com.itbu
        1.0.0
        ../pom.xml
    
    4.0.0
    com.itbu.study
    service
    1.0.0
    jar
    service

    
        1.8
    

    
        
            com.itbu.study
            common
            1.0.0
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

编写service各个接口

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

UserService.java

package com.itbu.study.service;

import com.itbu.study.common.bean.UserBean;

import java.util.List;

public interface UserService {
    List getAll();
}

5. 配置serviceimpl模块

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

配置pom.xml文件

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



    4.0.0
    com.itbu.study
    serviceimpl
    1.0.0
    serviceimpl
    Demo project for Spring Boot
    jar
    
        study
        com.itbu
        1.0.0
    

    
        1.8
        UTF-8
        UTF-8
        2.1.17.RELEASE
    

    
        
            com.itbu.study
            common
            1.0.0
        
        
            com.itbu.study
            service
            1.0.0
        
        
            com.itbu.study
            mapper
            1.0.0
        
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

根据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 getAll() {
        return userMapper.getAll();
    }
}

6. 配置web模块

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

配置pom.xml文件

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



    4.0.0
    com.itbu.study
    serviceimpl
    1.0.0
    serviceimpl
    Demo project for Spring Boot
    jar
    
        study
        com.itbu
        1.0.0
    

    
        1.8
        UTF-8
        UTF-8
        2.1.17.RELEASE
    

    
        
            com.itbu.study
            common
            1.0.0
        
        
            com.itbu.study
            service
            1.0.0
        
        
            com.itbu.study
            mapper
            1.0.0
        
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


编写各个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 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, 返回以下结果表明测试成功

SpringBoot集成mqtt的多模块项目配置详解_第11张图片

4. 配置MQTT模块

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

配置pom.xml文件

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



    
        study
        com.itbu
        1.0.0
    
    4.0.0

    com.itbu.study
    mqtt
    jar
    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-integration
        
        
            org.springframework.integration
            spring-integration-stream
        
        
            org.springframework.integration
            spring-integration-mqtt
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



在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 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");
    }

}

测试

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

SpringBoot集成mqtt的多模块项目配置详解_第12张图片

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

SpringBoot集成mqtt的多模块项目配置详解_第13张图片

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

在这里插入图片描述

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

SpringBoot集成mqtt的多模块项目配置详解_第14张图片

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

在这里插入图片描述

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

SpringBoot集成mqtt的多模块项目配置详解_第15张图片

测试成功

最后放上工程的源码:GitHub

到此这篇关于SpringBoot集成mqtt的多模块项目配置详解的文章就介绍到这了,更多相关SpringBoot mqtt多模块内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

你可能感兴趣的:(SpringBoot集成mqtt的多模块项目配置详解)