SpringBoot入门
注意:使用SpringBoot需提前了解Maven知识,并对Spring, Spring MVC,Mybatis,Mysql有一定了解。
1、什么是SpringBoot?
SpringBoot是一款开源的框架,旨在简化Spring应用的创建与配置。SpringBoot根据依赖管理和自动化配置以及约定大于配置的理念,以及丰富的模块支持,能够帮助开发者快速构建企业级应用,也帮助了开发者从繁琐配置的文件中解脱出来,尽可能让开发者的精力投入到业务环境中。
2、SpringBoot的核心特性?
2.1依赖管理
SpringBoot将常用框架包都整理到各自stater的maven包中,只要项目引入了相关start包,项目所依赖包会自动放入项目中,开发者也就不必手动导入jar包与记忆相关包。从而解放了开发者的精力与繁琐配置。
我们提出三个问题来帮助理解。
1、SpringBoot如何管理版本号的?
大家如果对Maven有了解的话,一定会想到导入的maven包中有一个版本指定,
那咋们看看SpringBoot的基础包:
是不是没有指定version版本,有没有感觉很奇怪,别急往下看马上就开始讲解了。
在SpringBoot的pom.xml文件中,有一个<parent>标签,它主要是当前项目的父级依赖,我们点击进去查看一哈。
通过整个文件的观察我们并没有发现版本的控制,但是我们发现了这个也有一个<parent>标签与jdk版本和其他的版本配置信息。
这个parent中既然没有发现(保留希望),那就继续查看这个<parent>标签的父级中有没有。
嘿嘿,惊喜,找到它了。他的版本控制放到父级的父级中统一管理(这个是默认的),是不是很清晰了。我们总结一哈,SpringBoot通过父级与父级的关系来管理SpringBoot官方指定版本,一般情况下不会更改,如果有特殊要求,可以根据自身的需求在本级pom.xml中指定version版本。
2、SpringBoot的start里面都有什么,为什么引入start就获取了其他jar包?
我们点击pom.xml文件中的<artifactId>spring-boot-starter-web</artifactId>来查看里面有什么,发现它里面在<dependencies>标签中帮我们制定了很多maven包,
这些包是不是有点眼熟,spring相关 就是我们之前SSM开发项目的Spring依赖包,上面的JSON与tomcat的Spring-boot的原理也是一样的。总结一哈,SpringBoot通过一个统一的start maven包,将我们本系列开发所需要的包都统一封装到一个start中,引入根start就会获取其相关的包。
3、SpringBoot又是什么加载配置文件的?
SpringBoot的配置信息都会统一放在一个yaml/yml/properties的文件中,官方规定默认采用application.yml/application.yaml/appliaction.properties文件来加载配置信息。既然我们说了结论,就需要来验证这个结论。我们先点击pom.xml的parent标签的<artifactId>spring-boot-starter-parent</artifactId>,进入后可以在<resources>中可查看到application.yml的加载顺序。
通过图中的配置信息,我们可以直观的查看到配置文件存放目录以及加载顺序,SpringBoot会加载这个三个配置文件(在都有的情况),后面加载的信息会覆盖前面加载的信息。
2.2 自动配置
SpringBoot的自动化配置是SpringBoot核心中的核心,本文档只会简单阐述,后面会专门出一篇自动化配置详解(基于源码讲解)。
Spring Boot在应用启动时根据添加的jar依赖自动配置Spring应用。也会根据项目中的依赖自动为你配置Spring容器。
3、示例
本次实例按照我们常用Web开发场景进行讲解。
开发软件:IDEA,Maven 工具。
开发技术:SpringBoot(Spring, Spring MVC),JDBC,MYSQL,Mybatis,Redis(缓存)
IDEA 下载地址:https://www.jetbrains.com.cn/idea/download/?section=windows
Maven 下载地址:https://maven.p2hp.com/
需求分析:简单开发一个用户的管理工具,包含基础的增删改查功能。
3.1 创建数据库/表
3.1.1 创建数据库
## 创建人员测试库
create database user_test_db;
## 切换数据库
use user_test_db;
3.1.2 创建数据表
## 创建数据表
create table d_user (
id int auto_increment primary key comment '主键id',
user_name varchar(50) not null comment '用户名',
age int default 0 comment '年龄',
gender tinyint default 0 comment '性别,0:未知,1:男性,2:女性',
update_time datetime default current_timestamp on update current_timestamp comment '更新时间',
create_time datetime default current_timestamp comment '创建时间'
)ENGINE=InnoDB comment='人员表';
3.1.3 新增测试数据
## 新增测试数据
insert into d_user (user_name, age, gender)
values
("张三丰", 28, 1),
("张无忌", 21, 1),
("范糯糯", 18, 2),
("李清", 21, 2);
3.2 创建项目
第一步:选择File,在选择New,在选择Project。
第二步:初始项目基本信息
第三步:选择要加入maven包
第四步:等待加载完成,项目检查,避免后期启动失败
保证项目结构完整:
保证配置了Maven仓库地址:
3.3 引入Maven包
<!-- web应用相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis相关 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.22</version>
</dependency>
<!-- mysql相关 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- springBoot测试类 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3.4 配置数据源(核心:连接数据库)
3.4.1 创建配置文件
注意:application.yml,application.yaml,application.properties 三个文件只需要一个就可以了。
application.yml/application.yaml 这两个文件出来后缀不一样,其他的都是一样的。
yml格式可以简单记忆:前缀相同的属性可以整合在一起,其子属性跨行+空格来书写,属性值采用 : + 空格 + 值的方式(还是不大明白的可查看yml官网)。
## 端口号
server:
port: 9090
## 数据源配置
spring:
## 项目名称
application:
name: SpringBoot_basic_demo
datasource:
## 数据库驱动
driver-class-name: com.mysql.cj.jdbc.Driver
## 数据库地址
url: jdbc:mysql://127.0.0.1:3306/user_test_db?characterEncoding=utf8&useSSL=false
## 用户名
username: root
## 密码
password: root
# 配置mybatis
mybatis:
#指定mapper.xml的位置
mapper-locations: mapper/**/*Mapper.xml
# 目录类型别名扫描,多个包之间采用 ; 号分割,注意:是英文的分号
typeAliasesPackage: com.test.springboot.**.pojo
configuration:
#开启驼峰命名法转换字段支持,用于对象关系绑定
map-underscore-to-camel-case: true
application.properties
## 项目名称
spring.application.name=SpringBoot_basic_demo
## 端口号
server.port=8080
## 数据源配置
## 数据库驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
## 数据库地址
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/user_test_db?characterEncoding=utf8&useSSL=false
## 用户名
spring.datasource.username=root
## 密码
spring.datasource.password=root
#指定mapper.xml的位置
mybatis.mapper-locations=mapper/**/*Mapper.xml
# 目录类型别名扫描,多个包之间采用 ; 号分割,注意:是英文的分号
mybatis.type-aliases-package=com.test.springboot.**.pojo
# #开启驼峰命名法转换字段支持,用于对象关系绑定
mybatis.configuration.map-underscore-to-camel-case=true
3.5 实体层
我们分析哈实体层需要做什么,先回顾哈需求(用户管理系统),那我们是不是需要创建一个用户类(User),那返回页面结果,我们是不是也需要在创建一个类来承接结果。
总结:1、创建用户类。2、创建结果类(可采用泛型)
3.5.1 用户实体
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
/**
* 主键id
*/
private Integer id;
/**
* 用户名
*/
private String userName;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private Integer gender;
/**
* 更新时间
*/
private Date updateTime;
/**
* 创建时间
*/
private Date createTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
}
2.5.2 结果实体
public class Response<T> {
/**
* 编码
*/
private Integer code;
/**
* 信息
*/
private String msg;
/**
* 数据
*/
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Response(Integer code, T data) {
this.code = code;
this.data = data;
}
public Response(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
3.5.3 传输实体
package com.test.springboot.core.dto;
public class UserVO {
/**
* 用户id
*/
private Integer id;
/**
* 用户名
*/
private String userName;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private String gender;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
/**
* 中文性别转换成数值性别
*
* @return 返回性别
*/
public Integer transferGender() {
if (gender == null || gender.length() < 1) {
// 未知
return 0;
}
if (gender.equals("男") || gender.equals("男性")) {
return 1;
}
if (gender.equals("女") || gender.equals("女性")) {
return 2;
}
return 0;
}
/**
* 验证信息
*
* @return 返回验证结果
*/
public boolean validate() {
if (userName == null || userName.length() < 1) {
return false;
}
if (age == null || gender == null) {
return false;
}
return true;
}
}
3.6 Mapper层
3.6.1 Mapper接口
主要存放操作d_user表数据的接口。
import com.test.springboot.core.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper {
/**
* 获取所有用户
*
* @return 返回用户列表
*/
List<User> findUser();
/**
* 根据用户id查询用户信息
* 注解方式
*
* @param id 用户id
* @return 返回用户信息
*/
@Select("select user_name, age, gender from d_user where id = #{id}")
User findUserId(@Param("id") Integer id);
/**
* 指定名称+年龄条件筛选
*
* @param name 姓名
* @param age 年龄
* @return 返回用户列表
*/
List<User> findUserOption(@Param("name") String name, @Param("age") Integer age);
/**
* 新增用户
*
* @param user 用户信息
*/
void saveUpdate(@Param("user") User user);
/**
* 移除用户
*
* @param id 主键id
*/
void removeUser(@Param("id") Integer id);
}
3.6.2 Mapper配置文件
创建userMapper.xml文件,放入resource目录中的mapper目录中,注意:mapper.xml配置文件存放路径只要在resource目录即可,本次我放在resource/mapper目录中,后期会统一配置在application.yml文件中,具体可查看application.yml./application.properties。
<?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.test.springboot.core.mapper.UserMapper">
<!--新增用户-->
<insert id="saveUpdate">
insert into d_user(id, user_name, age, gender)
values (#{user.id}, #{user.userName}, #{user.age}, #{user.gender})
ON DUPLICATE KEY UPDATE
user_name = values(user_name),
age = values(age),
gender = values(gender)
</insert>
<!--移除用户-->
<delete id="removeUser">
delete
from d_user
where id = #{id}
</delete>
<!--获取所有用户-->
<select id="findUser" resultType="com.test.springboot.core.pojo.User">
select id, user_name, age, gender
from d_user
</select>
<!--指定名称+年龄条件筛选-->
<select id="findUserOption" resultType="com.test.springboot.core.pojo.User">
select id, user_name, age, gender
from d_user
where user_name like concat('%', #{name}, '%')
and age = #{age}
</select>
</mapper>
3.7 业务层
主要创建基础业务得增删改查已经参数验证等。采用接口隔离原则。
3.7.1 业务接口层
import com.test.springboot.core.dto.UserVO;
import com.test.springboot.core.pojo.User;
import java.util.List;
public interface UserServie {
/**
* 获取所有用户
*
* @return 返回用户列表
*/
List<User> findUsers();
/**
* 根据姓名+年龄查询用户
*
* @param name 用户名
* @param age 年龄
* @return 返回用户列表
*/
List<User> findUserCondition(String name, Integer age) throws Exception;
/**
* 新增/更改用户
*
* @param user 用户信息
*/
void saveUpdate(UserVO user) throws Exception;
/**
* 移除用户
*
* @param id 用户id
*/
void removeUser(Integer id) throws Exception;
}
3.7.2 业务实现类
import com.test.springboot.core.dto.UserVO;
import com.test.springboot.core.mapper.UserMapper;
import com.test.springboot.core.pojo.User;
import com.test.springboot.core.service.UserServie;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserServie {
@Resource
private UserMapper userMapper;
@Override
public List<User> findUsers() {
return userMapper.findUser();
}
@Override
public List<User> findUserCondition(String name, Integer age) throws Exception {
if (name == null || name.length() < 1 || age == null) {
throw new Exception("参数为空");
}
return userMapper.findUserOption(name, age);
}
@Override
public void saveUpdate(UserVO user) throws Exception {
if (!user.validate()) {
throw new Exception("参数核验失败");
}
// 实例化用户对象
User userPo = new User();
// 属性赋值
BeanUtils.copyProperties(user, userPo);
// 性别中文转数值
userPo.setGender(user.transferGender());
// 更新/保存信息,这里会根据对象的 id 值来自动判断新增还是更新
userMapper.saveUpdate(userPo);
}
@Override
public void removeUser(Integer id) throws Exception {
if (id == null) {
throw new Exception("参数为空");
}
// 查询用户信息
User user = userMapper.findUserId(id);
if (user == null) {
throw new Exception("删除失败。");
}
userMapper.removeUser(id);
}
}
3.8 控制层
import com.test.springboot.core.dto.UserVO;
import com.test.springboot.core.pojo.Response;
import com.test.springboot.core.pojo.User;
import com.test.springboot.core.service.UserServie;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/user")
public class UserController {
@Resource
private UserServie userServie;
/**
* 全量用户
*
* @return 返回用户列表
*/
@GetMapping("list")
public Response userList() {
return new Response(200, userServie.findUsers());
}
/**
* 筛选用户
*
* @param userName 用户名
* @param age 年龄
* @return 返回用户列表
* @throws Exception 异常
*/
@GetMapping("/choose")
public Response userOption(String userName, Integer age) throws Exception {
return new Response(200, userServie.findUserCondition(userName, age));
}
/**
* 新增用户
*
* @param user 用户信息
* @return 返回执行结果
* @throws Exception 异常
*/
@PostMapping("saveUpdate")
public Response insertUser(@RequestBody UserVO user) throws Exception {
userServie.saveUpdate(user);
return new Response(200, "success");
}
/**
* 移除用户
*
* @param user 用户信息
* @return 返回执行结果
* @throws Exception 异常
*/
@PostMapping("remove")
public Response deleteUser(@RequestBody UserVO user) throws Exception {
if (user == null) {
throw new Exception("参数为空");
}
userServie.removeUser(user.getId());
return new Response(200, "success");
}
}
3.9 测试
3.9.1 测试工具(Apipost)
下载地址:Apipost-API 文档、设计、调试、自动化测试一体化协作平台
3.9.2 初始化各接口
接口 | 描述 | 请求类型 | 参数 |
/api/user/list | 用户列表 | GET | 无 |
/api/user/choose | 用户筛选列表 | GET | userName=xxx&age=xxx |
/api/user/saveUpdate | 新增/更改用户信息 | POST | { "id": 用户id, "userName": "用户名", "age": 年龄, "gender": "性别" } |
/api/user/remove | 移除用户 | POST | { "id": 用户id } |
3.9.3 用户列表接口测试
数据库数据:
接口测试数据:
结论:符合
3.9.4 新增用户信息
数据库数据:
接口测试:
结论:符合。
3.9.5 更改用户信息
数据库数据:我们修改《李斯》这一条数据。
接口测试:
3.9.6 移除用户信息
数据库数据:
接口测试:
结论:符合。
4、总结
看到这里SpringBoot入门就基本结束了,里面有些知识点并未详解(篇幅有限),例如:maven,yml文件,注解等都没详细说明,后续有时间在整理哈相关知识,再放入本文档中。在这祝大家在学习路上越战越勇,保持初心,技有所成。
题外话,本次测试demo其实还有优化的地方,我放到下面整理出来,大家可以根据下面的思路进行修改源码。
1、用户全量列表需要分页来提升性能,获取一次性全量表数据会对整个数据库是致命的,常见的问题,IO飙升,性能降低,负载增加等等(一千万的数据表,生产环境很正常)。
2、接口未授权,容易被攻击,且数据泄露等安全问题。
3、经常查询数据未缓存,降低对数据库的访问,提升性能。
4、设置全局异常处理器统一处理异常信息。
标签:return,SpringBoot,age,public,user,Integer,id,入门 From: https://blog.csdn.net/2401_85207246/article/details/144446832