SpringBoot集成mqtt的多模块项目配置详解
⽬录
前⾔
开发⼯具及系统环境项⽬路径配置过程
1.搭建⽗项⽬2.搭建⼦项⽬3.配置各个模块4.配置MQTT模块前⾔
近期为了准备毕设,准备使⽤SpringBoot搭建mqtt后端,本篇主要记录了在IDEA中搭建SpringBoot mqtt的多模块项⽬的过程
开发⼯具及系统环境
IDE:IntelliJ IDEA 2020.2操作系统:Windows 10 2004Java 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⽂件如下:
2. 配置common模块配置pom.xml⽂件
common模块主要包括⼀些通⽤的类和接⼝,固这⾥只需要配置下parent这⼀项指向⽗项⽬即可,common模块的pom.xml配置⽂件如下:
xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">
创建所需要的类和接⼝
配置完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 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⽀持,固配置⽂件编写如下: 编写接⼝和映射⽂件 和不分模块的操作⼀样,在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 UserMapper.xml 4. 配置service模块 service模块也就是service层,主要是⼀些服务接⼝⽅便给controller层调⽤。步骤如下:配置pom.xml⽂件 service层需要⽤到common模块中的pojo类,这⾥需要对该模块添加依赖项 xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"> 编写service各个接⼝ 这⾥接⼝与mapper层类似,就不⼀⼀赘述,这⾥直接放代码UserService.java package com.itbu.study.service; import com.itbu.study.common.bean.UserBean;import java.util.List; public interface UserService { List 5. 配置serviceimpl模块 serviceimpl即service接⼝的各个实现类,实现步骤如下:配置pom.xml⽂件 serviceimpl需要mapper层的⽀持,需要实现service层的各个接⼝,也需要引⽤到common模块中的pojo类,我们直接加上这三项的依赖 根据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 6. 配置web模块 接下来就到了核⼼部分,也就是与不分模块配置差异较⼤的部分。Web层需要配置启动类以及配置⽂件,内容较多,配置步骤如下:配置pom.xml⽂件 Web层将直接引⽤Service层的各个接⼝,Common模块的各个类,这⾥我们直接加上依赖 编写各个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 编写启动类,记得加上MapperScanWebApplication.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 在配置⽂件中设置数据源和mapper映射⽂件以及监听端⼝application-dev.xml server: port: 10000mybatis: 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后端基本项⽬,接下来进⾏简单测试 4. 配置MQTT模块 前⾯我们完成了SpringBoot基础项⽬的配置,接下来我们将mqtt也做成模块,步骤如下:配置pom.xml⽂件 我们集成mqtt功能主要使⽤了spring-integration-mqtt这个jar包,所以我们在pom中添加对这个包的依赖,pom.xml⽂件如下: xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"> 在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\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\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\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\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消息, 主题:{} 消息:{}\ }} 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.*\@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 @RequestMapping(\"/mqtt\") public JsonResult> mqtt_sender(@RequestParam(\"msg\")String msg){ logger.info(\"Send mqtt msg: {}\ mqttMessageSender.sendToMqtt(msg); logger.info(\"Send successfully!\"); return new JsonResult<>(0,\"Send Successfully\"); }} 测试 ⾸先我们运⾏后端项⽬,可以看到⽇志打出以下输出,说明后端项⽬正常启动 然后我们使⽤mqtt.fx这个软件往订阅主题default发送helloworld 发现⽇志打印如下信息,表⾯输⼊通道正常: 可以看到⽇志中打印了如下内容: 因为我们订阅的主题也是default,所以也收到了⽣产者发送的信息,我们打开mqtt.fx, 订阅default主题,可以收到如下信息: 测试成功 最后放上⼯程的源码: 到此这篇关于SpringBoot集成mqtt的多模块项⽬配置详解的⽂章就介绍到这了,更多相关SpringBoot mqtt多模块内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持! 因篇幅问题不能全部显示,请点此查看更多更全内容