云图库平台(一)后端项目初始化

前言

  • 这里jdk版本是1.8(版本必须是java8或java11或java17)
  • mysql版本是8.0以上的版本

目录

一、创建项目

由于java8比较稳定,所需这里项目创建时选择的java8版本,如果没有java8这个选项的话,可以将Server URL改为https://start.aliyun.com/

spring boot版本是2.7.6,同时引入一些常用依赖:

项目创建成功后,先运行看能够运行成功,结果发现错误:Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

报错原因:由于我们在项目创建之初引入了Mysql Driver驱动依赖,所以在项目启动的时候就会自动连接mysql,但是我们没有进行数据库的配置,所以我们需要编写一个配置文件进行数据库配置(application.yml)。

  • 数据库基础配置
yaml 复制代码
server:
  port: 8126
  servlet:
    context-path: /api
spring:
  application:
    name: cloud-picture-backend
  # 数据库配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306
    username: root
    password: 111111

现在就可以正常运行了。

二、整合依赖

Mybatis Plus依赖

可以参考官方文档:https://baomidou.com/getting-started/#spring-boot2

  • 在Maven的pom.xml中添加依赖,注意:添加mybatis plus依赖后,需要一处mybatis相关的依赖,即引入Mybatis-Plus之后不能再次引入Mybatismybatis-spring-boot-starter,否则会导致版本冲突问题:
xml 复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.9</version>
</dependency>
  • 首先项目中新建mapper目录,然后复制mapper的路径,在项目启动类中添加扫描Mapper的@MapperScan注解:
java 复制代码
@SpringBootApplication
@MapperScan("com.yf.cloudpicturebackend.mapper")
public class CloudPictureBackendApplication {
    public static void main(String[] args) {
        SpringApplication.run(CloudPictureBackendApplication.class, args);
    }
}
  • 在application.yml中添加相应的配置(可以参照上面的mybatis plus官方文档):
yaml 复制代码
mybatis-plus:
  configuration:
    # MyBatis 配置
    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
      logic-not-delete-value: 0

Hutool工具库

可以参考官方文档:https://doc.hutool.cn/pages/index/#🍊maven

xml 复制代码
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>

Knife4j

Knife4j是一个基于Swagger的接口文档工具(可以理解为Swagger的升级版),可以让我们快速了解项目中的接口,方便后续进行接口调试。简单说Knife4j的作用:我们写完代码后,Knife4j会自动生成接口文档

可以参考官方文档:https://doc.xiaominfo.com/docs/quick-start#spring-boot-2

新建controller包(用于存放API接口)

xml 复制代码
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

进行Knife4j的相关yml配置:

yaml 复制代码
# 接口文档配置
knife4j:
  enable: true
  openapi:
    title: Knife4j官方文档
    version: 1.0
    group:
      default:
        group-name: 默认分组
        api-rule: package
        api-rule-resources:
          - com.yf.cloudpicturebackend.controller

然后我们再次运行项目后会发现多了一个路径:

访问http://localhost:8126/api/doc.html可以看到接口文档,方便测试接口

AOP切面编程

依赖引入:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后给启动类添加注解:

java 复制代码
@EnableAspectJAutoProxy(exposeProxy = true)

exposeProxy = true的作用:用于启动aspectj自动代理功能。在Spring AOP中,通过该注解可以将代理对象暴露出来,方便在AOP切面中获取代理对象并进行操作。exposeProxy = true就表示暴露代理对象。

三、通用代码基础

自定义异常

通过自定义异常对错误码进行收敛,便于前端统一进行处理。注意:

自定义错误码时最好跟主流的HTTP错误码含义(回忆一下常用的HTTP响应码:400表示bad request401表示没权限403表示被禁止404表示没资源)保持一致:

  • exception包下创建错误码枚举类(ErrorCode.java)
java 复制代码
@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 复制代码
/**
 * 自定义业务异常
 */
