为什么需要个人通用模板?
提高项目初始化效率
- 避免每次新建项目时重复配置基础依赖
- 统一技术栈版本,减少兼容性问题
- 快速集成常用组件(如MyBatis Plus等)
统一项目规范
- 预置代码风格配置
- 统一的日志格式和收集方案
- 标准化异常处理机制
积累最佳实践
- 封装经过验证的工具类
- 沉淀业务通用解决方案
- 记录踩坑经验与解决方案
新建项目
现在使用IDEA新建项目十分简单,直接左上角新建项目即可
对于jdk版本,开发的要求当然是越稳定越好,所以我们可以选择11或者17

但是注意,官方的Server Url不支持选择Java8和Java11,所以我们可以将上方的uel设置为https://start.aliyun.com/
同样是因为稳定性需求,我们可以选择Springboot2.7.6版本,点击下一步,然后在此页面我们可以加入一些自己常用的依赖
Spring Web、MySQL、Lombok自然是少不了,此时勾选即可

选择完后直接创建即可
添加依赖
MyBatis-Plus
MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生
在使用 MyBatis-Plus 时,通常不需要再单独引入 MyBatis 的依赖,因为 MyBatis-Plus 本身已经内置了 MyBatis 的核心依赖(即 mybatis 和 mybatis-spring),它会自动传递依赖进来
具体可以看文档:https://baomidou.com/
在Maven中的pom.xml中添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.12</version>
</dependency>添加完以来后我们需要配置一下,在resource文件夹下删除原来的配置文件,新建一个application.yml文件
# Spring框架配置
# 配置Spring应用的基本信息和数据源连接
spring:
# 应用配置
application:
# 应用名称,用于服务注册与发现
name: 你的项目名字
# 数据源配置
datasource:
# MySQL数据库驱动类名
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据库连接URL
url: jdbc:mysql://localhost:3306/dmoye_picture
# 数据库用户名
username: root
# 数据库密码
password: xxxxx
# MyBatis-Plus配置
# 配置MyBatis-Plus的映射规则和全局设置
mybatis-plus:
# MyBatis配置项
configuration:
#MyBatis配置
# 是否开启下划线到驼峰命名的自动转换
map-underscore-to-camel-case: false
#仅在开发环境使用
# SQL执行日志实现类,用于控制台输出SQL语句
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# MyBatis-Plus全局配置
global-config:
# 数据库配置
db-config:
# 逻辑删除字段名
logic-delete-field: isDelete
# 逻辑已删除值
logic-delete-value: 1
# 逻辑未删除值
logic-not-delete-value: 0我们配置好后,可以启动测试,发现项目可以正常启动
Hutool工具库
Hutool是一个 Java 工具类库,它封装了 Java 开发中常用的功能,提供了简单易用的 API,能够显著减少代码量,提高开发效率。Hutool 的目标是成为 Java 界的 "Swiss Army Knife"(瑞士军刀),涵盖工具方法、IO、加密、HTTP、缓存、JSON、Excel 等众多实用模块
官方文档:https://doc.hutool.cn/pages/index
在Maven中的pom.xml中添加依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.38</version>
</dependency>Knife4j 接口文档
Knife4j是一个为Java MVC框架集成Swagger生成API文档的增强解决方案,它集成了Swagger2和OpenAPI3规范,提供了一系列强大的文档展示和调试功能,让我们能够快速的调试我们开发的接口
文档:https://doc.xiaominfo.com/docs/quick-start#spring-boot-2
在Maven中的pom.xml中添加依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>我们先创建一个controller包,然后配置yml属性,如下:
# Knife4j接口文档配置
# 配置Knife4j Swagger增强工具的相关参数
knife4j:
# 是否启用Knife4j
enable: true
# OpenAPI规范配置
openapi:
# API文档标题
title: Knife4j官方文档
# API版本号
version: v1.0
# API分组配置
group:
test1:
# 分组名称
group-name: default
# API规则类型
api-rule: package
# API资源路径配置
api-rule-resources:
# 控制器包路径
- com.domye.xxxx.controller #自己的controller路径
最后,访问Knife4j的文档地址:http://ip:port/doc.html即可查看文档
通用基础代码
自定义异常
我们需要自定义错误码,对错误进行处理,便于前端管理
我们新建一个exception包,用来存放异常处理相关的类
@Getter
public enum ErrorCode {
SUCCESS(0, "ok"),
PARAMS_ERROR(40000, "请求参数错误"),
NOT_LOGIN_ERROR(40100, "未登录"),
NO_AUTH_ERROR(40101, "无权限"),
NOT_FOUND_ERROR(40400, "请求数据不存在"),
FORBIDDEN_ERROR(40300, "禁止访问"),
SYSTEM_ERROR(50000, "系统内部异常"),
OPERATION_ERROR(50001, "操作失败");
/**
* 状态码
*/
private final int code;
/**
* 信息
*/
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
}接下来,我们需要自定义一个异常类,就像空指针异常类、IO流异常类一样。此处自定义的异常类属于异常类,所有肯定是要继承一个异常类的,此处需要继承RuntimeException
相比Exception来讲,RuntimeException是在程序运行时才会爆出异常,在编译时是不会出现异常的,这就表示,如果你throw了一个RuntimeException,不需要做额外操作;而throw一个Exception,程序会要求你try-catch,否则你根本启动不了程序,程序会提示(必须对其进行捕获或声明以便抛出)
@Getter
public class BusinessException extends RuntimeException {
/*
* 错误码
*/
private final int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
}
public BusinessException(ErrorCode errorCode, String message) {
super(message);
this.code = errorCode.getCode();
}
}对于这个代码,我们使用了super(message),这是因为
- message 是 Throwable 的标准属性:Java 的异常体系中,Throwable 类(所有异常的基类)本身就有一个 detailMessage 字段用于存储异常信息。通过调用 super(message),消息会自动存储在父类的这个标准字段中
- code 是业务扩展属性:错误码是业务层面的概念,Java 标准异常类中没有这个字段,所以需要在子类中自定义。
而现在这样写,抛出异常时,需要
throw new BusinessException(ErrorCode.PARAMS_ERROR);显然这样的写法不够优雅,也不够便捷,于是我们可以再进行封装一次
public class ThrowUtils {
/**
* 条件成立则抛异常
*
* @param condition 条件
* @param runtimeException 异常
*/
public static void throwIf(boolean condition, RuntimeException runtimeException) {
if (condition) {
throw runtimeException;
}
}
/**
* 条件成立则抛异常
*
* @param condition 条件
* @param errorCode 错误码
*/
public static void throwIf(boolean condition, ErrorCode errorCode) {
throwIf(condition, new BusinessException(errorCode));
}
/**
* 条件成立则抛异常
*
* @param condition 条件
* @param errorCode 错误码
* @param message 错误信息
*/
public static void throwIf(boolean condition, ErrorCode errorCode, String message) {
throwIf(condition, new BusinessException(errorCode, message));
}
}响应包装
一般情况下,每个后端接口都要返回调用码、数据、调用信息等,前端可以根据这些信息进行相应的处理。
我们可以封装统一的响应结果类,便于前端统一获取这些信息
我们新建一个common包,创建BaseResponse类
@Data
public class BaseResponse<T> implements Serializable {
private int code;
private T data;
private String message;
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, data, "");
}
public BaseResponse(ErrorCode errorCode) {
this(errorCode.getCode(), null, errorCode.getMessage());
}
}但之后每次接口返回值时,都要手动 new 一个 BaseResponse 对象并传入参数,比较麻烦,我们可以新建一个工具类,提供成功调用和失败调用的方法,支持灵活地传参,简化调用
public class ResultUtils {
/**
* 成功
* @param data 数据
* @param <T> 数据类型
* @return 响应
*/
public static <T> BaseResponse<T> success(T data) {
return new BaseResponse<>(0, data, "ok");
}
/**
* 失败
* @param errorCode 错误码
* @return 响应
*/
public static BaseResponse<?> error(ErrorCode errorCode) {
return new BaseResponse<>(errorCode);
}
/**
* 失败
* @param code 错误码
* @param message 错误信息
* @return 响应
*/
public static BaseResponse<?> error(int code, String message) {
return new BaseResponse<>(code, null, message);
}
/**
* 失败
* @param errorCode 错误码
* @return 响应
*/
public static BaseResponse<?> error(ErrorCode errorCode, String message) {
return new BaseResponse<>(errorCode.getCode(), null, message);
}
}这样,我们返回的时候,就可以直接调用 ResultUtils.success(xxx)
全局异常处理器
为了防止意料之外的异常,利用 AOP 切面全局对业务异常和 RuntimeException 进行捕获:
▼java复制代码@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public BaseResponse<?> businessExceptionHandler(BusinessException e) {
log.error("BusinessException", e);
return ResultUtils.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(RuntimeException.class)
public BaseResponse<?> runtimeExceptionHandler(RuntimeException e) {
log.error("RuntimeException", e);
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误");
}
}请求包装
对于 分页这类通用的请求,可以封装统一的请求包装类,用于接受前端传来的参数,之后相同参数的请求就不用专门再新建一个类了
分页请求包装类,接受页号、页面大小、排序字段、排序顺序参数:
@Data
public class PageRequest {
/**
* 当前页号
*/
private int current = 1;
/**
* 页面大小
*/
private int pageSize = 10;
/**
* 排序字段
*/
private String sortField;
/**
* 排序顺序(默认降序)
*/
private String sortOrder = "descend";
}全局跨域配置
跨域是指浏览器访问的 URL(前端地址)和后端接口地址的域名(或端口号)不一致导致的,浏览器为了安全,默认禁止跨域请求访问。
为了开发调试方便,我们可以通过全局跨域配置,让整个项目所有的接口支持跨域,解决跨域报错。
新建 config 包,用于存放所有的配置相关代码。全局跨域配置代码如下:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 覆盖所有请求
registry.addMapping("/**")
// 允许发送 Cookie
.allowCredentials(true)
// 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突)
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("*");
}
}编写示例接口
移除 controller 包下的其他代码,让项目干净一些,然后编写一个纯净的 /health 接口用于健康检查:
@RestController
@RequestMapping("/")
public class MainController {
/**
* 健康检查
*/
@GetMapping("/health")
public BaseResponse<String> health() {
return ResultUtils.success("ok");
}
}健康检查是指可以通过访问该接口,来快速验证后端服务是否正常运行,所以该接口的返回值非常简单。
2 条评论
果博东方客服开户联系方式【182-8836-2750—】?薇- cxs20250806】
果博东方公司客服电话联系方式【182-8836-2750—】?薇- cxs20250806】
果博东方开户流程【182-8836-2750—】?薇- cxs20250806】
果博东方客服怎么联系【182-8836-2750—】?薇- cxs20250806】
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com