feat(oss): 增强OSS存储功能
- 新增MinioConfig配置类,支持Minio对象存储 - 新增MinioStorageService实现,提供完整的Minio存储操作 - 优化OssAutoConfiguration自动配置,增强扩展性 - 改进LocalStorageService本地存储服务 - 完善StorageServiceFactory存储服务工厂 - 更新OSS插件依赖配置
This commit is contained in:
parent
1127319f22
commit
e3e992e5a3
@ -25,7 +25,12 @@
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>3.17.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MinIO SDK -->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Configuration Processor -->
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
package org.leocoder.thin.oss.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* MinIO配置类
|
||||
*
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "coder.minio")
|
||||
public class MinioConfig {
|
||||
|
||||
/**
|
||||
* MinIO服务端点
|
||||
*/
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* Access Key
|
||||
*/
|
||||
private String accessKey;
|
||||
|
||||
/**
|
||||
* Secret Key
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 存储桶名称
|
||||
*/
|
||||
private String bucketName;
|
||||
|
||||
/**
|
||||
* 自定义域名
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 路径前缀
|
||||
*/
|
||||
private String pathPrefix = "coder-files";
|
||||
|
||||
/**
|
||||
* 连接超时时间(毫秒)
|
||||
*/
|
||||
private Long connectTimeout = 10000L;
|
||||
|
||||
/**
|
||||
* 写入超时时间(毫秒)
|
||||
*/
|
||||
private Long writeTimeout = 10000L;
|
||||
|
||||
/**
|
||||
* 读取超时时间(毫秒)
|
||||
*/
|
||||
private Long readTimeout = 10000L;
|
||||
|
||||
/**
|
||||
* 是否启用MinIO存储
|
||||
*/
|
||||
private Boolean enabled = false;
|
||||
|
||||
/**
|
||||
* 区域设置(可选)
|
||||
*/
|
||||
private String region;
|
||||
}
|
||||
@ -3,8 +3,10 @@ package org.leocoder.thin.oss.config;
|
||||
import com.aliyun.oss.ClientBuilderConfiguration;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import io.minio.MinioClient;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.leocoder.thin.oss.service.LocalStorageService;
|
||||
import org.leocoder.thin.oss.service.MinioStorageService;
|
||||
import org.leocoder.thin.oss.service.OssStorageService;
|
||||
import org.leocoder.thin.oss.service.StorageServiceFactory;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@ -21,7 +23,7 @@ import org.springframework.core.env.Environment;
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(OssConfig.class)
|
||||
@EnableConfigurationProperties({OssConfig.class, MinioConfig.class})
|
||||
@Slf4j
|
||||
public class OssAutoConfiguration {
|
||||
|
||||
@ -101,6 +103,57 @@ public class OssAutoConfiguration {
|
||||
return new LocalStorageService(environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [MinIO客户端配置]
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "coder.minio.enabled", havingValue = "true")
|
||||
@ConditionalOnMissingBean
|
||||
public MinioClient minioClient(MinioConfig minioConfig) {
|
||||
log.info("初始化MinIO客户端: endpoint={}, bucketName={}",
|
||||
minioConfig.getEndpoint(), minioConfig.getBucketName());
|
||||
|
||||
try {
|
||||
MinioClient.Builder builder = MinioClient.builder()
|
||||
.endpoint(minioConfig.getEndpoint())
|
||||
.credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey());
|
||||
|
||||
// 如果配置了区域,则设置区域
|
||||
if (minioConfig.getRegion() != null && !minioConfig.getRegion().trim().isEmpty()) {
|
||||
builder.region(minioConfig.getRegion());
|
||||
}
|
||||
|
||||
MinioClient minioClient = builder.build();
|
||||
|
||||
// 设置超时时间
|
||||
minioClient.setTimeout(
|
||||
minioConfig.getConnectTimeout(),
|
||||
minioConfig.getWriteTimeout(),
|
||||
minioConfig.getReadTimeout()
|
||||
);
|
||||
|
||||
log.info("MinIO客户端初始化成功");
|
||||
return minioClient;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("MinIO客户端初始化失败", e);
|
||||
throw new RuntimeException("MinIO客户端初始化失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [MinIO存储服务]
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "coder.minio.enabled", havingValue = "true")
|
||||
@ConditionalOnMissingBean
|
||||
public MinioStorageService minioStorageService(MinioClient minioClient, MinioConfig minioConfig) {
|
||||
log.info("初始化MinIO存储服务");
|
||||
return new MinioStorageService(minioClient, minioConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [存储服务工厂(始终可用)]
|
||||
* @author Leocoder
|
||||
|
||||
@ -50,18 +50,7 @@ public class LocalStorageService implements StorageService {
|
||||
// 使用现有的上传工具类
|
||||
Map<String, Object> fileMap = UploadUtil.coderSingleFile(file, fullPath, 2);
|
||||
|
||||
// 生成访问URL
|
||||
String fileUploadPath = (String) fileMap.get("fileUploadPath");
|
||||
String protocol = IpUtil.getProtocol(ServletUtil.getRequest());
|
||||
if (!StringUtils.hasText(protocol)) {
|
||||
protocol = "http";
|
||||
}
|
||||
String hostIp = IpUtil.getHostIp(ServletUtil.getRequest());
|
||||
String hostPort = StringUtils.hasText(env.getProperty("server.port")) ?
|
||||
env.getProperty("server.port") : "18099";
|
||||
|
||||
String fullUrl = protocol + "://" + hostIp + ":" + hostPort + fileUploadPath;
|
||||
fileMap.put("fileUploadPath", fullUrl);
|
||||
// UploadUtil已经返回了正确的相对路径,不需要再次构建URL
|
||||
|
||||
log.info("本地存储上传成功: {}", fileMap.get("filePath"));
|
||||
return fileMap;
|
||||
|
||||
@ -0,0 +1,229 @@
|
||||
package org.leocoder.thin.oss.service;
|
||||
|
||||
import io.minio.*;
|
||||
import io.minio.errors.ErrorResponseException;
|
||||
import io.minio.http.Method;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.leocoder.thin.common.constants.CoderConstants;
|
||||
import org.leocoder.thin.common.exception.BusinessException;
|
||||
import org.leocoder.thin.common.utils.file.FileTypeUtil;
|
||||
import org.leocoder.thin.oss.config.MinioConfig;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* MinIO对象存储服务实现
|
||||
*
|
||||
* @author Leocoder
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "coder.minio.enabled", havingValue = "true")
|
||||
public class MinioStorageService implements StorageService {
|
||||
|
||||
private final MinioClient minioClient;
|
||||
private final MinioConfig minioConfig;
|
||||
|
||||
/**
|
||||
* @description [上传文件到MinIO]
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> uploadFile(MultipartFile file, String fileName, String folderPath) {
|
||||
try {
|
||||
// 确保存储桶存在
|
||||
ensureBucketExists();
|
||||
|
||||
// 构建对象名称
|
||||
String objectName = buildObjectName(folderPath, fileName);
|
||||
|
||||
// 上传文件
|
||||
minioClient.putObject(
|
||||
PutObjectArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.object(objectName)
|
||||
.stream(file.getInputStream(), file.getSize(), -1)
|
||||
.contentType(file.getContentType())
|
||||
.build()
|
||||
);
|
||||
|
||||
// 构建返回结果Map(保持与现有接口兼容)
|
||||
Map<String, Object> fileMap = new HashMap<>();
|
||||
fileMap.put("fileName", file.getOriginalFilename());
|
||||
fileMap.put("newName", fileName);
|
||||
fileMap.put("fileSize", FileTypeUtil.getFileSize(file));
|
||||
fileMap.put("suffixName", FileTypeUtil.getFileType(file.getOriginalFilename()));
|
||||
// MinIO对象名,用于删除操作
|
||||
fileMap.put("filePath", objectName);
|
||||
// 完整的访问URL
|
||||
fileMap.put("fileUploadPath", getFileUrl(objectName));
|
||||
|
||||
log.info("MinIO文件上传成功: {}", fileName);
|
||||
return fileMap;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("MinIO文件上传失败", e);
|
||||
throw new BusinessException(500, "文件上传失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [从MinIO删除文件]
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteFile(String objectName) {
|
||||
try {
|
||||
if (!StringUtils.hasText(objectName)) {
|
||||
log.warn("MinIO对象名为空,跳过删除");
|
||||
return true;
|
||||
}
|
||||
|
||||
log.info("MinIO删除文件: {}", objectName);
|
||||
minioClient.removeObject(
|
||||
RemoveObjectArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.object(objectName)
|
||||
.build()
|
||||
);
|
||||
|
||||
log.info("MinIO删除成功: {}", objectName);
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("MinIO文件删除失败: {}", objectName, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [获取文件访问URL]
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public String getFileUrl(String objectName) {
|
||||
if (!StringUtils.hasText(objectName)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
// 如果配置了自定义域名,构建直接访问URL
|
||||
if (StringUtils.hasText(minioConfig.getDomain())) {
|
||||
String cleanDomain = minioConfig.getDomain().replaceAll("/$", "");
|
||||
String cleanObjectName = objectName.startsWith("/") ? objectName.substring(1) : objectName;
|
||||
String directUrl = cleanDomain + "/" + minioConfig.getBucketName() + "/" + cleanObjectName;
|
||||
return directUrl;
|
||||
}
|
||||
|
||||
// 如果没有自定义域名,使用MinIO的预签名URL(有效期24小时)
|
||||
String presignedUrl = minioClient.getPresignedObjectUrl(
|
||||
GetPresignedObjectUrlArgs.builder()
|
||||
.method(Method.GET)
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.object(objectName)
|
||||
.expiry(24 * 60 * 60)
|
||||
.build()
|
||||
);
|
||||
return presignedUrl;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("生成MinIO文件访问URL失败: {}", objectName, e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [检查文件是否存在]
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public boolean fileExists(String objectName) {
|
||||
try {
|
||||
if (!StringUtils.hasText(objectName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
minioClient.statObject(
|
||||
StatObjectArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.object(objectName)
|
||||
.build()
|
||||
);
|
||||
return true;
|
||||
|
||||
} catch (ErrorResponseException e) {
|
||||
if ("NoSuchKey".equals(e.errorResponse().code())) {
|
||||
return false;
|
||||
}
|
||||
log.error("检查MinIO文件是否存在失败: {}", objectName, e);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
log.error("检查MinIO文件是否存在失败: {}", objectName, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [获取存储服务类型]
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Override
|
||||
public String getStorageType() {
|
||||
// MinIO存储对应数据库中的"2"
|
||||
return CoderConstants.TWO_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [构建MinIO对象名称]
|
||||
* @author Leocoder
|
||||
*/
|
||||
private String buildObjectName(String folderPath, String fileName) {
|
||||
StringBuilder nameBuilder = new StringBuilder();
|
||||
|
||||
// 添加路径前缀
|
||||
if (StringUtils.hasText(minioConfig.getPathPrefix())) {
|
||||
nameBuilder.append(minioConfig.getPathPrefix()).append("/");
|
||||
}
|
||||
|
||||
// 添加文件夹路径
|
||||
if (StringUtils.hasText(folderPath)) {
|
||||
// 确保路径以/结尾
|
||||
String normalizedPath = folderPath.endsWith("/") ? folderPath : folderPath + "/";
|
||||
nameBuilder.append(normalizedPath);
|
||||
}
|
||||
|
||||
// 添加文件名
|
||||
nameBuilder.append(fileName);
|
||||
|
||||
return nameBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [确保存储桶存在]
|
||||
* @author Leocoder
|
||||
*/
|
||||
private void ensureBucketExists() throws Exception {
|
||||
boolean bucketExists = minioClient.bucketExists(
|
||||
BucketExistsArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.build()
|
||||
);
|
||||
|
||||
if (!bucketExists) {
|
||||
log.info("创建MinIO存储桶: {}", minioConfig.getBucketName());
|
||||
minioClient.makeBucket(
|
||||
MakeBucketArgs.builder()
|
||||
.bucket(minioConfig.getBucketName())
|
||||
.region(minioConfig.getRegion())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,20 +48,26 @@ public class StorageServiceFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [获取默认存储服务(OSS优先,如果不可用则使用本地存储)]
|
||||
* @description [获取默认存储服务(MinIO优先,然后OSS,最后本地存储)]
|
||||
* @author Leocoder
|
||||
*/
|
||||
public StorageService getDefaultStorageService() {
|
||||
try {
|
||||
// 优先尝试获取OSS服务
|
||||
return getStorageService("oss");
|
||||
// 优先尝试获取MinIO服务
|
||||
return getStorageService("minio");
|
||||
} catch (Exception e) {
|
||||
log.warn("OSS服务不可用,使用本地存储作为降级方案", e);
|
||||
log.warn("MinIO服务不可用,尝试OSS服务", e);
|
||||
try {
|
||||
return getStorageService("local");
|
||||
// 尝试获取OSS服务
|
||||
return getStorageService("oss");
|
||||
} catch (Exception ex) {
|
||||
log.error("本地存储服务也不可用", ex);
|
||||
throw new BusinessException(500, "没有可用的存储服务");
|
||||
log.warn("OSS服务不可用,使用本地存储作为降级方案", ex);
|
||||
try {
|
||||
return getStorageService("local");
|
||||
} catch (Exception localEx) {
|
||||
log.error("本地存储服务也不可用", localEx);
|
||||
throw new BusinessException(500, "没有可用的存储服务");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,6 +84,8 @@ public class StorageServiceFactory {
|
||||
return serviceClassName.contains("local");
|
||||
case "oss":
|
||||
return serviceClassName.contains("oss");
|
||||
case "minio":
|
||||
return serviceClassName.contains("minio");
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
477
script/README.md
477
script/README.md
@ -1,477 +0,0 @@
|
||||
# 项目重构脚本使用指南
|
||||
|
||||
这是一套用于Maven项目重构和包名修复的自动化脚本,可以帮助你快速将一个项目模板重构为新的项目,并修复常见的包名重复问题。
|
||||
|
||||
## 📋 脚本概览
|
||||
|
||||
本目录包含了用于项目重构和包名修复的自动化脚本:
|
||||
|
||||
### 🔧 脚本文件说明
|
||||
|
||||
```
|
||||
script/
|
||||
├── project-refactor.sh # ⭐ 主要推荐:完整重构脚本
|
||||
├── simple-fix.sh # ⭐ 简单修复脚本
|
||||
├── fix-duplicate-packages.sh # 专门修复重复包名
|
||||
├── fix-directory-structure.sh # 目录结构重建脚本
|
||||
├── batch-refactor.sh # 批量重构脚本(配置文件)
|
||||
├── refactor-config.example # 配置文件模板
|
||||
└── README.md # 本使用说明文件
|
||||
```
|
||||
|
||||
## 🎯 脚本选择建议
|
||||
|
||||
### 1. **主要推荐:`project-refactor.sh`** ⭐⭐⭐⭐⭐
|
||||
|
||||
**适用场景**:
|
||||
- 完整的项目重构(包名、模块名、数据库名等全面修改)
|
||||
- 从一个框架模板创建新项目
|
||||
- 大规模的包名重构
|
||||
|
||||
**功能特点**:
|
||||
- ✅ 功能最完整(POM文件、Java文件、XML文件、配置文件全覆盖)
|
||||
- ✅ 有备份功能
|
||||
- ✅ 有验证步骤
|
||||
- ✅ 支持嵌套模块处理
|
||||
- ✅ **已修复包名重复问题**
|
||||
|
||||
### 2. **简单场景:`simple-fix.sh`** ⭐⭐⭐
|
||||
|
||||
**适用场景**:
|
||||
- 只需要修复包名重复问题
|
||||
- 简单的包名调整
|
||||
- 紧急修复
|
||||
|
||||
**功能特点**:
|
||||
- ✅ 执行速度快
|
||||
- ✅ 逻辑简单可靠
|
||||
- ✅ 不需要交互
|
||||
|
||||
### 3. **备用选择:`fix-duplicate-packages.sh`** ⭐⭐
|
||||
|
||||
**适用场景**:
|
||||
- 专门修复包名重复问题
|
||||
- 需要详细的检测报告
|
||||
|
||||
## 🚀 新项目重构完整指南
|
||||
|
||||
### 步骤 1: 准备工作
|
||||
|
||||
1. **确保项目已提交到Git**
|
||||
```bash
|
||||
cd /path/to/your/new/project
|
||||
git status
|
||||
git add .
|
||||
git commit -m "Initial commit before refactoring"
|
||||
```
|
||||
|
||||
2. **准备重构信息**
|
||||
- 新的包名信息(如:`org.leocoder.newproject`)
|
||||
- 新的模块前缀(如:`coder-newproject`)
|
||||
- 新的数据库名称(可选)
|
||||
|
||||
### 步骤 2: 执行重构脚本
|
||||
|
||||
```bash
|
||||
# 进入项目目录
|
||||
cd /path/to/your/new/project
|
||||
|
||||
# 执行完整重构脚本
|
||||
bash script/project-refactor.sh
|
||||
```
|
||||
|
||||
### 步骤 3: 交互式配置
|
||||
|
||||
脚本会提示你输入以下信息:
|
||||
|
||||
#### 3.1 项目目录
|
||||
```
|
||||
请输入项目根目录路径 (默认: 当前目录):
|
||||
项目路径: [直接回车使用当前目录]
|
||||
```
|
||||
|
||||
#### 3.2 旧配置信息
|
||||
```
|
||||
旧的 GroupId (例如: org.leocoder.thin): org.leocoder.estate
|
||||
旧的 ArtifactId (例如: coder-common-thin-backend): coder-estate-backend
|
||||
旧的模块前缀 (例如: coder-common-thin): coder-estate
|
||||
```
|
||||
|
||||
#### 3.3 新配置信息
|
||||
```
|
||||
新的 GroupId (例如: org.leocoder.course): org.leocoder.newproject
|
||||
新的 ArtifactId (例如: coder-course-backend): coder-newproject-backend
|
||||
新的模块前缀 (例如: coder-course): coder-newproject
|
||||
```
|
||||
|
||||
#### 3.4 数据库配置(可选)
|
||||
```
|
||||
旧的数据库名称 (留空跳过): coder_estate
|
||||
新的数据库名称: coder_newproject
|
||||
```
|
||||
|
||||
#### 3.5 确认执行
|
||||
```
|
||||
是否创建备份? (Y/n): Y
|
||||
是否继续重构? (y/N): y
|
||||
```
|
||||
|
||||
### 步骤 4: 验证重构结果
|
||||
|
||||
#### 4.1 检查目录结构
|
||||
```bash
|
||||
# 检查是否还有重复目录
|
||||
find . -type d -path "*/org/leocoder/org/leocoder*"
|
||||
|
||||
# 应该没有任何输出,如果有输出说明还存在重复目录
|
||||
```
|
||||
|
||||
#### 4.2 检查包名
|
||||
```bash
|
||||
# 检查Java文件包名是否正确
|
||||
grep -r "package org.leocoder" . --include="*.java" | head -5
|
||||
|
||||
# 输出应该类似:
|
||||
# ./src/main/java/org/leocoder/newproject/web/Application.java:package org.leocoder.newproject.web;
|
||||
```
|
||||
|
||||
#### 4.3 检查import语句
|
||||
```bash
|
||||
# 检查import语句是否正确
|
||||
grep -r "import org.leocoder" . --include="*.java" | head -5
|
||||
|
||||
# 输出应该使用新的包名
|
||||
```
|
||||
|
||||
#### 4.4 编译验证
|
||||
```bash
|
||||
# 重新编译项目
|
||||
mvn clean compile
|
||||
|
||||
# 如果编译成功,说明重构正确
|
||||
```
|
||||
|
||||
### 步骤 5: 测试验证
|
||||
|
||||
```bash
|
||||
# 运行测试
|
||||
mvn test
|
||||
|
||||
# 启动应用(如果是Spring Boot项目)
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
## 🛠️ 常见问题处理
|
||||
|
||||
### 问题 1: 发现重复包名目录
|
||||
|
||||
**症状**:
|
||||
```bash
|
||||
find . -type d -path "*/org/leocoder/org/leocoder*"
|
||||
# 有输出,存在重复目录
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 使用简单修复脚本
|
||||
bash script/simple-fix.sh
|
||||
```
|
||||
|
||||
### 问题 2: 编译失败
|
||||
|
||||
**可能原因**:
|
||||
- 包名引用不一致
|
||||
- import语句错误
|
||||
- 配置文件中的包名未更新
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查具体错误信息
|
||||
mvn clean compile
|
||||
|
||||
# 2. 手动检查和修复特定文件
|
||||
grep -r "org\.leocoder\.estate" . --include="*.java"
|
||||
grep -r "org\.leocoder\.estate" . --include="*.xml"
|
||||
grep -r "org\.leocoder\.estate" . --include="*.yml"
|
||||
|
||||
# 3. 如果需要,再次运行修复脚本
|
||||
bash script/fix-duplicate-packages.sh
|
||||
```
|
||||
|
||||
### 问题 3: IDE中显示错误
|
||||
|
||||
**解决方案**:
|
||||
1. **刷新项目**:在IDE中刷新整个项目
|
||||
2. **重新导入**:重新导入Maven项目
|
||||
3. **清理缓存**:清理IDE缓存和索引
|
||||
4. **重启IDE**:重启开发环境
|
||||
|
||||
## 📚 方法二:配置文件批量重构(推荐批量处理)
|
||||
|
||||
```bash
|
||||
# 1. 复制配置文件模板
|
||||
cp refactor-config.example my-project.conf
|
||||
|
||||
# 2. 编辑配置文件
|
||||
vim my-project.conf
|
||||
|
||||
# 3. 运行批量重构
|
||||
./batch-refactor.sh my-project.conf
|
||||
```
|
||||
|
||||
#### 配置文件格式
|
||||
|
||||
```bash
|
||||
# 项目基本信息
|
||||
PROJECT_DIR="/path/to/your/project"
|
||||
|
||||
# 旧配置
|
||||
OLD_GROUP_ID="org.leocoder.thin"
|
||||
OLD_ARTIFACT_ID="coder-common-thin-backend"
|
||||
OLD_MODULE_PREFIX="coder-common-thin"
|
||||
OLD_DATABASE_NAME="coder-common-thin"
|
||||
|
||||
# 新配置
|
||||
NEW_GROUP_ID="org.leocoder.course"
|
||||
NEW_ARTIFACT_ID="coder-course-backend"
|
||||
NEW_MODULE_PREFIX="coder-course"
|
||||
NEW_DATABASE_NAME="coder-course"
|
||||
|
||||
# 其他选项
|
||||
CREATE_BACKUP="true" # 是否创建备份
|
||||
AUTO_CONFIRM="false" # 是否自动确认(跳过确认步骤)
|
||||
```
|
||||
|
||||
## 📋 脚本详细说明
|
||||
|
||||
### `project-refactor.sh` 执行步骤
|
||||
|
||||
1. **步骤 1**: 获取重构参数
|
||||
2. **步骤 2**: 配置摘要确认
|
||||
3. **步骤 3**: 备份项目
|
||||
4. **步骤 4**: 修改 POM 文件
|
||||
5. **步骤 5**: 修改 Java 包名
|
||||
6. **步骤 6**: 修改 XML 映射文件
|
||||
7. **步骤 7**: 修改配置文件
|
||||
8. **步骤 8**: 重命名目录结构
|
||||
9. **步骤 9**: 处理遗漏的嵌套模块
|
||||
10. **步骤 10**: 修复重复包名
|
||||
11. **步骤 11**: 重命名 SQL 文件
|
||||
12. **步骤 12**: 清理和验证
|
||||
|
||||
### `simple-fix.sh` 执行内容
|
||||
|
||||
- 删除错误的目录结构
|
||||
- 清理空目录
|
||||
- 修复Java文件中的包名
|
||||
- 修复XML文件中的包名
|
||||
- 验证修复结果
|
||||
|
||||
## 🔧 重构内容说明
|
||||
|
||||
脚本会自动处理以下内容:
|
||||
|
||||
### 1. POM文件修改
|
||||
- ✅ 修改根POM和所有子模块的 `<groupId>`
|
||||
- ✅ 修改根POM和所有子模块的 `<artifactId>`
|
||||
- ✅ 修改 `<name>` 标签
|
||||
- ✅ 修改 `<module>` 引用
|
||||
- ✅ 修改依赖引用中的groupId和artifactId
|
||||
|
||||
### 2. Java源码修改
|
||||
- ✅ 修改所有Java文件的 `package` 声明
|
||||
- ✅ 修改所有Java文件的 `import` 语句
|
||||
- ✅ 修改注解中的包名引用(如@SpringBootApplication的scanBasePackages)
|
||||
|
||||
### 3. XML映射文件
|
||||
- ✅ 修改MyBatis Mapper文件的 `namespace`
|
||||
- ✅ 修改 `resultType` 中的包名引用
|
||||
|
||||
### 4. 配置文件
|
||||
- ✅ 修改YAML/Properties文件中的包扫描配置
|
||||
- ✅ 修改数据库连接配置中的数据库名
|
||||
- ✅ 修改文件路径配置
|
||||
|
||||
### 5. 目录结构重构
|
||||
- ✅ 重命名Java包目录结构(src/main/java/com/old/package → src/main/java/com/new/package)
|
||||
- ✅ 重命名模块目录(old-module-name → new-module-name)
|
||||
- ✅ 重命名SQL文件
|
||||
- ✅ **修复重复包名问题**
|
||||
|
||||
## 🎯 最佳实践
|
||||
|
||||
### 重构流程建议
|
||||
|
||||
```bash
|
||||
# 1. 创建新分支
|
||||
git checkout -b refactor-to-newproject
|
||||
|
||||
# 2. 执行重构
|
||||
bash script/project-refactor.sh
|
||||
|
||||
# 3. 验证结果
|
||||
mvn clean compile
|
||||
mvn test
|
||||
|
||||
# 4. 提交变更
|
||||
git add .
|
||||
git commit -m "refactor: change package from org.leocoder.estate to org.leocoder.newproject"
|
||||
|
||||
# 5. 合并到主分支(如果一切正常)
|
||||
git checkout main
|
||||
git merge refactor-to-newproject
|
||||
```
|
||||
|
||||
### 命名规范建议
|
||||
|
||||
- **包名**:`org.leocoder.{项目名}`
|
||||
- **模块前缀**:`coder-{项目名}`
|
||||
- **数据库名**:`coder_{项目名}`
|
||||
|
||||
### 示例配置
|
||||
|
||||
```
|
||||
# 电商项目示例
|
||||
旧包名: org.leocoder.estate → 新包名: org.leocoder.ecommerce
|
||||
旧模块: coder-estate → 新模块: coder-ecommerce
|
||||
旧数据库: coder_estate → 新数据库: coder_ecommerce
|
||||
|
||||
# 教育项目示例
|
||||
旧包名: org.leocoder.estate → 新包名: org.leocoder.education
|
||||
旧模块: coder-estate → 新模块: coder-education
|
||||
旧数据库: coder_estate → 新数据库: coder_education
|
||||
```
|
||||
|
||||
## 💡 使用示例
|
||||
|
||||
### 示例1:从通用框架改造为选课系统
|
||||
|
||||
```bash
|
||||
# 交互式输入
|
||||
./project-refactor.sh
|
||||
|
||||
# 输入示例:
|
||||
# 项目路径: /Users/leocoder/my-project
|
||||
# 旧的 GroupId: org.leocoder.estate
|
||||
# 旧的 ArtifactId: coder-estate-backend
|
||||
# 旧的模块前缀: coder-estate
|
||||
# 新的 GroupId: org.leocoder.course
|
||||
# 新的 ArtifactId: coder-course-backend
|
||||
# 新的模块前缀: coder-course
|
||||
```
|
||||
|
||||
### 示例2:批量处理多个项目
|
||||
|
||||
```bash
|
||||
# 为选课系统创建配置
|
||||
cat > course-system.conf << EOF
|
||||
PROJECT_DIR="/Users/leocoder/course-project"
|
||||
OLD_GROUP_ID="org.leocoder.estate"
|
||||
OLD_ARTIFACT_ID="coder-estate-backend"
|
||||
OLD_MODULE_PREFIX="coder-estate"
|
||||
NEW_GROUP_ID="org.leocoder.course"
|
||||
NEW_ARTIFACT_ID="coder-course-backend"
|
||||
NEW_MODULE_PREFIX="coder-course"
|
||||
CREATE_BACKUP="true"
|
||||
AUTO_CONFIRM="false"
|
||||
EOF
|
||||
|
||||
# 为库存系统创建配置
|
||||
cat > inventory-system.conf << EOF
|
||||
PROJECT_DIR="/Users/leocoder/inventory-project"
|
||||
OLD_GROUP_ID="org.leocoder.estate"
|
||||
OLD_ARTIFACT_ID="coder-estate-backend"
|
||||
OLD_MODULE_PREFIX="coder-estate"
|
||||
NEW_GROUP_ID="org.leocoder.inventory"
|
||||
NEW_ARTIFACT_ID="coder-inventory-backend"
|
||||
NEW_MODULE_PREFIX="coder-inventory"
|
||||
CREATE_BACKUP="true"
|
||||
AUTO_CONFIRM="false"
|
||||
EOF
|
||||
|
||||
# 执行批量重构
|
||||
./batch-refactor.sh course-system.conf
|
||||
./batch-refactor.sh inventory-system.conf
|
||||
```
|
||||
|
||||
## ⚠️ 重要注意事项
|
||||
|
||||
### 使用前必读
|
||||
|
||||
1. **备份项目**:始终在Git中提交代码后再执行脚本
|
||||
2. **关闭IDE**:执行脚本前关闭IDE,避免文件锁定
|
||||
3. **检查权限**:确保脚本有执行权限(`chmod +x script/*.sh`)
|
||||
4. **逐步验证**:每个步骤完成后都进行验证
|
||||
|
||||
### 安全建议
|
||||
|
||||
1. **测试环境**:先在测试环境中执行,确认无误后再在生产代码中使用
|
||||
2. **分支操作**:建议在新的Git分支中执行重构操作
|
||||
3. **备份重要**:重要项目建议手动备份整个项目目录
|
||||
|
||||
### 重构后需要手动检查的项目
|
||||
- [ ] IDE中的运行配置(主类路径)
|
||||
- [ ] 数据库连接配置
|
||||
- [ ] 第三方服务配置
|
||||
- [ ] 测试用例
|
||||
- [ ] 文档更新
|
||||
|
||||
## 🆘 获取帮助
|
||||
|
||||
如果在使用过程中遇到问题:
|
||||
|
||||
1. **查看日志**:脚本执行过程中的详细日志
|
||||
2. **检查文件**:手动检查具体的错误文件
|
||||
3. **重新执行**:如果部分失败,可以重新执行脚本
|
||||
4. **手动修复**:对于特殊情况,可能需要手动修复部分文件
|
||||
|
||||
### 常见问题
|
||||
|
||||
**Q: 脚本执行后项目无法启动?**
|
||||
A: 检查IDE的运行配置,确保主类路径已更新为新的包名。
|
||||
|
||||
**Q: 某些文件没有被修改?**
|
||||
A: 检查文件是否在target目录下,脚本会跳过编译输出目录。
|
||||
|
||||
**Q: 包名格式验证失败?**
|
||||
A: 确保包名符合Java命名规范,只能包含字母、数字、下划线和点号。
|
||||
|
||||
**Q: 权限被拒绝?**
|
||||
A: 确保脚本有执行权限:`chmod +x *.sh`
|
||||
|
||||
### 调试技巧
|
||||
|
||||
1. **查看详细日志**: 脚本会显示处理的文件信息
|
||||
2. **检查备份**: 如果出现问题,可以从备份恢复
|
||||
3. **分步执行**: 可以注释掉脚本中的某些步骤来分步调试
|
||||
|
||||
## 🔧 扩展功能
|
||||
|
||||
你可以根据需要扩展脚本功能:
|
||||
|
||||
1. **添加新的文件类型**: 在相应的函数中添加处理逻辑
|
||||
2. **自定义替换规则**: 修改sed命令的正则表达式
|
||||
3. **集成到CI/CD**: 将脚本集成到自动化流水线中
|
||||
|
||||
---
|
||||
|
||||
**创建时间**: 2025-01-09
|
||||
**最后更新**: 2025-01-09
|
||||
**版本**: v2.0
|
||||
**作者**: Leocoder
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v2.0 (2025-01-09)
|
||||
- ✅ 新增重复包名检测和修复功能
|
||||
- ✅ 新增 `simple-fix.sh` 快速修复脚本
|
||||
- ✅ 新增 `fix-duplicate-packages.sh` 专门修复重复包名
|
||||
- ✅ 完善了使用指南和最佳实践
|
||||
- ✅ 增加了详细的问题排查步骤
|
||||
- ✅ 优化了目录结构处理逻辑
|
||||
|
||||
### v1.0 (2025-07-06)
|
||||
- ✅ 基础项目重构功能
|
||||
- ✅ 支持POM文件、Java文件、XML文件修改
|
||||
- ✅ 支持配置文件批量处理
|
||||
- ✅ 基础的目录结构重命名功能
|
||||
@ -1,53 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 演示脚本 - 快速测试重构功能
|
||||
# Author: Leocoder
|
||||
|
||||
# 颜色定义
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 项目重构脚本演示 ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo -e "${GREEN}🚀 项目重构自动化脚本已就绪!${NC}"
|
||||
echo ""
|
||||
echo "包含以下脚本文件:"
|
||||
echo "├── project-refactor.sh (交互式重构脚本)"
|
||||
echo "├── batch-refactor.sh (批量重构脚本)"
|
||||
echo "├── refactor-config.example (配置文件模板)"
|
||||
echo "├── README.md (详细使用说明)"
|
||||
echo "└── demo.sh (演示脚本)"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}快速使用方法:${NC}"
|
||||
echo ""
|
||||
echo "1️⃣ 交互式重构(推荐新手):"
|
||||
echo " ./project-refactor.sh"
|
||||
echo ""
|
||||
echo "2️⃣ 批量重构(推荐批量处理):"
|
||||
echo " cp refactor-config.example my-config.conf"
|
||||
echo " vim my-config.conf # 编辑配置"
|
||||
echo " ./batch-refactor.sh my-config.conf"
|
||||
echo ""
|
||||
|
||||
echo -e "${GREEN}✨ 脚本功能特性:${NC}"
|
||||
echo "• 🔄 自动修改 Maven POM 文件"
|
||||
echo "• 📦 批量更新 Java 包名和 import"
|
||||
echo "• 🗂️ 重命名目录结构"
|
||||
echo "• ⚙️ 更新配置文件"
|
||||
echo "• 🗃️ 处理 MyBatis XML 映射"
|
||||
echo "• 💾 可选项目备份"
|
||||
echo "• 📊 详细的进度显示"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}查看完整使用说明:${NC}"
|
||||
echo "cat README.md"
|
||||
echo ""
|
||||
|
||||
echo -e "${GREEN}🎯 现在你可以轻松地将任何 Maven 项目重构为新项目!${NC}"
|
||||
@ -1,286 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 目录结构修复脚本 - 专门修复重复包名目录问题
|
||||
# Author: Leocoder
|
||||
# Version: 1.0
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 全局变量
|
||||
PROJECT_DIR=""
|
||||
|
||||
# 打印信息
|
||||
print_step() {
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${WHITE}$1${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}✗ $1${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${PURPLE}ℹ $1${NC}"
|
||||
}
|
||||
|
||||
# 获取项目目录
|
||||
get_project_dir() {
|
||||
if [ -z "$1" ]; then
|
||||
PROJECT_DIR="$(pwd)"
|
||||
else
|
||||
PROJECT_DIR="$1"
|
||||
fi
|
||||
|
||||
if [ ! -d "$PROJECT_DIR" ]; then
|
||||
print_error "项目目录不存在: $PROJECT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$PROJECT_DIR/pom.xml" ]; then
|
||||
print_error "这不是一个Maven项目"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_success "项目目录: $PROJECT_DIR"
|
||||
}
|
||||
|
||||
# 备份重要文件
|
||||
backup_files() {
|
||||
print_step "步骤 1: 备份重要文件"
|
||||
|
||||
local backup_dir="/tmp/package_fix_backup_$(date +%Y%m%d_%H%M%S)"
|
||||
mkdir -p "$backup_dir"
|
||||
|
||||
# 查找所有Java文件并备份
|
||||
find "$PROJECT_DIR" -name "*.java" | while read java_file; do
|
||||
local rel_path="${java_file#$PROJECT_DIR/}"
|
||||
local target_file="$backup_dir/$rel_path"
|
||||
mkdir -p "$(dirname "$target_file")"
|
||||
cp "$java_file" "$target_file"
|
||||
done
|
||||
|
||||
print_success "文件已备份到: $backup_dir"
|
||||
}
|
||||
|
||||
# 收集所有Java文件
|
||||
collect_java_files() {
|
||||
print_step "步骤 2: 收集所有Java文件"
|
||||
|
||||
local temp_dir="/tmp/java_files_$(date +%Y%m%d_%H%M%S)"
|
||||
mkdir -p "$temp_dir"
|
||||
|
||||
# 查找所有Java文件并复制到临时目录
|
||||
find "$PROJECT_DIR" -name "*.java" -path "*/org/leocoder/*" | while read java_file; do
|
||||
# 提取相对于org的路径
|
||||
local rel_path=$(echo "$java_file" | sed 's|.*/org/leocoder/|org/leocoder/|')
|
||||
local target_file="$temp_dir/$rel_path"
|
||||
|
||||
# 创建目标目录
|
||||
mkdir -p "$(dirname "$target_file")"
|
||||
|
||||
# 复制文件
|
||||
cp "$java_file" "$target_file"
|
||||
|
||||
print_info "收集文件: $rel_path"
|
||||
done
|
||||
|
||||
echo "$temp_dir"
|
||||
}
|
||||
|
||||
# 清理错误的目录结构
|
||||
cleanup_wrong_structure() {
|
||||
print_step "步骤 3: 清理错误的目录结构"
|
||||
|
||||
# 删除所有org目录
|
||||
find "$PROJECT_DIR" -type d -name "org" -path "*/src/main/java/*" | while read org_dir; do
|
||||
print_info "删除目录: $org_dir"
|
||||
rm -rf "$org_dir"
|
||||
done
|
||||
|
||||
print_success "已清理所有org目录"
|
||||
}
|
||||
|
||||
# 重建正确的目录结构
|
||||
rebuild_structure() {
|
||||
print_step "步骤 4: 重建正确的目录结构"
|
||||
|
||||
local temp_dir="$1"
|
||||
local count=0
|
||||
|
||||
# 查找所有Java源码目录
|
||||
find "$PROJECT_DIR" -type d -path "*/src/main/java" | while read java_src_dir; do
|
||||
print_info "处理目录: $java_src_dir"
|
||||
|
||||
# 在每个java目录下重建org/leocoder/estate结构
|
||||
local target_base="$java_src_dir/org/leocoder/estate"
|
||||
mkdir -p "$target_base"
|
||||
|
||||
# 从临时目录复制对应的文件
|
||||
if [ -d "$temp_dir/org/leocoder/estate" ]; then
|
||||
# 获取模块名称来判断应该复制哪些文件
|
||||
local module_name=$(echo "$java_src_dir" | grep -o 'coder-estate-[^/]*' | head -1)
|
||||
|
||||
case "$module_name" in
|
||||
"coder-estate-common")
|
||||
if [ -d "$temp_dir/org/leocoder/estate/common" ]; then
|
||||
cp -r "$temp_dir/org/leocoder/estate/common" "$target_base/"
|
||||
print_info "复制common模块文件"
|
||||
fi
|
||||
;;
|
||||
"coder-estate-model")
|
||||
if [ -d "$temp_dir/org/leocoder/estate/domain" ]; then
|
||||
cp -r "$temp_dir/org/leocoder/estate/domain" "$target_base/"
|
||||
print_info "复制model模块文件"
|
||||
fi
|
||||
;;
|
||||
"coder-estate-system")
|
||||
if [ -d "$temp_dir/org/leocoder/estate/system" ]; then
|
||||
cp -r "$temp_dir/org/leocoder/estate/system" "$target_base/"
|
||||
print_info "复制system模块文件"
|
||||
fi
|
||||
;;
|
||||
"coder-estate-web")
|
||||
if [ -d "$temp_dir/org/leocoder/estate/web" ]; then
|
||||
cp -r "$temp_dir/org/leocoder/estate/web" "$target_base/"
|
||||
print_info "复制web模块文件"
|
||||
fi
|
||||
;;
|
||||
"coder-estate-mybatisplus")
|
||||
if [ -d "$temp_dir/org/leocoder/estate/mybatisplus" ]; then
|
||||
cp -r "$temp_dir/org/leocoder/estate/mybatisplus" "$target_base/"
|
||||
print_info "复制mybatisplus模块文件"
|
||||
fi
|
||||
;;
|
||||
*plugin*)
|
||||
# 处理插件模块
|
||||
local plugin_type=$(echo "$module_name" | sed 's/coder-estate-//')
|
||||
if [ -d "$temp_dir/org/leocoder/estate/$plugin_type" ]; then
|
||||
cp -r "$temp_dir/org/leocoder/estate/$plugin_type" "$target_base/"
|
||||
print_info "复制${plugin_type}插件文件"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
((count++))
|
||||
done
|
||||
|
||||
print_success "已重建 $count 个模块的目录结构"
|
||||
}
|
||||
|
||||
# 修复文件内容中的包名
|
||||
fix_package_names() {
|
||||
print_step "步骤 5: 修复文件内容中的包名"
|
||||
|
||||
local count=0
|
||||
|
||||
# 查找所有Java文件并修复包名
|
||||
find "$PROJECT_DIR" -name "*.java" -path "*/org/leocoder/estate/*" | while read java_file; do
|
||||
# 检查是否包含错误的包名
|
||||
if grep -q "org\.leocoder\.org\.leocoder" "$java_file"; then
|
||||
print_info "修复包名: $(basename "$java_file")"
|
||||
|
||||
# 修复包名
|
||||
sed -i '' 's|org\.leocoder\.org\.leocoder\.estate|org.leocoder.estate|g' "$java_file"
|
||||
sed -i '' 's|org\.leocoder\.org\.leocoder|org.leocoder|g' "$java_file"
|
||||
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已修复 $count 个文件的包名"
|
||||
}
|
||||
|
||||
# 验证修复结果
|
||||
verify_result() {
|
||||
print_step "步骤 6: 验证修复结果"
|
||||
|
||||
# 检查是否还有重复目录
|
||||
local duplicate_dirs=$(find "$PROJECT_DIR" -type d -path "*/org/leocoder/org/leocoder*" 2>/dev/null)
|
||||
if [ -n "$duplicate_dirs" ]; then
|
||||
print_warning "仍然存在重复目录:"
|
||||
echo "$duplicate_dirs"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查Java文件数量
|
||||
local java_count=$(find "$PROJECT_DIR" -name "*.java" -path "*/org/leocoder/estate/*" | wc -l)
|
||||
print_info "Java文件总数: $java_count"
|
||||
|
||||
# 检查模块结构
|
||||
local modules=$(find "$PROJECT_DIR" -type d -path "*/src/main/java/org/leocoder/estate" | wc -l)
|
||||
print_info "模块数量: $modules"
|
||||
|
||||
print_success "目录结构修复完成"
|
||||
}
|
||||
|
||||
# 清理临时文件
|
||||
cleanup_temp() {
|
||||
local temp_dir="$1"
|
||||
if [ -d "$temp_dir" ]; then
|
||||
rm -rf "$temp_dir"
|
||||
print_info "已清理临时文件"
|
||||
fi
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo -e "${CYAN}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 目录结构修复脚本 ║"
|
||||
echo "║ Directory Structure Fix Tool ║"
|
||||
echo "║ Version 1.0 ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
|
||||
get_project_dir "$1"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}警告: 此操作将重新组织项目目录结构,建议先备份项目!${NC}"
|
||||
echo ""
|
||||
read -p "是否继续? (y/N): " confirm
|
||||
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||
print_info "操作已取消"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 执行修复步骤
|
||||
backup_files
|
||||
local temp_dir=$(collect_java_files)
|
||||
cleanup_wrong_structure
|
||||
rebuild_structure "$temp_dir"
|
||||
fix_package_names
|
||||
verify_result
|
||||
cleanup_temp "$temp_dir"
|
||||
|
||||
echo -e "${GREEN}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 目录结构修复完成! ║"
|
||||
echo "║ ║"
|
||||
echo "║ 下一步建议: ║"
|
||||
echo "║ 1. 重新编译项目验证修复效果 ║"
|
||||
echo "║ 2. 检查IDE中的导入语句 ║"
|
||||
echo "║ 3. 运行测试确保功能正常 ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# 脚本入口
|
||||
main "$@"
|
||||
@ -1,493 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 包名重复修复脚本 - 专门用于修复已经重复的包名
|
||||
# Author: Leocoder
|
||||
# Version: 1.0
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 全局变量
|
||||
PROJECT_DIR=""
|
||||
|
||||
# 打印banner
|
||||
print_banner() {
|
||||
echo -e "${CYAN}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 包名重复修复脚本 ║"
|
||||
echo "║ Fix Duplicate Packages Tool ║"
|
||||
echo "║ Version 1.0 ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# 打印步骤标题
|
||||
print_step() {
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${WHITE}$1${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
# 打印成功信息
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓ $1${NC}"
|
||||
}
|
||||
|
||||
# 打印警告信息
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠ $1${NC}"
|
||||
}
|
||||
|
||||
# 打印错误信息
|
||||
print_error() {
|
||||
echo -e "${RED}✗ $1${NC}"
|
||||
}
|
||||
|
||||
# 打印信息
|
||||
print_info() {
|
||||
echo -e "${PURPLE}ℹ $1${NC}"
|
||||
}
|
||||
|
||||
# 获取项目目录
|
||||
get_project_dir() {
|
||||
print_step "步骤 1: 获取项目目录"
|
||||
|
||||
# 获取项目根目录
|
||||
echo -e "${CYAN}请输入项目根目录路径 (默认: 当前目录):${NC}"
|
||||
read -p "项目路径: " PROJECT_DIR
|
||||
if [ -z "$PROJECT_DIR" ]; then
|
||||
PROJECT_DIR="$(pwd)"
|
||||
fi
|
||||
|
||||
# 检查项目目录是否存在
|
||||
if [ ! -d "$PROJECT_DIR" ]; then
|
||||
print_error "项目目录不存在: $PROJECT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查是否是Maven项目
|
||||
if [ ! -f "$PROJECT_DIR/pom.xml" ]; then
|
||||
print_error "这不是一个Maven项目 (未找到pom.xml)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_success "项目目录: $PROJECT_DIR"
|
||||
}
|
||||
|
||||
# 检测重复包名
|
||||
detect_duplicate_packages() {
|
||||
print_step "步骤 2: 检测重复包名"
|
||||
|
||||
local all_files=$(find "$PROJECT_DIR" -name "*.java" -o -name "*.xml" -o -name "*.yml" -o -name "*.yaml" -o -name "*.properties" | grep -v target)
|
||||
local found_duplicates=false
|
||||
|
||||
echo -e "${WHITE}检测结果:${NC}"
|
||||
|
||||
# 1. 检测目录结构中的重复
|
||||
echo -e "${CYAN}1. 检测目录结构重复:${NC}"
|
||||
local duplicate_dirs=$(find "$PROJECT_DIR" -type d -path "*/org/leocoder/org/leocoder*" 2>/dev/null)
|
||||
if [ -n "$duplicate_dirs" ]; then
|
||||
found_duplicates=true
|
||||
echo -e "${YELLOW}发现重复目录结构:${NC}"
|
||||
echo "$duplicate_dirs" | while read dir; do
|
||||
echo " - $dir"
|
||||
done
|
||||
else
|
||||
echo -e "${GREEN}目录结构正常${NC}"
|
||||
fi
|
||||
|
||||
# 2. 检测文件内容中的重复包名
|
||||
echo -e "${CYAN}2. 检测文件内容重复:${NC}"
|
||||
local duplicate_patterns=(
|
||||
"org\.leocoder\.org\.leocoder"
|
||||
"org\.leocoder\.thin\.org\.leocoder"
|
||||
"org\.leocoder\.course\.org\.leocoder"
|
||||
"org\.leocoder\.estate\.org\.leocoder"
|
||||
)
|
||||
|
||||
local file_duplicates_found=false
|
||||
for pattern in "${duplicate_patterns[@]}"; do
|
||||
local files_with_pattern=$(grep -l "$pattern" $all_files 2>/dev/null | head -10)
|
||||
if [ -n "$files_with_pattern" ]; then
|
||||
found_duplicates=true
|
||||
file_duplicates_found=true
|
||||
echo -e "${YELLOW}发现重复模式: $pattern${NC}"
|
||||
echo "$files_with_pattern" | while read file; do
|
||||
echo " - $(basename $file)"
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# 通用重复检测
|
||||
local general_duplicates=$(grep -l "org\.leocoder\.[^.]*\.org\.leocoder" $all_files 2>/dev/null | head -10)
|
||||
if [ -n "$general_duplicates" ]; then
|
||||
found_duplicates=true
|
||||
file_duplicates_found=true
|
||||
echo -e "${YELLOW}发现其他重复模式:${NC}"
|
||||
echo "$general_duplicates" | while read file; do
|
||||
echo " - $(basename $file)"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$file_duplicates_found" = false ]; then
|
||||
echo -e "${GREEN}文件内容正常${NC}"
|
||||
fi
|
||||
|
||||
if [ "$found_duplicates" = false ]; then
|
||||
echo -e "${GREEN}未发现重复包名问题${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}警告: 发现重复包名问题,建议进行修复!${NC}"
|
||||
echo ""
|
||||
read -p "是否继续修复? (y/N): " confirm
|
||||
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||
print_info "操作已取消"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
# 备份项目
|
||||
backup_project() {
|
||||
print_step "步骤 3: 备份项目"
|
||||
|
||||
local backup_dir="${PROJECT_DIR}_backup_fix_$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
echo -e "${CYAN}是否创建项目备份?${NC}"
|
||||
read -p "创建备份到 $backup_dir (Y/n): " create_backup
|
||||
|
||||
if [[ "$create_backup" =~ ^[Nn]$ ]]; then
|
||||
print_warning "跳过备份步骤"
|
||||
return
|
||||
fi
|
||||
|
||||
print_info "正在创建备份..."
|
||||
cp -r "$PROJECT_DIR" "$backup_dir"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
print_success "备份创建成功: $backup_dir"
|
||||
else
|
||||
print_error "备份创建失败"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理现有错误的目录结构
|
||||
cleanup_existing_duplicates() {
|
||||
print_step "步骤 3.5: 清理现有错误的目录结构"
|
||||
|
||||
local cleaned_count=0
|
||||
|
||||
# 清理空的org目录
|
||||
echo -e "${CYAN}清理空的org目录:${NC}"
|
||||
local empty_org_dirs=$(find "$PROJECT_DIR" -type d -name "org" -exec sh -c 'for dir; do if [ -z "$(ls -A "$dir" 2>/dev/null)" ]; then echo "$dir"; fi; done' _ {} +)
|
||||
if [ -n "$empty_org_dirs" ]; then
|
||||
echo "$empty_org_dirs" | while read empty_dir; do
|
||||
if [ -d "$empty_dir" ]; then
|
||||
print_info "删除空目录: $empty_dir"
|
||||
rmdir "$empty_dir" 2>/dev/null || true
|
||||
((cleaned_count++))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# 清理重复的配置文件(如果存在)
|
||||
echo -e "${CYAN}清理重复的配置文件:${NC}"
|
||||
local config_files=$(find "$PROJECT_DIR" -name "*.java" -path "*/config/*" | grep -E "(OpenApiConfig|CoderApplication)" | sort)
|
||||
if [ -n "$config_files" ]; then
|
||||
local prev_file=""
|
||||
echo "$config_files" | while read config_file; do
|
||||
if [ -n "$prev_file" ] && [ "$(basename "$config_file")" = "$(basename "$prev_file")" ]; then
|
||||
# 检查文件内容是否相同
|
||||
if diff "$config_file" "$prev_file" > /dev/null 2>&1; then
|
||||
print_info "删除重复文件: $config_file"
|
||||
rm -f "$config_file"
|
||||
((cleaned_count++))
|
||||
fi
|
||||
fi
|
||||
prev_file="$config_file"
|
||||
done
|
||||
fi
|
||||
|
||||
print_success "清理完成,已处理 $cleaned_count 个项目"
|
||||
}
|
||||
|
||||
# 修复重复包名
|
||||
fix_duplicate_packages() {
|
||||
print_step "步骤 4: 修复重复包名"
|
||||
|
||||
local file_count=0
|
||||
local dir_count=0
|
||||
|
||||
# 1. 修复目录结构重复
|
||||
echo -e "${CYAN}1. 修复目录结构重复:${NC}"
|
||||
|
||||
# 找到所有重复的根目录(org/leocoder/org/leocoder)
|
||||
local duplicate_root_dirs=$(find "$PROJECT_DIR" -type d -path "*/org/leocoder/org/leocoder" ! -path "*/org/leocoder/org/leocoder/*" 2>/dev/null)
|
||||
|
||||
if [ -n "$duplicate_root_dirs" ]; then
|
||||
echo "$duplicate_root_dirs" | while read duplicate_root; do
|
||||
if [ -d "$duplicate_root" ]; then
|
||||
# 计算正确的目标目录
|
||||
local java_dir=$(dirname "$duplicate_root")
|
||||
local correct_target="$java_dir/org/leocoder"
|
||||
|
||||
print_info "处理重复目录: $duplicate_root"
|
||||
print_info "目标目录: $correct_target"
|
||||
|
||||
# 创建正确的目标目录(如果不存在)
|
||||
mkdir -p "$correct_target"
|
||||
|
||||
# 移动所有文件和子目录到正确位置
|
||||
if [ -d "$duplicate_root" ] && [ "$(ls -A "$duplicate_root" 2>/dev/null)" ]; then
|
||||
# 移动所有内容
|
||||
for item in "$duplicate_root"/*; do
|
||||
if [ -e "$item" ]; then
|
||||
local item_name=$(basename "$item")
|
||||
local target_item="$correct_target/$item_name"
|
||||
|
||||
if [ -d "$item" ] && [ -d "$target_item" ]; then
|
||||
# 如果是目录且目标已存在,递归合并
|
||||
cp -r "$item/"* "$target_item/" 2>/dev/null || true
|
||||
else
|
||||
# 直接移动
|
||||
mv "$item" "$target_item" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# 删除重复的目录结构
|
||||
rm -rf "$duplicate_root" 2>/dev/null || true
|
||||
|
||||
# 清理空的父目录
|
||||
local cleanup_dir=$(dirname "$duplicate_root")
|
||||
while [ "$cleanup_dir" != "$java_dir" ] && [ -d "$cleanup_dir" ]; do
|
||||
# 检查目录是否为空
|
||||
if [ -z "$(ls -A "$cleanup_dir" 2>/dev/null)" ]; then
|
||||
rmdir "$cleanup_dir" 2>/dev/null || true
|
||||
cleanup_dir=$(dirname "$cleanup_dir")
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
((dir_count++))
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已处理重复目录结构"
|
||||
else
|
||||
echo -e "${GREEN}目录结构正常${NC}"
|
||||
fi
|
||||
|
||||
# 2. 修复文件内容中的重复包名
|
||||
echo -e "${CYAN}2. 修复文件内容重复:${NC}"
|
||||
local all_files=$(find "$PROJECT_DIR" -name "*.java" -o -name "*.xml" -o -name "*.yml" -o -name "*.yaml" -o -name "*.properties" | grep -v target)
|
||||
|
||||
# 检查常见的重复模式
|
||||
local duplicate_patterns=(
|
||||
"org\.leocoder\.org\.leocoder"
|
||||
"org\.leocoder\.thin\.org\.leocoder"
|
||||
"org\.leocoder\.course\.org\.leocoder"
|
||||
"org\.leocoder\.estate\.org\.leocoder"
|
||||
)
|
||||
|
||||
for file in $all_files; do
|
||||
local modified=false
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
# 处理每个重复模式
|
||||
cp "$file" "$temp_file"
|
||||
|
||||
for pattern in "${duplicate_patterns[@]}"; do
|
||||
if grep -q "$pattern" "$temp_file"; then
|
||||
# 修复重复的包名,保留最后一个正确的部分
|
||||
case "$pattern" in
|
||||
"org\.leocoder\.org\.leocoder")
|
||||
sed -i '' "s|org\.leocoder\.org\.leocoder|org.leocoder|g" "$temp_file"
|
||||
modified=true
|
||||
;;
|
||||
"org\.leocoder\.thin\.org\.leocoder")
|
||||
sed -i '' "s|org\.leocoder\.thin\.org\.leocoder|org.leocoder|g" "$temp_file"
|
||||
modified=true
|
||||
;;
|
||||
"org\.leocoder\.course\.org\.leocoder")
|
||||
sed -i '' "s|org\.leocoder\.course\.org\.leocoder|org.leocoder.course|g" "$temp_file"
|
||||
modified=true
|
||||
;;
|
||||
"org\.leocoder\.estate\.org\.leocoder")
|
||||
sed -i '' "s|org\.leocoder\.estate\.org\.leocoder|org.leocoder.estate|g" "$temp_file"
|
||||
modified=true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
|
||||
# 通用重复修复:修复任何 org.leocoder.*.org.leocoder.* 的模式
|
||||
if grep -q "org\.leocoder\.[^.]*\.org\.leocoder" "$temp_file"; then
|
||||
# 更精确的处理:提取中间部分并重构
|
||||
sed -i '' 's|org\.leocoder\.\([^.]*\)\.org\.leocoder\.\(.*\)|org.leocoder.\1.\2|g' "$temp_file"
|
||||
modified=true
|
||||
fi
|
||||
|
||||
# 检查是否有实际变化
|
||||
if [ "$modified" = true ] && ! diff "$file" "$temp_file" > /dev/null; then
|
||||
mv "$temp_file" "$file"
|
||||
print_info "修复文件内容: $(basename $file)"
|
||||
((file_count++))
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_success "已修复 $dir_count 个目录结构和 $file_count 个文件中的重复包名"
|
||||
}
|
||||
|
||||
# 验证修复结果
|
||||
verify_fix() {
|
||||
print_step "步骤 5: 验证修复结果"
|
||||
|
||||
local all_files=$(find "$PROJECT_DIR" -name "*.java" -o -name "*.xml" -o -name "*.yml" -o -name "*.yaml" -o -name "*.properties" | grep -v target)
|
||||
local remaining_duplicates=false
|
||||
|
||||
# 1. 验证目录结构
|
||||
echo -e "${CYAN}1. 验证目录结构:${NC}"
|
||||
local duplicate_dirs=$(find "$PROJECT_DIR" -type d -path "*/org/leocoder/org/leocoder*" 2>/dev/null)
|
||||
if [ -n "$duplicate_dirs" ]; then
|
||||
remaining_duplicates=true
|
||||
echo -e "${RED}仍然存在重复目录结构:${NC}"
|
||||
echo "$duplicate_dirs" | while read dir; do
|
||||
echo " - $dir"
|
||||
done
|
||||
else
|
||||
echo -e "${GREEN}目录结构正常${NC}"
|
||||
fi
|
||||
|
||||
# 检查是否有孤立的org目录需要清理
|
||||
local orphan_org_dirs=$(find "$PROJECT_DIR" -type d -name "org" -exec sh -c 'for dir; do if [ -z "$(ls -A "$dir" 2>/dev/null)" ]; then echo "$dir"; fi; done' _ {} +)
|
||||
if [ -n "$orphan_org_dirs" ]; then
|
||||
echo -e "${YELLOW}发现空的org目录,建议清理:${NC}"
|
||||
echo "$orphan_org_dirs" | while read dir; do
|
||||
echo " - $dir"
|
||||
rmdir "$dir" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
|
||||
# 2. 验证文件内容
|
||||
echo -e "${CYAN}2. 验证文件内容:${NC}"
|
||||
|
||||
# 检查是否还有重复
|
||||
local duplicate_patterns=(
|
||||
"org\.leocoder\.org\.leocoder"
|
||||
"org\.leocoder\.thin\.org\.leocoder"
|
||||
"org\.leocoder\.course\.org\.leocoder"
|
||||
"org\.leocoder\.estate\.org\.leocoder"
|
||||
)
|
||||
|
||||
local file_duplicates_found=false
|
||||
for pattern in "${duplicate_patterns[@]}"; do
|
||||
local files_with_pattern=$(grep -l "$pattern" $all_files 2>/dev/null)
|
||||
if [ -n "$files_with_pattern" ]; then
|
||||
remaining_duplicates=true
|
||||
file_duplicates_found=true
|
||||
echo -e "${RED}仍然存在重复模式: $pattern${NC}"
|
||||
echo "$files_with_pattern" | while read file; do
|
||||
echo " - $(basename $file)"
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# 通用重复检测
|
||||
local general_duplicates=$(grep -l "org\.leocoder\.[^.]*\.org\.leocoder" $all_files 2>/dev/null)
|
||||
if [ -n "$general_duplicates" ]; then
|
||||
remaining_duplicates=true
|
||||
file_duplicates_found=true
|
||||
echo -e "${RED}仍然存在其他重复模式${NC}"
|
||||
echo "$general_duplicates" | while read file; do
|
||||
echo " - $(basename $file)"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$file_duplicates_found" = false ]; then
|
||||
echo -e "${GREEN}文件内容正常${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ "$remaining_duplicates" = false ]; then
|
||||
print_success "所有重复包名已成功修复"
|
||||
else
|
||||
print_warning "部分重复包名可能需要手动修复"
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理临时文件
|
||||
cleanup() {
|
||||
print_step "步骤 6: 清理工作"
|
||||
|
||||
# 清理可能遗留的临时文件
|
||||
find "$PROJECT_DIR" -name "*.bak" -type f -delete 2>/dev/null
|
||||
find "$PROJECT_DIR" -name ".DS_Store" -type f -delete 2>/dev/null
|
||||
|
||||
# 显示统计信息
|
||||
local java_files_count=$(find "$PROJECT_DIR" -name "*.java" -type f | wc -l)
|
||||
local xml_files_count=$(find "$PROJECT_DIR" -name "*.xml" -type f | wc -l)
|
||||
local config_files_count=$(find "$PROJECT_DIR" -name "*.yml" -o -name "*.yaml" -o -name "*.properties" | wc -l)
|
||||
|
||||
echo ""
|
||||
echo -e "${WHITE}项目文件统计:${NC}"
|
||||
echo -e "${CYAN}Java 文件:${NC} $java_files_count"
|
||||
echo -e "${CYAN}XML 文件:${NC} $xml_files_count"
|
||||
echo -e "${CYAN}配置文件:${NC} $config_files_count"
|
||||
|
||||
print_success "清理完成"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
# 检查依赖
|
||||
if ! command -v sed &> /dev/null; then
|
||||
print_error "sed 命令未找到,请安装 sed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_banner
|
||||
|
||||
get_project_dir
|
||||
detect_duplicate_packages
|
||||
backup_project
|
||||
|
||||
# 进入项目目录
|
||||
cd "$PROJECT_DIR" || exit 1
|
||||
|
||||
# 执行修复步骤
|
||||
cleanup_existing_duplicates
|
||||
fix_duplicate_packages
|
||||
verify_fix
|
||||
cleanup
|
||||
|
||||
print_step "🎉 修复完成!"
|
||||
|
||||
echo -e "${GREEN}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 重复包名修复完成! ║"
|
||||
echo "║ ║"
|
||||
echo "║ 下一步建议: ║"
|
||||
echo "║ 1. 重新编译项目验证修复效果 ║"
|
||||
echo "║ 2. 检查IDE中的导入语句 ║"
|
||||
echo "║ 3. 运行测试确保功能正常 ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# 脚本入口
|
||||
main "$@"
|
||||
@ -1,21 +0,0 @@
|
||||
# 项目重构配置文件示例
|
||||
# 复制此文件为 refactor-config.conf 并修改相应值
|
||||
|
||||
# 项目基本信息
|
||||
PROJECT_DIR="/path/to/your/project"
|
||||
|
||||
# 旧配置
|
||||
OLD_GROUP_ID="org.leocoder.thin"
|
||||
OLD_ARTIFACT_ID="coder-common-thin-backend"
|
||||
OLD_MODULE_PREFIX="coder-common-thin"
|
||||
OLD_DATABASE_NAME="coder-common-thin"
|
||||
|
||||
# 新配置
|
||||
NEW_GROUP_ID="org.leocoder.course"
|
||||
NEW_ARTIFACT_ID="coder-course-backend"
|
||||
NEW_MODULE_PREFIX="coder-course"
|
||||
NEW_DATABASE_NAME="coder-course"
|
||||
|
||||
# 其他选项
|
||||
CREATE_BACKUP="true"
|
||||
AUTO_CONFIRM="false"
|
||||
@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 简单目录修复脚本
|
||||
# Author: Leocoder
|
||||
|
||||
echo "开始修复目录结构..."
|
||||
|
||||
PROJECT_DIR="/Users/leocoder/leocoder/develop/2025/estate/coder-estate-backend"
|
||||
|
||||
# 1. 删除所有错误的org目录结构
|
||||
echo "删除错误的目录结构..."
|
||||
find "$PROJECT_DIR" -type d -path "*/org/leocoder/org/leocoder*" -exec rm -rf {} + 2>/dev/null
|
||||
|
||||
# 2. 清理空的org目录
|
||||
echo "清理空目录..."
|
||||
find "$PROJECT_DIR" -type d -name "org" -empty -delete 2>/dev/null
|
||||
|
||||
# 3. 查找所有包含重复包名的Java文件并修复
|
||||
echo "修复Java文件中的包名..."
|
||||
find "$PROJECT_DIR" -name "*.java" -exec sed -i '' 's|org\.leocoder\.org\.leocoder\.estate|org.leocoder.estate|g' {} + 2>/dev/null
|
||||
find "$PROJECT_DIR" -name "*.java" -exec sed -i '' 's|org\.leocoder\.org\.leocoder|org.leocoder|g' {} + 2>/dev/null
|
||||
|
||||
# 4. 修复XML文件中的包名
|
||||
echo "修复XML文件中的包名..."
|
||||
find "$PROJECT_DIR" -name "*.xml" -exec sed -i '' 's|org\.leocoder\.org\.leocoder\.estate|org.leocoder.estate|g' {} + 2>/dev/null
|
||||
find "$PROJECT_DIR" -name "*.xml" -exec sed -i '' 's|org\.leocoder\.org\.leocoder|org.leocoder|g' {} + 2>/dev/null
|
||||
|
||||
# 5. 验证结果
|
||||
echo "验证修复结果..."
|
||||
duplicate_count=$(find "$PROJECT_DIR" -type d -path "*/org/leocoder/org/leocoder*" | wc -l)
|
||||
if [ "$duplicate_count" -eq 0 ]; then
|
||||
echo "✅ 目录结构修复成功!"
|
||||
else
|
||||
echo "⚠️ 仍然存在 $duplicate_count 个重复目录"
|
||||
fi
|
||||
|
||||
# 6. 统计Java文件数量
|
||||
java_count=$(find "$PROJECT_DIR" -name "*.java" -path "*/org/leocoder/estate/*" | wc -l)
|
||||
echo "📊 Java文件总数: $java_count"
|
||||
|
||||
echo "修复完成!"
|
||||
Loading…
Reference in New Issue
Block a user