SpringBoot 2 后端通用开发模板搭建(异常处理,请求响应)

news2025/2/28 8:17:01

目录

一、环境准备

二、新建项目

三、整合依赖

1、MyBatis Plus 数据库操作

2、Hutool 工具库

3、Knife4j 接口文档

4、其他依赖

四、通用基础代码

1、自定义异常

2、响应包装类

3、全局异常处理器

4、请求包装类

5、全局跨域配置

补充:设置新建类/接口文件的类/接口注释模版


一、环境准备

1) 安装的 JDK 版本可以是 8、11 或 17(一般情况下使用  8 也可以了 ,不过具体情况需要根据使用到的中间件的适配性决定最终使用 JDK 多少的版本,如:若后续要用到缓存库 Caffeine ,则要求使用 11 版本 JDK )

2) MySQL数据库最好安装 8.x版本,或者 5.7/ 5.6 版本。(MySQL 可以是5.X ,数据库连接的 xml 配置可以是8 版本的)

3) Maven 仓库 3.6.X 版本即可;

二、新建项目

        在 IDEA 中新建项目,选择 Spring Initializr 模板,考虑到稳定性,此处选择创建 Java8 版本项目注意需要替换 阿里云的链接 ,Server URL为 : Cloud Native App Initializerhttps://start.aliyun.com/因为官方的 Server URL 不支持选择 Java 8.配置如图 : 

选择 Spring Boot 2.7.6 版本,可以根据自己的需要添加一些依赖,比如 Spring Web、MyBatis、MySQL、Lombok: 

当然,后续通过修改 Maven 配置添加依赖也是可以的。点击创建,就得到了一个 Spring Boot 项目,需要等待 Maven 为我们安装依赖。安装完依赖后,先尝试启动一下项目,结果会报错:

        因为我们在 Maven 中引入了 MySQL 依赖,但是项目配置文件中并没有填写 MySQL 的配置。修改资源日录下的配置文件为 application.yml (默认的是 application.properties 且.properties优先级会比.yml后缀的优先级要高,但.yml 的格式会更方便,不用写更多重复的代码,且树形结构更清晰,建议使用 application.yml文件格式 ),指定项目启动的端口号和访问地址前缀、项目名称、数据库配置等。  代码如下 :  

server:
  port: 8123
  servlet:
    context-path: /api
spring:
  application:
    name: backend
  # 数据库配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ss_picture
    username: root
    password: 123456

更改之后,发现可以正常运行了: 

三、整合依赖

接下来我们要整合一些开发项目常用的依赖。

1、MyBatis Plus 数据库操作

        MyBatis Plus 是 MyBatis 增强工具,旨在简化开发流程。它提供了开箱即用的 CRUD 方法、动态查询构造器、分页插件和代码生成器等功能,大幅减少重复代码,同时保持与 MyBatis 原生功能的兼容性。例如,通过调用 baseMapper.selectById(id),可以直接查询数据库中的记录,而无需手动编写 SQL。参考官方文档引入:(教程有时效性,一切以官方文档为主)

https://baomidou.com/getting-started/#spring-boot2

在pom文件中引入:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.9</version>
</dependency>

注意,添加该依赖后,记得移除 MyBatis 相关的依赖!否则很容易导致版本冲突!!!

在项目中新建 mapper包,)后续用于存放操作数据库的 Mapper类,然后在项目启动类中添加扫描 Mapper 的 @MapperScan 注解 :

@SpringBootApplication
@MapperScan("com.ss.picturebackend.mapper")
public class PictureBackendApplication {

    public static void main(String[] args) {
        SpringApplication.run(YuPictureBackendApplication.class, args);
    }
}

 在 application.yml 中追加配置,开启日志和逻辑删除功能 :

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: false
    # 仅在开发环境开启日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      logic-delete-field: isDelete # 全局逻辑删除的实体字段名
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

2、Hutool 工具库

        Hutool是主流的 java 工具类库,集合了丰富的工具类,涵盖字符串处理、日期操作、文件处理、加解密、反射、正则匹配等常见功能。它的轻量化和无侵入性让开发者能够专注于业务逻辑而不必编写重复的工具代码。例如, Dateuti1.formatDate(new Date())可以快速将当前日期格式化为字符串。
