UNPKG

jackboot

Version:

A cross-platform command line tool to create SpringBoot projects

1,159 lines (983 loc) 37.7 kB
#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const readline = require('readline'); const { execSync } = require('child_process'); // 创建命令行交互界面 const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); // 用于替代shell脚本中的read命令 function prompt(question) { return new Promise((resolve) => { rl.question(question, (answer) => { resolve(answer); }); }); } // 创建目录的函数 function createDirectory(dir) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } // 写入文件的函数 function writeFile(filePath, content) { fs.writeFileSync(filePath, content); } // 主函数 async function main() { try { // 获取项目名称 const projectNameInput = await prompt("输入你要生成的项目名 (如: my-project): "); // 处理项目名称(替代sed命令的功能) let projectName = projectNameInput.trim().replace(/\s+/g, '-'); // 验证项目名格式 if (!/^[a-zA-Z]+(-[a-zA-Z]+)*$/.test(projectName)) { console.error("项目名称格式不正确。请使用字母和空格组合(空格将被替换为单个连字符)。"); process.exit(1); } // 生成包名和类名 const packageName = projectName.toLowerCase().replace(/-/g, ''); // 生成驼峰命名的类名 let className = ''; const parts = projectName.split('-'); for (const part of parts) { className += part.charAt(0).toUpperCase() + part.slice(1).toLowerCase(); } // 确认类名不为空 if (className === '') { console.error("生成的类名为空,请检查项目名称输入。"); process.exit(1); } // 检查项目目录是否已存在 if (fs.existsSync(projectName)) { const choice = await prompt(`项目目录 '${projectName}' 已存在。是否覆盖现有目录?(y/n): `); if (choice.toLowerCase() !== 'y') { console.log("脚本终止。"); process.exit(1); } // 递归删除目录 fs.rmdirSync(projectName, { recursive: true }); } // 创建目录结构(与shell脚本中相同) const baseDir = `${projectName}/src/main/java/com/jackasher/${packageName}`; const testDir = `${projectName}/src/test/java/com/jackasher/${packageName}`; // 创建主要目录 createDirectory(`${baseDir}/controller`); createDirectory(`${baseDir}/service/impl`); createDirectory(`${baseDir}/mapper`); // 创建模型目录 createDirectory(`${baseDir}/model/pojo`); createDirectory(`${baseDir}/model/request`); createDirectory(`${baseDir}/model/response`); createDirectory(`${baseDir}/model/dto`); createDirectory(`${baseDir}/model/vo`); createDirectory(`${baseDir}/model/param`); createDirectory(`${baseDir}/model/enums`); createDirectory(`${baseDir}/model/form`); createDirectory(`${baseDir}/model/event`); createDirectory(`${baseDir}/model/query`); createDirectory(`${baseDir}/model/command`); // 创建其他目录 createDirectory(`${baseDir}/config`); createDirectory(`${baseDir}/common`); createDirectory(`${baseDir}/constant`); createDirectory(`${baseDir}/exception`); createDirectory(`${baseDir}/util`); createDirectory(`${baseDir}/job`); createDirectory(`${projectName}/src/main/resources/static`); createDirectory(`${projectName}/src/main/resources/templates`); createDirectory(`${projectName}/src/main/resources/mapper`); createDirectory(testDir); console.log("目录结构创建完成。"); // 创建文件内容(这里省略具体内容,与原shell脚本相同) // 你需要将原shell脚本中的所有文件内容生成部分转换为Node.js的writeFile调用 // 创建pom.xml writeFile(`${projectName}/pom.xml`, `<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 父项目依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.7</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!-- 项目信息 --> <groupId>com.jackasher.${packageName}</groupId> <artifactId>${packageName}</artifactId> <version>0.0.1-SNAPSHOT</version> <name>${className}</name> <description>${className}服务</description> <!-- 项目属性配置 --> <properties> <java.version>17</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>\${java.version}</maven.compiler.source> <maven.compiler.target>\${java.version}</maven.compiler.target> <!-- 依赖版本管理 --> <mybatis-plus.version>3.5.7</mybatis-plus.version> <mybatis-spring.version>3.0.4</mybatis-spring.version> <commons-lang3.version>3.14.0</commons-lang3.version> <lombok.version>1.18.30</lombok.version> <springdoc.version>2.3.0</springdoc.version> <hutool.version>5.8.25</hutool.version> <druid.version>1.2.20</druid.version> <fastjson2.version>2.0.45</fastjson2.version> <easyexcel.version>3.3.3</easyexcel.version> <redisson.version>3.25.2</redisson.version> </properties> <!-- 依赖管理 --> <dependencies> <!-- Spring Boot 核心依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- knife4j --> <!-- http://127.0.0.1:8080/doc.html --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.4.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!-- 数据库相关 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>\${mybatis-spring.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>\${mybatis-plus.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>\${druid.version}</version> </dependency> <!-- 缓存相关 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>\${redisson.version}</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <!-- API文档 --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>\${springdoc.version}</version> </dependency> <!-- 工具类库 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>\${lombok.version}</version> <optional>true</optional> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>\${commons-lang3.version}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.15.1</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>\${hutool.version}</version> </dependency> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>\${fastjson2.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>\${easyexcel.version}</version> </dependency> <!-- 日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </dependency> <!-- 测试相关 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter-test</artifactId> <version>\${mybatis-spring.version}</version> <scope>test</scope> </dependency> </dependencies> <!-- 构建配置 --> <build> <finalName>\${project.artifactId}</finalName> <plugins> <!-- Spring Boot Maven 插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <!-- Maven 编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>\${java.version}</source> <target>\${java.version}</target> <encoding>\${project.build.sourceEncoding}</encoding> <annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>\${lombok.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> <!-- 资源插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> <configuration> <encoding>\${project.build.sourceEncoding}</encoding> </configuration> </plugin> <!-- 打包跳过测试 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build> <!-- 多环境配置 --> <profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <spring.profiles.active>dev</spring.profiles.active> </properties> </profile> <profile> <id>test</id> <properties> <spring.profiles.active>test</spring.profiles.active> </properties> </profile> <profile> <id>prod</id> <properties> <spring.profiles.active>prod</spring.profiles.active> </properties> </profile> </profiles> </project>`); // 创建主应用类文件 writeFile(`${baseDir}/${className}Application.java`, `package com.jackasher.${packageName}; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @MapperScan("com.jackasher.${packageName}.mapper") @EnableScheduling public class ${className}Application { public static void main(String[] args) { SpringApplication.run(${className}Application.class, args); } }`); // 创建服务实现类 writeFile(`${baseDir}/service/impl/${className}ServiceImpl.java`, `package com.jackasher.${packageName}.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jackasher.${packageName}.mapper.${className}Mapper; import com.jackasher.${packageName}.model.pojo.${className}; import com.jackasher.${packageName}.service.${className}Service; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * ${className} 服务实现类 */ @Service @Slf4j public class ${className}ServiceImpl extends ServiceImpl<${className}Mapper, ${className}> implements ${className}Service { }`); // 创建控制器类 writeFile(`${baseDir}/controller/${className}Controller.java`, `package com.jackasher.${packageName}.controller; import com.jackasher.${packageName}.common.BaseResponse; import com.jackasher.${packageName}.common.ErrorCode; import com.jackasher.${packageName}.common.ResultUtils; import com.jackasher.${packageName}.exception.BusinessException; import com.jackasher.${packageName}.model.pojo.${className}; import com.jackasher.${packageName}.service.${className}Service; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; /** * ${className} 控制器 */ @RestController @RequestMapping("/${packageName}") @Slf4j @Tag(name = "${className}接口", description = "${className}相关接口") public class ${className}Controller { @Resource private ${className}Service ${packageName}Service; @GetMapping("/hello") @Operation(summary = "测试接口", description = "Hello World测试接口") public BaseResponse<String> hello() { return ResultUtils.success("Hello, ${className}!"); } @GetMapping("/get/{id}") @Operation(summary = "获取${className}信息", description = "根据ID获取${className}详情") public BaseResponse<${className}> getById(@PathVariable("id") Long id) { if (id <= 0) { throw new BusinessException(ErrorCode.PARAMS_ERROR); } ${className} ${packageName} = ${packageName}Service.getById(id); if (${packageName} == null) { throw new BusinessException(ErrorCode.NOT_FOUND); } return ResultUtils.success(${packageName}); } }`); // 创建定时任务类 writeFile(`${baseDir}/job/${className}Job.java`, `package com.jackasher.${packageName}.job; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * ${className} 定时任务 */ @Component @Slf4j public class ${className}Job { /** * 每天凌晨2点执行 */ @Scheduled(cron = "0 0 2 * * ?") public void cronJob() { log.info("定时任务开始执行"); // TODO 定时任务逻辑 log.info("定时任务执行完毕"); } }`); // 创建测试类 writeFile(`${testDir}/${className}ApplicationTests.java`, `package com.jackasher.${packageName}; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; /** * 应用测试类 */ @SpringBootTest class ${className}ApplicationTests { @Test void contextLoads() { } }`); // 创建 application.properties writeFile(`${projectName}/src/main/resources/application.properties`, `# Spring Boot 配置示例 # 服务器端口 server.port=8080 spring.session.store-type=redis # 数据库配置 spring.datasource.url=jdbc:mysql://localhost:3306/user-center?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=YOUR_PASSWORD spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true # 逻辑删除 mybatis-plus.global-config.db-config.logic-delete-field=isDelete mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl server.servlet.context-path=/api/ # 设置 session 过期时间 30s server.servlet.session.timeout=3600 spring.data.redis.host=127.0.0.1 spring.data.redis.port=6379 spring.data.redis.database=0 # 支持多个源用逗号分隔,支持通配符 cors.allowed-origins=http://172.20.10.3:3000,http://localhost:3000`); // 创建开发环境配置 writeFile(`${projectName}/src/main/resources/application-dev.properties`, `# 开发环境配置 server.port=8080 # 开发环境数据库配置 spring.datasource.url=jdbc:mysql://localhost:3306/${packageName}_dev?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=root # 开发环境日志级别 logging.level.com.jackasher.${packageName}=debug`); // 创建测试环境配置 writeFile(`${projectName}/src/main/resources/application-test.properties`, `# 测试环境配置 server.port=8080 # 测试环境数据库配置 spring.datasource.url=jdbc:mysql://localhost:3306/${packageName}_test?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=root # 测试环境日志级别 logging.level.com.jackasher.${packageName}=info`); // 创建生产环境配置 writeFile(`${projectName}/src/main/resources/application-prod.properties`, `# 生产环境配置 server.port=8080 # 生产环境数据库配置 spring.datasource.url=jdbc:mysql://localhost:3306/${packageName}_prod?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8 spring.datasource.username=production_user spring.datasource.password=strong_password # 生产环境日志级别 logging.level.root=warn logging.level.com.jackasher.${packageName}=info # 禁用开发相关功能 springdoc.api-docs.enabled=false springdoc.swagger-ui.enabled=false knife4j.enable=false spring.devtools.restart.enabled=false spring.devtools.livereload.enabled=false`); // 创建 Swagger 配置类 writeFile(`${baseDir}/config/SwaggerConfig.java`, `package com.jackasher.${packageName}.config; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.Contact; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SwaggerConfig { @Bean public OpenAPI ${packageName}OpenAPI() { return new OpenAPI() .info(new Info() .title("${className} API") .description("${className} API文档") .version("1.0") .contact(new Contact() .name("JackAsher") .email("jackasher36@gmail.com"))); } }`); // 创建 MybatisPlus 配置类 writeFile(`${baseDir}/config/MybatisPlusConfig.java`, `package com.jackasher.${packageName}.config; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisPlusConfig { /** * 配置MyBatis-Plus拦截器,添加分页功能支持 * * @return MybatisPlusInterceptor 包含分页拦截器的拦截器实例,用于处理分页查询逻辑 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ // 创建MyBatis-Plus拦截器核心对象 MybatisPlusInterceptor mpInterceptor=new MybatisPlusInterceptor(); // 添加内置分页拦截器,用于自动处理SQL分页语句 mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return mpInterceptor; } }`); // 创建 Web 配置类 writeFile(`${baseDir}/config/WebConfig.java`, `package com.jackasher.${packageName}.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * 配置类,用于配置 Spring MVC 的相关设置,这里主要处理跨域请求。 */ @Configuration public class WebConfig implements WebMvcConfigurer { /** * 从配置文件中读取允许的跨域源,将其注入到 allowedOrigins 数组中。 * 配置文件中应包含类似 cors.allowed-origins=http://example1.com,http://example2.com 的配置。 */ @Value("\${cors.allowed-origins:http://localhost:3000}") private String[] allowedOrigins; /** * 重写 WebMvcConfigurer 接口的 addCorsMappings 方法,用于配置跨域请求映射。 * * @param registry 用于注册跨域映射的对象。 */ @Override public void addCorsMappings(CorsRegistry registry) { // 配置所有的请求路径都支持跨域 registry.addMapping("/**") // 使用允许的源模式匹配,允许来自 allowedOrigins 数组中指定的源的请求 .allowedOriginPatterns(allowedOrigins) // 允许的 HTTP 请求方法 .allowedMethods("GET", "POST", "PUT", "DELETE") // 明确允许的请求头,这里允许 Content-Type 和 Authorization 头 .allowedHeaders("Content-Type", "Authorization") // 允许携带凭证(如 cookies)进行跨域请求 .allowCredentials(true); } }`); // 创建 Redis 配置类 writeFile(`${baseDir}/config/RedisConfig.java`, `package com.jackasher.${packageName}.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(connectionFactory); // 使用StringRedisSerializer来序列化和反序列化redis的key值 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } }`); // 创建 Redis 服务类 writeFile(`${baseDir}/util/RedisService.java`, `package com.jackasher.${packageName}.util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; @Component public class RedisService { @Autowired private RedisTemplate<String, Object> redisTemplate; /** * 设置缓存 */ public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } /** * 设置缓存并设置过期时间 */ public void set(String key, Object value, long time) { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } } /** * 获取缓存 */ public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } /** * 删除缓存 */ public Boolean delete(String key) { return redisTemplate.delete(key); } }`); // 创建数据库工具类 writeFile(`${baseDir}/util/DBUtil.java`, `package com.jackasher.${packageName}.util; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; @Slf4j public class DBUtil { // 数据库工具类 private static final String URL = "jdbc:mysql://localhost:3306/${packageName}?useSSL=false&serverTimezone=UTC"; private static final String USERNAME = "root"; private static final String PASSWORD = "root"; /** * 获取数据库连接 */ public static Connection getConnection() { try { Class.forName("com.mysql.cj.jdbc.Driver"); return DriverManager.getConnection(URL, USERNAME, PASSWORD); } catch (ClassNotFoundException | SQLException e) { log.error("获取数据库连接失败", e); throw new RuntimeException("获取数据库连接失败", e); } } /** * 关闭数据库连接 */ public static void closeConnection(Connection connection) { if (connection != null) { try { connection.close(); } catch (SQLException e) { log.error("关闭数据库连接失败", e); } } } /** * SQL注入检查 */ public static boolean containsSqlInjection(String str) { if (StrUtil.isBlank(str)) { return false; } // SQL注入关键字 String[] sqlKeywords = {"and", "or", "delete", "drop", "truncate", "update", "insert", "select", "union", "exec", "execute", "declare", "create", "alter", "database", "master"}; String checkStr = str.toLowerCase(); for (String keyword : sqlKeywords) { if (checkStr.contains(" " + keyword + " ") || checkStr.contains(";" + keyword + " ")) { return true; } } return false; } }`); // 创建 ErrorCode 枚举类 writeFile(`${baseDir}/common/ErrorCode.java`, `package com.jackasher.${packageName}.common; /** * 错误码枚举 */ public enum ErrorCode { SUCCESS(0, "ok"), PARAMS_ERROR(40001, "请求参数错误"), NULL_ERROR(40002, "请求数据为空"), NOT_LOGIN(40100, "未登录"), NO_AUTH(40101, "无权限"), SYSTEM_ERROR(50000, "系统内部异常"), OPERATION_ERROR(50001, "操作失败"), NOT_FOUND(40400,"未查询到" ); private final int code; private final String message; ErrorCode(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } }`); // 创建 BaseResponse 类 writeFile(`${baseDir}/common/BaseResponse.java`, `package com.jackasher.${packageName}.common; import lombok.Data; import java.io.Serializable; /** * 通用返回类 */ @Data public class BaseResponse<T> implements Serializable { private int code; private String message; private T data; public BaseResponse(int code, T data, String message) { this.code = code; this.data = data; this.message = message; } public BaseResponse(int code, T data) { this.code = code; this.data = data; this.message = ""; } public BaseResponse(ErrorCode errorCode) { this.code = errorCode.getCode(); this.message = errorCode.getMessage(); this.data = null; } }`); // 创建 ResultUtils 类 writeFile(`${baseDir}/common/ResultUtils.java`, `package com.jackasher.${packageName}.common; /** * 返回工具类 */ public class ResultUtils { /** * 成功 * * @param data 数据 * @param <T> 类型 * @return 通用返回类 */ public static <T> BaseResponse<T> success(T data) { return new BaseResponse<>(0, data, "ok"); } /** * 失败 * * @param errorCode 错误码 * @param <T> 类型 * @return 通用返回类 */ public static <T> BaseResponse<T> error(ErrorCode errorCode) { return new BaseResponse<>(errorCode.getCode(), null, errorCode.getMessage()); } /** * 失败 * * @param errorCode 错误码 * @param message 错误信息 * @param <T> 类型 * @return 通用返回类 */ public static <T> BaseResponse<T> error(ErrorCode errorCode, String message) { return new BaseResponse<>(errorCode.getCode(), null, message); } /** * 失败 * * @param code 错误码 * @param message 错误信息 * @param <T> 类型 * @return 通用返回类 */ public static <T> BaseResponse<T> error(int code, String message) { return new BaseResponse<>(code, null, message); } }`); // 创建异常类 writeFile(`${baseDir}/exception/BusinessException.java`, `package com.jackasher.${packageName}.exception; import com.jackasher.${packageName}.common.ErrorCode; /** * 业务异常类 */ public class BusinessException extends RuntimeException { private final int code; private final String description; public BusinessException(int code, String message, String description) { super(message); this.code = code; this.description = description; } public BusinessException(ErrorCode errorCode) { super(errorCode.getMessage()); this.code = errorCode.getCode(); this.description = errorCode.getMessage(); } public BusinessException(ErrorCode errorCode, String description) { super(errorCode.getMessage()); this.code = errorCode.getCode(); this.description = description; } public int getCode() { return code; } public String getDescription() { return description; } }`); // 创建全局异常处理类 writeFile(`${baseDir}/exception/GlobalExceptionHandler.java`, `package com.jackasher.${packageName}.exception; import com.jackasher.${packageName}.common.BaseResponse; import com.jackasher.${packageName}.common.ErrorCode; import com.jackasher.${packageName}.common.ResultUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; /** * 全局异常处理器 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) public BaseResponse<?> businessExceptionHandler(BusinessException e) { log.error("BusinessException: {}", e.getMessage(), e); return ResultUtils.error(e.getCode(), e.getDescription()); } @ExceptionHandler(RuntimeException.class) public BaseResponse<?> runtimeExceptionHandler(RuntimeException e) { log.error("RuntimeException", e); return ResultUtils.error(ErrorCode.SYSTEM_ERROR, e.getMessage()); } @ExceptionHandler(Exception.class) public BaseResponse<?> exceptionHandler(Exception e) { log.error("Exception", e); return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误"); } }`); // 创建常量类 writeFile(`${baseDir}/constant/${className}Constant.java`, `package com.jackasher.${packageName}.constant; /** * ${className} 常量 */ public interface ${className}Constant { /** * 用户登录态键 */ String USER_LOGIN_STATE = "userLoginState"; /** * 默认角色 */ int DEFAULT_ROLE = 0; /** * 管理员角色 */ int ADMIN_ROLE = 1; }`); // 创建 POJO 类 writeFile(`${baseDir}/model/pojo/${className}.java`, `package com.jackasher.${packageName}.model.pojo; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * ${className} 实体类 */ @Data @TableName("${packageName}") public class ${className} implements Serializable { /** * 主键 */ @TableId(type = IdType.AUTO) private Long id; /** * 创建时间 */ @TableField(fill = FieldFill.INSERT) private Date createTime; /** * 更新时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; /** * 是否删除(0-未删, 1-已删) */ @TableLogic private Integer isDelete; @TableField(exist = false) private static final long serialVersionUID = 1L; }`); // 创建 Mapper 接口 writeFile(`${baseDir}/mapper/${className}Mapper.java`, `package com.jackasher.${packageName}.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.jackasher.${packageName}.model.pojo.${className}; import org.apache.ibatis.annotations.Mapper; /** * ${className} Mapper 接口 */ @Mapper public interface ${className}Mapper extends BaseMapper<${className}> { }`); // 创建 Mapper XML writeFile(`${projectName}/src/main/resources/mapper/${className}Mapper.xml`, `<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.jackasher.${packageName}.mapper.${className}Mapper"> <resultMap id="BaseResultMap" type="com.jackasher.${packageName}.model.pojo.${className}"> <id property="id" column="id" jdbcType="BIGINT"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> <result property="isDelete" column="is_delete" jdbcType="TINYINT"/> </resultMap> <sql id="Base_Column_List"> id,create_time,update_time,is_delete </sql> </mapper>`); // 创建请求类 writeFile(`${baseDir}/model/request/${className}Request.java`, `package com.jackasher.${packageName}.model.request; import lombok.Data; /** * ${className} 请求类 */ @Data public class ${className}Request { private Long id; }`); // 创建服务接口 writeFile(`${baseDir}/service/${className}Service.java`, `package com.jackasher.${packageName}.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jackasher.${packageName}.model.pojo.${className}; /** * ${className} 服务接口 */ public interface ${className}Service extends IService<${className}> { }`); console.log("所有文件创建完成。"); console.log(`项目 '${projectName}' 构建完成。`); console.log("进入项目目录并使用 Maven 构建项目:"); console.log(`cd '${projectName}'`); console.log("mvn clean install -DskipTests"); } catch (error) { console.error("发生错误:", error); } finally { rl.close(); } } // 执行主函数 main();