jackboot
Version:
A cross-platform command line tool to create SpringBoot projects
1,159 lines (983 loc) • 37.7 kB
JavaScript
#!/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"?>
<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();