全面掌握Spring Boot + MyBatis + Maven + MySQL:从开发到部署的后端技术详解
前言
从零开始:我的第一篇后端开发技术文档
- 作为一名后端开发的新手,我曾在自己的学习过程中遇到过许多挑战:如何选择合适的技术栈、如何理解框架的工作原理、以及如何将这些技术应用到实际的项目中。在这篇文档中,我将分享我在学习 Spring Boot、MyBatis、Maven 和 MySQL 的过程中的心得体会,并一步步带领大家搭建一个简单的后端应用。虽然我自己才刚刚起步,但我希望通过这篇文档,能够帮助像我一样的后端开发新手,少走一些弯路,快速掌握这些基础技术。
本文适合后端开发的初学者,特别是那些对Spring Boot、MyBatis、Maven等技术栈感兴趣、并希望从零开始构建后端应用的同学,通过这篇文档,你将学会如何搭建一个基本的后端应用,并掌握与数据库交互的基本技巧。
项目概述
- 在这一部分,我会简单介绍这个项目的背景和目标,让读者明白为什么要学习这个技术栈,以及这个项目将帮助他们解决什么问题。
项目背景
- 本项目是一个简单的后端系统,基于 Spring Boot 框架搭建,结合 MyBatis 用于数据库操作。通过 Maven 来管理项目依赖,使用 MySQL 数据库来存储应用数据。项目的目标是帮助大家快速了解如何利用这些流行的工具和框架,搭建一个简单的 API 服务。这里我使用医院门诊信息的数据作为示例。
目标
通过本项目,你将学会:
- 使用 Spring Boot 快速搭建后端应用
- 使用 MyBatis 进行数据库的 CRUD(增、删、改、查)操作
- 配置 Maven 进行依赖管理
- 通过 MySQL 存储数据,并用 Navicat 进行数据库管理
环境搭建
这一部分是每个新手在开发过程中必须经历的步骤。前期我也是配置了许久,各种版本的兼容问题层出不穷。这里我会以简单易懂的语言说明每个工具的安装与配置过程。
安装开发环境
在开始编码之前,我们需要先准备好开发环境。首先需要安装 JDK(Java Development Kit),因为我们将使用 Java 来进行开发。接下来,安装 Maven 以方便我们管理项目的依赖。之后,安装 MySQL 数据库,并使用 Navicat 工具进行数据库的可视化管理。
具体步骤:
-
安装 JDK:这里我使用的是JDK1.8。大家不会安装和进行环境配置的可以参考这个教程
-
安装 Maven:Maven 是一个项目管理工具,能够帮助我们管理项目依赖和自动化构建。
-
安装 MySQL:MySQL 是我们项目的数据存储中心,建议通过 Navicat 来方便地管理数据库。
-
安装 IDEA:推荐使用 IntelliJ IDEA ,安装过程中可以选择支持 Maven 和 Spring Boot 的插件。
-
安装Navicat:一款功能强大且广泛使用的数据库管理工具,适用于多种数据库系统,如 MySQL、MariaDB、Oracle、PostgreSQL、SQLite、SQL Server 和 MongoDB 等。
项目创建与配置
创建 Spring Boot 项目:
方法一:使用 Spring Initializr 创建基础项目,选择依赖:
- Spring Web
- MyBatis Framework
- MySQL Driver
- Spring Data JPA
导入项目到IDE中。
方法二:使用IDEA,这里推荐使用这个创建
-
第一步:点击文件>新建项目
- 第二步:选择版本,添加依赖,点击创建
-
第三步:项目创建成功之后是这个界面
注意:点击右上角落的运行来测试一下,。如果出现下面的这个报错,说明本地 Maven 仓库或缓存可能被污染或损坏。
解决方法:删除libraries文件夹,打开文件>设置>构建工具>Maven>点击下拉菜单,选择 “Bundled (Maven 3)” 选项>应用或确定
点击右边的Maven,点击重构,这时问题解决
如果你的依赖(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>
<!-- 项目信息 -->
<groupId>com.example</groupId>
<artifactId>demo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo2</name>
<description>Spring Boot + MyBatis 后端配置</description>
<!-- 项目属性 -->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version> <!-- Spring Boot 版本 -->
<mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version> <!-- MyBatis 版本 -->
<mysql.version>8.0.26</mysql.version> <!-- MySQL 驱动版本 -->
</properties>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 项目依赖 -->
<dependencies>
<!-- Spring Boot Starter Web:用于开发 Web 应用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
<!-- MyBatis Spring Boot Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok:简化 Getter/Setter/ToString 等代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot Starter Test:测试依赖(可选) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建插件 -->
<build>
<plugins>
<!-- Maven 编译插件:设置 Java 版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Spring Boot Maven 插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</build>
</project>
第四步:使用Navicat连接到我们的数据库MySQL,点击连接,这里取名demo,密码是刚在MySQL中自己设置的,测试连接,确定
查看我的表结构,这里我已经建过了,新手这里右键表,点击新建,根据自己的需求设置字段,一般来说将主键设置为自动自增
第五步:打开IDEA,在页面右侧找到我们的数据库,点击+号,点击数据源,选择MySQL,
这里输入我们刚才的账号和密码,点击测试连接,可以看到已成功,这时我们的数据库配置完成
这个时候可以看到我的数据库名称和我的data表的数据
点击文件>设置,设置我们的文件编码为UTF-8
项目结构与配置
这里我习惯将static目录下的application.properties给为application.xml,并进行配置,这是我的配置,建议直接复制,然后修改自己的数据库表名,账号和密码改为你刚才在MySQL中设置的账号密码
- 这里的驼峰命名配置,当你的数据库中表中的字段为patient_id时,会在后端映射为patientId,这个不可忽略
server:
port: 8688 # 后端端口
spring:
banner:
charset: UTF-8
location: classpath:banner.txt
datasource:
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root # MySQL 用户名
password: ****** # MySQL 密码
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
# mapper xml 文件路径
mapper-locations: classpath:mapper/*.xml
# 实体类包路径
type-aliases-package: com.example.demo.entity
configuration:
# 开启驼峰命名
map-underscore-to-camel-case: true
做好这些准备工作,下一步,让我们来启动我们的项目,可以看到项目成功启动
编写后端代码
作为新手,我会在这里尽量简化并清晰地说明每个步骤的代码,帮助读者理解每个组件的职责。我们从实体类、Mapper、Service 到 Controller 层,逐步构建项目。
项目目录
实体类
首先,我们定义实体类,它将映射到 MySQL 数据库中的表格。比如在我们的com.example.demo包下有一个 实体类包entity,下有一个患者信息实体类PatientInfo
package com.example.demo.entity;
/*使用Lombok注解@Data,自动生成getter和setter方法*/
import lombok.Data;
/**
* 患者信息实体类
*/
@Data
public class PatientInfo {
/**
* 患者ID
*/
private Integer patientId;
/**
* 患者姓名
*/
private String name;
/**
* 患者性别
*/
private String gender;
/**
* 患者年龄
*/
private Integer age;
/**
* 患者主要症状
*/
private String mainSymptom;
/**
* 患者所在科室
*/
private String department;
/**
* 患者诊断结果
*/
private String diagnosis;
}
Mapper 接口
Mapper 接口是 MyBatis 的核心,它负责与数据库进行交互。在我们的com.example.demo包下有一个包mapper,下有一个PatientInfoMapper接口
- 作用:接口中的方法名与
mapper.xml
中定义的 SQL 语句一一对应,MyBatis 会根据方法的参数和返回类型自动生成执行 SQL 语句的代码。我们创建一个 PatientInfoMapper 接口,用于执行对患者信息的增删改查操作:
package com.example.demo.mapper;
import com.example.demo.entity.PatientInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 患者信息Mapper接口
*/
@Mapper
public interface PatientInfoMapper {
/**
* 查询所有患者信息
*
* @return 患者信息列表
*/
List<PatientInfo> findAll();
/**
* 根据患者ID查询患者信息
*
* @param patientId 患者ID
* @return 患者信息
*/
PatientInfo findById(int patientId);
/**
* 插入患者信息
*
* @param patientInfo 患者信息
*/
void insert(PatientInfo patientInfo);
/**
* 更新患者信息
*
* @param patientInfo 患者信息
*/
void update(PatientInfo patientInfo);
/**
* 删除患者信息
*
* @param patientId 患者ID
*/
void delete(int patientId);
/**
* 根据页码和每页大小查询患者信息
*
* @param offset 偏移量
* @param limit 每页大小
* @return 患者信息列表
*/
List<PatientInfo> findPatients(@Param("offset") int offset, @Param("limit") int limit);
/**
* 根据姓名和页码、每页大小查询患者信息
*
* @param name 姓名
* @param offset 偏移量
* @param limit 每页大小
* @return 患者信息列表
*/
List<PatientInfo> findPatientsByName(@Param("name") String name, @Param("offset") int offset, @Param("limit") int limit);
/**
* 统计所有患者数量
*
* @return 患者总数
*/
int countAllPatients();
/**
* 根据姓名统计患者数量
*
* @param name 姓名
* @return 患者总数
*/
int countPatientsByName(@Param("name") String name);
}
PatientInfoMapper.xml 文件:
- 职责:定义具体的 SQL 语句及其映射规则。在我们的src包下的resources下有一个 包mapper下有一个PatientInfoMapper.xml 文件
- 作用:
mapper.xml
文件提供了具体的 SQL 语句及其执行方式(查询、插入、更新等)。通过 XML 文件,你可以定义更复杂的 SQL 语句,比如联合查询、条件判断等。
<?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.example.demo.mapper.PatientInfoMapper">
<!-- 定义结果映射 -->
<resultMap id="PatientInfoResult" type="com.example.demo.entity.PatientInfo">
<id property="patientId" column="patient_id"/>
<result property="name" column="name"/>
<result property="gender" column="gender"/>
<result property="age" column="age"/>
<result property="mainSymptom" column="main_symptom"/>
<result property="department" column="department"/>
<result property="diagnosis" column="diagnosis"/>
</resultMap>
<!-- 查询所有患者信息 -->
<select id="findAll" resultMap="PatientInfoResult">
SELECT * FROM data
</select>
<!-- 根据患者ID查询患者信息 -->
<select id="findById" parameterType="int" resultMap="PatientInfoResult">
SELECT * FROM data WHERE patient_id = #{patientId}
</select>
<!-- 插入患者信息 -->
<insert id="insert" parameterType="com.example.demo.entity.PatientInfo">
INSERT INTO data(name, gender, age, main_symptom, department, diagnosis)
VALUES(#{name}, #{gender}, #{age}, #{mainSymptom}, #{department}, #{diagnosis})
</insert>
<!-- 更新患者信息 -->
<update id="update" parameterType="com.example.demo.entity.PatientInfo">
UPDATE data
SET name = #{name}, gender = #{gender}, age = #{age}, main_symptom = #{mainSymptom}, department = #{department}, diagnosis = #{diagnosis}
WHERE patient_id = #{patientId}
</update>
<!-- 删除患者信息 -->
<delete id="delete" parameterType="int">
DELETE FROM data WHERE patient_id = #{patientId}
</delete>
<!-- 根据页码和每页大小查询患者信息 -->
<select id="findPatients" resultMap="PatientInfoResult">
SELECT * FROM data LIMIT #{limit} OFFSET #{offset}
</select>
<!-- 根据姓名和页码、每页大小查询患者信息 -->
<select id="findPatientsByName" resultMap="PatientInfoResult">
SELECT * FROM data WHERE name LIKE CONCAT('%', #{name}, '%') LIMIT #{limit} OFFSET #{offset}
</select>
<!-- 查询所有患者总数 -->
<select id="countAllPatients" resultType="int">
SELECT COUNT(*) FROM data
</select>
<!-- 根据姓名查询患者总数 -->
<select id="countPatientsByName" resultType="int">
SELECT COUNT(*) FROM data WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
</mapper>
Service 层
Service 层是业务逻辑层,负责协调 Mapper 层和 Controller 层。我们在这里编写患者信息的业务逻辑,通过这种方式,可以方便地管理和操作患者信息,同时保持代码的清晰和可维护性
- 定义患者信息服务的接口和其实现类,在我们的com.example.demo包下有一个service包,在这个包下有一个患者信息服务的接口PatientInfoService
package com.example.demo.service;
import com.example.demo.entity.PatientInfo;
import java.util.List;
/**
* 患者信息服务接口
*/
public interface PatientInfoService {
/**
* 获取所有患者信息
*
* @return 患者信息列表
*/
List<PatientInfo> getAllPatients();
/**
* 根据患者ID获取患者信息
*
* @param patientId 患者ID
* @return 患者信息
*/
PatientInfo getPatientById(int patientId);
/**
* 添加患者信息
*
* @param patientInfo 患者信息
*/
void addPatient(PatientInfo patientInfo);
/**
* 更新患者信息
*
* @param patientInfo 患者信息
*/
void updatePatient(PatientInfo patientInfo);
/**
* 删除患者信息
*
* @param patientId 患者ID
*/
void deletePatient(int patientId);
/**
* 根据页码、每页大小和姓名获取患者信息
*
* @param page 页码
* @param size 每页大小
* @param name 姓名
* @return 患者信息列表
*/
List<PatientInfo> getPatients(int page, int size, String name);
/**
* 根据姓名获取患者总数
*
* @param name 姓名
* @return 患者总数
*/
int getTotalPatientsCount(String name);
}
- 在我们的com.example.demo包下有一个service包,在这个包下新建包impl,编写其实现类PatientInfoServiceImpl
package com.example.demo.service.impl;
import com.example.demo.entity.PatientInfo;
import com.example.demo.mapper.PatientInfoMapper;
import com.example.demo.service.PatientInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 患者信息服务实现类
*/
@Service
public class PatientInfoServiceImpl implements PatientInfoService {
/**
* 注入PatientInfoMapper
*/
@Autowired
private PatientInfoMapper patientInfoMapper;
/**
* 获取所有患者信息
*
* @return 患者信息列表
*/
@Override
public List<PatientInfo> getAllPatients() {
return patientInfoMapper.findAll();
}
/**
* 根据患者ID获取患者信息
*
* @param patientId 患者ID
* @return 患者信息
*/
@Override
public PatientInfo getPatientById(int patientId) {
return patientInfoMapper.findById(patientId);
}
/**
* 添加患者信息
*
* @param patientInfo 患者信息
*/
@Override
public void addPatient(PatientInfo patientInfo) {
patientInfoMapper.insert(patientInfo);
}
/**
* 更新患者信息
*
* @param patientInfo 患者信息
*/
@Override
public void updatePatient(PatientInfo patientInfo) {
patientInfoMapper.update(patientInfo);
}
/**
* 删除患者信息
*
* @param patientId 患者ID
*/
@Override
public void deletePatient(int patientId) {
patientInfoMapper.delete(patientId);
}
/**
* 根据页码、每页大小和姓名获取患者信息
*
* @param page 页码
* @param size 每页大小
* @param name 姓名
* @return 患者信息列表
*/
@Override
public List<PatientInfo> getPatients(int page, int size, String name) {
int offset = (page - 1) * size;
if (name == null || name.isEmpty()) {
return patientInfoMapper.findPatients(offset, size);
} else {
return patientInfoMapper.findPatientsByName(name, offset, size);
}
}
/**
* 根据姓名获取患者总数
*
* @param name 姓名
* @return 患者总数
*/
@Override
public int getTotalPatientsCount(String name) {
if (name == null || name.isEmpty()) {
return patientInfoMapper.countAllPatients();
} else {
return patientInfoMapper.countPatientsByName(name);
}
}
}
Controller 层
-
这里定义了一个 RESTful API,用于管理患者信息,包括获取、添加、更新和删除患者信息。通过使用 Spring Boot 的注解,可以方便地处理 HTTP 请求和响应。在我们的com.example.demo包下有一个controller包,下有一个PatientInfoController类
这里的@CrossOrigin(origins = “http://localhost:5173/”),因为我的项目是前后端分离的,这是我的前端地址,这里是为了解决允许来自
http://localhost:5173/
的跨域请求。
package com.example.demo.controller;
import com.example.demo.entity.PatientInfo;
import com.example.demo.service.PatientInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 患者信息控制器
*/
@CrossOrigin(origins = "http://localhost:5173/")
@RestController
@RequestMapping("/api/patients")
public class PatientInfoController {
/**
* 注入PatientInfoService
*/
@Autowired
private PatientInfoService patientInfoService;
/**
* 获取患者信息列表
*
* @param page 页码
* @param size 每页大小
* @param name 姓名
* @return 包含患者信息和总记录数的响应
*/
@GetMapping
public ResponseEntity<Map<String, Object>> getPatients(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(required = false) String name) {
/*传递搜索参数*/
List<PatientInfo> patients = patientInfoService.getPatients(page, size, name);
/*获取总记录数*/
int total = patientInfoService.getTotalPatientsCount(name);
Map<String, Object> response = new HashMap<>();
response.put("patients", patients);
/*返回总记录数*/
response.put("total", total);
return ResponseEntity.ok(response);
}
/**
* 根据患者ID获取患者信息
*
* @param id 患者ID
* @return 患者信息
*/
@GetMapping("/{id}")
public PatientInfo getPatientById(@PathVariable int id) {
return patientInfoService.getPatientById(id);
}
/**
* 添加患者信息
*
* @param patientInfo 患者信息
* @return 添加成功的响应
*/
@PostMapping
public ResponseEntity<String> addPatient(@RequestBody PatientInfo patientInfo) {
if (patientInfo.getName() == null || patientInfo.getGender() == null || patientInfo.getAge() == null) {
return ResponseEntity.badRequest().body("缺少必填字段");
}
patientInfoService.addPatient(patientInfo);
return ResponseEntity.ok("添加成功");
}
/**
* 更新患者信息
*
* @param id 患者ID
* @param patientInfo 患者信息
*/
@PutMapping("/{id}")
public void updatePatient(@PathVariable int id, @RequestBody PatientInfo patientInfo) {
patientInfo.setPatientId(id);
patientInfoService.updatePatient(patientInfo);
}
/**
* 删除患者信息
*
* @param id 患者ID
*/
@DeleteMapping("/{id}")
public void deletePatient(@PathVariable int id) {
patientInfoService.deletePatient(id);
}
}
接口调试
到这里,我们的后端工作准备完成,打开我们的接口调试Apifox下载安装【官方版】工具,看是否可以访问到我们的信息,点击右边发送
-
获取所有患者信息:
- URL:
http://localhost:8688/api/patients
- 请求方法:
GET
,可以看到获取成功
- URL:
-
添加患者信息:
URL: http://localhost:8688/api/patients
请求方法: POST
请求体: JSON 格式的患者信息
来看我们的后端,可以看到已经添加进去,因为主键是自增的,所以默认在最后一个
总结
最后,我会总结自己在这次学习过程中的收获,并鼓励读者继续探索。如果我哪里写的有问题,欢迎各位程序大佬在评论区对鄙人指点迷津,我会继续完善。
在这篇文档中,我通过简单的示例搭建了一个 Spring Boot 后端应用,学习了如何使用 MyBatis 进行数据库操作,如何使用 Maven 管理项目依赖,以及如何通过 Navicat 管理 MySQL 数据库。虽然过程充满挑战,但每一步都让我更加深入理解了后端开发的基本概念。希望这篇文章能够对你有所帮助,继续加油!未来我将继续学习更多技术,欢迎大家一起交流。
-4-126834243-null-null.142v101pc_search_result_base8&utm_term=apifox%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE&spm=1018.2226.3001.4187)工具,看是否可以访问到我们的信息,点击右边发送
- 获取所有患者信息:
- URL:
http://localhost:8688/api/patients
- 请求方法:
GET
,可以看到获取成功
- URL:
[外链图片转存中…(img-OtdKcBYk-1736172591711)]
- 添加患者信息:
URL: http://localhost:8688/api/patients
请求方法: POST
请求体: JSON 格式的患者信息
[外链图片转存中…(img-PcQvJNup-1736172591711)]
来看我们的后端,可以看到已经添加进去,因为主键是自增的,所以默认在最后一个
[外链图片转存中…(img-zl036XT6-1736172591711)]
总结
最后,我会总结自己在这次学习过程中的收获,并鼓励读者继续探索。如果我哪里写的有问题,欢迎各位程序大佬在评论区对鄙人指点迷津,我会继续完善。
在这篇文档中,我通过简单的示例搭建了一个 Spring Boot 后端应用,学习了如何使用 MyBatis 进行数据库操作,如何使用 Maven 管理项目依赖,以及如何通过 Navicat 管理 MySQL 数据库。虽然过程充满挑战,但每一步都让我更加深入理解了后端开发的基本概念。希望这篇文章能够对你有所帮助,继续加油!未来我将继续学习更多技术,欢迎大家一起交流。
标签:return,name,int,Spring,Boot,param,Maven,信息,患者 From: https://blog.csdn.net/m0_70814680/article/details/144973552