参考官方文档引入:

https://doc.hutool.cn/pages/index/#%F0%9F%8D%8Amaven

在 Maven 的 pom.xm| 中添加依赖:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>

3、Knife4j 接口文档

Knife4j 是基于 swagger 接口文档的增强工具,提供了更加友好的 AP! 文档界面和功能扩展,例如动态参数调试、分组文档等。它适合用于 Spring Boot 项目中,能够通过简单的配置自动生成接口文档,让开发者和前端快速了解和调试接口,提高写作效率。
参考官方文档引入:

https://doc.xiaominfo.com/docs/quick-start#spring-boot-2

由于使用的是 Spring Boot 2.x,注意要选择 OpenAPI 2 的版本。
在 Maven 的 pom.xml 中添加依赖: 

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

在 application.ym| 中追加接口文档配置,扫描 Controller 包:

# 接口文档配置
knife4j:
  enable: true
  openapi:
    title: "接口文档"
    version: 1.0
    group:
      default:
        api-rule: package
        api-rule-resources:
          - com.ss.picturebackend.controller

 重启项目,访问 http://localhost:8123/api/doc.html 能够看到接口文档,可以测试调用

4、其他依赖

可以按需引入其他依赖,比如 AOP 切面编程:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

 给启动类添加注解(可选):

@EnableAspectJAutoProxy(exposeProxy = true)

exposeProxy =true的作用:   通过 Spring AOP 提供对当前代理对象的访问,使得可以在业务逻辑中访问到当前的代理对象。你可以在方法执行时通过 AopContext.currentProxy()  获取当前的代理对象。 当然随着业务具体的需求,还有更多的依赖,后续随用随装即可。

四、通用基础代码

通用基础代码是指:无论在任何后端项目中,都可以复用的代码。这种代码一般"只用写一次”,了解作用之后复制粘贴即可,无需记忆。

1、自定义异常

自定义错误码,对错误进行收敛,便于前端统一处理。
这里有 2 个小技巧:
① .自定义错误码时,建议跟主流的错误码 (比如 HTTP 错误码) 的含义保持一致,比如“未登录”定义为 40100,和 HTTP 401 错误 (用户需要进行身份认证) 保持一致,会更容易理解。

② .错误码不要完全连续,预留一些间隔,便于后续扩展。
在 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;
    }

}

一般不建议直接抛出 Java 内置的 RuntimeException,而是自定义一个业务异常,和内置的异常类区分开,便于定制化输出错误信息 : 

@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();
    }

}

为了更方便地根据情况抛出异常,可以封装一个 ThrowUtils,类似断言类,简化抛异常的代码:

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));
    }
}

2、响应包装类

一般情况下,每个后端接口都要返回调用码、数据、调用信息等,前端可以根据这些信息进行相应的处理我们可以封装统一的响应结果类,便于前端统一获取这些信息,通用响应类:

@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);
    }
}

3、全局异常处理器

为了防止意料之外的异常,利用 AOP 切面全局对业务异常和 RuntimeException 进行捕获:

@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, "系统错误");
    }
}

4、请求包装类

对于“分页”、“删除某条数据”这类通用的请求,可以封装统一的请求包装类,用于接受前端传来的参数,之后相同参数的请求就不用专门再新建一个类了。
分页请求包装类,接受页号、页面大小、排序字段、排序顺序参数: 

@Data
public class PageRequest {

    /**
     * 当前页号
     */
    private int current = 1;

    /**
     * 页面大小
     */
    private int pageSize = 10;

    /**
     * 排序字段
     */
    private String sortField;

    /**
     * 排序顺序(默认降序)
     */
    private String sortOrder = "descend";
}

删除请求包装类,接受要删除数据的id 作为参数

@Data
public class DeleteRequest implements Serializable {

    /**
     * id
     */
    private Long id;

    private static final long serialVersionUID = 1L;
}

5、全局跨域配置

跨域是指浏览器访问的 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");
    }
}

 访问 http://localhost:8123/api/health,看到输出结果,表示后端初始化完成:

补充:设置新建类/接口文件的类/接口注释模版

