项目结构
本指南介绍 LCGYL Framework 项目的标准目录结构和组织方式。
标准项目结构
基础结构
my-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── myapp/
│ │ │ ├── Application.java # 主应用类
│ │ │ ├── config/ # 配置类
│ │ │ ├── controller/ # 控制器(Web)
│ │ │ ├── service/ # 业务逻辑
│ │ │ ├── repository/ # 数据访问
│ │ │ ├── model/ # 领域模型
│ │ │ ├── dto/ # 数据传输对象
│ │ │ ├── event/ # 事件定义
│ │ │ ├── listener/ # 事件监听器
│ │ │ └── util/ # 工具类
│ │ └── resources/
│ │ ├── application.properties # 主配置文件
│ │ ├── application-dev.properties # 开发环境配置
│ │ ├── application-prod.properties # 生产环境配置
│ │ ├── logback.xml # 日志配置
│ │ └── static/ # 静态资源
│ └── test/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── myapp/
│ │ ├── service/ # 服务测试
│ │ ├── repository/ # 数据访问测试
│ │ └── integration/ # 集成测试
│ └── resources/
│ └── application-test.properties # 测试配置
├── build.gradle # Gradle 构建文件
├── settings.gradle # Gradle 设置
├── README.md # 项目说明
└── .gitignore # Git 忽略文件目录说明
源码目录 (src/main/java)
Application.java - 主应用类
应用的入口点,负责启动框架。
java
package com.example.myapp;
import com.lcgyl.core.application.LcgylApplication;
import com.lcgyl.core.application.annotation.ComponentScan;
@ComponentScan("com.example.myapp")
public class Application {
public static void main(String[] args) {
LcgylApplication app = LcgylApplication.run(Application.class, args);
System.out.println("应用启动成功!");
}
}config/ - 配置类
存放应用配置相关的类。
java
package com.example.myapp.config;
import com.lcgyl.framework.core.annotation.Component;
import com.lcgyl.framework.core.annotation.Value;
@Component
public class AppConfig {
@Value("app.name")
private String appName;
@Value("app.version")
private String version;
// Getters
}controller/ - 控制器
处理 HTTP 请求(Web 应用)。
java
package com.example.myapp.controller;
import com.lcgyl.web.annotation.RestController;
import com.lcgyl.web.annotation.GetMapping;
import com.lcgyl.framework.core.annotation.Inject;
@RestController("/api/users")
public class UserController {
@Inject
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}service/ - 业务逻辑
包含应用的核心业务逻辑。
java
package com.example.myapp.service;
import com.lcgyl.framework.core.annotation.Component;
import com.lcgyl.framework.core.annotation.Inject;
@Component
public class UserService {
@Inject
private UserRepository userRepository;
@Inject
private EventBus eventBus;
public User createUser(String name) {
User user = new User(name);
userRepository.save(user);
eventBus.publish(new UserCreatedEvent(user));
return user;
}
public User findById(Long id) {
return userRepository.findById(id);
}
}repository/ - 数据访问
负责数据持久化操作。
java
package com.example.myapp.repository;
import com.lcgyl.framework.core.annotation.Component;
import com.lcgyl.data.annotation.Repository;
@Component
@Repository
public class UserRepository {
@Inject
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, User.class, id);
}
public void save(User user) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
jdbcTemplate.update(sql, user.getName(), user.getEmail());
}
}model/ - 领域模型
定义业务实体。
java
package com.example.myapp.model;
public class User {
private Long id;
private String name;
private String email;
// 构造器、Getters、Setters
}dto/ - 数据传输对象
用于 API 请求和响应。
java
package com.example.myapp.dto;
public record UserRequest(String name, String email) {
}
public record UserResponse(Long id, String name, String email) {
}event/ - 事件定义
定义应用事件。
java
package com.example.myapp.event;
import com.lcgyl.framework.core.event.Event;
public record UserCreatedEvent(User user) implements Event {
}listener/ - 事件监听器
处理应用事件。
java
package com.example.myapp.listener;
import com.lcgyl.framework.core.annotation.Component;
import com.lcgyl.framework.core.event.Subscribe;
@Component
public class UserEventListener {
@Subscribe
public void onUserCreated(UserCreatedEvent event) {
System.out.println("用户创建:" + event.user().getName());
}
}util/ - 工具类
通用工具方法。
java
package com.example.myapp.util;
public class StringUtils {
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
}资源目录 (src/main/resources)
application.properties - 主配置文件
properties
# 应用配置
app.name=MyApp
app.version=1.0.0
# 服务器配置
server.port=8080
server.host=localhost
# 数据库配置
datasource.url=jdbc:mysql://localhost:3306/myapp
datasource.username=root
datasource.password=password
# 日志配置
logging.level.root=INFO
logging.level.com.example.myapp=DEBUGapplication-dev.properties - 开发环境
properties
# 开发环境配置
server.port=8080
datasource.url=jdbc:mysql://localhost:3306/myapp_dev
logging.level.root=DEBUGapplication-prod.properties - 生产环境
properties
# 生产环境配置
server.port=80
datasource.url=jdbc:mysql://prod-db:3306/myapp
logging.level.root=WARNlogback.xml - 日志配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>测试目录 (src/test/java)
单元测试
java
package com.example.myapp.service;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import static org.testng.Assert.*;
import static org.mockito.Mockito.*;
public class UserServiceTest {
private UserService userService;
private UserRepository userRepository;
@BeforeMethod
public void setUp() {
userRepository = mock(UserRepository.class);
userService = new UserService(userRepository);
}
@Test
public void testFindById() {
// Given
User user = new User(1L, "张三");
when(userRepository.findById(1L)).thenReturn(user);
// When
User result = userService.findById(1L);
// Then
assertNotNull(result);
assertEquals(result.getName(), "张三");
}
}集成测试
java
package com.example.myapp.integration;
import org.testng.annotations.Test;
import com.lcgyl.core.application.LcgylApplication;
public class ApplicationIntegrationTest {
@Test
public void testApplicationStartup() {
LcgylApplication app = LcgylApplication.run(Application.class);
assertNotNull(app);
app.stop();
}
}构建文件
build.gradle
gradle
plugins {
id 'java'
id 'application'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '21'
repositories {
mavenCentral()
}
dependencies {
// LCGYL Framework
implementation 'com.lcgyl:lcgyl-framework-core:2.2.0'
implementation 'com.lcgyl:lcgyl-web-plugin:2.2.0'
implementation 'com.lcgyl:lcgyl-data-plugin:2.2.0'
// 日志
implementation 'org.slf4j:slf4j-api:2.0.9'
runtimeOnly 'ch.qos.logback:logback-classic:1.4.14'
// 测试
testImplementation 'org.testng:testng:7.8.0'
testImplementation 'org.mockito:mockito-core:5.7.0'
}
application {
mainClass = 'com.example.myapp.Application'
}
test {
useTestNG()
}最佳实践
1. 包命名规范
com.{company}.{project}.{module}
示例:
com.example.myapp.user.service
com.example.myapp.order.repository2. 类命名规范
- Controller:
UserController、OrderController - Service:
UserService、OrderService - Repository:
UserRepository、OrderRepository - Model:
User、Order - DTO:
UserRequest、UserResponse - Event:
UserCreatedEvent、OrderPlacedEvent - Listener:
UserEventListener、OrderEventListener
3. 文件组织
✅ 按功能模块组织(推荐)
com.example.myapp/
├── user/
│ ├── UserController.java
│ ├── UserService.java
│ ├── UserRepository.java
│ └── User.java
└── order/
├── OrderController.java
├── OrderService.java
├── OrderRepository.java
└── Order.java
✅ 按层次组织(也可以)
com.example.myapp/
├── controller/
│ ├── UserController.java
│ └── OrderController.java
├── service/
│ ├── UserService.java
│ └── OrderService.java
└── repository/
├── UserRepository.java
└── OrderRepository.java4. 配置文件组织
resources/
├── application.properties # 通用配置
├── application-dev.properties # 开发环境
├── application-test.properties # 测试环境
├── application-prod.properties # 生产环境
├── logback.xml # 日志配置
└── db/
├── schema.sql # 数据库表结构
└── data.sql # 初始化数据5. 测试文件组织
test/java/
├── unit/ # 单元测试
│ ├── service/
│ └── repository/
├── integration/ # 集成测试
│ └── api/
└── performance/ # 性能测试多模块项目
结构示例
my-app/
├── my-app-api/ # API 模块
│ └── src/main/java/
│ └── com/example/myapp/api/
├── my-app-service/ # 服务模块
│ └── src/main/java/
│ └── com/example/myapp/service/
├── my-app-repository/ # 数据访问模块
│ └── src/main/java/
│ └── com/example/myapp/repository/
├── my-app-common/ # 公共模块
│ └── src/main/java/
│ └── com/example/myapp/common/
└── settings.gradlesettings.gradle
gradle
rootProject.name = 'my-app'
include 'my-app-api'
include 'my-app-service'
include 'my-app-repository'
include 'my-app-common'