Compare commits
No commits in common. "a2adaf38d124472ce7798fa8e06f265436ea83f1" and "1127319f227a1d9535112e01e0a716df96ea833b" have entirely different histories.
a2adaf38d1
...
1127319f22
3
.gitignore
vendored
3
.gitignore
vendored
@ -44,6 +44,3 @@ spy.log
|
||||
|
||||
### Upload Files ###
|
||||
picture/
|
||||
|
||||
### Local Configuration Files ###
|
||||
**/application-local.yml
|
||||
|
||||
@ -34,12 +34,16 @@ public class UploadUtil {
|
||||
YUtil.isTrue("上传文件必须小于" + figure + "MB");
|
||||
}
|
||||
LocalDateTime nowDateTime = LocalDateTime.now();
|
||||
// 当前日期格式
|
||||
DateTimeFormatter fileFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
|
||||
// 获取文件大小
|
||||
String fileSize = FileTypeUtil.getFileSize(multipartFile);
|
||||
log.info("文件大小fileSize:{}", fileSize);
|
||||
// 文件上传路径(basePath已经包含了完整路径,包括日期)
|
||||
String fileUploadPath = basePath;
|
||||
log.info("文件上传目录:{}", fileUploadPath);
|
||||
// 文件日期路径
|
||||
String fileDatePath = nowDateTime.format(fileFormatter) + "/";
|
||||
log.info("文件日期路径:{}", fileDatePath);
|
||||
// 文件上传路径
|
||||
String fileUploadPath = basePath + fileDatePath;
|
||||
// 获取绝对路径
|
||||
File fl = new File(fileUploadPath);
|
||||
// 如果不存在,直接创建
|
||||
@ -61,7 +65,7 @@ public class UploadUtil {
|
||||
String newName = nowDateTime.format(formatterTemplate) + "-" + UUIDUtil.getUUIDValue(6) + "." + suffixName;
|
||||
log.info("上传文件新名字newName:{}", newName);
|
||||
// 拼接的文件绝对路径
|
||||
String absoluteFilePath = fileUploadPath + "/" + newName;
|
||||
String absoluteFilePath = fileUploadPath + newName;
|
||||
log.info("拼接的文件绝对路径filePath:{}", absoluteFilePath);
|
||||
File file = new File(absoluteFilePath);
|
||||
// 上传文件
|
||||
@ -77,12 +81,12 @@ public class UploadUtil {
|
||||
map.put("fileName", originalFilename);
|
||||
// 文件后缀
|
||||
map.put("suffixName", suffixName);
|
||||
// 构建Web访问路径(完整路径)
|
||||
// 使用完整的文件上传路径作为Web访问路径
|
||||
String webPath = fileUploadPath + "/" + newName;
|
||||
log.info("文件Web访问路径fileUploadPath:{}", webPath);
|
||||
int index = fileUploadPath.indexOf(":");
|
||||
String fileUploadPathString = fileUploadPath.substring(index + 1) + newName;
|
||||
// 文件上传路径
|
||||
map.put("fileUploadPath", webPath);
|
||||
log.info("文件上传路径fileUploadPath:{}", fileUploadPathString);
|
||||
// 文件上传路径
|
||||
map.put("fileUploadPath", fileUploadPathString);
|
||||
// 新文件名字
|
||||
map.put("newName", newName);
|
||||
// 绝对文件路径
|
||||
|
||||
@ -158,9 +158,8 @@ public class FileController {
|
||||
|
||||
// 设置文件访问路径
|
||||
String fileUploadPath = (String) fileMap.get("fileUploadPath");
|
||||
|
||||
if (isFullUrl(fileUploadPath)) {
|
||||
// 如果已经是完整URL(如OSS、MinIO),直接使用
|
||||
// 如果已经是完整URL(如OSS),直接使用
|
||||
sysPicture.setPicturePath(fileUploadPath);
|
||||
} else {
|
||||
// 如果是相对路径(如本地存储),构建完整URL
|
||||
@ -170,8 +169,7 @@ public class FileController {
|
||||
}
|
||||
String hostIp = IpUtil.getHostIp(ServletUtil.getRequest());
|
||||
String hostPort = StringUtils.isNotBlank(env.getProperty("server.port")) ? env.getProperty("server.port") : "18099";
|
||||
String fullUrl = protocol + "://" + hostIp + ":" + hostPort + fileUploadPath;
|
||||
sysPicture.setPicturePath(fullUrl);
|
||||
sysPicture.setPicturePath(protocol + "://" + hostIp + ":" + hostPort + fileUploadPath);
|
||||
}
|
||||
|
||||
log.info("图片回显地址:{}", sysPicture.getPicturePath());
|
||||
@ -200,11 +198,10 @@ public class FileController {
|
||||
sysFile.setFileUpload(fileMap.get("filePath").toString());
|
||||
sysFile.setFileService(storageType);
|
||||
|
||||
// 判断是否为完整URL(如OSS、MinIO存储)
|
||||
// 判断是否为完整URL(如OSS存储)
|
||||
String fileUploadPath = (String) fileMap.get("fileUploadPath");
|
||||
|
||||
if (isFullUrl(fileUploadPath)) {
|
||||
// 如果已经是完整URL(如OSS、MinIO),直接使用
|
||||
// 如果已经是完整URL(如OSS),直接使用
|
||||
sysFile.setFilePath(fileUploadPath);
|
||||
} else {
|
||||
// 如果是相对路径(如本地存储),构建完整URL
|
||||
@ -214,8 +211,7 @@ public class FileController {
|
||||
}
|
||||
String hostIp = IpUtil.getHostIp(ServletUtil.getRequest());
|
||||
String hostPort = StringUtils.isNotBlank(env.getProperty("server.port")) ? env.getProperty("server.port") : "18099";
|
||||
String fullUrl = protocol + "://" + hostIp + ":" + hostPort + fileUploadPath;
|
||||
sysFile.setFilePath(fullUrl);
|
||||
sysFile.setFilePath(protocol + "://" + hostIp + ":" + hostPort + fileUploadPath);
|
||||
}
|
||||
|
||||
log.info("文件回显地址:{}", sysFile.getFilePath());
|
||||
@ -249,8 +245,6 @@ public class FileController {
|
||||
return "local";
|
||||
case "OSS":
|
||||
return "oss";
|
||||
case "MINIO":
|
||||
return "minio";
|
||||
default:
|
||||
log.warn("未知的存储类型: {}, 使用默认配置", requestStorageType);
|
||||
break;
|
||||
@ -269,19 +263,15 @@ public class FileController {
|
||||
|
||||
// 根据返回的文件路径判断实际使用的存储类型
|
||||
if (isFullUrl(fileUploadPath)) {
|
||||
// 如果是完整URL,检查具体的存储类型
|
||||
// 如果是完整URL,检查是否包含OSS域名
|
||||
if (fileUploadPath.contains(".aliyuncs.com") || fileUploadPath.contains("oss-")) {
|
||||
// 阿里云OSS
|
||||
// OSS
|
||||
return "3";
|
||||
} else if (fileUploadPath.contains("minio.leocoder.cn") ||
|
||||
fileUploadPath.contains("/coder-files/") ||
|
||||
fileUploadPath.contains("X-Amz-Algorithm")) {
|
||||
// MinIO存储(支持多种识别方式)
|
||||
return "2";
|
||||
}
|
||||
}
|
||||
|
||||
// 默认为本地存储
|
||||
// Local
|
||||
return "1";
|
||||
}
|
||||
|
||||
|
||||
@ -25,12 +25,7 @@
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MinIO SDK -->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>3.17.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Configuration Processor -->
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
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,10 +3,8 @@ 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;
|
||||
@ -23,7 +21,7 @@ import org.springframework.core.env.Environment;
|
||||
* @author Leocoder
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({OssConfig.class, MinioConfig.class})
|
||||
@EnableConfigurationProperties(OssConfig.class)
|
||||
@Slf4j
|
||||
public class OssAutoConfiguration {
|
||||
|
||||
@ -103,57 +101,6 @@ 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,7 +50,18 @@ public class LocalStorageService implements StorageService {
|
||||
// 使用现有的上传工具类
|
||||
Map<String, Object> fileMap = UploadUtil.coderSingleFile(file, fullPath, 2);
|
||||
|
||||
// UploadUtil已经返回了正确的相对路径,不需要再次构建URL
|
||||
// 生成访问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);
|
||||
|
||||
log.info("本地存储上传成功: {}", fileMap.get("filePath"));
|
||||
return fileMap;
|
||||
|
||||
@ -1,229 +0,0 @@
|
||||
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,26 +48,20 @@ public class StorageServiceFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description [获取默认存储服务(MinIO优先,然后OSS,最后本地存储)]
|
||||
* @description [获取默认存储服务(OSS优先,如果不可用则使用本地存储)]
|
||||
* @author Leocoder
|
||||
*/
|
||||
public StorageService getDefaultStorageService() {
|
||||
try {
|
||||
// 优先尝试获取MinIO服务
|
||||
return getStorageService("minio");
|
||||
// 优先尝试获取OSS服务
|
||||
return getStorageService("oss");
|
||||
} catch (Exception e) {
|
||||
log.warn("MinIO服务不可用,尝试OSS服务", e);
|
||||
log.warn("OSS服务不可用,使用本地存储作为降级方案", e);
|
||||
try {
|
||||
// 尝试获取OSS服务
|
||||
return getStorageService("oss");
|
||||
return getStorageService("local");
|
||||
} catch (Exception ex) {
|
||||
log.warn("OSS服务不可用,使用本地存储作为降级方案", ex);
|
||||
try {
|
||||
return getStorageService("local");
|
||||
} catch (Exception localEx) {
|
||||
log.error("本地存储服务也不可用", localEx);
|
||||
throw new BusinessException(500, "没有可用的存储服务");
|
||||
}
|
||||
log.error("本地存储服务也不可用", ex);
|
||||
throw new BusinessException(500, "没有可用的存储服务");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,8 +78,6 @@ public class StorageServiceFactory {
|
||||
return serviceClassName.contains("local");
|
||||
case "oss":
|
||||
return serviceClassName.contains("oss");
|
||||
case "minio":
|
||||
return serviceClassName.contains("minio");
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ spring:
|
||||
# 主库数据源
|
||||
master: # 没有@DS,默认数据源
|
||||
type: ${spring.datasource.type}
|
||||
url: jdbc:mysql://localhost:3306/xxxxxxxx?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true
|
||||
url: jdbc:mysql://localhost:3306/coder-common-thin?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
username: root
|
||||
password: coder
|
||||
@ -39,7 +39,7 @@ spring:
|
||||
slave: # @DS("dsName"),dsName可以为组名也可以为具体某个库的名称,使用多数据源遵循格式,注解都在mapper层使用。
|
||||
lazy: true
|
||||
type: ${spring.datasource.type}
|
||||
url: jdbc:mysql://localhost:3306/xxxxxxxx?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true
|
||||
url: jdbc:mysql://localhost:3306/coder-common-thin-backup?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false&rewriteBatchedStatements=true
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
username: root
|
||||
password: coder
|
||||
@ -89,7 +89,7 @@ coder:
|
||||
# 版本
|
||||
projectVersion: 1.0.0
|
||||
# 文件路径 示例[Windows配置D:/CoderFile,Linux配置 /usr/local/CoderFile]
|
||||
filePath:
|
||||
filePath: /Users/leocoder/leocoder/develop/templates/coder-common-thin/coder-common-thin-backend/picture
|
||||
# 存储服务配置
|
||||
storage:
|
||||
# 存储类型:local(本地存储) | oss(阿里云OSS)
|
||||
@ -99,17 +99,17 @@ coder:
|
||||
# 是否启用OSS存储
|
||||
enabled: true
|
||||
# OSS服务端点
|
||||
endpoint: xxxxxxxx
|
||||
endpoint: oss-cn-hangzhou.aliyuncs.com
|
||||
# 访问密钥ID
|
||||
access-key-id: xxxxxxxx
|
||||
access-key-id: ${OSS_ACCESS_KEY_ID:LTAI5t982gXi7A72gAa9yugE}
|
||||
# 访问密钥Secret
|
||||
access-key-secret: xxxxxxxx
|
||||
access-key-secret: ${OSS_ACCESS_KEY_SECRET:Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30}
|
||||
# 存储桶名称
|
||||
bucket-name: xxxxxxxx
|
||||
bucket-name: gaoziman
|
||||
# 自定义域名(可选)
|
||||
domain: xxxxxxxx
|
||||
domain: https://gaoziman.oss-cn-hangzhou.aliyuncs.com
|
||||
# 路径前缀
|
||||
path-prefix: xxxxxxxx
|
||||
path-prefix: coder-files
|
||||
# 是否使用HTTPS
|
||||
https: true
|
||||
# 连接超时时间(毫秒)
|
||||
|
||||
@ -25,7 +25,7 @@ spring:
|
||||
encoding: UTF-8
|
||||
basename: i18n/messages
|
||||
profiles:
|
||||
active: local
|
||||
active: dev
|
||||
|
||||
# 操作日志配置
|
||||
coder:
|
||||
|
||||
@ -44,13 +44,6 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<springProfile name="local">
|
||||
<root level="info">
|
||||
<appender-ref ref="stdout"/>
|
||||
<appender-ref ref="combinedFile"/>
|
||||
</root>
|
||||
</springProfile>
|
||||
|
||||
<springProfile name="dev">
|
||||
<root level="info">
|
||||
<appender-ref ref="stdout"/>
|
||||
|
||||
@ -83,14 +83,6 @@
|
||||
|
||||
<!-- 配置多环境日志输出 可以在application.properties中配置选择哪个profiles : spring.profiles.active=dev -->
|
||||
<!-- 开发环境:打印控制台 -->
|
||||
|
||||
<springProfile name="local">
|
||||
<root level="info">
|
||||
<appender-ref ref="stdout"/>
|
||||
<appender-ref ref="combinedFile"/>
|
||||
</root>
|
||||
</springProfile>
|
||||
|
||||
<springProfile name="dev">
|
||||
<root level="info">
|
||||
<appender-ref ref="stdout"/>
|
||||
|
||||
@ -48,13 +48,6 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<springProfile name="local">
|
||||
<root level="info">
|
||||
<appender-ref ref="stdout"/>
|
||||
<appender-ref ref="combinedFile"/>
|
||||
</root>
|
||||
</springProfile>
|
||||
|
||||
<springProfile name="dev">
|
||||
<root level="info">
|
||||
<appender-ref ref="stdout"/>
|
||||
|
||||
161
fix_end_of_line_comments.py
Normal file
161
fix_end_of_line_comments.py
Normal file
@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
批量修改Java文件中的行尾注释脚本
|
||||
将行尾注释改为单独占行的注释
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def find_java_files(root_path):
|
||||
"""查找所有Java文件"""
|
||||
java_files = []
|
||||
for root, dirs, files in os.walk(root_path):
|
||||
for file in files:
|
||||
if file.endswith('.java'):
|
||||
java_files.append(os.path.join(root, file))
|
||||
return java_files
|
||||
|
||||
def process_file(file_path):
|
||||
"""处理单个Java文件"""
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
original_content = content
|
||||
changes = []
|
||||
|
||||
# 分行处理
|
||||
lines = content.split('\n')
|
||||
new_lines = []
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
# 检查是否包含行尾注释
|
||||
# 模式1: 代码行后跟 // 注释
|
||||
match1 = re.match(r'^(\s*)(.*?)(;)\s*(//\s*(.*))\s*$', line)
|
||||
if match1:
|
||||
indent = match1.group(1)
|
||||
code_part = match1.group(2)
|
||||
semicolon = match1.group(3)
|
||||
comment_part = match1.group(4)
|
||||
comment_text = match1.group(5)
|
||||
|
||||
# 添加单独的注释行
|
||||
new_lines.append(f'{indent}{comment_part}')
|
||||
# 添加代码行
|
||||
new_lines.append(f'{indent}{code_part}{semicolon}')
|
||||
changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行')
|
||||
continue
|
||||
|
||||
# 模式2: 代码行后跟 /* 注释 */
|
||||
match2 = re.match(r'^(\s*)(.*?)(;)\s*(/\*\s*(.*?)\s*\*/)\s*$', line)
|
||||
if match2:
|
||||
indent = match2.group(1)
|
||||
code_part = match2.group(2)
|
||||
semicolon = match2.group(3)
|
||||
comment_text = match2.group(5)
|
||||
|
||||
# 添加单独的注释行(转换为//格式)
|
||||
new_lines.append(f'{indent}// {comment_text}')
|
||||
# 添加代码行
|
||||
new_lines.append(f'{indent}{code_part}{semicolon}')
|
||||
changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行')
|
||||
continue
|
||||
|
||||
# 模式3: 其他行尾注释情况(不以分号结尾)
|
||||
match3 = re.match(r'^(\s*)(.*?)\s*(//\s*(.*))\s*$', line)
|
||||
if match3 and not line.strip().startswith('//'):
|
||||
indent = match3.group(1)
|
||||
code_part = match3.group(2).strip()
|
||||
comment_part = match3.group(3)
|
||||
comment_text = match3.group(4)
|
||||
|
||||
# 确保不是整行注释
|
||||
if code_part and not code_part.startswith('//'):
|
||||
# 添加单独的注释行
|
||||
new_lines.append(f'{indent}{comment_part}')
|
||||
# 添加代码行
|
||||
new_lines.append(f'{indent}{code_part}')
|
||||
changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行')
|
||||
continue
|
||||
|
||||
# 模式4: 其他行尾注释情况(/* */格式,不以分号结尾)
|
||||
match4 = re.match(r'^(\s*)(.*?)\s*(/\*\s*(.*?)\s*\*/)\s*$', line)
|
||||
if match4 and not line.strip().startswith('/*'):
|
||||
indent = match4.group(1)
|
||||
code_part = match4.group(2).strip()
|
||||
comment_text = match4.group(4)
|
||||
|
||||
# 确保不是整行注释
|
||||
if code_part and not code_part.startswith('/*'):
|
||||
# 添加单独的注释行(转换为//格式)
|
||||
new_lines.append(f'{indent}// {comment_text}')
|
||||
# 添加代码行
|
||||
new_lines.append(f'{indent}{code_part}')
|
||||
changes.append(f'第{i+1}行: {line.strip()} -> 拆分为注释行和代码行')
|
||||
continue
|
||||
|
||||
# 没有匹配的模式,保持原样
|
||||
new_lines.append(line)
|
||||
|
||||
# 如果有变化,写入文件
|
||||
if changes:
|
||||
new_content = '\n'.join(new_lines)
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(new_content)
|
||||
return len(changes), changes
|
||||
else:
|
||||
return 0, []
|
||||
|
||||
except Exception as e:
|
||||
print(f"处理文件 {file_path} 时出错: {e}")
|
||||
return 0, []
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 项目根目录
|
||||
root_path = '/Users/leocoder/leocoder/develop/templates/coder-common-thin/coder-common-thin-backend'
|
||||
|
||||
# 查找所有Java文件
|
||||
java_files = find_java_files(root_path)
|
||||
|
||||
print(f"找到 {len(java_files)} 个Java文件")
|
||||
print("开始处理...")
|
||||
|
||||
total_changes = 0
|
||||
modified_files = []
|
||||
|
||||
for file_path in java_files:
|
||||
change_count, changes = process_file(file_path)
|
||||
if change_count > 0:
|
||||
total_changes += change_count
|
||||
modified_files.append({
|
||||
'file': file_path,
|
||||
'changes': change_count,
|
||||
'details': changes
|
||||
})
|
||||
print(f"✓ 修改了 {file_path} - {change_count} 处更改")
|
||||
|
||||
print("\n" + "="*80)
|
||||
print("修改报告")
|
||||
print("="*80)
|
||||
print(f"总共修改了 {len(modified_files)} 个文件")
|
||||
print(f"总共修改了 {total_changes} 处行尾注释")
|
||||
|
||||
if modified_files:
|
||||
print("\n详细修改列表:")
|
||||
for file_info in modified_files:
|
||||
print(f"\n文件: {file_info['file']}")
|
||||
print(f"修改数量: {file_info['changes']}")
|
||||
for detail in file_info['details'][:5]: # 只显示前5个变化
|
||||
print(f" - {detail}")
|
||||
if len(file_info['details']) > 5:
|
||||
print(f" ... 还有 {len(file_info['details']) - 5} 个变化")
|
||||
|
||||
print("\n处理完成!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
14
pom.xml
14
pom.xml
@ -52,8 +52,6 @@
|
||||
<captcha.version>1.6.2</captcha.version>
|
||||
<freemarker.version>2.3.34</freemarker.version>
|
||||
<springdoc.version>2.7.0</springdoc.version>
|
||||
<aliyun.oss.version>3.17.4</aliyun.oss.version>
|
||||
<minio.version>8.5.7</minio.version>
|
||||
|
||||
<!-- 插件版本 -->
|
||||
<maven-compiler-plugin.verison>3.14.0</maven-compiler-plugin.verison>
|
||||
@ -218,18 +216,6 @@
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
</dependency>
|
||||
<!-- 阿里云OSS SDK -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>${aliyun.oss.version}</version>
|
||||
</dependency>
|
||||
<!-- MinIO SDK -->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>${minio.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
623
script/README.md
623
script/README.md
@ -1,242 +1,477 @@
|
||||
# 项目模板重构脚本
|
||||
# 项目重构脚本使用指南
|
||||
|
||||
这是一个用于将 `coder-common-thin-backend` 项目重构为新项目模板的自动化脚本。
|
||||
这是一套用于Maven项目重构和包名修复的自动化脚本,可以帮助你快速将一个项目模板重构为新的项目,并修复常见的包名重复问题。
|
||||
|
||||
## 功能特性
|
||||
## 📋 脚本概览
|
||||
|
||||
🚀 **全自动重构**:一键完成整个项目的重构过程
|
||||
📁 **目录重命名**:自动重命名所有模块目录和子模块目录
|
||||
📦 **Maven配置**:更新所有 pom.xml 文件中的 groupId、artifactId 和模块名
|
||||
☕ **Java包结构**:重构所有 Java 文件的包名和 import 语句
|
||||
⚙️ **配置文件**:更新所有配置文件中的包名引用
|
||||
🗄️ **数据库配置**:重命名 SQL 文件和更新数据库名引用
|
||||
🔄 **多层级支持**:支持插件模块等多层级子模块结构
|
||||
本目录包含了用于项目重构和包名修复的自动化脚本:
|
||||
|
||||
## 使用方法
|
||||
### 🔧 脚本文件说明
|
||||
|
||||
### 1. 进入脚本目录
|
||||
```bash
|
||||
cd /Users/leocoder/leocoder/develop/frameworks/coder-common-thin/coder-common-thin-backend/script
|
||||
```
|
||||
script/
|
||||
├── project-refactor.sh # ⭐ 主要推荐:完整重构脚本
|
||||
├── simple-fix.sh # ⭐ 简单修复脚本
|
||||
├── fix-duplicate-packages.sh # 专门修复重复包名
|
||||
├── fix-directory-structure.sh # 目录结构重建脚本
|
||||
├── batch-refactor.sh # 批量重构脚本(配置文件)
|
||||
├── refactor-config.example # 配置文件模板
|
||||
└── README.md # 本使用说明文件
|
||||
```
|
||||
|
||||
### 2. 执行重构脚本
|
||||
## 🎯 脚本选择建议
|
||||
|
||||
### 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
|
||||
./project-template-refactor.sh
|
||||
# 进入项目目录
|
||||
cd /path/to/your/new/project
|
||||
|
||||
# 执行完整重构脚本
|
||||
bash script/project-refactor.sh
|
||||
```
|
||||
|
||||
### 3. 按提示输入新项目信息
|
||||
### 步骤 3: 交互式配置
|
||||
|
||||
脚本会提示你输入以下信息:
|
||||
- **新项目名称**:例如 `my-project-backend`
|
||||
- **新的GroupId**:例如 `com.company.project`
|
||||
- **新的包名**:例如 `com.company.project`
|
||||
- **新的模块前缀**:例如 `my-project`
|
||||
- **新的数据库名**:例如 `my_project_db`
|
||||
|
||||
### 4. 确认配置并开始重构
|
||||
脚本会显示所有配置信息供你确认,输入 `y` 开始重构。
|
||||
|
||||
## 重构内容详解
|
||||
|
||||
### 📁 目录结构重构
|
||||
**原始结构:**
|
||||
#### 3.1 项目目录
|
||||
```
|
||||
/parent-directory/
|
||||
└── coder-common-thin-backend/ ← 项目根目录
|
||||
├── coder-common-thin-web/
|
||||
├── coder-common-thin-common/
|
||||
├── coder-common-thin-model/
|
||||
├── coder-common-thin-mybatisplus/
|
||||
├── coder-common-thin-modules/
|
||||
├── coder-common-thin-plugins/
|
||||
│ ├── coder-common-thin-easyexcel/
|
||||
│ ├── coder-common-thin-oss/
|
||||
│ ├── coder-common-thin-sa-token/
|
||||
│ └── ...其他插件模块
|
||||
└── sql/
|
||||
└── coder-common-thin.sql
|
||||
请输入项目根目录路径 (默认: 当前目录):
|
||||
项目路径: [直接回车使用当前目录]
|
||||
```
|
||||
|
||||
**重构后结构(以 my-project-backend 为例):**
|
||||
#### 3.2 旧配置信息
|
||||
```
|
||||
/parent-directory/
|
||||
├── coder-common-thin-backend_backup_* ← 自动创建的备份
|
||||
└── my-project-backend/ ← 重命名后的项目根目录
|
||||
├── my-project-web/
|
||||
├── my-project-common/
|
||||
├── my-project-model/
|
||||
├── my-project-mybatisplus/
|
||||
├── my-project-modules/
|
||||
├── my-project-plugins/
|
||||
│ ├── my-project-easyexcel/
|
||||
│ ├── my-project-oss/
|
||||
│ ├── my-project-sa-token/
|
||||
│ └── ...其他插件模块
|
||||
└── sql/
|
||||
└── my_project_db.sql
|
||||
旧的 GroupId (例如: org.leocoder.thin): org.leocoder.estate
|
||||
旧的 ArtifactId (例如: coder-common-thin-backend): coder-estate-backend
|
||||
旧的模块前缀 (例如: coder-common-thin): coder-estate
|
||||
```
|
||||
|
||||
⭐ **v1.2.0 新特性**:脚本现在会自动重命名项目根目录,无需手动操作!
|
||||
|
||||
### 📦 Maven 配置重构
|
||||
- **groupId**:`org.leocoder.thin` → `com.company.project`
|
||||
- **artifactId**:`coder-common-thin-*` → `my-project-*`
|
||||
- **name**:相应模块名称更新
|
||||
- **依赖引用**:所有模块间依赖的 groupId 和 artifactId
|
||||
|
||||
### ☕ Java 包结构重构
|
||||
- **包声明**:`package org.leocoder.thin.*` → `package com.company.project.*`
|
||||
- **import语句**:`import org.leocoder.thin.*` → `import com.company.project.*`
|
||||
- **目录结构**:`src/main/java/org/leocoder/thin/` → `src/main/java/com/company/project/`
|
||||
|
||||
### ⚙️ 配置文件重构
|
||||
- **application.yml / application-dev.yml / application-local.yml**:
|
||||
- `packages-to-scan: org.leocoder.thin` → `packages-to-scan: com.company.project`
|
||||
- `projectName: CORDER-ADMIN-THIN` → `projectName: MY-PROJECT-ADMIN`
|
||||
- `pool-name: CORDER-HIKARI-DEV` → `pool-name: MY-PROJECT-HIKARI-DEV`
|
||||
- `name: coder-web` → `name: my-project-web`
|
||||
- `jdbc:mysql://localhost:3306/coder-common-thin` → `jdbc:mysql://localhost:3306/new-db-name`
|
||||
- `jdbc:mysql://localhost:3306/coder-common-thin-backup` → `jdbc:mysql://localhost:3306/new-db-name-backup`
|
||||
- `filePath: /path/coder-common-thin-backend/` → `filePath: /path/new-project-backend/`
|
||||
- **logback配置文件**(logback-spring*.xml):
|
||||
- `<contextName>coder-common-thin-logback</contextName>` → `<contextName>my-project-logback</contextName>`
|
||||
- `<property name="CORDER_ADMIN_LOGS" value="./logs"/>` → `<property name="MY_PROJECT_ADMIN_LOGS" value="./logs"/>`
|
||||
- 所有日志路径引用:`${CORDER_ADMIN_LOGS}` → `${MY_PROJECT_ADMIN_LOGS}`
|
||||
- **其他配置文件**:包名和项目相关引用更新
|
||||
|
||||
### 🗄️ SQL 文件重构
|
||||
- **文件重命名**:`coder-common-thin.sql` → `my_project_db.sql`
|
||||
- **数据库名更新**:SQL文件中的数据库名引用更新
|
||||
|
||||
## 安全特性
|
||||
|
||||
### 🔒 自动备份
|
||||
脚本执行前会自动创建项目备份:
|
||||
#### 3.3 新配置信息
|
||||
```
|
||||
coder-common-thin-backend_backup_20250922_143022/
|
||||
新的 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: 验证重构结果
|
||||
|
||||
重构完成后请执行以下步骤:
|
||||
|
||||
### 1. 验证编译
|
||||
#### 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
|
||||
|
||||
# 如果编译成功,说明重构正确
|
||||
```
|
||||
|
||||
### 2. 更新数据库配置
|
||||
手动检查并更新以下配置文件中的数据库连接信息:
|
||||
- `*/src/main/resources/application-dev.yml`
|
||||
- `*/src/main/resources/application-local.yml`
|
||||
### 步骤 5: 测试验证
|
||||
|
||||
### 3. 验证功能
|
||||
- 启动应用程序验证功能正常
|
||||
- 检查所有插件模块是否正常加载
|
||||
|
||||
### 4. IDE配置
|
||||
- 重新导入Maven项目
|
||||
- 检查项目结构和依赖
|
||||
|
||||
### 5. Git管理
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "refactor: 重构项目为新模板"
|
||||
# 运行测试
|
||||
mvn test
|
||||
|
||||
# 启动应用(如果是Spring Boot项目)
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
## 🛠️ 常见问题处理
|
||||
|
||||
⚠️ **重要提醒:**
|
||||
1. 重构前请确保代码已提交到Git仓库
|
||||
2. 脚本会自动创建备份,但建议额外手动备份重要数据
|
||||
3. 重构过程不可逆,请谨慎操作
|
||||
4. 重构后需要手动更新数据库连接配置
|
||||
5. 如果项目中有自定义的特殊配置,可能需要手动调整
|
||||
### 问题 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. **手动修复**:对于特殊情况,可能需要手动修复部分文件
|
||||
|
||||
### 常见问题
|
||||
1. **权限错误**:确保脚本有可执行权限 `chmod +x project-template-refactor.sh`
|
||||
2. **路径错误**:确保在正确的项目根目录下执行脚本
|
||||
3. **Maven错误**:重构后如果编译失败,检查依赖配置是否正确
|
||||
4. **包名冲突**:如果新包名已存在,选择不同的包名
|
||||
5. **Bash版本兼容性**:脚本已修复了bash版本兼容性问题
|
||||
6. **包名未正确替换**:使用修复脚本 `./fix-existing-project.sh`
|
||||
7. **多余src目录**:使用修复脚本自动清理
|
||||
|
||||
### 项目修复工具
|
||||
**Q: 脚本执行后项目无法启动?**
|
||||
A: 检查IDE的运行配置,确保主类路径已更新为新的包名。
|
||||
|
||||
#### 1. 快速修复目录名反斜杠问题
|
||||
如果目录名中出现反斜杠(如 `leocoder\`):
|
||||
```bash
|
||||
./quick-fix-backslash.sh
|
||||
```
|
||||
**Q: 某些文件没有被修改?**
|
||||
A: 检查文件是否在target目录下,脚本会跳过编译输出目录。
|
||||
|
||||
#### 2. 修复遗漏的modules子模块
|
||||
如果modules目录下的子模块没有被重命名:
|
||||
```bash
|
||||
./fix-missing-modules.sh
|
||||
```
|
||||
**Q: 包名格式验证失败?**
|
||||
A: 确保包名符合Java命名规范,只能包含字母、数字、下划线和点号。
|
||||
|
||||
#### 3. 修复已有问题的项目
|
||||
如果重构过程中出现包名未正确替换或目录结构问题:
|
||||
```bash
|
||||
./fix-existing-project.sh
|
||||
```
|
||||
**Q: 权限被拒绝?**
|
||||
A: 确保脚本有执行权限:`chmod +x *.sh`
|
||||
|
||||
#### 4. 检查项目状态
|
||||
检查项目重构后的整体状态:
|
||||
```bash
|
||||
./project-status-check.sh
|
||||
```
|
||||
### 调试技巧
|
||||
|
||||
#### 5. 演示logback配置处理
|
||||
查看logback配置处理效果:
|
||||
```bash
|
||||
./logback-demo.sh
|
||||
```
|
||||
1. **查看详细日志**: 脚本会显示处理的文件信息
|
||||
2. **检查备份**: 如果出现问题,可以从备份恢复
|
||||
3. **分步执行**: 可以注释掉脚本中的某些步骤来分步调试
|
||||
|
||||
#### 6. 测试反斜杠修复功能
|
||||
验证反斜杠问题修复效果:
|
||||
```bash
|
||||
./test-backslash-fix.sh
|
||||
```
|
||||
## 🔧 扩展功能
|
||||
|
||||
#### 7. 测试配置文件修复功能
|
||||
验证数据库连接字符串和文件路径配置修复效果:
|
||||
```bash
|
||||
./test-config-fix.sh
|
||||
```
|
||||
你可以根据需要扩展脚本功能:
|
||||
|
||||
### 回滚操作
|
||||
如果重构出现问题,可以:
|
||||
1. 删除重构后的项目目录
|
||||
2. 从备份目录恢复:`cp -r coder-common-thin-backend_backup_* coder-common-thin-backend`
|
||||
3. 或使用修复脚本进行增量修复
|
||||
|
||||
### 脚本版本信息
|
||||
- **v1.0.0**:初始版本
|
||||
- **v1.1.0**:修复bash兼容性问题,改进Java包结构迁移逻辑,增加修复工具
|
||||
- **v1.1.1**:修复sed正则表达式导致的目录名反斜杠问题,增加快速修复工具
|
||||
- **v1.2.0**:**重大更新** - 完善反斜杠自动清理,增加项目根目录自动重命名功能
|
||||
- **v1.2.1**:**关键修复** - 彻底解决反斜杠问题,增强MyBatis XML处理,改进验证逻辑
|
||||
- **v1.2.2**:**模块修复** - 修复modules子模块重命名遗漏问题,支持多层级子模块处理
|
||||
- **v1.2.3**:**配置修复** - 修复数据库连接字符串和文件路径配置未更新问题
|
||||
|
||||
## 技术支持
|
||||
|
||||
如果在使用过程中遇到问题,请:
|
||||
1. 检查脚本执行日志
|
||||
2. 查看备份目录是否完整
|
||||
3. 联系开发团队获取支持
|
||||
1. **添加新的文件类型**: 在相应的函数中添加处理逻辑
|
||||
2. **自定义替换规则**: 修改sed命令的正则表达式
|
||||
3. **集成到CI/CD**: 将脚本集成到自动化流水线中
|
||||
|
||||
---
|
||||
|
||||
**版本**:v1.2.3
|
||||
**作者**:Leocoder
|
||||
**更新时间**:2025-09-22
|
||||
**创建时间**: 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文件修改
|
||||
- ✅ 支持配置文件批量处理
|
||||
- ✅ 基础的目录结构重命名功能
|
||||
189
script/batch-refactor.sh
Executable file
189
script/batch-refactor.sh
Executable file
@ -0,0 +1,189 @@
|
||||
#!/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
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}✗ $1${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${PURPLE}ℹ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠ $1${NC}"
|
||||
}
|
||||
|
||||
# 检查配置文件
|
||||
check_config_file() {
|
||||
local config_file="$1"
|
||||
|
||||
if [ ! -f "$config_file" ]; then
|
||||
print_error "配置文件不存在: $config_file"
|
||||
echo ""
|
||||
echo "请先创建配置文件:"
|
||||
echo "1. 复制 refactor-config.example 为 refactor-config.conf"
|
||||
echo "2. 编辑 refactor-config.conf 设置正确的值"
|
||||
echo "3. 运行: ./batch-refactor.sh refactor-config.conf"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 加载配置文件
|
||||
load_config() {
|
||||
local config_file="$1"
|
||||
|
||||
print_info "加载配置文件: $config_file"
|
||||
|
||||
# 读取配置文件
|
||||
source "$config_file"
|
||||
|
||||
# 验证必需的配置项
|
||||
local required_vars=("PROJECT_DIR" "OLD_GROUP_ID" "NEW_GROUP_ID" "OLD_ARTIFACT_ID" "NEW_ARTIFACT_ID" "OLD_MODULE_PREFIX" "NEW_MODULE_PREFIX")
|
||||
|
||||
for var in "${required_vars[@]}"; do
|
||||
if [ -z "${!var}" ]; then
|
||||
print_error "配置项 $var 未设置"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "配置加载成功"
|
||||
}
|
||||
|
||||
# 显示配置信息
|
||||
show_config() {
|
||||
echo ""
|
||||
echo -e "${WHITE}批量重构配置:${NC}"
|
||||
echo -e "${CYAN}项目目录:${NC} $PROJECT_DIR"
|
||||
echo -e "${CYAN}旧 GroupId:${NC} $OLD_GROUP_ID"
|
||||
echo -e "${CYAN}新 GroupId:${NC} $NEW_GROUP_ID"
|
||||
echo -e "${CYAN}旧 ArtifactId:${NC} $OLD_ARTIFACT_ID"
|
||||
echo -e "${CYAN}新 ArtifactId:${NC} $NEW_ARTIFACT_ID"
|
||||
echo -e "${CYAN}旧模块前缀:${NC} $OLD_MODULE_PREFIX"
|
||||
echo -e "${CYAN}新模块前缀:${NC} $NEW_MODULE_PREFIX"
|
||||
|
||||
if [ -n "$OLD_DATABASE_NAME" ]; then
|
||||
echo -e "${CYAN}旧数据库名:${NC} $OLD_DATABASE_NAME"
|
||||
echo -e "${CYAN}新数据库名:${NC} $NEW_DATABASE_NAME"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 执行重构
|
||||
execute_refactor() {
|
||||
local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
local refactor_script="$script_dir/project-refactor.sh"
|
||||
|
||||
if [ ! -f "$refactor_script" ]; then
|
||||
print_error "重构脚本不存在: $refactor_script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建临时输入文件
|
||||
local temp_input=$(mktemp)
|
||||
|
||||
# 生成自动化输入
|
||||
cat > "$temp_input" << EOF
|
||||
$PROJECT_DIR
|
||||
$OLD_GROUP_ID
|
||||
$OLD_ARTIFACT_ID
|
||||
$OLD_MODULE_PREFIX
|
||||
$NEW_GROUP_ID
|
||||
$NEW_ARTIFACT_ID
|
||||
$NEW_MODULE_PREFIX
|
||||
$OLD_DATABASE_NAME
|
||||
$NEW_DATABASE_NAME
|
||||
y
|
||||
EOF
|
||||
|
||||
if [ "$CREATE_BACKUP" = "true" ]; then
|
||||
echo "y" >> "$temp_input"
|
||||
else
|
||||
echo "n" >> "$temp_input"
|
||||
fi
|
||||
|
||||
# 执行重构脚本
|
||||
print_info "开始执行重构..."
|
||||
"$refactor_script" < "$temp_input"
|
||||
|
||||
# 清理临时文件
|
||||
rm -f "$temp_input"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
print_success "批量重构完成!"
|
||||
else
|
||||
print_error "重构过程中出现错误"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo -e "${CYAN}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 批量重构脚本 ║"
|
||||
echo "║ Batch Refactoring Tool ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
|
||||
local config_file="$1"
|
||||
|
||||
if [ -z "$config_file" ]; then
|
||||
config_file="refactor-config.conf"
|
||||
print_info "使用默认配置文件: $config_file"
|
||||
fi
|
||||
|
||||
check_config_file "$config_file"
|
||||
load_config "$config_file"
|
||||
show_config
|
||||
|
||||
if [ "$AUTO_CONFIRM" != "true" ]; then
|
||||
echo -e "${YELLOW}警告: 此操作将修改项目中的所有相关文件!${NC}"
|
||||
read -p "是否继续? (y/N): " confirm
|
||||
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||
print_info "操作已取消"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
execute_refactor
|
||||
}
|
||||
|
||||
# 使用说明
|
||||
usage() {
|
||||
echo "使用方法:"
|
||||
echo " $0 [配置文件]"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 # 使用默认配置文件 refactor-config.conf"
|
||||
echo " $0 my-project-config.conf # 使用指定配置文件"
|
||||
echo ""
|
||||
echo "配置文件格式请参考 refactor-config.example"
|
||||
}
|
||||
|
||||
# 参数检查
|
||||
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
53
script/demo.sh
Executable file
53
script/demo.sh
Executable file
@ -0,0 +1,53 @@
|
||||
#!/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}"
|
||||
286
script/fix-directory-structure.sh
Executable file
286
script/fix-directory-structure.sh
Executable file
@ -0,0 +1,286 @@
|
||||
#!/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 "$@"
|
||||
493
script/fix-duplicate-packages.sh
Executable file
493
script/fix-duplicate-packages.sh
Executable file
@ -0,0 +1,493 @@
|
||||
#!/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 "$@"
|
||||
728
script/project-refactor.sh
Executable file
728
script/project-refactor.sh
Executable file
@ -0,0 +1,728 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 项目重构脚本 - 自动化修改包名、groupId、artifactId
|
||||
# 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=""
|
||||
OLD_GROUP_ID=""
|
||||
NEW_GROUP_ID=""
|
||||
OLD_ARTIFACT_ID=""
|
||||
NEW_ARTIFACT_ID=""
|
||||
OLD_PACKAGE=""
|
||||
NEW_PACKAGE=""
|
||||
OLD_MODULE_PREFIX=""
|
||||
NEW_MODULE_PREFIX=""
|
||||
OLD_DATABASE_NAME=""
|
||||
NEW_DATABASE_NAME=""
|
||||
|
||||
# 打印banner
|
||||
print_banner() {
|
||||
echo -e "${CYAN}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 项目重构自动化脚本 ║"
|
||||
echo "║ Project Refactoring 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}"
|
||||
}
|
||||
|
||||
# 验证输入
|
||||
validate_input() {
|
||||
local input="$1"
|
||||
local pattern="$2"
|
||||
local description="$3"
|
||||
|
||||
if [[ ! "$input" =~ $pattern ]]; then
|
||||
print_error "$description 格式不正确: $input"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# 获取用户输入
|
||||
get_user_input() {
|
||||
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"
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}请输入旧的配置信息:${NC}"
|
||||
|
||||
# 获取旧的groupId
|
||||
read -p "旧的 GroupId (例如: org.leocoder.thin): " OLD_GROUP_ID
|
||||
validate_input "$OLD_GROUP_ID" "^[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)*$" "GroupId"
|
||||
if [ $? -ne 0 ]; then exit 1; fi
|
||||
|
||||
# 获取旧的artifactId
|
||||
read -p "旧的 ArtifactId (例如: coder-common-thin-backend): " OLD_ARTIFACT_ID
|
||||
validate_input "$OLD_ARTIFACT_ID" "^[a-zA-Z][a-zA-Z0-9_-]*$" "ArtifactId"
|
||||
if [ $? -ne 0 ]; then exit 1; fi
|
||||
|
||||
# 获取旧的模块前缀
|
||||
read -p "旧的模块前缀 (例如: coder-common-thin): " OLD_MODULE_PREFIX
|
||||
validate_input "$OLD_MODULE_PREFIX" "^[a-zA-Z][a-zA-Z0-9_-]*$" "模块前缀"
|
||||
if [ $? -ne 0 ]; then exit 1; fi
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}请输入新的配置信息:${NC}"
|
||||
|
||||
# 获取新的groupId
|
||||
read -p "新的 GroupId (例如: org.leocoder.course): " NEW_GROUP_ID
|
||||
validate_input "$NEW_GROUP_ID" "^[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)*$" "GroupId"
|
||||
if [ $? -ne 0 ]; then exit 1; fi
|
||||
|
||||
# 获取新的artifactId
|
||||
read -p "新的 ArtifactId (例如: coder-course-backend): " NEW_ARTIFACT_ID
|
||||
validate_input "$NEW_ARTIFACT_ID" "^[a-zA-Z][a-zA-Z0-9_-]*$" "ArtifactId"
|
||||
if [ $? -ne 0 ]; then exit 1; fi
|
||||
|
||||
# 获取新的模块前缀
|
||||
read -p "新的模块前缀 (例如: coder-course): " NEW_MODULE_PREFIX
|
||||
validate_input "$NEW_MODULE_PREFIX" "^[a-zA-Z][a-zA-Z0-9_-]*$" "模块前缀"
|
||||
if [ $? -ne 0 ]; then exit 1; fi
|
||||
|
||||
# 获取数据库名称(可选)
|
||||
echo ""
|
||||
echo -e "${CYAN}数据库配置 (可选):${NC}"
|
||||
read -p "旧的数据库名称 (留空跳过): " OLD_DATABASE_NAME
|
||||
if [ -n "$OLD_DATABASE_NAME" ]; then
|
||||
read -p "新的数据库名称: " NEW_DATABASE_NAME
|
||||
if [ -z "$NEW_DATABASE_NAME" ]; then
|
||||
print_warning "新数据库名称为空,将跳过数据库配置修改"
|
||||
OLD_DATABASE_NAME=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# 设置包名
|
||||
OLD_PACKAGE="$OLD_GROUP_ID"
|
||||
NEW_PACKAGE="$NEW_GROUP_ID"
|
||||
}
|
||||
|
||||
# 显示配置摘要
|
||||
show_summary() {
|
||||
print_step "步骤 2: 配置摘要"
|
||||
|
||||
echo -e "${WHITE}重构配置摘要:${NC}"
|
||||
echo -e "${CYAN}项目目录:${NC} $PROJECT_DIR"
|
||||
echo -e "${CYAN}旧 GroupId:${NC} $OLD_GROUP_ID"
|
||||
echo -e "${CYAN}新 GroupId:${NC} $NEW_GROUP_ID"
|
||||
echo -e "${CYAN}旧 ArtifactId:${NC} $OLD_ARTIFACT_ID"
|
||||
echo -e "${CYAN}新 ArtifactId:${NC} $NEW_ARTIFACT_ID"
|
||||
echo -e "${CYAN}旧模块前缀:${NC} $OLD_MODULE_PREFIX"
|
||||
echo -e "${CYAN}新模块前缀:${NC} $NEW_MODULE_PREFIX"
|
||||
echo -e "${CYAN}旧包名:${NC} $OLD_PACKAGE"
|
||||
echo -e "${CYAN}新包名:${NC} $NEW_PACKAGE"
|
||||
|
||||
if [ -n "$OLD_DATABASE_NAME" ]; then
|
||||
echo -e "${CYAN}旧数据库名:${NC} $OLD_DATABASE_NAME"
|
||||
echo -e "${CYAN}新数据库名:${NC} $NEW_DATABASE_NAME"
|
||||
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_$(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
|
||||
}
|
||||
|
||||
# 修改POM文件
|
||||
update_pom_files() {
|
||||
print_step "步骤 4: 修改 POM 文件"
|
||||
|
||||
local pom_files=$(find "$PROJECT_DIR" -name "pom.xml" -type f)
|
||||
local count=0
|
||||
|
||||
for pom_file in $pom_files; do
|
||||
print_info "处理: $(basename $(dirname $pom_file))/pom.xml"
|
||||
|
||||
# 创建临时文件
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
# 修改groupId和artifactId,使用更全面的替换规则
|
||||
sed "s|<groupId>$OLD_GROUP_ID</groupId>|<groupId>$NEW_GROUP_ID</groupId>|g" "$pom_file" | \
|
||||
sed "s|<artifactId>$OLD_ARTIFACT_ID</artifactId>|<artifactId>$NEW_ARTIFACT_ID</artifactId>|g" | \
|
||||
sed "s|<name>$OLD_ARTIFACT_ID</name>|<name>$NEW_ARTIFACT_ID</name>|g" | \
|
||||
sed "s|<module>$OLD_MODULE_PREFIX-|<module>$NEW_MODULE_PREFIX-|g" | \
|
||||
sed "s|<artifactId>$OLD_MODULE_PREFIX-|<artifactId>$NEW_MODULE_PREFIX-|g" | \
|
||||
sed "s|<name>$OLD_MODULE_PREFIX-|<name>$NEW_MODULE_PREFIX-|g" | \
|
||||
sed "s|$OLD_MODULE_PREFIX-|$NEW_MODULE_PREFIX-|g" > "$temp_file"
|
||||
|
||||
# 替换原文件
|
||||
mv "$temp_file" "$pom_file"
|
||||
|
||||
((count++))
|
||||
done
|
||||
|
||||
# 第二轮处理:确保所有嵌套模块引用都被更新
|
||||
print_info "第二轮处理:更新嵌套模块引用..."
|
||||
|
||||
for pom_file in $pom_files; do
|
||||
local temp_file=$(mktemp)
|
||||
local modified=false
|
||||
|
||||
# 检查是否还有遗漏的旧模块前缀
|
||||
if grep -q "$OLD_MODULE_PREFIX-" "$pom_file"; then
|
||||
# 处理依赖中的模块引用
|
||||
sed "s|<groupId>$OLD_GROUP_ID</groupId>|<groupId>$NEW_GROUP_ID</groupId>|g" "$pom_file" | \
|
||||
sed "s|>$OLD_MODULE_PREFIX-|>$NEW_MODULE_PREFIX-|g" | \
|
||||
sed "s|/$OLD_MODULE_PREFIX-|/$NEW_MODULE_PREFIX-|g" | \
|
||||
sed "s|\\\"$OLD_MODULE_PREFIX-|\\\">$NEW_MODULE_PREFIX-|g" | \
|
||||
sed "s|=$OLD_MODULE_PREFIX-|=$NEW_MODULE_PREFIX-|g" > "$temp_file"
|
||||
|
||||
mv "$temp_file" "$pom_file"
|
||||
modified=true
|
||||
fi
|
||||
|
||||
if [ "$modified" = true ]; then
|
||||
print_info "更新嵌套引用: $(basename $(dirname $pom_file))/pom.xml"
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已修改 $count 个 POM 文件"
|
||||
}
|
||||
|
||||
# 修改Java文件包名
|
||||
update_java_packages() {
|
||||
print_step "步骤 5: 修改 Java 包名"
|
||||
|
||||
local java_files=$(find "$PROJECT_DIR" -name "*.java" -type f)
|
||||
local count=0
|
||||
|
||||
# 转换包名格式(用于文件内容替换)
|
||||
local old_package_escaped=$(echo "$OLD_PACKAGE" | sed 's/\./\\./g')
|
||||
local new_package_escaped="$NEW_PACKAGE"
|
||||
|
||||
for java_file in $java_files; do
|
||||
if grep -q "$OLD_PACKAGE" "$java_file"; then
|
||||
print_info "处理: $(basename $java_file)"
|
||||
|
||||
# 创建临时文件
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
# 修改package声明 - 使用精确匹配
|
||||
sed "s|^package $old_package_escaped\(\.[a-zA-Z0-9_]*\)\*;|package $new_package_escaped\1;|g" "$java_file" | \
|
||||
# 修改import语句 - 使用精确匹配
|
||||
sed "s|^import $old_package_escaped\(\.[a-zA-Z0-9_\.]*\);|import $new_package_escaped\1;|g" | \
|
||||
# 修改import static语句
|
||||
sed "s|^import static $old_package_escaped\(\.[a-zA-Z0-9_\.]*\);|import static $new_package_escaped\1;|g" | \
|
||||
# 修改注释和字符串中的包名引用(谨慎处理)
|
||||
sed "s|\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|\"$new_package_escaped\1\"|g" | \
|
||||
# 修改注解中的包名引用
|
||||
sed "s|@$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)|@$new_package_escaped\1|g" > "$temp_file"
|
||||
|
||||
# 检查是否有实际变化
|
||||
if ! diff "$java_file" "$temp_file" > /dev/null; then
|
||||
mv "$temp_file" "$java_file"
|
||||
((count++))
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已修改 $count 个 Java 文件"
|
||||
}
|
||||
|
||||
# 修改XML映射文件
|
||||
update_xml_files() {
|
||||
print_step "步骤 6: 修改 XML 映射文件"
|
||||
|
||||
local xml_files=$(find "$PROJECT_DIR" -name "*.xml" -type f | grep -E "(mapper|mybatis)")
|
||||
local count=0
|
||||
|
||||
if [ -z "$xml_files" ]; then
|
||||
print_info "未找到需要修改的XML映射文件"
|
||||
return
|
||||
fi
|
||||
|
||||
local old_package_escaped=$(echo "$OLD_PACKAGE" | sed 's/\./\\./g')
|
||||
|
||||
for xml_file in $xml_files; do
|
||||
if grep -q "$OLD_PACKAGE" "$xml_file"; then
|
||||
print_info "处理: $(basename $xml_file)"
|
||||
|
||||
# 创建临时文件
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
# 修改namespace属性 - 精确匹配
|
||||
sed "s|namespace=\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|namespace=\"$NEW_PACKAGE\1\"|g" "$xml_file" | \
|
||||
# 修改resultType属性
|
||||
sed "s|resultType=\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|resultType=\"$NEW_PACKAGE\1\"|g" | \
|
||||
# 修改parameterType属性
|
||||
sed "s|parameterType=\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|parameterType=\"$NEW_PACKAGE\1\"|g" | \
|
||||
# 修改type属性
|
||||
sed "s|type=\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|type=\"$NEW_PACKAGE\1\"|g" | \
|
||||
# 修改javaType属性
|
||||
sed "s|javaType=\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|javaType=\"$NEW_PACKAGE\1\"|g" | \
|
||||
# 修改jdbcType中的包名引用(如果有)
|
||||
sed "s|select=\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|select=\"$NEW_PACKAGE\1\"|g" | \
|
||||
# 修改注释中的包名引用
|
||||
sed "s|<!--.*$old_package_escaped\(\.[a-zA-Z0-9_\.]*\).*-->|<!--.*$NEW_PACKAGE\1.*-->|g" > "$temp_file"
|
||||
|
||||
# 检查是否有实际变化
|
||||
if ! diff "$xml_file" "$temp_file" > /dev/null; then
|
||||
mv "$temp_file" "$xml_file"
|
||||
((count++))
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已修改 $count 个 XML 文件"
|
||||
}
|
||||
|
||||
# 修改配置文件
|
||||
update_config_files() {
|
||||
print_step "步骤 7: 修改配置文件"
|
||||
|
||||
local config_files=$(find "$PROJECT_DIR" -name "*.yml" -o -name "*.yaml" -o -name "*.properties" | grep -v target)
|
||||
local count=0
|
||||
|
||||
local old_package_escaped=$(echo "$OLD_PACKAGE" | sed 's/\./\\./g')
|
||||
|
||||
for config_file in $config_files; do
|
||||
local modified=false
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
# 处理包扫描配置
|
||||
if grep -q "$OLD_PACKAGE" "$config_file"; then
|
||||
# 修改包扫描配置 - 精确匹配
|
||||
sed "s|base-package: $old_package_escaped|base-package: $NEW_PACKAGE|g" "$config_file" | \
|
||||
sed "s|basePackage: $old_package_escaped|basePackage: $NEW_PACKAGE|g" | \
|
||||
sed "s|base-packages: $old_package_escaped|base-packages: $NEW_PACKAGE|g" | \
|
||||
sed "s|basePackages: $old_package_escaped|basePackages: $NEW_PACKAGE|g" | \
|
||||
# 修改mybatis配置
|
||||
sed "s|mapper-locations: classpath:$old_package_escaped|mapper-locations: classpath:$NEW_PACKAGE|g" | \
|
||||
sed "s|type-aliases-package: $old_package_escaped|type-aliases-package: $NEW_PACKAGE|g" | \
|
||||
# 修改日志配置
|
||||
sed "s|<logger name=\"$old_package_escaped|<logger name=\"$NEW_PACKAGE|g" | \
|
||||
# 修改其他包名引用
|
||||
sed "s|\"$old_package_escaped\(\.[a-zA-Z0-9_\.]*\)\"|\"$NEW_PACKAGE\1\"|g" | \
|
||||
# 修改注释中的包名引用
|
||||
sed "s|# $old_package_escaped|# $NEW_PACKAGE|g" > "$temp_file"
|
||||
|
||||
# 检查是否有实际变化
|
||||
if ! diff "$config_file" "$temp_file" > /dev/null; then
|
||||
mv "$temp_file" "$config_file"
|
||||
modified=true
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 修改数据库配置
|
||||
if [ -n "$OLD_DATABASE_NAME" ] && grep -q "$OLD_DATABASE_NAME" "$config_file"; then
|
||||
local temp_file2=$(mktemp)
|
||||
# 精确匹配数据库名称
|
||||
sed "s|database: $OLD_DATABASE_NAME|database: $NEW_DATABASE_NAME|g" "$config_file" | \
|
||||
sed "s|jdbc:mysql://[^/]*/\{0,1\}$OLD_DATABASE_NAME|jdbc:mysql://localhost:3306/$NEW_DATABASE_NAME|g" | \
|
||||
sed "s|url: .*/$OLD_DATABASE_NAME|url: jdbc:mysql://localhost:3306/$NEW_DATABASE_NAME|g" > "$temp_file2"
|
||||
|
||||
if ! diff "$config_file" "$temp_file2" > /dev/null; then
|
||||
mv "$temp_file2" "$config_file"
|
||||
modified=true
|
||||
else
|
||||
rm -f "$temp_file2"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$modified" = true ]; then
|
||||
print_info "处理: $(basename $config_file)"
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已修改 $count 个配置文件"
|
||||
}
|
||||
|
||||
# 重命名目录结构
|
||||
rename_directories() {
|
||||
print_step "步骤 8: 重命名目录结构"
|
||||
|
||||
# 重命名Java包目录
|
||||
print_info "重命名Java包目录结构..."
|
||||
|
||||
# 将点分隔的包名转换为路径
|
||||
local old_package_path=$(echo "$OLD_PACKAGE" | tr '.' '/')
|
||||
local new_package_path=$(echo "$NEW_PACKAGE" | tr '.' '/')
|
||||
|
||||
# 查找所有需要重命名的包目录
|
||||
local package_dirs=$(find "$PROJECT_DIR" -type d -path "*/java/$old_package_path" 2>/dev/null)
|
||||
|
||||
for package_dir in $package_dirs; do
|
||||
local parent_dir=$(dirname "$package_dir")
|
||||
local new_package_dir="$parent_dir/$new_package_path"
|
||||
|
||||
# 创建新的目录结构
|
||||
mkdir -p "$(dirname $new_package_dir)"
|
||||
|
||||
# 移动内容
|
||||
if [ "$package_dir" != "$new_package_dir" ]; then
|
||||
print_info "移动: $package_dir -> $new_package_dir"
|
||||
mv "$package_dir" "$new_package_dir" 2>/dev/null || {
|
||||
# 如果直接移动失败,尝试复制后删除
|
||||
cp -r "$package_dir" "$new_package_dir"
|
||||
rm -rf "$package_dir"
|
||||
}
|
||||
fi
|
||||
done
|
||||
|
||||
# 重命名模块目录(递归处理所有层级)
|
||||
print_info "重命名模块目录..."
|
||||
|
||||
# 递归函数来处理所有层级的模块目录
|
||||
rename_module_directories() {
|
||||
local search_dir="$1"
|
||||
local depth="$2"
|
||||
|
||||
# 在当前目录查找匹配的模块目录
|
||||
local module_dirs=$(find "$search_dir" -maxdepth 1 -type d -name "$OLD_MODULE_PREFIX-*" 2>/dev/null)
|
||||
|
||||
for module_dir in $module_dirs; do
|
||||
local parent_dir=$(dirname "$module_dir")
|
||||
local old_name=$(basename "$module_dir")
|
||||
local new_name=$(echo "$old_name" | sed "s/^$OLD_MODULE_PREFIX-/$NEW_MODULE_PREFIX-/")
|
||||
local new_module_dir="$parent_dir/$new_name"
|
||||
|
||||
if [ "$module_dir" != "$new_module_dir" ]; then
|
||||
print_info "重命名模块 (深度$depth): $old_name -> $new_name"
|
||||
mv "$module_dir" "$new_module_dir"
|
||||
|
||||
# 递归处理重命名后的目录
|
||||
rename_module_directories "$new_module_dir" $((depth + 1))
|
||||
else
|
||||
# 如果目录名没有变化,仍然需要递归处理其子目录
|
||||
rename_module_directories "$module_dir" $((depth + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# 处理不匹配模块前缀但可能包含子模块的目录
|
||||
local subdirs=$(find "$search_dir" -maxdepth 1 -type d ! -name ".*" ! -name "target" ! -name "src" ! -name "test" ! -name "main" ! -name "java" ! -name "resources" -not -path "$search_dir" 2>/dev/null)
|
||||
|
||||
for subdir in $subdirs; do
|
||||
local dir_name=$(basename "$subdir")
|
||||
# 如果目录名不是以旧模块前缀开头,但可能包含子模块,继续递归
|
||||
if [[ ! "$dir_name" =~ ^$OLD_MODULE_PREFIX- ]] && [[ "$dir_name" != "target" ]] && [[ "$dir_name" != "src" ]]; then
|
||||
rename_module_directories "$subdir" $((depth + 1))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 从项目根目录开始递归处理
|
||||
rename_module_directories "$PROJECT_DIR" 1
|
||||
|
||||
print_success "目录重命名完成"
|
||||
}
|
||||
|
||||
# 处理遗漏的嵌套模块
|
||||
process_nested_modules() {
|
||||
print_step "步骤 9: 处理遗漏的嵌套模块"
|
||||
|
||||
print_info "检查是否有未处理的嵌套模块..."
|
||||
|
||||
# 查找所有仍然使用旧模块前缀的目录
|
||||
local remaining_dirs=$(find "$PROJECT_DIR" -type d -name "$OLD_MODULE_PREFIX-*" ! -path "*/target/*" 2>/dev/null)
|
||||
|
||||
if [ -z "$remaining_dirs" ]; then
|
||||
print_info "没有找到遗漏的嵌套模块"
|
||||
return
|
||||
fi
|
||||
|
||||
local count=0
|
||||
|
||||
# 处理每个遗漏的目录
|
||||
for old_dir in $remaining_dirs; do
|
||||
local parent_dir=$(dirname "$old_dir")
|
||||
local old_name=$(basename "$old_dir")
|
||||
local new_name=$(echo "$old_name" | sed "s/^$OLD_MODULE_PREFIX-/$NEW_MODULE_PREFIX-/")
|
||||
local new_dir="$parent_dir/$new_name"
|
||||
|
||||
if [ "$old_dir" != "$new_dir" ]; then
|
||||
print_info "处理遗漏的模块: $old_name -> $new_name"
|
||||
|
||||
# 重命名目录
|
||||
mv "$old_dir" "$new_dir"
|
||||
|
||||
# 更新该模块的POM文件
|
||||
local pom_file="$new_dir/pom.xml"
|
||||
if [ -f "$pom_file" ]; then
|
||||
local temp_file=$(mktemp)
|
||||
sed "s|<groupId>$OLD_GROUP_ID</groupId>|<groupId>$NEW_GROUP_ID</groupId>|g" "$pom_file" | \
|
||||
sed "s|<artifactId>$old_name</artifactId>|<artifactId>$new_name</artifactId>|g" | \
|
||||
sed "s|<name>$old_name</name>|<name>$new_name</name>|g" | \
|
||||
sed "s|$OLD_MODULE_PREFIX-|$NEW_MODULE_PREFIX-|g" > "$temp_file"
|
||||
|
||||
mv "$temp_file" "$pom_file"
|
||||
print_info "更新模块POM: $new_name/pom.xml"
|
||||
fi
|
||||
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
|
||||
# 最后检查父级POM文件,确保模块引用已更新
|
||||
print_info "最终检查父级POM文件的模块引用..."
|
||||
local parent_poms=$(find "$PROJECT_DIR" -name "pom.xml" -type f)
|
||||
|
||||
for pom_file in $parent_poms; do
|
||||
if grep -q "$OLD_MODULE_PREFIX-" "$pom_file"; then
|
||||
local temp_file=$(mktemp)
|
||||
sed "s|<module>$OLD_MODULE_PREFIX-|<module>$NEW_MODULE_PREFIX-|g" "$pom_file" | \
|
||||
sed "s|$OLD_MODULE_PREFIX-|$NEW_MODULE_PREFIX-|g" > "$temp_file"
|
||||
|
||||
mv "$temp_file" "$pom_file"
|
||||
print_info "更新父级POM引用: $(basename $(dirname $pom_file))/pom.xml"
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已处理 $count 个遗漏的嵌套模块"
|
||||
}
|
||||
|
||||
# 修复已经重复的包名
|
||||
fix_duplicate_packages() {
|
||||
print_step "步骤 10: 修复重复包名"
|
||||
|
||||
local all_files=$(find "$PROJECT_DIR" -name "*.java" -o -name "*.xml" -o -name "*.yml" -o -name "*.yaml" -o -name "*.properties" | grep -v target)
|
||||
local count=0
|
||||
|
||||
# 检查常见的重复模式
|
||||
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|g" "$temp_file"
|
||||
modified=true
|
||||
fi
|
||||
|
||||
# 检查是否有实际变化
|
||||
if [ "$modified" = true ] && ! diff "$file" "$temp_file" > /dev/null; then
|
||||
mv "$temp_file" "$file"
|
||||
print_info "修复重复包名: $(basename $file)"
|
||||
((count++))
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已修复 $count 个文件中的重复包名"
|
||||
}
|
||||
|
||||
# 重命名SQL文件
|
||||
rename_sql_files() {
|
||||
print_step "步骤 11: 重命名 SQL 文件"
|
||||
|
||||
local sql_files=$(find "$PROJECT_DIR" -name "*.sql" -type f | grep -i "$OLD_MODULE_PREFIX")
|
||||
local count=0
|
||||
|
||||
if [ -z "$sql_files" ]; then
|
||||
print_info "未找到需要重命名的SQL文件"
|
||||
return
|
||||
fi
|
||||
|
||||
for sql_file in $sql_files; do
|
||||
local dir_name=$(dirname "$sql_file")
|
||||
local old_name=$(basename "$sql_file")
|
||||
local new_name=$(echo "$old_name" | sed "s/$OLD_MODULE_PREFIX/$NEW_MODULE_PREFIX/g")
|
||||
local new_sql_file="$dir_name/$new_name"
|
||||
|
||||
if [ "$sql_file" != "$new_sql_file" ]; then
|
||||
print_info "重命名SQL文件: $old_name -> $new_name"
|
||||
mv "$sql_file" "$new_sql_file"
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
|
||||
print_success "已重命名 $count 个 SQL 文件"
|
||||
}
|
||||
|
||||
# 清理临时文件
|
||||
cleanup() {
|
||||
print_step "步骤 12: 清理和验证"
|
||||
|
||||
# 清理可能遗留的备份文件
|
||||
find "$PROJECT_DIR" -name "*.bak" -type f -delete 2>/dev/null
|
||||
|
||||
# 显示统计信息
|
||||
local java_files_count=$(find "$PROJECT_DIR" -name "*.java" -type f | wc -l)
|
||||
local pom_files_count=$(find "$PROJECT_DIR" -name "pom.xml" -type f | wc -l)
|
||||
local xml_files_count=$(find "$PROJECT_DIR" -name "*.xml" -type f | grep -E "(mapper|mybatis)" | wc -l)
|
||||
|
||||
echo ""
|
||||
echo -e "${WHITE}重构统计:${NC}"
|
||||
echo -e "${CYAN}Java 文件:${NC} $java_files_count"
|
||||
echo -e "${CYAN}POM 文件:${NC} $pom_files_count"
|
||||
echo -e "${CYAN}XML 映射文件:${NC} $xml_files_count"
|
||||
|
||||
print_success "清理完成"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
# 检查依赖
|
||||
if ! command -v sed &> /dev/null; then
|
||||
print_error "sed 命令未找到,请安装 sed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_banner
|
||||
|
||||
get_user_input
|
||||
show_summary
|
||||
backup_project
|
||||
|
||||
# 进入项目目录
|
||||
cd "$PROJECT_DIR" || exit 1
|
||||
|
||||
# 执行重构步骤
|
||||
update_pom_files
|
||||
update_java_packages
|
||||
update_xml_files
|
||||
update_config_files
|
||||
rename_directories
|
||||
process_nested_modules
|
||||
fix_duplicate_packages
|
||||
rename_sql_files
|
||||
cleanup
|
||||
|
||||
print_step "🎉 重构完成!"
|
||||
|
||||
echo -e "${GREEN}"
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ 重构成功完成! ║"
|
||||
echo "║ ║"
|
||||
echo "║ 项目已成功从 $OLD_GROUP_ID 重构为 $NEW_GROUP_ID"
|
||||
echo "║ ║"
|
||||
echo "║ 下一步建议: ║"
|
||||
echo "║ 1. 检查IDE中的运行配置 ║"
|
||||
echo "║ 2. 更新数据库连接配置 ║"
|
||||
echo "║ 3. 清理并重新编译项目 ║"
|
||||
echo "║ 4. 测试项目是否正常运行 ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# 脚本入口
|
||||
main "$@"
|
||||
@ -1,567 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
#=============================================================================
|
||||
# 项目模板重构脚本
|
||||
# 用于将coder-common-thin-backend项目重构为新的项目模板
|
||||
#
|
||||
# 功能:
|
||||
# 1. 重构项目名称和模块名
|
||||
# 2. 修改包名和groupId
|
||||
# 3. 更新配置文件中的包名引用
|
||||
# 4. 重命名SQL文件和数据库名
|
||||
# 5. 处理多层级子模块结构
|
||||
# 6. 更新数据库连接字符串
|
||||
# 7. 更新文件路径配置
|
||||
#
|
||||
# 作者: Leocoder
|
||||
# 版本: 1.2.3
|
||||
#=============================================================================
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_step() {
|
||||
echo -e "${BLUE}[STEP]${NC} $1"
|
||||
}
|
||||
|
||||
# 当前项目信息
|
||||
CURRENT_PROJECT_NAME="coder-common-thin-backend"
|
||||
CURRENT_GROUP_ID="org.leocoder.thin"
|
||||
CURRENT_PACKAGE_NAME="org.leocoder.thin"
|
||||
CURRENT_MODULE_PREFIX="coder-common-thin"
|
||||
CURRENT_DB_NAME="coder-common-thin"
|
||||
|
||||
# 脚本目录
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
log_info "=== 项目模板重构脚本 v1.2.3 ==="
|
||||
log_info "项目根目录: $PROJECT_ROOT"
|
||||
|
||||
# 验证当前目录
|
||||
if [[ ! -f "$PROJECT_ROOT/pom.xml" ]]; then
|
||||
log_error "当前目录不是有效的Maven项目根目录"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 获取用户输入
|
||||
echo ""
|
||||
log_step "请输入新项目的配置信息:"
|
||||
|
||||
read -p "新项目名称 (例如: my-project-backend): " NEW_PROJECT_NAME
|
||||
read -p "新的GroupId (例如: com.company.project): " NEW_GROUP_ID
|
||||
read -p "新的包名 (例如: com.company.project): " NEW_PACKAGE_NAME
|
||||
read -p "新的模块前缀 (例如: my-project): " NEW_MODULE_PREFIX
|
||||
read -p "新的数据库名 (例如: my_project_db): " NEW_DB_NAME
|
||||
|
||||
# 验证输入
|
||||
if [[ -z "$NEW_PROJECT_NAME" || -z "$NEW_GROUP_ID" || -z "$NEW_PACKAGE_NAME" || -z "$NEW_MODULE_PREFIX" || -z "$NEW_DB_NAME" ]]; then
|
||||
log_error "所有参数都不能为空"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 显示配置信息确认
|
||||
echo ""
|
||||
log_info "=== 重构配置确认 ==="
|
||||
echo "项目名称: $CURRENT_PROJECT_NAME -> $NEW_PROJECT_NAME"
|
||||
echo "GroupId: $CURRENT_GROUP_ID -> $NEW_GROUP_ID"
|
||||
echo "包名: $CURRENT_PACKAGE_NAME -> $NEW_PACKAGE_NAME"
|
||||
echo "模块前缀: $CURRENT_MODULE_PREFIX -> $NEW_MODULE_PREFIX"
|
||||
echo "数据库名: $CURRENT_DB_NAME -> $NEW_DB_NAME"
|
||||
echo ""
|
||||
|
||||
read -p "确认开始重构?[y/N]: " CONFIRM
|
||||
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
|
||||
log_info "重构已取消"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 备份项目
|
||||
BACKUP_DIR="${PROJECT_ROOT}_backup_$(date +%Y%m%d_%H%M%S)"
|
||||
log_step "创建项目备份: $BACKUP_DIR"
|
||||
cp -r "$PROJECT_ROOT" "$BACKUP_DIR"
|
||||
log_info "备份完成"
|
||||
|
||||
# 重构函数
|
||||
|
||||
# 1. 重命名模块目录
|
||||
rename_module_directories() {
|
||||
log_step "重命名模块目录..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# 主模块重命名
|
||||
local modules=(
|
||||
"$CURRENT_MODULE_PREFIX-web"
|
||||
"$CURRENT_MODULE_PREFIX-common"
|
||||
"$CURRENT_MODULE_PREFIX-model"
|
||||
"$CURRENT_MODULE_PREFIX-mybatisplus"
|
||||
"$CURRENT_MODULE_PREFIX-modules"
|
||||
"$CURRENT_MODULE_PREFIX-plugins"
|
||||
)
|
||||
|
||||
for module in "${modules[@]}"; do
|
||||
if [[ -d "$module" ]]; then
|
||||
new_module="${module/$CURRENT_MODULE_PREFIX/$NEW_MODULE_PREFIX}"
|
||||
log_info "重命名: $module -> $new_module"
|
||||
mv "$module" "$new_module"
|
||||
fi
|
||||
done
|
||||
|
||||
# 递归重命名所有子模块(modules、plugins等)
|
||||
local parent_modules=(
|
||||
"$NEW_MODULE_PREFIX-modules"
|
||||
"$NEW_MODULE_PREFIX-plugins"
|
||||
)
|
||||
|
||||
for parent_module in "${parent_modules[@]}"; do
|
||||
if [[ -d "$parent_module" ]]; then
|
||||
log_info "处理子模块目录: $parent_module"
|
||||
cd "$parent_module"
|
||||
|
||||
# 重命名当前目录下的所有子模块
|
||||
for sub_dir in $CURRENT_MODULE_PREFIX-*; do
|
||||
if [[ -d "$sub_dir" ]]; then
|
||||
new_sub_dir="${sub_dir/$CURRENT_MODULE_PREFIX/$NEW_MODULE_PREFIX}"
|
||||
log_info "重命名子模块: $sub_dir -> $new_sub_dir"
|
||||
mv "$sub_dir" "$new_sub_dir"
|
||||
|
||||
# 递归处理子模块中的子子模块(如果存在)
|
||||
if [[ -d "$new_sub_dir" ]]; then
|
||||
cd "$new_sub_dir"
|
||||
for sub_sub_dir in $CURRENT_MODULE_PREFIX-*; do
|
||||
if [[ -d "$sub_sub_dir" ]]; then
|
||||
new_sub_sub_dir="${sub_sub_dir/$CURRENT_MODULE_PREFIX/$NEW_MODULE_PREFIX}"
|
||||
log_info "重命名子子模块: $sub_sub_dir -> $new_sub_sub_dir"
|
||||
mv "$sub_sub_dir" "$new_sub_sub_dir"
|
||||
fi
|
||||
done
|
||||
cd ".."
|
||||
fi
|
||||
fi
|
||||
done
|
||||
cd "$PROJECT_ROOT"
|
||||
fi
|
||||
done
|
||||
|
||||
log_info "模块目录重命名完成"
|
||||
}
|
||||
|
||||
# 2. 更新POM文件
|
||||
update_pom_files() {
|
||||
log_step "更新POM文件..."
|
||||
|
||||
# 查找所有pom.xml文件
|
||||
find "$PROJECT_ROOT" -name "pom.xml" -type f | while read pom_file; do
|
||||
log_info "更新POM: $pom_file"
|
||||
|
||||
# 使用sed进行替换
|
||||
sed -i.bak \
|
||||
-e "s|<groupId>$CURRENT_GROUP_ID</groupId>|<groupId>$NEW_GROUP_ID</groupId>|g" \
|
||||
-e "s|<artifactId>$CURRENT_PROJECT_NAME</artifactId>|<artifactId>$NEW_PROJECT_NAME</artifactId>|g" \
|
||||
-e "s|<name>$CURRENT_PROJECT_NAME</name>|<name>$NEW_PROJECT_NAME</name>|g" \
|
||||
-e "s|$CURRENT_MODULE_PREFIX-|$NEW_MODULE_PREFIX-|g" \
|
||||
"$pom_file"
|
||||
|
||||
# 删除备份文件
|
||||
rm -f "${pom_file}.bak"
|
||||
done
|
||||
|
||||
log_info "POM文件更新完成"
|
||||
}
|
||||
|
||||
# 3. 更新Java包结构
|
||||
update_java_packages() {
|
||||
log_step "更新Java包结构..."
|
||||
|
||||
# 转换包名路径
|
||||
local current_package_path="${CURRENT_PACKAGE_NAME//./\/}"
|
||||
local new_package_path="${NEW_PACKAGE_NAME//./\/}"
|
||||
|
||||
log_info "包路径转换: $current_package_path -> $new_package_path"
|
||||
|
||||
# 查找所有Java文件并更新包名和import语句
|
||||
find "$PROJECT_ROOT" -name "*.java" -type f | while read java_file; do
|
||||
log_info "更新Java文件内容: $java_file"
|
||||
|
||||
# 更新package声明和import语句,使用更精确的匹配(避免转义字符问题)
|
||||
sed -i.bak \
|
||||
-e "s|^package ${CURRENT_PACKAGE_NAME};|package ${NEW_PACKAGE_NAME};|g" \
|
||||
-e "s|^package ${CURRENT_PACKAGE_NAME}[.]|package ${NEW_PACKAGE_NAME}.|g" \
|
||||
-e "s|^import ${CURRENT_PACKAGE_NAME};|import ${NEW_PACKAGE_NAME};|g" \
|
||||
-e "s|^import ${CURRENT_PACKAGE_NAME}[.]|import ${NEW_PACKAGE_NAME}.|g" \
|
||||
-e "s|${CURRENT_PACKAGE_NAME}[.]|${NEW_PACKAGE_NAME}.|g" \
|
||||
"$java_file"
|
||||
|
||||
rm -f "${java_file}.bak"
|
||||
done
|
||||
|
||||
# 重构Java包目录结构
|
||||
log_info "开始重构Java包目录结构..."
|
||||
|
||||
# 查找所有包含当前包路径的java源码目录
|
||||
find "$PROJECT_ROOT" -path "*/src/main/java/$current_package_path" -type d | while read old_package_dir; do
|
||||
log_info "处理包目录: $old_package_dir"
|
||||
|
||||
# 获取java源码根目录
|
||||
local java_root="${old_package_dir%/$current_package_path}"
|
||||
local new_package_dir="$java_root/$new_package_path"
|
||||
|
||||
log_info " 源目录: $old_package_dir"
|
||||
log_info " 目标目录: $new_package_dir"
|
||||
|
||||
# 创建新的包目录结构
|
||||
mkdir -p "$(dirname "$new_package_dir")"
|
||||
|
||||
# 移动整个包目录到新位置
|
||||
if [[ -d "$old_package_dir" && "$old_package_dir" != "$new_package_dir" ]]; then
|
||||
mv "$old_package_dir" "$new_package_dir"
|
||||
log_info " 已移动包目录"
|
||||
|
||||
# 清理空的父级目录
|
||||
local old_parent="$(dirname "$old_package_dir")"
|
||||
while [[ "$old_parent" != "$java_root" && -d "$old_parent" ]]; do
|
||||
if [[ -z "$(ls -A "$old_parent" 2>/dev/null)" ]]; then
|
||||
rmdir "$old_parent" 2>/dev/null && log_info " 清理空目录: $old_parent"
|
||||
old_parent="$(dirname "$old_parent")"
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
log_info "Java包结构更新完成"
|
||||
}
|
||||
|
||||
# 4. 清理目录名中的反斜杠(独立函数)
|
||||
cleanup_backslash_directories() {
|
||||
log_step "清理目录名中的反斜杠..."
|
||||
|
||||
local fixed_count=0
|
||||
local attempts=0
|
||||
|
||||
# 重复检查和修复,直到没有反斜杠目录或达到最大尝试次数
|
||||
while [[ $attempts -lt 5 ]]; do
|
||||
local found_backslash=false
|
||||
|
||||
# 查找包含反斜杠的目录
|
||||
for dir_path in $(find "$PROJECT_ROOT" -path "*/src/main/java/*" -type d 2>/dev/null); do
|
||||
if [[ ! -d "$dir_path" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
dir_name=$(basename "$dir_path")
|
||||
|
||||
# 检查目录名是否包含反斜杠
|
||||
if [[ "$dir_name" == *"\\"* ]]; then
|
||||
found_backslash=true
|
||||
|
||||
# 清理反斜杠,获取正确的目录名
|
||||
clean_dir_name="${dir_name//\\/}"
|
||||
parent_dir=$(dirname "$dir_path")
|
||||
new_dir_path="$parent_dir/$clean_dir_name"
|
||||
|
||||
log_info "修复目录名: '$dir_name' -> '$clean_dir_name'"
|
||||
|
||||
# 重命名目录
|
||||
if [[ "$dir_path" != "$new_dir_path" && ! -e "$new_dir_path" ]]; then
|
||||
if mv "$dir_path" "$new_dir_path" 2>/dev/null; then
|
||||
log_info " ✓ 目录重命名成功: $(basename "$new_dir_path")"
|
||||
((fixed_count++))
|
||||
else
|
||||
log_warn " ✗ 目录重命名失败: $dir_path"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 如果没有找到反斜杠目录,退出循环
|
||||
if [[ "$found_backslash" == false ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
((attempts++))
|
||||
sleep 0.1 # 短暂等待,确保文件系统操作完成
|
||||
done
|
||||
|
||||
if [[ $fixed_count -gt 0 ]]; then
|
||||
log_info "总共修复了 $fixed_count 个包含反斜杠的目录(用了 $attempts 轮处理)"
|
||||
else
|
||||
log_info "未发现包含反斜杠的目录"
|
||||
fi
|
||||
|
||||
log_info "反斜杠清理完成"
|
||||
}
|
||||
|
||||
# 5. 更新配置文件
|
||||
update_config_files() {
|
||||
log_step "更新配置文件..."
|
||||
|
||||
# 更新application配置文件
|
||||
find "$PROJECT_ROOT" -name "application*.yml" -o -name "application*.yaml" -o -name "application*.properties" | while read config_file; do
|
||||
log_info "更新配置文件: $config_file"
|
||||
|
||||
# 计算新的配置名称(兼容各种bash版本)
|
||||
local new_pool_name="$(echo "$NEW_MODULE_PREFIX" | tr '[:lower:]' '[:upper:]')-HIKARI-DEV"
|
||||
local new_project_name="$(echo "$NEW_MODULE_PREFIX" | tr '[:lower:]' '[:upper:]')-ADMIN"
|
||||
|
||||
sed -i.bak \
|
||||
-e "s|packages-to-scan: $CURRENT_PACKAGE_NAME|packages-to-scan: $NEW_PACKAGE_NAME|g" \
|
||||
-e "s|$CURRENT_PACKAGE_NAME|$NEW_PACKAGE_NAME|g" \
|
||||
-e "s|name: coder-web|name: ${NEW_MODULE_PREFIX}-web|g" \
|
||||
-e "s|projectName: CORDER-ADMIN-THIN|projectName: $new_project_name|g" \
|
||||
-e "s|pool-name: CORDER-HIKARI-DEV|pool-name: $new_pool_name|g" \
|
||||
-e "s|jdbc:mysql://localhost:3306/$CURRENT_DB_NAME|jdbc:mysql://localhost:3306/$NEW_DB_NAME|g" \
|
||||
-e "s|jdbc:mysql://localhost:3306/$CURRENT_DB_NAME-backup|jdbc:mysql://localhost:3306/$NEW_DB_NAME-backup|g" \
|
||||
-e "s|/$CURRENT_PROJECT_NAME/|/$NEW_PROJECT_NAME/|g" \
|
||||
-e "s|$CURRENT_MODULE_PREFIX|$NEW_MODULE_PREFIX|g" \
|
||||
"$config_file"
|
||||
|
||||
rm -f "${config_file}.bak"
|
||||
done
|
||||
|
||||
# 更新logback配置文件(专门处理logback特有的配置)
|
||||
find "$PROJECT_ROOT" -name "logback*.xml" | while read logback_file; do
|
||||
log_info "更新Logback配置: $logback_file"
|
||||
|
||||
# 计算新的日志配置名称(兼容各种bash版本)
|
||||
local new_context_name="${NEW_MODULE_PREFIX}-logback"
|
||||
local new_property_name="$(echo "$NEW_MODULE_PREFIX" | tr '[:lower:]' '[:upper:]')_ADMIN_LOGS"
|
||||
|
||||
sed -i.bak \
|
||||
-e "s|$CURRENT_PACKAGE_NAME|$NEW_PACKAGE_NAME|g" \
|
||||
-e "s|<contextName>$CURRENT_MODULE_PREFIX-logback</contextName>|<contextName>$new_context_name</contextName>|g" \
|
||||
-e "s|CORDER_ADMIN_LOGS|$new_property_name|g" \
|
||||
-e "s|name=\"CORDER_ADMIN_LOGS\"|name=\"$new_property_name\"|g" \
|
||||
"$logback_file"
|
||||
|
||||
rm -f "${logback_file}.bak"
|
||||
done
|
||||
|
||||
# 更新MyBatis XML文件(处理namespace和resultType)
|
||||
find "$PROJECT_ROOT" -name "*.xml" -path "*/mapper/*" | while read mapper_file; do
|
||||
log_info "更新MyBatis配置: $mapper_file"
|
||||
|
||||
sed -i.bak \
|
||||
-e "s|namespace=\"$CURRENT_PACKAGE_NAME|namespace=\"$NEW_PACKAGE_NAME|g" \
|
||||
-e "s|resultType=\"$CURRENT_PACKAGE_NAME|resultType=\"$NEW_PACKAGE_NAME|g" \
|
||||
-e "s|parameterType=\"$CURRENT_PACKAGE_NAME|parameterType=\"$NEW_PACKAGE_NAME|g" \
|
||||
"$mapper_file"
|
||||
|
||||
rm -f "${mapper_file}.bak"
|
||||
done
|
||||
|
||||
log_info "配置文件更新完成"
|
||||
}
|
||||
|
||||
# 6. 更新SQL文件
|
||||
update_sql_files() {
|
||||
log_step "更新SQL文件..."
|
||||
|
||||
local sql_dir="$PROJECT_ROOT/sql"
|
||||
if [[ -d "$sql_dir" ]]; then
|
||||
# 重命名SQL文件
|
||||
local current_sql_file="$sql_dir/$CURRENT_DB_NAME.sql"
|
||||
local new_sql_file="$sql_dir/$NEW_DB_NAME.sql"
|
||||
|
||||
if [[ -f "$current_sql_file" ]]; then
|
||||
log_info "重命名SQL文件: $CURRENT_DB_NAME.sql -> $NEW_DB_NAME.sql"
|
||||
mv "$current_sql_file" "$new_sql_file"
|
||||
|
||||
# 更新SQL文件内容中的数据库名引用
|
||||
sed -i.bak \
|
||||
-e "s|Source Schema.*: $CURRENT_DB_NAME|Source Schema : $NEW_DB_NAME|g" \
|
||||
-e "s|$CURRENT_DB_NAME|$NEW_DB_NAME|g" \
|
||||
"$new_sql_file"
|
||||
|
||||
rm -f "${new_sql_file}.bak"
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info "SQL文件更新完成"
|
||||
}
|
||||
|
||||
# 7. 更新其他文件
|
||||
update_other_files() {
|
||||
log_step "更新其他相关文件..."
|
||||
|
||||
# 更新README文件
|
||||
find "$PROJECT_ROOT" -name "README*" -type f | while read readme_file; do
|
||||
log_info "更新README: $readme_file"
|
||||
|
||||
sed -i.bak \
|
||||
-e "s|$CURRENT_PROJECT_NAME|$NEW_PROJECT_NAME|g" \
|
||||
-e "s|$CURRENT_MODULE_PREFIX|$NEW_MODULE_PREFIX|g" \
|
||||
-e "s|$CURRENT_PACKAGE_NAME|$NEW_PACKAGE_NAME|g" \
|
||||
"$readme_file"
|
||||
|
||||
rm -f "${readme_file}.bak"
|
||||
done
|
||||
|
||||
# 更新CLAUDE.md文件
|
||||
if [[ -f "$PROJECT_ROOT/CLAUDE.md" ]]; then
|
||||
log_info "更新CLAUDE.md"
|
||||
|
||||
sed -i.bak \
|
||||
-e "s|$CURRENT_PROJECT_NAME|$NEW_PROJECT_NAME|g" \
|
||||
-e "s|$CURRENT_MODULE_PREFIX|$NEW_MODULE_PREFIX|g" \
|
||||
-e "s|$CURRENT_PACKAGE_NAME|$NEW_PACKAGE_NAME|g" \
|
||||
"$PROJECT_ROOT/CLAUDE.md"
|
||||
|
||||
rm -f "$PROJECT_ROOT/CLAUDE.md.bak"
|
||||
fi
|
||||
|
||||
# 更新其他配置文件(如果存在)
|
||||
find "$PROJECT_ROOT" -name "*.properties" -o -name "*.yml" -o -name "*.yaml" | while read prop_file; do
|
||||
if [[ "$prop_file" != *"application"* ]]; then
|
||||
log_info "更新属性文件: $prop_file"
|
||||
|
||||
sed -i.bak \
|
||||
-e "s|$CURRENT_PACKAGE_NAME|$NEW_PACKAGE_NAME|g" \
|
||||
-e "s|$CURRENT_MODULE_PREFIX|$NEW_MODULE_PREFIX|g" \
|
||||
"$prop_file"
|
||||
|
||||
rm -f "${prop_file}.bak"
|
||||
fi
|
||||
done
|
||||
|
||||
log_info "其他文件更新完成"
|
||||
}
|
||||
|
||||
# 8. 清理和验证
|
||||
cleanup_and_verify() {
|
||||
log_step "清理临时文件和验证..."
|
||||
|
||||
# 清理备份文件
|
||||
find "$PROJECT_ROOT" -name "*.bak" -delete
|
||||
|
||||
# 验证重构结果
|
||||
log_info "验证重构结果..."
|
||||
|
||||
# 检查是否还有旧的引用(排除脚本文件、日志文件、备份等)
|
||||
local old_refs=$(grep -r "$CURRENT_PACKAGE_NAME" "$PROJECT_ROOT" \
|
||||
--exclude-dir=".git" \
|
||||
--exclude-dir="target" \
|
||||
--exclude-dir=".idea" \
|
||||
--exclude-dir="script" \
|
||||
--exclude="*.log" \
|
||||
--exclude="spy.log" \
|
||||
--exclude="*.bak" \
|
||||
--exclude="*.sh" \
|
||||
2>/dev/null | wc -l)
|
||||
|
||||
if [[ $old_refs -gt 0 ]]; then
|
||||
log_warn "发现 $old_refs 处旧包名引用,请手动检查"
|
||||
grep -r "$CURRENT_PACKAGE_NAME" "$PROJECT_ROOT" \
|
||||
--exclude-dir=".git" \
|
||||
--exclude-dir="target" \
|
||||
--exclude-dir=".idea" \
|
||||
--exclude-dir="script" \
|
||||
--exclude="*.log" \
|
||||
--exclude="spy.log" \
|
||||
--exclude="*.bak" \
|
||||
--exclude="*.sh" \
|
||||
2>/dev/null | head -10
|
||||
else
|
||||
log_info "✓ 验证通过:未发现旧包名引用"
|
||||
fi
|
||||
|
||||
log_info "清理完成"
|
||||
}
|
||||
|
||||
# 9. 重命名项目根目录
|
||||
rename_project_directory() {
|
||||
log_step "重命名项目根目录..."
|
||||
|
||||
# 获取当前项目目录名
|
||||
local current_dir_name=$(basename "$PROJECT_ROOT")
|
||||
local parent_dir=$(dirname "$PROJECT_ROOT")
|
||||
local new_project_dir="$parent_dir/$NEW_PROJECT_NAME"
|
||||
|
||||
log_info "项目目录重命名: $current_dir_name -> $NEW_PROJECT_NAME"
|
||||
|
||||
# 检查目标目录是否已存在
|
||||
if [[ -d "$new_project_dir" && "$PROJECT_ROOT" != "$new_project_dir" ]]; then
|
||||
log_warn "目标目录已存在: $new_project_dir"
|
||||
log_warn "跳过项目目录重命名"
|
||||
return
|
||||
fi
|
||||
|
||||
# 重命名项目目录
|
||||
if [[ "$PROJECT_ROOT" != "$new_project_dir" ]]; then
|
||||
log_info "移动项目目录: $PROJECT_ROOT -> $new_project_dir"
|
||||
|
||||
# 切换到父目录
|
||||
cd "$parent_dir"
|
||||
|
||||
# 重命名目录
|
||||
if mv "$current_dir_name" "$NEW_PROJECT_NAME" 2>/dev/null; then
|
||||
log_info "✓ 项目目录重命名成功"
|
||||
log_info "新的项目路径: $new_project_dir"
|
||||
|
||||
# 更新PROJECT_ROOT变量为新路径
|
||||
PROJECT_ROOT="$new_project_dir"
|
||||
else
|
||||
log_warn "✗ 项目目录重命名失败,请手动重命名"
|
||||
fi
|
||||
else
|
||||
log_info "项目目录名已正确,无需重命名"
|
||||
fi
|
||||
|
||||
log_info "项目目录处理完成"
|
||||
}
|
||||
|
||||
# 执行重构
|
||||
echo ""
|
||||
log_info "=== 开始执行重构 ==="
|
||||
|
||||
rename_module_directories
|
||||
update_pom_files
|
||||
update_java_packages
|
||||
cleanup_backslash_directories
|
||||
update_config_files
|
||||
update_sql_files
|
||||
update_other_files
|
||||
cleanup_and_verify
|
||||
rename_project_directory
|
||||
|
||||
echo ""
|
||||
log_info "=== 重构完成 ==="
|
||||
log_info "新项目名称: $NEW_PROJECT_NAME"
|
||||
log_info "新的GroupId: $NEW_GROUP_ID"
|
||||
log_info "新的包名: $NEW_PACKAGE_NAME"
|
||||
log_info "新的模块前缀: $NEW_MODULE_PREFIX"
|
||||
log_info "新的数据库名: $NEW_DB_NAME"
|
||||
echo ""
|
||||
log_info "项目备份位置: $BACKUP_DIR"
|
||||
log_info "新项目位置: $PROJECT_ROOT"
|
||||
echo ""
|
||||
log_warn "重构完成后请执行以下操作:"
|
||||
echo "1. 进入新项目目录: cd \"$PROJECT_ROOT\""
|
||||
echo "2. 验证项目能否正常编译: mvn clean compile"
|
||||
echo "3. 更新数据库连接配置中的数据库名"
|
||||
echo "4. 在IDE中重新导入项目,检查包结构"
|
||||
echo "5. 提交代码到新的Git仓库"
|
||||
echo ""
|
||||
|
||||
log_info "感谢使用项目模板重构脚本!"
|
||||
21
script/refactor-config.example
Normal file
21
script/refactor-config.example
Normal file
@ -0,0 +1,21 @@
|
||||
# 项目重构配置文件示例
|
||||
# 复制此文件为 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"
|
||||
41
script/simple-fix.sh
Executable file
41
script/simple-fix.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#!/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