在设置中输入“File and Code Templates” 或者 “文件和代码模板” 可增加自定义注释

参考:SpringBoot IDEA 开发必备使用小技巧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2307291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DeepSeek本地部署与Dify结合创建私有知识库指南

python调用本地deepseek+Dify的API使用--测试WX自动发送信息-CSDN博客 DeepSeek,一家在人工智能领域具有显著技术实力的公司,凭借其千亿参数规模的AI大模型,以及仅需0.5元人民币即可进行百万tokens的API调用成本,已经取得了令人瞩目的成就。不仅如此,DeepSeek的模…

Nginx 报错:413 Request Entity Too Large

做web开发时&#xff0c;对于上传附件的功能&#xff0c;如果nginx没有调整配置&#xff0c;上传大一点的文件就会发生下面这种错误&#xff1a; 要解决上面的问题&#xff0c;只需要调整Nginx配置文件中的 client_max_body_size 参数即可&#xff0c;这个配置参数一般在http配…

Arduino项目实战:使用MQ-2气体传感器与OLED屏幕监测环境气体

概述 在这个项目中,MQ-2气体传感器是一个多功能的气体检测设备,能够感知多种常见气体,如甲烷、丁烷、丙烷、酒精和烟雾等。你可以把它想象成一个超级灵敏的“嗅觉”,能够帮助你实时检测环境中的各种有害气体。与Arduino板连接后,MQ-2传感器把捕捉到的气体浓度数据传送给A…

C#实现本地Deepseek模型及其他模型的对话

前言 1、C#实现本地AI聊天功能 WPFOllamaSharpe实现本地聊天功能,可以选择使用Deepseek 及其他模型。 2、此程序默认你已经安装好了Ollama。 在运行前需要线安装好Ollama,如何安装请自行搜索 Ollama下载地址&#xff1a; https://ollama.org.cn Ollama模型下载地址&#xf…

【ESP32S3接入讯飞在线语音识别】

视频地址: 【ESP32S3接入讯飞在线语音识别】 1. 前言 使用Seeed XIAO ESP32S3 Sense开发板接入讯飞实现在线语音识别。自带麦克风模块用做语音输入,通过串口发送字符“1”来控制数据的采集和上传。 语音识别对比 平台api教程评分百度

【问题记录】Go项目Docker中的consul访问主机8080端口被拒绝

【问题记录】Go项目Docker中的consul访问主机8080端口被拒绝 问题展示解决办法 问题展示 在使用docker中的consul服务的时候&#xff0c;通过命令行注册相应的服务&#xff08;比如cloudwego项目的demo_proto以及user服务&#xff09;失败。 解决办法 经过分析&#xff0c;是…

DeepSeek实现FunctionCalling调用API查询天气

什么是FunctionCalling Function Calling&#xff08;函数调用&#xff09;是大型语言模型&#xff08;如 OpenAI 的 GPT 系列&#xff09;提供的一种能力&#xff0c;允许模型在生成文本的过程中调用外部函数或工具&#xff0c;以完成更复杂的任务。通过 Function Calling&am…

windows设置暂停更新时长

windows设置暂停更新时长 win11与win10修改注册表操作一致 &#xff0c;系统界面不同 1.打开注册表 2.在以下路径 \HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 右键新建 DWORD 32位值&#xff0c;名称为FlightSettingsMaxPauseDays 根据需求填写数…

【Kimi】自动生成PPT-并支持下载和在线编辑--全部免费

【Kimi】免费生成PPT并免费下载 用了好几个大模型&#xff0c;有些能生成PPT内容&#xff1b; 有些能生成PPT&#xff0c;但下载需要付费&#xff1b; 目前只有Kimi生成的PPT&#xff0c;能选择模板、能在线编辑、能下载&#xff0c;关键全部免费&#xff01; 一、用kimi生成PP…

一款在手机上制作电子表格

今天给大家分享一款在手机上制作电子表格的&#xff0c;免费好用的Exce1表格软件&#xff0c;让工作变得更加简单。 1 软件介绍 Exce1是一款手机制作表格的办公软件&#xff0c;您可以使用手机exce1在线制作表格、工资表、编辑xlsx和xls表格文件等&#xff0c;还可以学习使用…

