IDEA构建SpringBoot多模块项目
前言
最近一直在思考一个问题,springboot的多模块项目到底是怎么运行和运作的?
一般我们大部分的springboot项目都是单模块的项目,但是如果后续有要求开发多模块的项目应该怎么处理?于是基于这点进行了研究。
本次文章将会带大家从头到尾搭建多模块项目,讲解怎么去串接以及如何去运行
优缺点
🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️🖊️
多模块的项目,一般也叫
微服务
项目,微服务是一种架构模式或者说是一种架构风格
,它提倡单一应用程序
划分为一组小的服务,每个服务在其独立的自己的进程中,服务之间相互协调,互相配合,为用户提供最终价值
而我们的多模块的恰恰是这种思想
🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️🖌️
🩷🩷优点🩷🩷
❤️ 每个服务足够内聚,足够小,代码容易理解这样能聚焦一个指定的业务功能或业务需求
❤️开发简单、开发效率提高,一个服务可能就是专一的只干一件事
❤️微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的
以及其他…
🖤🖤缺点🖤🖤
🖤 开发人员要处理分布式系统的复杂性
🖤 多服务运维难度,随着服务的增加,运维的压力也在增大
🖤维护,分工合作困难
模块划分及依赖引用
模块划分
我的风格可能和别人不一样,别人一上来就会教你步骤,但是针对于这点,我们首先得明确一点,我们要搭建一个什么样的项目,针对你要搭建的项目,需要建立的模块也不一样
🖍️🖍️🖍️🖍️🖍️
以业务层划分为例,也就是我们熟知的三层架构
也就是可以划分为数据库层,web层和实现层,对应可划分的框架明细如下
模块名称 | 模块功能范围 |
---|---|
data | 实体类模块,负责实体对象的构建 |
config | 配置类模块,负责springboot相关的基础配置 |
dao | 数据库类模块,负责数据库增删改查相关逻辑 |
service | 业务实现类模块,负责具体业务实现相关逻辑 |
web | 项目启用类模块,负责项目启用,接口调用相关逻辑 |
🖊️🖊️🖊️🖊️🖊️
除了按照我们的三层架构的进行划分模块外,我们也可以用我们具体的实际业务进行划分
- 举一个例子,按照学校为例,我们学校如果要记录数据,可以按照这些进行划分
模块名称 | 模块功能范围 |
---|---|
student | 学生信息类模块,负责记录学生基本数据 |
teacher | 老师信息类模块,负责记录教师相关基本数据 |
grade | 学生成绩类模块,负责记录学生成绩数据 |
那么这里我只是简单的举一个例子,那么为了演示方便,
本文章会按照三层架构的进行讲解
依赖引用
✏️✏️✏️✏️✏️
在正式搭建项目之前,我们有一个比较重要的事情需要确认,那就是我们的模块之间应该要怎么进行引用?
因为这会涉及到一个问题,那就是
循环依赖
什么是循环依赖?
循环依赖即你A模块引入了B模块,但是B模块也引入了A模块,导致报错
循环依赖有什么影响?
✨第一点,最重要,会导致项目无法启动
✨第二点,如果前期不规划好怎么引入,会导致出现一个问题,假如有A,B,C三个模块,你要在C模块开发逻辑,但是需要引入A模块的代码,目前的引入是A引入B和C,B引入C,因为C已经被A引入了,但是C无法引入A,如果强行引入会造成循环依赖,但是假如你要在C拿到A的代码,是无法拿到的,因为没有引入对应模块,无法调用对方的方法感觉有点绕,那么简单的说,就是
我们需要规范好怎么引入模块,才能确保所有模块各司其职,不会出现需要调用到对应的代码但是调用不到的情况
✏️✏️✏️✏️✏️
按照我们的三层框架,我们应该怎么引入?
首先,
config
是配置,应该是一个独立的模块,其他模块可以依赖于它
data
是一个实体类相关的,那么它应该可以被任意的模块调用到
service
依赖于data
,dao
,需要进行数据库的调用,才能做到业务相关的逻辑
dao
,因为和数据库相关的进行交互,而数据库连接相关逻辑一般会写在config
,所以dao
依赖于config
web
,是接口调用和启动相关的逻辑,所以依赖于service
和config
模块
模块名称 | 模块引入范围 |
---|---|
data | 无 |
config | 无 |
dao | data, config |
service | data,dao,service |
web | config,service |
✒️✒️✒️✒️✒️
搭建步骤
那么正式开始我们的搭建
- 首先,我们选择新建项目
新建一个MAVEN项目,填写项目名称,组织等
PS: 我的IDEA为2024,可能部分操作有些不一样,但是建立的项目大差不差
初始项目搭建为如下:
接下来把搭建的项目的
src文件夹删掉,只保留pom.xml
然后在该项目,选择新建module
NEW -> Module..
新建config模块
然后把config模块的Main的主入口文件删除
按照如上步骤,把剩下的模块新建出来,同样把Main入口删除,但是
只保留web模块的Main入口文件
最终项目结构如下:
这里为了方便标识,我把web模块的Main修改为WebApplication
然后我们把父模块的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"><modelVersion>4.0.0</modelVersion><groupId>com.hxc</groupId><artifactId>multipleModuleDemo</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><name>multipleModule</name><description>多module项目demo</description><modules><module>config</module><module>web</module><module>dao</module><module>service</module><module>data</module></modules><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.6.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId><version>2.6.2</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.8.1</version> <!-- 根据需要调整版本 --><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><version>2.6.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version><optional>true</optional></dependency></dependencies></project>
这里我引入了springboot相关的一些必要依赖,后续可根据实际项目情况进行添加,另外父模块的依赖是能够被子模块引入的,有什么必要的也可以引入到父模块的pom,或者新加一个common模块,专门供其他子模块调用
config的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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hxc</groupId><artifactId>multipleModulesDemo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>config</artifactId><name>config</name><version>1.0-SNAPSHOT</version><description>配置模块</description></project>
data的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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hxc</groupId><artifactId>multipleModulesDemo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>data</artifactId><version>1.0-SNAPSHOT</version><name>data</name><description>数据实体模块</description></project>
dao的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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hxc</groupId><artifactId>multipleModulesDemo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>dao</artifactId><version>1.0-SNAPSHOT</version><name>dao</name><description>数据库</description><dependencies><dependency><groupId>com.hxc</groupId><artifactId>data</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.hxc</groupId><artifactId>config</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency></dependencies></project>
service的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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hxc</groupId><artifactId>multipleModulesDemo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>service</artifactId><version>1.0-SNAPSHOT</version><name>service</name><description>逻辑层</description><dependencies><dependency><groupId>com.hxc</groupId><artifactId>dao</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.hxc</groupId><artifactId>data</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.hxc</groupId><artifactId>config</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies></project>
web的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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hxc</groupId><artifactId>multipleModulesDemo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>web</artifactId><dependencies><dependency><groupId>com.hxc</groupId><artifactId>config</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.hxc</groupId><artifactId>service</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.6.2</version></dependency></dependencies></project>
那么,为了能够正常的搭建一个可以启用的多模块项目,我这里补充一个逻辑代码,实现查询和新增接口正常调用和项目启动
在数据库新建一个用户表userData,建表语句如下
CREATE TABLE userData (user_id varchar(100) NOT NULL COMMENT 'userId',nick_name varchar(100) NULL COMMENT '名称',sex varchar(10) NULL COMMENT '性别',age INT NULL COMMENT '年龄',CONSTRAINT userData_pk PRIMARY KEY (user_id)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_unicode_ci;
在data模块新建一个实体UserData
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;@Getter
@Setter
@ToString
public class UserData {private String userId;private String nickName;private String sex;private Integer age;
}
在dao模块新建一个jdbc数据库查询代码UserDataDao
import com.hxc.user.UserData;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class UserDataDao {private static final String SQL_INS = "INSERT INTO userdata(user_id,nick_name,sex,age) VALUES (?,?,?,?)";private static final String SQL_UPD = "UPDATE userdata SET nick_name=?,sex=?,age=? WHERE userid=?";private static final String SQL_SEL = "SELECT user_id,nick_name,sex,age FROM userdata ";private static final String SQL_DEL = "DELETE FROM userdata WHERE user_id = ?";private final Connection conn;public UserDataDao(Connection conn) {this.conn = conn;}public int insert(UserData data) {try (PreparedStatement ps = this.conn.prepareStatement(SQL_INS)) {ps.setString(1, data.getUserId());ps.setString(2, data.getNickName());ps.setString(3, data.getSex());ps.setInt(4, data.getAge());return ps.executeUpdate();} catch (SQLException e) {throw new IllegalStateException("数据库查询错误, " + e.getMessage(), e);}}public int update(UserData data) {try (PreparedStatement ps = this.conn.prepareStatement(SQL_UPD)) {ps.setString(1, data.getNickName());ps.setString(2, data.getSex());ps.setInt(3, data.getAge());ps.setString(4, data.getUserId());return ps.executeUpdate();} catch (SQLException e) {throw new IllegalStateException("数据库查询错误, " + e.getMessage(), e);}}public int delete(String userId) {try (PreparedStatement ps = this.conn.prepareStatement(SQL_DEL)) {ps.setString(1, userId);return ps.executeUpdate();} catch (SQLException e) {throw new IllegalStateException("数据库查询错误, " + e.getMessage(), e);}}public List<UserData> selectAll() {ArrayList<UserData> result = new ArrayList<UserData>();try (PreparedStatement ps = this.conn.prepareStatement(SQL_SEL)) {ResultSet rs = ps.executeQuery();while (rs.next()) {result.add(convert(rs));}return result;} catch (SQLException e) {throw new IllegalStateException("数据库查询错误, " + e.getMessage(), e);}}public UserData selectByUserId(String userId) throws SQLException {UserData result = null;try (PreparedStatement ps = conn.prepareStatement(SQL_SEL + "WHERE user_id = ?")) {ps.setString(1, userId);ResultSet rs = ps.executeQuery();if (rs.next()) {result = convert(rs);}return result;} catch (SQLException e) {throw new SQLException(e.getMessage());}}private UserData convert(ResultSet rs) throws SQLException {UserData data = new UserData();int index = 1;data.setUserId(rs.getString(index++));data.setNickName(rs.getString(index++));data.setSex(rs.getString(index++));data.setAge(rs.getInt(index++));return data;}
}
在config模块新建一个数据库连接配置DataSourceConfig,和数据库连接实现类PrimeDB
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;/*** 数据库配置* */
@Configuration
public class DataSourceConfig {@Value("${spring.datasource.prime-data.driver-class-name}")private String primeDataDriver;@Value("${spring.datasource.prime-data.url}")private String primeDataUrl;@Value("${spring.datasource.prime-data.username}")private String primeDataUsername;@Value("${spring.datasource.prime-data.password}")private String primeDataPassword;@Beanpublic DriverManagerDataSource primeDataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(primeDataDriver);dataSource.setUrl(primeDataUrl);dataSource.setUsername(primeDataUsername);dataSource.setPassword(primeDataPassword);return dataSource;}// 配置其他数据库连接(待定占位)@Beanpublic DriverManagerDataSource otherDataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName(primeDataDriver);dataSource.setUrl(primeDataUrl);dataSource.setUsername(primeDataUsername);dataSource.setPassword(primeDataPassword);return dataSource;}
}
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;@Component
public class PrimeDB {private final DataSource primeDataSource;@Autowiredpublic PrimeDB(@Qualifier("primeDataSource")DataSource primeDataSource) {this.primeDataSource = primeDataSource;}public Connection create() throws SQLException {Connection connection = null;try {connection = primeDataSource.getConnection();return connection;} catch (SQLException e) {// 处理连接获取失败的异常情况throw new RuntimeException("连接数据库失败:", e);}}
}
那么为了可以实现测试类正常调用,可在config的resource下建立一个application.yml,为数据库连接配置,但是为了正常启用项目,需要在web模块的resource新建一个application.yml
如下为config的resource下建立一个application.yml
spring:application:name: multipleModuleBackdatasource:prime-data:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/primeData?useUnicode=true&characterEncoding=UTF-8&useServerPrepStmts=false&rewriteBatchedStatements=true&useCompression=false&useSSL=falseusername: rootpassword: root
在我们的service模块,新建一个UserService
import com.hxc.dao.UserDataDao;
import com.hxc.user.UserData;
import java.sql.Connection;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;@Service
public class UserService {public UserData findUser(Connection conn, String userId) throws Exception {try {UserDataDao userDataDao = new UserDataDao(conn);UserData userData = userDataDao.selectByUserId(userId);if (null == userData) {throw new Exception("查无用户:" + userId);}return userData;} catch (Exception e) {throw new Exception("获取用户失败:" + e);}}public String insertUser(Connection conn, UserData userData) throws Exception {try {UserDataDao userDataDao = new UserDataDao(conn);if (!StringUtils.hasText(userData.getUserId())) {throw new Exception("用户id不能为空!");}if (!StringUtils.hasText(userData.getNickName())) {throw new Exception("用户名称不能为空!");}UserData record = userDataDao.selectByUserId(userData.getUserId());if (null != record) {throw new Exception("用户:" + userData.getUserId() + "已存在");}userDataDao.insert(userData);return "新增成功!";} catch (Exception e) {throw new Exception("新增用户失败:" + e);}}
}
在web模块下建立一个接口调用文件UserWebServicer
import com.hxc.configs.db.PrimeDB;
import com.hxc.user.UserData;
import java.sql.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserWebServicer {@Autowiredprivate PrimeDB primeDB;@GetMapping("/findUser")public UserData findUser(@RequestParam("userId") String userId) throws Exception {System.out.println("Received request with userId: " + userId);try (Connection conn = primeDB.create()) {return new UserService().findUser(conn, userId);} catch (Exception e) {throw new Exception(e);}}@PostMapping("/insertUser")public String sendMessage(@RequestBody UserData userData) throws Exception {try (Connection conn = primeDB.create()) {return new UserService().insertUser(conn, userData);} catch (Exception e) {throw new Exception(e);}}
}
同时把webApplication的代码修改为:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class WebApplication {public static void main(String[] args) {System.out.println("多模块项目启动主入口");SpringApplication.run(WebApplication.class, args);}
}
然后在web模块的resource下新建一个application.yml
server:port: 8082servlet:context-path: /multipleModulespring:application:name: multipleModuleBackdatasource:prime-data:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/primeData?useUnicode=true&characterEncoding=UTF-8&useServerPrepStmts=false&rewriteBatchedStatements=true&useCompression=false&useSSL=falseusername: rootpassword: root
这个时候我们就可以右键WebApplication启动我们的项目了
现在我的数据该表的数据有如下:
调用我的查询接口结果如下:
我们的项目正常运行
重要信息
以此,我们的项目就正式搭建好了,后续我们这个项目的调用情况是在data模块进行建立实体,我们的dao模块调用data模块的实体,和config的数据库连接进行数据库的增删改查,然后我们的service模块进行业务逻辑的开发,在web编写接口调用我们的业务逻辑,按照这个顺序执行就能够正常的运行我们的项目,不会出现循环依赖问题,后续如果有新加别的模块也是按照这个思路进行添加
git项目demo
如下为本次教学的项目demo链接,可进行参考
SPRINGBOOT 多模块项目DEMO
结语
以上为springboot搭建多模块的方法和步骤,如有遗漏将在本文章补充
相关文章:

IDEA构建SpringBoot多模块项目
前言 最近一直在思考一个问题,springboot的多模块项目到底是怎么运行和运作的? 一般我们大部分的springboot项目都是单模块的项目,但是如果后续有要求开发多模块的项目应该怎么处理?于是基于这点进行了研究。 本次文章将会带大…...

【前端】NodeJS:nvm
文章目录 1 介绍2 使用2.1 下载安装2.2 常用命令 1 介绍 nvm全称:Node Version Manager,顾名思义它是用来管理node版本的工具,方便切换不同版本的Node.js。 2 使用 nvm的使用非常的简单,跟npm的使用方法类似。 2.1 下载安装 …...

Docker网络模式及通信
一、Docker默认的网络通信 1.1 Docker安装后默认的网络设置 Docker服务器安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡,其IP地址都是172.17.0.1/16 [rootubuntu1804 ~]#apt -y install bridge-utils [rootubuntu1804 ~]#brctl show 另…...

类模板实现实现Qt click/hover自定义操作
一、场景 常常会需要实现点击/hover时修改图片,可能是一个QPushButton、QLabel、QToolButton…… 由于Qt bug,QIcon/QSS只能实现常规态、按下态的图标切换,hover态的图片设置无效。 解决思路无非是安装事件过滤器、自定义类并重实现事件。 …...

Arco Design:引领未来的Vue 3创意先锋,一键开启高效与美感并重的Web开发之旅!
Arco Design 是一个基于 Vue 3 的 UI 框架,它提供了丰富的组件和样式,可以帮助开发者快速构建高质量的 Web 应用程序。以下是 Arco Design 的一些详细特点: 完整的设计系统:Arco Design 提供了一套完整的设计系统,包括…...

【MySQL】Linux下用C/C++链接MySQL数据库
文章目录 一、准备工作二、验证库和接口的使用三、链接数据库四、对数据库进行增删查改增删改查 五、结尾 一、准备工作 要使用C链接数据库, 首先要去MySQL官网下载官网提供的库, MySQL 社区下载. 如图所示: 接着选择: 按需选择版本: 如果用的是云服务器, 那么在安装mysql时…...

Python金融量化专栏简介
量化分析实战 - 专栏大纲 👉👉👉 《玩转Python金融量化专栏》👈👈👈 订阅本专栏的可以下载对应的代码和数据集 专栏目标 本专栏旨在帮助读者全面掌握使用Python进行金融技术指标的计算与应用,从基础到高级,涵盖各种技术指标的实现、策略开发与回测等内容。通过…...

出行365:依托分布式数据库,让出行无忧 | OceanBase案例
*本文首发自“新华社环球”杂志,作者张海鑫 每年的暑期旅游旺季,都会触发一轮轮的文旅消费的热潮,对于互联网出行服务行业而言,这既是一场盛大的狂欢,也是对其综合实力的严峻考验。 然而,自去年暑假起&…...

【C语言】位段详解
🦄个人主页:小米里的大麦-CSDN博客 🎏所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html 🎁代码托管:黄灿灿 (huang-cancan-xbc) - Gitee.com ⚙️操作环境:Visual Studio 2022 目录 一、什么是位段? 二、…...

LVS集群实验
NAT模式 本质是多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和PORT实现转发RIP和DIP应在同一个IP网络,且应使用私网地址:RS的网关要指向DIP请求报文和响应报文都必须经由Direclor转发,Direclor易于成为系统瓶…...

在 Spring Boot 中使用适配器模式实现支付网关的统一接口
引言 在许多电子商务系统中,集成多个支付网关是常见的需求。不同的支付网关有着不同的接口和实现细节。适配器模式可以帮助我们以一种灵活的方式实现这些不同的支付网关接口。 适配器模式简介 适配器模式将一个类的接口转换为客户期望的另一个接口。适配器模式使…...

【书生·浦语大模型实战营】第三期 入门岛作业
入门岛作业 Linux闯关任务:完成 SSH 连接与端口映射并运行 hello_world.py。配置vscode作业内容 可选任务1:将Linux基础命令在开发机上完成一遍作业内容 可选任务 2:使用 VSCODE 远程连接开发机并创建一个conda环境作业内容 可选任务 3&#…...

Redis的String类型常用命令总结
1. set 设置一个键的值。 set key value示例: set username "alice"2. get 获取一个键的值。 get key示例: get username3. getset 设置键的值,并返回键的旧值。 getset key value示例: getset username "…...

河南萌新联赛2024第(四)场:河南理工大学
A 思路: B 思路:有一种贪心的写法,将整个数组排序以后比较两个相邻数的同或值,取 m a x max max,不会证明 int th(int x, int y, int z) {int res 0;for (int i z - 1; i > 0; i --) {int dx (x >> i &…...

Linux中临时使用账号提权进行业务操作
普通账号提权 su:永久提权 Switching users with su sudo:临时提权 Running commands as root with sudo 1)su切换账号 需要对方的密码 示例:切换到超级管理员 su - root 建议用-这个 su root 普通用户需要执行特殊指令&…...

lwip 3. 网线拔掉后 lwip_recvfrom不能返回
当网线被拔掉后,LWIP的lwip_recvfrom函数无法返回,这通常意味着网络连接已经断开,而LWIP没有自动检测到这种断开并进行相应的处理。具体卡在这个地方: ret xQueueReceive(mbox->mbx, &(*msg), portMAX_DELAY); //具…...

Linux环境安装Docker Engine
Docker是一个开源的应用容器引擎,由Go语言开发,基于Linux内核技术。Docker通过将应用及其依赖打包到可移植的容器中,实现了应用的快速部署和高效管理。Docker容器具有轻量级、快速启动、可移植性强等特点,能够显著提升资源利用率和…...

大厂面试题分享
大厂面试题分享 Redis持久化方式AOF优缺点RDB优缺点 如何保证Redis和Myql的一致性索引下推输入url到浏览器发生了什么ReentranLock底层原理SpringBoot 的启动流程 Redis持久化方式 Redis提供了两种主要的持久化机制,分别是AOF(Append-Only File…...

FPGA面试问题整理
1. 逻辑设计中竞争与冒险概念,如何识别和消除? 竞争:在组合逻辑电路中,信号经过多条路径到达输出端,每条路径经过的逻辑门不同存在时差,在信号变化的瞬间存在先后顺序。这种现象叫竞争。 冒险:由…...

3Done学习笔记
一、基本操作 1、旋转视角 使用左下角立方体选择; 右键可以拖动视角; 中间滑轮按住拖动整个舞台界面。 2、平移和旋转 右键选择移动,有两种方式。 第一种选择起始点,按照起始点位置移动到终止点(边、角、中心点…...

AI学习指南深度学习篇-卷积层详解
AI学习指南深度学习篇-卷积层详解 一、引言 随着人工智能技术的不断发展,深度学习作为人工智能领域的热门分支之一,正在逐渐成为各个领域的核心技术。而在深度学习中,卷积神经网络(Convolutional Neural Network,CNN…...

2024年TI杯E题-三子棋游戏装置方案分享-jdk123团队-第二弹 手搓机械臂
第一弹赛题的选择与前期方案的准备 opencv调用摄像头bug的解决 机械臂的组装 采用三个舵机,组成一个三自由度的机械臂。 并且利用电磁吸盘的方式,完成对棋子的抓取工作,后面的事实证明,在预算不足的情况下,队友手搓…...

如何在Java、C、Ruby语言中使用Newscatcher API
Newscatcher 世界实时新闻聚合API 一款强大的数据服务工具,它通过先进的网络爬虫技术,实时从全球超过70,000个新闻源聚合新闻内容。这个API能够提供全面、多角度的新闻报道,包括但不限于标题、作者、发布日期、全文内容以及媒体资源链接。它使…...

集合: Collection的成员方法和相关实现类
Collection: - List(有序【指的是存储和取出的顺序是一致的】且可以发生重复,且有索引的概念) - ArrayList: 底层数据结构是数组,查询快,增删慢,线程不安全的,效率高。 - …...

过滤器与监听器:深入了解 Java Web 开发中的核心概念
在 Java Web 开发中,过滤器(Filter)和监听器(Listener)是两个重要的组件,它们帮助开发者在请求处理的各个阶段进行预处理和后处理。这篇博客将深入探讨这两个概念,并展示它们如何在实际应用中发…...

【Linux学习】动静态库从原理到制作
🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊 目录 🍑动静态库🐟动静态库的制作与使用🚀生成静态库🔒生成动态库 🦌动态库的查…...

WPF篇(10)-Label标签+TextBlock文字块+TextBox文本框+RichTextBox富文本框
Label标签 Label控件继承于ContentControl控件,它是一个文本标签,如果您想修改它的标签内容,请设置Content属性。我们曾提过ContentControl的Content属性是object类型,意味着Label的Content也是可以设置为任意的引用类型的。 案…...

JavaFX对话框控件-ChoiceDialog
JavaFX对话框控件-ChoiceDialog 常用属性titlecontentTextinitOwnergraphicheaderTextdefaultValuechoicesdialogPane 常用事件显示事件setOnShowing显示事件setOnShown弹框按钮点击 综合案例自定义下拉框内容 与Alert大部分功能类似按钮不可以自定义多一个下拉框 常用属性 …...

一文了解BTC中的二层协议中Nervos network,CKB,RGB++,UTXO stack 之间的关系
注:该内容不构成投资建议,有些内容摘抄其他地方,如侵权,请联系删除。 Nervos network Nervos Network 是一个开源的区块链生态项目,该项目提供一套解决方案来应对区块链扩展性和互操作性的问题。 Nervos Network 成立…...

Oracle(47)如何创建和使用集合?
在PL/SQL中,集合(Collection)是一种复合数据类型,用于存储一组相关的数据项。集合主要有三种类型:关联数组(Associative Arrays)、嵌套表(Nested Tables)和可变数组&…...