SpringBoot進(jìn)行模塊化開(kāi)發(fā)的5種組織方式小結(jié)
在企業(yè)級(jí)應(yīng)用開(kāi)發(fā)中,隨著業(yè)務(wù)復(fù)雜度的不斷提升,單體應(yīng)用往往變得臃腫難以維護(hù)。
模塊化開(kāi)發(fā)作為解決復(fù)雜性的關(guān)鍵策略,能夠有效提升代碼的可維護(hù)性、可擴(kuò)展性和團(tuán)隊(duì)協(xié)作效率。
SpringBoot作為Java領(lǐng)域流行的應(yīng)用開(kāi)發(fā)框架,提供了多種模塊化組織方式,以適應(yīng)不同的業(yè)務(wù)場(chǎng)景和團(tuán)隊(duì)需求。
本文將介紹SpringBoot模塊化開(kāi)發(fā)的5種組織方式。
一、Maven/Gradle多模塊項(xiàng)目
核心理念
Maven/Gradle多模塊項(xiàng)目是最基礎(chǔ)、最常用的模塊化方式,通過(guò)將應(yīng)用拆分為多個(gè)子模塊,每個(gè)模塊負(fù)責(zé)特定的功能,共同構(gòu)成一個(gè)完整的應(yīng)用。這種方式保持了單體應(yīng)用的部署簡(jiǎn)便性,同時(shí)獲得了代碼組織的清晰度。
實(shí)現(xiàn)方式
1. 項(xiàng)目結(jié)構(gòu)
my-app/
├── pom.xml (父POM)
├── my-app-core/
│ ├── pom.xml
│ └── src/
├── my-app-service/
│ ├── pom.xml
│ └── src/
├── my-app-web/
│ ├── pom.xml
│ └── src/
└── my-app-api/
├── pom.xml
└── src/
2. 父POM配置
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>my-app-core</module>
<module>my-app-service</module>
<module>my-app-web</module>
<module>my-app-api</module>
</modules>
<properties>
<java.version>11</java.version>
<spring-boot.version>2.6.3</spring-boot.version>
</properties>
<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>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>3. 子模塊POM示例(my-app-web)
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>my-app-web</artifactId>
<dependencies>
<!-- 依賴其他內(nèi)部模塊 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-app-service</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>4. 模塊之間的依賴關(guān)系
- my-app-core: 包含通用工具類(lèi)、基礎(chǔ)配置等
- my-app-service: 包含業(yè)務(wù)服務(wù)實(shí)現(xiàn),依賴core模塊
- my-app-api: 包含API定義,可能被其他項(xiàng)目引用
- my-app-web: 包含Web控制器,依賴service模塊
優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 結(jié)構(gòu)清晰,各模塊職責(zé)明確
- 支持模塊間代碼復(fù)用
- 構(gòu)建、測(cè)試和發(fā)布過(guò)程統(tǒng)一管理
- 保持了單體應(yīng)用的簡(jiǎn)單部署方式
- IDE支持良好
缺點(diǎn):
- 所有模塊仍然是一個(gè)整體部署單元
- 模塊間邊界不夠嚴(yán)格,容易產(chǎn)生依賴混亂
- 隨著項(xiàng)目增長(zhǎng),構(gòu)建時(shí)間可能變長(zhǎng)
適用場(chǎng)景
• 中小型應(yīng)用,代碼量適中
• 團(tuán)隊(duì)規(guī)模不大,溝通成本較低
• 需要清晰的代碼組織但又不希望引入分布式復(fù)雜性
• 作為向微服務(wù)架構(gòu)演進(jìn)的過(guò)渡階段
二、基于Spring Profiles的功能模塊化
核心理念
利用Spring的Profiles機(jī)制,在同一代碼庫(kù)中定義不同的功能模塊,并通過(guò)配置文件激活或禁用特定功能。
這種方式不需要物理拆分代碼,而是通過(guò)邏輯分組和條件加載實(shí)現(xiàn)功能模塊化。
實(shí)現(xiàn)方式
1. 定義不同功能模塊的配置類(lèi)
@Configuration
@Profile("payment")
public class PaymentConfig {
@Bean
public PaymentService paymentService() {
return new PaymentServiceImpl();
}
@Bean
public PaymentRepository paymentRepository() {
return new PaymentRepositoryImpl();
}
}@Configuration
@Profile("notification")
public class NotificationConfig {
@Bean
public NotificationService notificationService() {
return new EmailNotificationService();
}
@Bean
public NotificationTemplate notificationTemplate() {
return new StandardNotificationTemplate();
}
}2. 在應(yīng)用屬性中激活特定模塊
# application.properties spring.profiles.active=core,payment,notification
或者通過(guò)環(huán)境變量:
java -jar app.jar --spring.profiles.active=core,payment
3. 在代碼中使用條件注解
@Service
@Profile("payment")
public class PaymentServiceImpl implements PaymentService {
// 實(shí)現(xiàn)代碼
}
@Controller
@Profile("admin")
@RequestMapping("/admin")
public class AdminController {
// 管理員功能
}4. 環(huán)境特定配置
# application-payment.properties payment.gateway.url=https://payment.example.com payment.timeout=30
# application-notification.properties notification.email.host=smtp.example.com notification.sms.enabled=true
優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 無(wú)需物理拆分代碼,實(shí)現(xiàn)簡(jiǎn)單
- 可根據(jù)部署環(huán)境靈活啟用/禁用功能
- 共享基礎(chǔ)設(shè)施代碼
- 便于實(shí)現(xiàn)功能的A/B測(cè)試或灰度發(fā)布
缺點(diǎn):
- 模塊邊界不夠清晰,容易導(dǎo)致耦合
- 隨著功能增多,單個(gè)代碼庫(kù)仍會(huì)變得龐大
- 所有功能模塊仍在同一個(gè)部署單元中
- 不便于不同團(tuán)隊(duì)并行開(kāi)發(fā)
適用場(chǎng)景
• 需要根據(jù)客戶需求定制功能的產(chǎn)品
• 同一應(yīng)用需要部署到不同環(huán)境且功能略有差異
• 需要進(jìn)行功能試驗(yàn)或灰度發(fā)布
• 功能相對(duì)獨(dú)立但又不希望創(chuàng)建多個(gè)項(xiàng)目
三、基于Spring Boot Starter的模塊化
核心理念
Spring Boot Starter是Spring生態(tài)系統(tǒng)的一個(gè)核心特性,它通過(guò)自動(dòng)配置和依賴管理簡(jiǎn)化了模塊集成。
通過(guò)創(chuàng)建自定義Starter,可以將功能封裝為獨(dú)立模塊,實(shí)現(xiàn)可插拔的組件化架構(gòu)。
實(shí)現(xiàn)方式
1. 創(chuàng)建自定義Starter的項(xiàng)目結(jié)構(gòu)
my-feature-spring-boot-starter/
├── pom.xml
└── src/main/java/
└── com/example/feature/
├── FeatureAutoConfiguration.java
├── FeatureProperties.java
├── service/
│ └── FeatureService.java
└── META-INF/
└── spring.factories
2. Starter的POM文件
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-feature-spring-boot-starter</artifactId>
<version>1.0.0</version>
<properties>
<java.version>11</java.version>
<spring-boot.version>2.6.3</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</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>
</dependencies>
</dependencyManagement>
</project>3. 自動(dòng)配置類(lèi)
@Configuration
@ConditionalOnClass(FeatureService.class)
@EnableConfigurationProperties(FeatureProperties.class)
public class FeatureAutoConfiguration {
private final FeatureProperties properties;
public FeatureAutoConfiguration(FeatureProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean
public FeatureService featureService() {
return new FeatureService(properties.getApiKey(), properties.isEnabled());
}
@Bean
@ConditionalOnProperty(prefix = "feature", name = "advanced-mode", havingValue = "true")
public AdvancedFeatureService advancedFeatureService() {
return new AdvancedFeatureService();
}
}4. 配置屬性類(lèi)
@ConfigurationProperties(prefix = "feature")
public class FeatureProperties {
/**
* API密鑰用于訪問(wèn)特性服務(wù)
*/
private String apiKey;
/**
* 是否啟用該特性
*/
private boolean enabled = true;
/**
* 是否開(kāi)啟高級(jí)模式
*/
private boolean advancedMode = false;
// getter和setter方法
}5. 注冊(cè)自動(dòng)配置(spring.factories文件)
# 自動(dòng)配置類(lèi) org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.feature.FeatureAutoConfiguration
6. 在應(yīng)用中使用自定義Starter
<dependency>
<groupId>com.example</groupId>
<artifactId>my-feature-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency># 在應(yīng)用配置文件中 feature.api-key=your-api-key feature.enabled=true feature.advanced-mode=false
@Service
public class MyService {
private final FeatureService featureService;
@Autowired
public MyService(FeatureService featureService) {
this.featureService = featureService;
}
public void doSomething() {
featureService.processFeature();
}
}優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 實(shí)現(xiàn)真正的"按需裝配",組件可插拔
- 模塊有明確的邊界和API
- 便于共享和復(fù)用
- 支持條件化配置
- 符合Spring Boot的設(shè)計(jì)理念
缺點(diǎn):
- 創(chuàng)建Starter的初始成本較高
- 版本管理較為復(fù)雜
- 需要考慮向后兼容性
- 調(diào)試相對(duì)困難
適用場(chǎng)景
• 需要在多個(gè)項(xiàng)目中復(fù)用的通用功能
• 提供給第三方使用的功能模塊
• 企業(yè)內(nèi)部的共享基礎(chǔ)設(shè)施
• 需要高度可配置性的功能
四、基于DDD的模塊化架構(gòu)
核心理念
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)是一種軟件開(kāi)發(fā)方法 論,強(qiáng)調(diào)將業(yè)務(wù)領(lǐng)域概念直接映射到軟件設(shè)計(jì)中。基于DDD的模塊化將系統(tǒng)按業(yè)務(wù)領(lǐng)域邊界(Bounded Context)劃分為多個(gè)模塊,每個(gè)模塊都有自己的領(lǐng)域模型和業(yè)務(wù)規(guī)則。
實(shí)現(xiàn)方式
1. 項(xiàng)目結(jié)構(gòu)
my-app/
├── pom.xml
├── common/
│ ├── pom.xml
│ └── src/
├── order/
│ ├── pom.xml
│ ├── src/main/java/com/example/order/
│ │ ├── application/
│ │ ├── domain/
│ │ ├── infrastructure/
│ │ └── interfaces/
│ └── src/test/
├── payment/
│ ├── pom.xml
│ ├── src/main/java/com/example/payment/
│ │ ├── application/
│ │ ├── domain/
│ │ ├── infrastructure/
│ │ └── interfaces/
│ └── src/test/
└── user/
├── pom.xml
└── src/...
2. 領(lǐng)域模塊內(nèi)部結(jié)構(gòu)
每個(gè)領(lǐng)域模塊遵循分層架構(gòu):
• domain: 包含實(shí)體、值對(duì)象、領(lǐng)域服務(wù)和領(lǐng)域事件
• application: 包含應(yīng)用服務(wù)、命令和查詢處理器
• infrastructure: 包含持久化實(shí)現(xiàn)、外部服務(wù)集成
• interfaces: 包含API控制器、DTO和轉(zhuǎn)換器
3. 領(lǐng)域模型示例(Order模塊)
// domain層
package com.example.order.domain.model;
@Entity
public class Order {
@Id
private OrderId id;
private CustomerId customerId;
private Money totalAmount;
private OrderStatus status;
private Set<OrderItem> items;
public Order(CustomerId customerId, Set<OrderItem> items) {
this.id = new OrderId(UUID.randomUUID());
this.customerId = customerId;
this.items = items;
this.status = OrderStatus.CREATED;
this.totalAmount = calculateTotalAmount();
}
public void confirm() {
if (status != OrderStatus.CREATED) {
throw new InvalidOrderStateException("Cannot confirm order in state: " + status);
}
status = OrderStatus.CONFIRMED;
// 發(fā)布領(lǐng)域事件
DomainEventPublisher.publish(new OrderConfirmedEvent(this.id));
}
private Money calculateTotalAmount() {
return items.stream()
.map(item -> item.getPrice().multiply(item.getQuantity()))
.reduce(Money.ZERO, Money::add);
}
// 其他業(yè)務(wù)方法...
}4. 應(yīng)用服務(wù)示例
// application層
package com.example.order.application.service;
@Service
@Transactional
public class OrderApplicationService {
private final OrderRepository orderRepository;
private final CustomerService customerService;
@Autowired
public OrderApplicationService(
OrderRepository orderRepository,
CustomerService customerService) {
this.orderRepository = orderRepository;
this.customerService = customerService;
}
public OrderId createOrder(CreateOrderCommand command) {
// 驗(yàn)證客戶
CustomerId customerId = new CustomerId(command.getCustomerId());
if (!customerService.exists(customerId)) {
throw new CustomerNotFoundException(customerId);
}
// 創(chuàng)建訂單項(xiàng)
Set<OrderItem> items = command.getItems().stream()
.map(this::toOrderItem)
.collect(Collectors.toSet());
// 創(chuàng)建訂單
Order order = new Order(customerId, items);
// 保存訂單
orderRepository.save(order);
return order.getId();
}
public void confirmOrder(ConfirmOrderCommand command) {
OrderId orderId = new OrderId(command.getOrderId());
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
order.confirm();
orderRepository.save(order);
}
private OrderItem toOrderItem(OrderItemDto dto) {
return new OrderItem(
new ProductId(dto.getProductId()),
dto.getQuantity(),
new Money(dto.getPrice())
);
}
}5. 模塊間通信
// 在支付模塊中集成訂單模塊
package com.example.payment.application.service;
@Service
public class PaymentService {
private final PaymentRepository paymentRepository;
private final OrderClient orderClient; // 防腐層
@Autowired
public PaymentService(
PaymentRepository paymentRepository,
OrderClient orderClient) {
this.paymentRepository = paymentRepository;
this.orderClient = orderClient;
}
public PaymentId processPayment(ProcessPaymentCommand command) {
// 從訂單模塊獲取訂單
Order order = orderClient.getOrder(command.getOrderId());
// 驗(yàn)證訂單狀態(tài)
if (order.getStatus() != OrderStatus.CONFIRMED) {
throw new InvalidOrderStateException("Cannot process payment for order: " + order.getId());
}
// 創(chuàng)建支付
Payment payment = new Payment(
new OrderId(order.getId()),
order.getTotalAmount(),
command.getPaymentMethod()
);
// 處理支付邏輯...
paymentGateway.process(payment);
// 保存支付記錄
paymentRepository.save(payment);
return payment.getId();
}
}優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 模塊邊界基于業(yè)務(wù)領(lǐng)域,更符合業(yè)務(wù)現(xiàn)實(shí)
- 高內(nèi)聚、低耦合,維護(hù)性好
- 適合大型復(fù)雜系統(tǒng)
- 支持團(tuán)隊(duì)自治
- 領(lǐng)域模型表達(dá)力強(qiáng),便于與業(yè)務(wù)人員溝通
缺點(diǎn):
- 學(xué)習(xí)曲線陡峭
- 初期設(shè)計(jì)成本高
- 可能導(dǎo)致代碼重復(fù)(每個(gè)領(lǐng)域有自己的模型)
- 需要精心設(shè)計(jì)模塊間通信
適用場(chǎng)景
• 業(yè)務(wù)復(fù)雜度高的企業(yè)應(yīng)用
• 長(zhǎng)期維護(hù)的核心系統(tǒng)
• 大型團(tuán)隊(duì)協(xié)作開(kāi)發(fā)
• 有明確領(lǐng)域邊界的系統(tǒng)
五、基于微服務(wù)的模塊化
核心理念
微服務(wù)架構(gòu)將應(yīng)用拆分為多個(gè)獨(dú)立部署的服務(wù),每個(gè)服務(wù)負(fù)責(zé)特定的業(yè)務(wù)功能,并通過(guò)輕量級(jí)通信機(jī)制(如HTTP API)或者其他RPC框架(如Dubbo)進(jìn)行交互。這種方式使得服務(wù)可以獨(dú)立開(kāi)發(fā)、測(cè)試、部署和擴(kuò)展。
實(shí)現(xiàn)方式
1. 服務(wù)劃分
將系統(tǒng)按業(yè)務(wù)能力劃分為多個(gè)獨(dú)立服務(wù):
電商系統(tǒng)/
├── 用戶服務(wù) (user-service)
├── 商品服務(wù) (product-service)
├── 訂單服務(wù) (order-service)
├── 支付服務(wù) (payment-service)
├── 庫(kù)存服務(wù) (inventory-service)
└── API網(wǎng)關(guān) (api-gateway)
2. 單個(gè)微服務(wù)的項(xiàng)目結(jié)構(gòu)
order-service/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/orderservice/
│ │ │ ├── OrderServiceApplication.java
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ ├── repository/
│ │ │ ├── model/
│ │ │ └── client/
│ │ └── resources/
│ │ └── application.yml
│ └── test/
└── Dockerfile
3. 服務(wù)間通信(REST API)
// 在訂單服務(wù)中調(diào)用產(chǎn)品服務(wù)
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final ProductClient productClient;
@Autowired
public OrderService(
OrderRepository orderRepository,
ProductClient productClient) {
this.orderRepository = orderRepository;
this.productClient = productClient;
}
public Order createOrder(OrderRequest request) {
// 驗(yàn)證產(chǎn)品是否存在且有庫(kù)存
for (OrderItemRequest item : request.getItems()) {
ProductResponse product = productClient.getProduct(item.getProductId());
if (product == null) {
throw new ProductNotFoundException(item.getProductId());
}
}
// 創(chuàng)建訂單
Order order = new Order();
order.setCustomerId(request.getCustomerId());
order.setItems(mapToOrderItems(request.getItems()));
order.setStatus(OrderStatus.CREATED);
return orderRepository.save(order);
}
}4. Feign客戶端定義
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/api/products/{productId}")
ProductResponse getProduct(@PathVariable("productId") String productId);
@GetMapping("/api/products")
List<ProductResponse> getAllProducts();
@PostMapping("/api/products/{productId}/reserve")
void reserveProduct(@PathVariable("productId") String productId, @RequestBody ReserveRequest request);
}5. 服務(wù)注冊(cè)與發(fā)現(xiàn)(Eureka)
# application.yml
spring:
application:
name: order-service
eureka:
client:
serviceUrl:
defaultZone: http://eureka-server:8761/eureka/
instance:
preferIpAddress: true6. API網(wǎng)關(guān)配置(Spring Cloud Gateway)
# gateway application.yml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**優(yōu)缺點(diǎn)分析
優(yōu)點(diǎn):
- 服務(wù)獨(dú)立部署和擴(kuò)展
- 技術(shù)??梢远鄻踊?/li>
- 故障隔離
- 適合大型團(tuán)隊(duì)并行開(kāi)發(fā)
- 支持按需擴(kuò)展高負(fù)載服務(wù)
缺點(diǎn):
- 分布式系統(tǒng)復(fù)雜性
- 運(yùn)維挑戰(zhàn)
- 跨服務(wù)調(diào)試?yán)щy
- 數(shù)據(jù)一致性難保證
- 網(wǎng)絡(luò)延遲和故障處理
適用場(chǎng)景
• 大型復(fù)雜系統(tǒng)
• 需要高可擴(kuò)展性的場(chǎng)景
• 多團(tuán)隊(duì)協(xié)作開(kāi)發(fā)
• 對(duì)不同組件有不同擴(kuò)展需求
六、方案對(duì)比
| 模塊化方式 | 復(fù)雜度 | 團(tuán)隊(duì)協(xié)作 | 部署獨(dú)立性 | 開(kāi)發(fā)效率 | 適合規(guī)模 |
|---|---|---|---|---|---|
| Maven多模塊 | 低 | 中 | 低 | 高 | 小到中型 |
| Profiles功能模塊 | 低 | 低 | 低 | 高 | 小型 |
| Spring Boot Starter | 中 | 中 | 中 | 中 | 中型 |
| DDD模塊化 | 高 | 高 | 中 | 中 | 中到大型 |
| 微服務(wù) | 高 | 高 | 高 | 低 | 大型 |
七、總結(jié)
SpringBoot模塊化開(kāi)發(fā)提供了多種組織方式,每種方式都有其適用場(chǎng)景和優(yōu)缺點(diǎn)。
選擇合適的模塊化策略應(yīng)考慮項(xiàng)目規(guī)模、團(tuán)隊(duì)結(jié)構(gòu)、業(yè)務(wù)復(fù)雜度和未來(lái)演進(jìn)方向。
最重要的是,模塊化應(yīng)該是漸進(jìn)式的過(guò)程,隨著項(xiàng)目的發(fā)展不斷調(diào)整和優(yōu)化模塊結(jié)構(gòu),以適應(yīng)不斷變化的業(yè)務(wù)需求和技術(shù)環(huán)境。
無(wú)論選擇哪種模塊化方式,清晰的模塊邊界、良好的接口設(shè)計(jì)和適當(dāng)?shù)鸟詈隙瓤刂贫际浅晒Φ年P(guān)鍵因素。
通過(guò)合理的模塊化,我們可以構(gòu)建出更加靈活、可維護(hù)且適應(yīng)未來(lái)變化的應(yīng)用。
以上就是SpringBoot進(jìn)行模塊化開(kāi)發(fā)的5種組織方式小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot模塊化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何實(shí)現(xiàn)Java的ArrayList經(jīng)典實(shí)體類(lèi)
ArrayList是Java集合框架中一個(gè)經(jīng)典的實(shí)現(xiàn)類(lèi)。他比起常用的數(shù)組而言,明顯的優(yōu)點(diǎn)在于,可以隨意的添加和刪除元素而不需考慮數(shù)組的大小。下面跟著小編一起來(lái)看下吧2017-02-02
Java嵌套for循環(huán)的幾種常見(jiàn)優(yōu)化方案
這篇文章主要給大家介紹了關(guān)于Java嵌套for循環(huán)的幾種常見(jiàn)優(yōu)化,在Java中優(yōu)化嵌套for循環(huán)可以通過(guò)以下幾種方式來(lái)提高性能和效率,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
MyBatis之foreach標(biāo)簽的用法及多種循環(huán)問(wèn)題
這篇文章主要介紹了MyBatis之foreach標(biāo)簽的用法及多種循環(huán)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
SpringBoot使用MyBatis實(shí)現(xiàn)數(shù)據(jù)的CRUD
MyBatis是一個(gè)輕量級(jí)的對(duì)象關(guān)系映射(Object-Relational Mapping,ORM)框架,它允許開(kāi)發(fā)者通過(guò)編寫(xiě)SQL動(dòng)態(tài)查詢數(shù)據(jù)庫(kù),而無(wú)需顯式地操作JDBC,對(duì)于增刪改查操作,MyBatis提供了一種基于XML或注解的方式來(lái)進(jìn)行,本文介紹了SpringBoot使用MyBatis實(shí)現(xiàn)數(shù)據(jù)的CRUD2024-11-11
Java Web使用Html5 FormData實(shí)現(xiàn)多文件上傳功能
這篇文章主要介紹了Java Web使用Html5 FormData實(shí)現(xiàn)多文件上傳功能,需要的朋友可以參考下2017-07-07
使用java批量寫(xiě)入環(huán)境變量的實(shí)現(xiàn)
本文主要介紹了使用java批量寫(xiě)入環(huán)境變量,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03

