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: 包含通用工具類、基礎(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. 定義不同功能模塊的配置類
@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)配置類
@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. 配置屬性類
@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)配置類 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ì)中?;贒DD的模塊化將系統(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: true
6. 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í)體類
ArrayList是Java集合框架中一個(gè)經(jīng)典的實(shí)現(xiàn)類。他比起常用的數(shù)組而言,明顯的優(yōu)點(diǎn)在于,可以隨意的添加和刪除元素而不需考慮數(shù)組的大小。下面跟著小編一起來(lái)看下吧2017-02-02Java嵌套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-07MyBatis之foreach標(biāo)簽的用法及多種循環(huán)問(wèn)題
這篇文章主要介紹了MyBatis之foreach標(biāo)簽的用法及多種循環(huán)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11SpringBoot使用MyBatis實(shí)現(xiàn)數(shù)據(jù)的CRUD
MyBatis是一個(gè)輕量級(jí)的對(duì)象關(guān)系映射(Object-Relational Mapping,ORM)框架,它允許開(kāi)發(fā)者通過(guò)編寫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-11Java Web使用Html5 FormData實(shí)現(xiàn)多文件上傳功能
這篇文章主要介紹了Java Web使用Html5 FormData實(shí)現(xiàn)多文件上傳功能,需要的朋友可以參考下2017-07-07使用java批量寫入環(huán)境變量的實(shí)現(xiàn)
本文主要介紹了使用java批量寫入環(huán)境變量,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03