@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();
    }
}
  • 自定义业务异常:与内置异常类进行区分,便于定制化输出错误信息。
java 复制代码
/**
 * 自定义业务异常
 */
@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类(类似于断言类的方法),简化抛异常的代码:

全局响应类封装

我们知道,每个后端接口都要返回调用吗、数据、调用信息;而前端则可以根据这些信息进行相应的处理。所以我们可以进行一个全局响应结果类的封装、这样便于前端同意获取这些信息。

通用响应类如下:

java 复制代码
@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());
    }
}

全局异常处理器

在exception包下创建GlobalExceptionHandler

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

请求包装类

我们对于分页删除某条数据这类通用的请求,可以封装统一的请求包装类,用于接受前端传来的参数。

  • commen包下创建PageRequest.java类(分页请求包装类如下):
java 复制代码
/**
 * 通用的分页请求类
 */
@Data
public class PageRequest {
    /**
     * 当前页号
     */
    private int current = 1;

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

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

    /**
     * 排序顺序(默认降序)
     */
    private String sortOrder = "descend";
}
  • commen包下创建DeleteRequest.java类(删除请求包装类如下):
java 复制代码
/**
 * 通用的删除请求类
 */
 @Data
public class DeleteRequest implements Serializable {

    /**
     * id
     */
    private Long id;

    private static final long serialVersionUID = 1L;
}

四、跨域问题

对于本地开发,前端启动一个项目会占用一个端口,后端启用一个项目又会占用另外一个端口,两个端口号是不一致的。比如使用前端localhost:5182页面去请求后端localhost:8135接口,这个时候就会出现跨域问题(跨域问题只在浏览器中出现)。解决该问题有如下两个解决方案

  • 后端支持跨域
  • 代理:比如前端localhost:5182网站可以通过一些工具访问前端localhost:5182/user。换句话说只要localhost:5182访问localhost:5182/user这个地址这个时候代理就会自动把请求转发到localhost:8175后端;对于前端来说访问的依然是localhost:5182,但实际上已经把请求转发给localhost:8175了。

现在我们通过第一种,即后端的方式来解决跨域问题:

  • 新建config包,用于存放所有的配置相关代码。全局跨域配置代码如下:
java 复制代码
/**
 * 全局跨域配置
 */
@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接口用于健康检查:

java 复制代码
@RestController
@RequestMapping("/")
public class MainController {

    /**
     * 健康检查
     */
    @GetMapping("/health")
    public BaseResponse<String> health() {
        return ResultUtils.success("ok");
    }
}


好了,到这里初始化就成功了。

相关推荐
李三醒25 分钟前
Apache Tomcat 漏洞CVE-2024-50379条件竞争文件上传漏洞 servlet readonly spring boot 修复方式
spring boot·tomcat·apache
星月前端34 分钟前
随记:springboot的xml中sql数据库表名动态写法
xml·数据库·spring boot
wh_xia_jun2 小时前
springboot集成websokcet+uniapp开发聊天原型验证(一)
spring boot·后端·uni-app
高克莱3 小时前
【SpringBoot 调度任务】
java·spring boot·后端
倩倩_ICE_王王4 小时前
Spring Boot 项目创建
java·spring boot·后端
工业互联网专业4 小时前
Python毕业设计选题:基于Python的社区爱心养老管理系统设计与实现_django
python·django·vue·毕业设计·源码·课程设计
等一场春雨4 小时前
Java 优化springboot jar 内存 年轻代和老年代的比例 减少垃圾清理耗时 如调整 -XX:NewRatio
java·spring boot·jar
Kali_076 小时前
OnOn-WebSsh (昂~昂~轻量级WebSSH) 可实现 网页 中的 ssh 客户端操作,支持多用户多线程操作 ssh 持久化
java·运维·spring boot·ssh
liuyunshengsir7 小时前
Spring Boot 中的 @Scheduled 定时任务以及开关控制
java·数据库·spring boot