【实战 ES】实战 Elasticsearch:快速上手与深度实践-1.3.1单节点安装(Docker与手动部署)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 10分钟快速部署Elasticsearch单节点环境1. 系统环境要求1.1 硬件配置推荐1.2 软件依赖 2. Docker部署方案2.1 部署流程2.2 参数说明2.3 性能优化建议 3. 手动部署方案3.1 安…

【Mac电脑本地部署Deepseek-r1:详细教程与Openwebui配置指南】

文章目录 前言电脑配置&#xff1a;安装的Deepseek版本&#xff1a;使用的UI框架&#xff1a;体验效果展示&#xff1a;本地部署体验总结 部署过程Ollama部署拉取模型运行模型Openwebui部署运行Ollama服务在Openwebui中配置ollama的服务 后话 前言 deepseek最近火的一塌糊涂&a…

网络安全学习中,web渗透的测试流程是怎样的?

渗透测试是什么&#xff1f;网络安全学习中&#xff0c;web渗透的测试流程是怎样的&#xff1f; 渗透测试就是利用我们所掌握的渗透知识&#xff0c;对网站进行一步一步的渗透&#xff0c;发现其中存在的漏洞和隐藏的风险&#xff0c;然后撰写一篇测试报告&#xff0c;提供给我…

将VsCode变得顺手好用(1

目录 设置中文 配置调试功能 提效和增强相关插件 主题和图标相关插件 创建js文件 设置中文 打开【拓展】 输入【Chinese】 下载完成后重启Vs即可变为中文 配置调试功能 在随便一个位置新建一个文件夹&#xff0c;用于放置调试文件以及你未来写的代码&#xff0c;随便命名但…

第6_7章_管理权限评估和测试策略

管理权限 权限将受保护的对象与必须评估以决定是否应授予访问权限的策略相关联。 在创建要保护的资源以及要用于保护这些资源的策略后&#xff0c; 您可以开始管理权限。要管理权限&#xff0c;请在编辑资源服务器时单击 Permissions 选项卡。 可以创建权限来保护两种主要类…

2025年网校系统源码开发趋势:技术革新的教育培训APP搭建实战

2025年&#xff0c;随着AI、大数据、云计算等技术的深度融合&#xff0c;网校教育系统的源码开发也迎来了新的发展趋势。本文将深入探讨这些趋势&#xff0c;并结合教育培训APP的开发实战&#xff0c;展示如何应对未来的技术挑战。 一、2025年网校教育系统源码的技术趋势 AI驱…

Linux驱动开发实战(一):LED控制驱动详解

Linux驱动开发野火实战&#xff08;一&#xff09;&#xff1a;LED控制驱动详解 文章目录 Linux驱动开发野火实战&#xff08;一&#xff09;&#xff1a;LED控制驱动详解引言一、基础知识1.1 什么是字符设备驱动1.2 重要的数据结构read 函数write 函数open 函数release 函数 二…

PowerShell 执行策略:fnm管理软件安装nodejs无法运行npm,错误信息:about_Execution_Policies

通过fnm管理软件安装NodeJS后添加环境变量依然无法执行npm,提示无法加载文件&#xff0c;错误如下&#xff1a; PowerShell 执行策略简介&#xff1a; PowerShell 执行策略是一项安全功能&#xff0c;用于控制 PowerShell 加载配置文件和运行脚本的条件。 此功能有助于防止恶…

论文阅读笔记:Deep Face Recognition: A Survey

论文阅读笔记&#xff1a;Deep Face Recognition: A Survey 1 介绍2 总览2.1 人脸识别组件2.1.1 人脸处理2.1.2 深度特征提取2.1.3 基于深度特征的人脸对比 3 网络结构和损失函数3.1 判别损失函数的演化3.1.1 基于欧式距离的损失3.1.2 基于角度/余弦边距的损失3.1.3 Softmax损失…

本地dify绑定notion

需要用到 notion 的“集成”功能。对于个人用户来说&#xff0c;选择使用**内部 internal **集成&#xff0c;公司用户可以考虑使用公开 public 集成。 在下面的 notion 集成网站中申请一个新的集成&#xff1a; Notion – The all-in-one workspace for your notes, tasks, …