AngeldayAngelday
Home
  • Java
  • MySQL
  • Maven
  • Spring
  • SpringMVC
  • SpringBoot
  • Mybatis-Plus
  • SpringCloud
  • Redis
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • VBA
  • CentOS
  • ApachePOI
  • 摄影
  • Photoshop
  • Premiere
  • Lightroom
  • Game
Home
  • Java
  • MySQL
  • Maven
  • Spring
  • SpringMVC
  • SpringBoot
  • Mybatis-Plus
  • SpringCloud
  • Redis
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • VBA
  • CentOS
  • ApachePOI
  • 摄影
  • Photoshop
  • Premiere
  • Lightroom
  • Game
  • Springboot

Springboot

SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程

快速使用

第一步:创建新模块

想要创建Spring boot程序则需要选择Spring Initializr

第二步:选择需要的技术集

由于我们开发的是Web项目,所以需要选择Spring Web技术

第三步:开发控制类

@RestController
@RequestMapping("/user")
public class UserController {
    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id) {
        System.out.println("Hello Spring boot" + id);
        return "Hello Spring boot";
    }
}

第四步:运行Application类

看到控制台输出以下内容,表示程序启动成功

通过这个入门案例,可以发现省去了很多配置操作,十分简化了项目的初始搭建。

快速启动

Spring boot还提供了快速启动方案,不需要安装任何软件,只需要拥有对应版本的Java,就可以运行。

首先开发人员对Spring boot项目打包 (执行Maven构建指令package) 其他人员就可以通过命令行窗口使用java -jar bootProjectName.jar就可以运行程序。

YML配置文件格式

三种文件格式:

  • application.properties
  • application.yml
  • application.yaml

优先级: .properties > .yml > .yaml

以后主要使用yml 格式的配置文件

YML(或YAML,即YAML Ain't Markup Language) 是一种常用的数据序列化格式,特别适合用于配置文件的编写。它采用一种易于人类阅读和编写的方式,同时允许简单的数据表示。

基本语法:

  1. 大小写敏感
  2. 数值前必须有空格作为分隔符
  3. 使用缩进表示层级,不允许使用Tab缩进,只能使用Space(一般使用2个或4个)
  4. 空格的数量不重要,只需要保证同级元素左侧对齐即可
  5. 井号表示注释,注释当前行

数据格式

  1. 使用冒号分割键和值,如:
person:  
  name: John Doe  
  age: 30  
  city: New York
  1. 数组(列表):使用短横线表示列表项,每个列表项占一行,如:
hobbies:  
  - reading  
  - sports  
  - movies  
# 或者行内写法  
hobbies: [reading, sports, movies]
  1. 字符串
    • 普通字符串:直接书写,不需要引号。
    • 双引号字符串:不会转义字符串中的特殊字符。
    • 单引号字符串:会转义字符串中的特殊字符。
  2. 多行字符串
    • 保留换行符的多行字符串:使用 “ | ”,如:
description: |  
  This is a multi-line  
  string with newlines preserved.
* 折叠换行的多行字符串:使用 > 如:
poem: >  
  Roses are red,  
  violets are blue.  
  Sugar is sweet,  
  and so are you.

实际案例

# 配置当前服务器的相关信息
server:
 port: 8080
 address: 127.0.0.1
# 配置数据源
spring:
 datasource:
  type: com.alibaba.druid.pool.DruidDataSource
  driverClassName: com.mysql.cj.jdbc.Driver
  druid:
   # 主库数据源
   master:
   url: jdbc:mysql://localhost:3306/dataBase
   username: root
   password: root

读取方式

  1. 方式一 在类中建立对应的私有的成员变量 再使用@Value注解标注内容 如:
lesson: "张三"
@Value("@{lesson}")
private String name;
  1. 方式二 或者使用自动装配,通过get()方法获取
@Autowired
private Environment environment;
  1. 方式三 再或者我们建立对应的一个实体类 首先将这个实体类声明为一个Bean,再使用@ConfigurationProperties()来进行接收。

多环境配置

在实际开发时,我们每个生产流程都会需要改变配置信息,所以我们可以设置多个环境,根据需求再进行切换 如:生产环境、开发环境、测试环境

只需要在 yml 文件中,不同的环境之间添加三个横线 ---

# 设置启动的环境
spring:
  profiles:
    active: dev

---
# 生产环境
spring:
  profiles: pro

server:
  port: 8081
---
# 开发环境
spring:
  profiles: dev

server:
  port: 8082
---
# 测试环境
spring:
  profiles: test

server:
  port: 8083

后续在使用jar包时,可以直接在命令行中输入

java -jar springbootName.jar --spring.profiles.active=dev
java -jar springbootName.jar --spring.profiles.active=pro
java -jar springbootName.jar --spring.profiles.active=test

与Maven的环境兼容

如果我们的yml配置文件中默认环境为dev,而maven中默认为pro。 则通过命令行启动jar包时,默认启动maven默认的pro

所以yml的默认环境,尽量写成从pom中读取的属性

<!--Maven中设置多环境属性-->
<profiles>
    <profile>
        <id>dev env</id>
        <properties>
        	<profile.active>dev</profile.active>
        </properties>
        <activation>
        	<activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>pro env</id>
        <properties>
        	<profile.active>pro</profile.active>
        </properties>
    </profile>
    <profile>
        <id>test env</id>
        <properties>
        	<profile.active>test</profile.active>
        </properties>
    </profile>
</profiles>
# SpringBoot中引用Maven属性
spring:
  profiles:
    active: ${profile.active}

---
spring:
  profiles: pro
server:
  port: 8081
---
spring:
  profiles: dev
server:
  port: 8082
---
spring:
  profiles: test
server:
  port: 8083

对资源文件开启对默认占位符解析

<build>
    <plugins>
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <configuration>
                <encoding>utf-8</encoding>
                <useDefaultDelimiters>true</useDefaultDelimiters>
            </configuration>
        </plugin>
    </plugins>
</build>

整合Mybatis

第一步:创建工程

这里仍然选择选择Spring Initializr

第二步:选择技术集

我们整合Mybatis,所以一定需要导入Mybatis的框架。 我们使用的数据库是MySQL,所以也要导入MySQL的依赖

第三步:创建实体类

假设我们数据库中拥有一个User的用户表,表结构如下

用户表user

字段名数据类型描述约束
idint主键主键、自增
namevarchar(5)姓名
phonevarchar(11)手机号
sexvarchar(2)性别

则我们应该创建如下的实体类

用户User

public class User {  
    private Long id;  
    private String name;  
    private String phone;  
    private String sex;  

    //setter & getter & toString
}

第四步:连接数据库

通过配置yml配置文件,来连接数据库

# 配置服务端口
server:
  port: 8080

# 配置数据源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/store
    username: root
    password: 123456
    # 如果要使用druid数据源则加上:
    type: com.alibaba.druid.pool.DruidDataSource

第五步:创建数据层

在Application引导类的同级下创建一个新目录 mapper ,并创建一个 UserMapper 接口

//注意不能缺少这个注解
@Mapper
public interface UserMapper {

    /**
     * 查询用户
     * @param id
     * @return
     */
    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectById(Long id);
}

测试

此时就可以在Springboot提供的SpringbootTest中进行测试

@SpringBootTest
class UserApplicationTests {

  @Autowired
  private UserMapper userMappper;

  @Test
  void test(){

      User user = userMapper.selectById(1);

      System.out.println(user);
  }
}

开发全流程

引言

目前绝大多数的增删改查网站都是基于 Springboot + mybatis 进行开发 本文以此技术栈进行一个企业级全流程的功能模块的开发

需求分析

这是极为关键的一步,要与需求方深入沟通交流,详细收集、梳理、分析项目需要实现的各种功能和业务要求。例如,明确用户使用系统时的操作流程、期望得到的数据展示形式、不同功能模块之间的关联等,最终形成清晰准确的需求文档,作为后续开发工作的重要依据。

此处我们模拟一个简单的管理用户信息的模块。

管理员可以对用户信息进行增删改查。

数据库定义

基于需求分析的结果,来确定数据库的结构和相关设置。包括选择合适的数据库管理系统(如 MySQL、Oracle、SQL Server 等),设计数据表的结构,定义各表中的字段及其数据类型、约束条件(如主键、外键、非空约束等),同时考虑数据库的存储容量规划、性能优化等方面,确保后续数据的高效存储、查询与管理。

此处我们使用 MySQL 数据库,并且创建出以下表结构:User

字段名类型描述约束
idint唯一标识符主键自增
usernamevarchar(50)账号非空,唯一
passwordvarchar(100)密码非空
namevarchar(10)用户姓名非空
phonevarchar(20)手机号非空、唯一
addressvarchar(50)用户地址非空
create_timedatetime创建时间非空
update_timedatetime修改时间非空

其对应的SQL语句为:

CREATE TABLE `user` (
    `id` int AUTO_INCREMENT PRIMARY KEY,
    `username` varchar(50) NOT NULL UNIQUE,
    `password` varchar(100) NOT NULL,
    `name` varchar(10) NOT NULL,
    `phone` varchar(20) NOT NULL UNIQUE,
    `address` varchar(50) NOT NULL,
    `create_time` datetime NOT NULL,
    `update_time` datetime NOT NULL
);

定义接口

对外需要定义好项目与外部系统交互的接口,比如提供给第三方应用调用的 API 接口,明确接口的请求方式(如 GET、POST 等)、请求参数格式、返回数据格式等内容

依照SpringMVC中的REST风格,定义以下接口:

  • http://localhost/users 查询全部用户信息 GET(查询)
  • http://localhost/users/1 查询指定用户信息 GET(查询)
  • http://localhost/users 添加用户信息 POST(新增/保存)
  • http://localhost/users 修改用户信息 PUT(修改/更新)
  • http://localhost/users/1 删除用户信息 DELETE(删除)

建议用以下格式都写出来,此处就以此为例

选择工具

我们在Win10系统上,使用IDEA开发工具开发。

  1. 操作系统:Windows 10 X 64
  2. Java开发包:JDK 21
  3. 项目管理工具:Maven 3.6.3
  4. 项目开发工具:IntelliJ IDEA 2021.1.3 x64
  5. 数据库:Mysql
  6. 浏览器:Edge
  7. 服务器架构:Spring Boot 3.3.3 + MyBatis 3.0.3 + Mysql Driver 8.3.0

为了简化开发,我们使用到 Lombok 1.18.34

创建项目

此处我们采用分模块的方式创建工程 分模块的好处在Maven篇中已讲,此处不再赘述。

我们的工程Store中由三个模块构成

  • store-common //存放公共的常量、异常、统一结果、工具包等
  • store-pojo //存放实体类
  • store-server //存放主要业务

如图所示:

连接数据库,创建实体类

server:
  port: 8080 # 配置应用程序所监听的端口号,这里设置为8080
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/store?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: yourPassword


mybatis:
  # 指定MyBatis的映射文件(Mapper XML文件)所在的位置,这里表示在类路径下的'mapper'.
  mapper-locations: classpath:mapper/*.xml
  # 设置MyBatis的类型别名所在的包名,通过配置这个包名,MyBatis可以自动扫描该包下的实体类,并创建对应的类型别名。
  type-aliases-package: com.store.entity
  configuration:
    # 设置MyBatis在将数据库列名(通常是下划线命名风格,如 'user_name')映射到Java实体类的属性名(通常是驼峰命名风格,如 'userName')时,自动进行转换。
    map-underscore-to-camel-case: true

我们实体类放到store-pojo包下的entity中

//使用Lombok生成setter&getter&toString
@Data
public class User{
  private Long id;
  private String username;
  private String password;
  private String name;
  private String phone;
  private String address;
  private LocalDateTime createTime;
  private LocalDateTime updateTime;
}

数据层

  • 我们应该遵循:数据库 -> 持久层 -> 业务层 -> 表现层 -> 前端页面 这样的顺序进行开发。
  • 功能上,我们应该先做基础功能,并遵循 增 -> 查 -> 删 -> 改的顺序来开发。

首先来新增一个用户,那么他对应的SQL语句应该是:

INSERT INTO `user` (`username`, `password`, `name`, `phone`, `address`, `create_time`, `update_time`)
VALUES ('test_user', 'hashed_password', '张三', '13812345678', '北京市朝阳区', '2024-12-20 10:00:00', '2024-12-20 10:00:00');

我们在store-service包下创建出mapper.UserMapper接口

package com.store.mapper;

import com.store.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {

    @Insert("INSERT INTO user (username,password,name,phone,address,create_time,update_time)" +
            "VALUES (#{username},#{password},#{name},#{phone},#{address},#{createTime},#{updateTime})")
    void addUser(User user);
}

也可以在resources包下创建一个包mapper用作UserMapper接口的映射文件

@Mapper
public interface UserMapper {

    void addUser(User user);
}
<?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.angelday.mapper.UserMapper">
    <!--id为对应接口的方法名,useGennerateadKeys开启自增,keyProperty指明自增字段-->
    <insert id="addUser" useGeneratedKeys="true" keyProperty="uid">
        INSERT INTO user (username,password,name,phone,address,create_time,update_time)" +
        "VALUES (#{username},#{password},#{name},#{phone},#{address},#{createTime},#{updateTime})
    </insert>
</mapper>

注意:使用映射文件必须在配置文件中指定扫描路径

mybatis:
 mapper-locations: classpath:mapper/*.xml

测试: 做完持久层之后我们要利用Springboot提供的SpringBootTest进行测试,测试一定不要省略,这样可以减小问题的范围。

@SpringBootTest
class StoreApplicationTests {

    @Autowired
    private UserMapper userMapper

    @Test
    void userMapperTest(){
    	User user = new User();
    	user.setUsername("Zhangsan");
    	user.setPassword("123456");
    	user.setSex(1);//一般都是规定1是男0是女
    	user.setPhone("12332112321");
    	
    	addUser(User user);
    }
}

业务层

根目录下创建service.UserService接口

/**
 * 用户模块
 */
public interface UserService {
	/**
   * 添加用户信息
   * @param user
   */
  void addUser(User user);
}

创建改接口的实现类service.impl.UserServiceImpl

@Service
public class UserServiceImpl implements UserService {
  
  @Autowired
  private UserMapper userMapper;

  /**
   * 添加用户信息
   * @param user
   */
  @Override
  public void add(User user) {
      user.setCreateTime(LocalDateTime.now());
      userMapper.addUser(user);
  }
}

编写完后一定要进行单元测试。

表现层

首先在开发前,我们前面规定了统一结果类,此处就在store-commen下创建result.Result类

@Data
public class Result<T> {

    private Integer code;
    private String msg;
    private T data;


    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 200;
        return result;
    }

    public static <T> Result<T> success(T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.code = 200;
        return result;
    }

    public static <T> Result<T> error(String msg) {
        Result result = new Result();
        result.msg = msg;
        result.code = 0;
        return result;
    }
}

根据前面定义好的接口,该模块的路径都在http://localhost/users下

创建出controller.UserController类

@RestController
@RequestMapping("users")
public class UserController{

    @Autowired
    private UserService userService;

    /**
     * 用户注册
     * @param user 表单内的注册信息
     * @return 返回成功状态码
     */
    @PostMapping()
    public Result addUser(@RequestBody User user){
        userService.addUser(user);
        /* 统一结果类 */
        return Result.success();
    }
}

前后端联调

作为后端人员,我们可以使用PostMan工具进行接口测试

localhost:8080/users

请求体中:

{
    "username": "test_user",
    "password": "test_password",
    "name": "张三",
    "phone": "13812345678",
    "address": "北京市朝阳区"
}

如果数据库中成功添加,则此模块开发完成。

优化

本文并没有规划异常,严格来讲应该按照SpringMVC中划分出异常,并集中处理

文中的200状态码,已字面值的形式写死,严格来讲应该在store-common包下创建出常量类,统一存放提前规划好的常量。