1. SpringBoot简介


1.1 SpringBoot是什么

SpringBoot不是什么新的框架,它仅仅对众多框架做好了默认的配置。 SpringBoot可以简化配置。


1.2 SpringBoot主要特性

a. 可以创建独立的spring应用(spring-boot-starter-web依赖中有内置的tomcat)

b. 提供“starter”依赖以简化应用的依赖配置

c. 自动配置

d. 不需要xml配置


1.3 SpringBoot版本统一

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.7.12</version>

</parent>


2. SpringBoot HelloWorld


2.1 编写HelloWorld案例

创建Maven项目

1.  SpringBoot基础篇_spring



编写pom.xml

<?xml versinotallow="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:schemaLocatinotallow="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>


<groupId>com.gao</groupId>

<artifactId>learn-springboot</artifactId>

<version>1.0-SNAPSHOT</version>


<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.7.12</version>

</parent>


<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</dependency>

</dependencies>


</project>


创建HelloController

package com.gao.web.controller;


import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;


@RestController

@RequestMapping("hello")

public class HelloController {

@RequestMapping("f1")

public String f1() {

return "hello,springboot";

}

}

创建启动类

package com.gao;


import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication

public class App {

public static void main(String[] args) {

SpringApplication.run(App.class, args);

}

}


注意,启动类必须创建在其他包的根目录下:

1.  SpringBoot基础篇_xml_02



启动应用,并访问hello/f1端点:

1.  SpringBoot基础篇_maven_03



在resources下创建static目录,在其中创建index.html页面:

<!doctype html>

<html lang="en">

<head>

<title>index</title>

<meta charset="utf-8">

</head>

<body>

<h3>index.html</h3>


飞雪连天射白鹿

笑书神侠倚碧鸳

</body>

</html>


访问index.html页面

1.  SpringBoot基础篇_xml_04



2.2 简单复盘HelloWorld案例

1. spring-boot-starter-parent的作用:

1.  SpringBoot基础篇_maven_05



2. spring-boot-starter-web的2个作用

只要引入了spring-boot-starter-web这个依赖,springboot就会自动搭建springmvc的环境,比如前端控制器、映射器、适配器、视图解析器等等

☐ 引入了一套依赖

a. spring-boot-starter

b. spring-boot-starter-json

c. spring-boot-starter-tomcat(内嵌tomcat)

d. spring-web

e. spring-webmvc

在spring-boot-starter中,又引入了spring-boot-autoconfigure,恰恰是这个依赖,完成了自动配置的功能。


3. 关于 starter依赖 的命名

一个springboot官方的starter依赖,看起来是这个样子:spring-boot-starter-xxx

一个第三方的(或自定义的)starter依赖,看起来是这个样子: xxx-spring-boot-starter


4. 扫描包

@SpringBootApplication注解会自动扫描当前类所在的包及其子包。


5. 在引入了spring-boot-starter-web依赖后,springboot就会自动搭建spring-webmvc环境,此web环境的静态资源路径可以设置如下:

1.  SpringBoot基础篇_xml_06



访问静态资源:

1.  SpringBoot基础篇_xml_07



2.3 打包SpringBoot HelloWorld应用

直接打包SpringBoot应用,然后在控制台上运行jar文件,会发现提示“没有主清单属性”

1.  SpringBoot基础篇_maven_08


这是因为在打包好的jar中,并没有指定主类。


为了在打包jar的同时,指定主类,需要在pom.xml中加入以下插件

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

也可以自己手动指定启动类的位置:

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<mainClass>com.gao.App</mainClass>

</configuration>

</plugin>

</plugins>

</build>

3.HelloWorld配置文件


我们已经感受到了SpringBoot的威力,正是它的自动配置,以至于我们不用写任何配置内容!不过要注意的是,SpringBoot帮我们完成了配置工作,是它很“主观”地配置,但是有些时候,我们需要自己定制配置,此时就需要编写SpringBoot的配置文件了。

3.1 application.yml

在项目的src/main/resources/下创建application.yml,并配置内置tomcat的端口为8888

server:

port: 8888


3.2 配置文件的名字和位置

配置文件的名字可以是(按优先级降序排列):

a. application.properties

b. application.yml


配置文件的位置(按优先级降序排列):

file: /config

file:

classpath(resources): /config

classpath(resources):


定制配置文件的名字和位置

java -jar learn-springboot.jar --spring.config.locatinotallow=D:\myconfig.yml


默认情况下,--spring.config.location的取值如下:

java -jar learn-springboot.jar --spring.config.locatinotallow=.\application.yml


3.2 加载配置文件中的数据

有User类如下

@Component

@ConfigurationProperties(prefix = "customize.myconfig")

@Data

public class MyConfig {

private Integer num;

private String url;

private Date birthday;

private Double money;

private String[] hobbies;

}

application.yml

server:

port: 8888


customize:

myconfig:

num: 100

url: http://localhost:8765

birthday: 2020/12/22 02:22:22

money: 27000.5

hobbies:

- Game

- Film

- Programming


UserController

@RestController

@RequestMapping("hello")

public class HelloController {


@Autowired

private MyConfig myConfig;


@RequestMapping("f1")

public MyConfig f1() {

return myConfig;

}

}

访问

1.  SpringBoot基础篇_maven_09



3.3 application.yml中提示自定义的属性

添加以下依赖即可

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-configuration-processor</artifactId>

</dependency>

3.4 @EanbleConfigurationProperties

若我们把MyConfig类上的@Component注解去掉,此时在HelloController中,就无法注入MyConfig的对象了。


而我们可以在HelloController上添加一个注解:@EnableConfigurationProperties,这样就仍然能在HelloController中注入MyConfig对象了,相关代码如下:


MyConfig类,注意去掉了@Component注解

@ConfigurationProperties(prefix = "customize.myconfig")

@Data

public class MyConfig {

private Integer num;

private String url;

private Date birthday;

private Double money;

private String[] hobbies;

}

HelloController类,注意加上了@EnableConfigurationProperties注解

@RestController

@RequestMapping("hello")

@EnableConfigurationProperties(MyConfig.class)

public class HelloController {

@Autowired

private MyConfig myConfig;

@RequestMapping("f1")

public MyConfig f1() {

return myConfig;

}

}

注意:

使用了@EnableConfigurationProperties(MyConfig.class)之后,就必须为MyConfig类的对象使用@ConfigurationProperties(prefix = "...") 注解,否则会报错!


测试:

1.  SpringBoot基础篇_maven_10



使用@EnableConfigurationProperties注解的价值何在呢?

☐ 由MyConfig的使用者HelloController来决定是否需要将MyConfig对象存入IOC容器中。如果HelloController不再需要MyConfig对象来加载配置了,则可以把HelloController类上的@EnableConfigurationProperties(MyConfig.class)注解去掉

☐ 如果在MyConfig类上添加@Component注解,则无论HelloController是否需要MyConfig的实例来加载相关配置,MyConfig的实例总是会存入IOC容器中


3.5 第三方配置

我们可以自由地编辑User类的代码,比如在MyConfig类上添加@ConfigurationProperties注解:

@ConfigurationProperties(prefix = "customize.myconfig")

@Data

public class MyConfig {

private Integer num;

private String url;

private Date birthday;

private Double money;

private String[] hobbies;

}


但是对于一些在我们控制之外的类,我们是无法直接在其上添加@ConfigurationProperties注解的,比如第三方类库中的类。因为我们手头没有第三方类库中的源代码!


@ConfigurationProperties除了可以使用在类上,也可以使用在被@Bean注解的public method上,这样就可以将application.yml中的属性绑定到第三方类库中的组件上了。以下假设MyConfig就是一个第三方类库中的类,代码看起来是这个样子:

@Configuration

public class RootConfig {

@Bean

@ConfigurationProperties(prefix = "customize.myconfig")

public MyConfig u() {

return new MyConfig();

}

}


4. 热启动


4.1 热启动配置

引入spring-boot-devtools依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-devtools</artifactId>

当前这个项目被继承后,该依赖不会向下传递 -->

<optional>true</optional>

</dependency>

同时添加以下Maven插件以让devtools生效

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

如果没有该配置,则devtools不会生效 -->

</configuration>

</plugin>

4.2 热启动的基本原理

SpringBoot提供的热启动技术,主要是依靠于两个类加载器:base classloader和restart classloader

base classloader用于加载那些不会发生变化的class,比如第三方类库,而restart classloader则用于加载那些你正在开发中的class。

每当你修改了你的java源代码,且按下快捷键ctrl+f9,idea就会进行热启动,此时当前正在使用当中的restart classloader就会被丢弃,并且一个新的restart classloader会被创建出来以加载你的修改。这种方式显然比“冷启动”要快很多,毕竟base classloader是不用重新创建的。


5. yaml中的profile

application-dev.yml

server:

port: 8081


application-pro.yml

server:

port: 8082


application.yml

spring:

profiles:

active: pro


注意:

1. 可以在运行SpringBoot的应用时,加上参数-Dspring.profiles.active=dev,来指定使用哪个环境下的配置文件。

2. 可以在运行SpringBoot的应用时,指定属性的值,比如:-Dserver.port=8083

1.  SpringBoot基础篇_maven_11




6. 使用SpringBoot搭建SSM环境


6.1 创建Maven项目

1.  SpringBoot基础篇_maven_12



6.2 pom.xml

<?xml versinotallow="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:schemaLocatinotallow="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>


<groupId>com.gao</groupId>

<artifactId>springboot-ssm</artifactId>

<version>1.0-SNAPSHOT</version>


<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.7.12</version>

</parent>


<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-aop</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jdbc</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>2.1.4</version>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>8.0.31</version>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.generator</groupId>

<artifactId>mybatis-generator-core</artifactId>

<version>1.3.2</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-configuration-processor</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-devtools</artifactId>

当前这个项目被继承后,该依赖不会向下传递 -->

<optional>true</optional>

</dependency>

</dependencies>


<build>

<resources>

<resource>

<directory>${basedir}/src/main/java</directory>

<includes>

<include>**/*.xml</include>

</includes>

</resource>

</resources>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<fork>true</fork>

如果没有该配置,则devtools不会生效 -->

</configuration>

</plugin>

</plugins>

</build>


</project>


6.3 建库建表

DROP DATABASE IF EXISTS test;


CREATE DATABASE test;


USE test;


CREATE TABLE USER

(

id INT PRIMARY KEY AUTO_INCREMENT,

NAME VARCHAR(20),

birthday DATE,

balance DECIMAL(10,2)

);


6.4 Mybatis逆向工程配置文件

在src/test/resources/mybatis目录下,创建generatorConfig.xml配置文件

<?xml versinotallow="1.0" encoding="UTF-8"?>

<!DOCTYPE generatorConfiguration

PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"

"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">


<generatorConfiguration>

<context id="ctx1">

配置pojo的序列化 -->

<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />


<commentGenerator>

是否去除自动生成的注释 true:是 : false:否 -->

<property name="suppressAllComments" value="true" />

</commentGenerator>

数据库连接的信息:驱动类、连接地址、用户名、密码,这里配置的是mysql的,当然也可以配置oracle等数据库 -->

<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"

cnotallow="jdbc:mysql://localhost:3306/test?serverTimeznotallow=Asia/Shanghai"

userId="root"

password="123">

<!--

在MySQL 8.0 以上的版本中,在生成 User 表的实体类时,Mybatis Generator 会找到多张 User表,

包括 MySQL information schemas 中的多张 User 表,生成了多个 User 相关的实体类。

添加以下配置,保证只生成自己需要的 User类

-->

<property name="nullCatalogMeansCurrent" value="true"/>

</jdbcConnection>


默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL

和 NUMERIC 类型解析为java.math.BigDecimal -->

<javaTypeResolver>

<property name="forceBigDecimals" value="false" />

</javaTypeResolver>


生成PO类的位置 -->

<javaModelGenerator targetPackage="com.gao.entity"

targetProject="./src/main/java">

是否让schema作为包的后缀 -->

<property name="enableSubPackages" value="false" />

从数据库返回的值被清理前后的空格 -->

<property name="trimStrings" value="true" />

</javaModelGenerator>

映射文件生成的位置 -->

<sqlMapGenerator targetPackage="com.gao.mapper"

targetProject="./src/main/java">

是否让schema作为包的后缀 -->

<property name="enableSubPackages" value="false" />

</sqlMapGenerator>

:mapper接口生成的位置 -->

<javaClientGenerator type="XMLMAPPER"

targetPackage="com.gao.mapper" targetProject="./src/main/java">

是否让schema作为包的后缀 -->

<property name="enableSubPackages" value="false" />

</javaClientGenerator>

指定数据库表 -->

<table tableName="user"></table>

</context>

</generatorConfiguration>


6.5 逆向工程实施代码

在src/test/java目录下,创建com.gao.test.GeneratorSqlmap类

package com.gao.test;


import org.mybatis.generator.api.MyBatisGenerator;

import org.mybatis.generator.config.Configuration;

import org.mybatis.generator.config.xml.ConfigurationParser;

import org.mybatis.generator.internal.DefaultShellCallback;


import java.io.File;

import java.util.ArrayList;

import java.util.List;


/**

* @author gao

* @time 2022/04/30 22:40:20

*/

public class GeneratorSqlmap {

public void generator() throws Exception {

List<String> warnings = new ArrayList<String>();

boolean overwrite = true;

指定Mybatis逆向工程配置文件的位置

File configFile = new File("src/test/resources/mybatis/generatorConfig.xml");

ConfigurationParser cp = new ConfigurationParser(warnings);

Configuration config = cp.parseConfiguration(configFile);

DefaultShellCallback callback = new DefaultShellCallback(overwrite);

MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);

myBatisGenerator.generate(null);


System.out.println("over");

}


public static void main(String[] args) throws Exception {

try {

GeneratorSqlmap t = new GeneratorSqlmap();

t.generator();

} catch (Exception e) {

e.printStackTrace();

}

}

}


6.6 执行Mybatis逆向工程实施代码

此时会生成UserMapper、UserMapper.xml、User、UserExample

1.  SpringBoot基础篇_xml_13



修改UserMapper.xml中的两个insert配置,让insert语句能够返回新生成的主键值

<insert id="insert" parameterType="com.gao.entity.User"

useGeneratedKeys="true" keyProperty="id" >

...

</insert>

<insert id="insertSelective" parameterType="com.gao.entity.User"

useGeneratedKeys="true" keyProperty="id" >

...

</insert>


6.7 创建UserService、UserServiceImpl

public interface UserService {

User save(User user);

}


@Service

@Transactional

public class UserServiceImpl implements UserService {

@Autowired

private UserMapper mapper;


@Override

public User save(User user) {

mapper.insert(user);

return user;

}

}


6.8 创建ResultVo

@Data

@AllArgsConstructor

@NoArgsConstructor

public class ResultVo {

private Integer code;

private String msg;

private Object data;


public static ResultVo success(String msg) {

ResultVo success = new ResultVo();

success.setCode(HttpStatus.OK.value());

success.setMsg(msg);

return success;

}


public static ResultVo success(Object data) {

ResultVo success = new ResultVo();

success.setCode(HttpStatus.OK.value());

success.setMsg("success");

success.setData(data);

return success;

}


public static ResultVo success() {

ResultVo success = new ResultVo();

success.setCode(HttpStatus.OK.value());

success.setMsg("success");

return success;

}


public static ResultVo success(String msg, Object data) {

ResultVo success = new ResultVo();

success.setCode(HttpStatus.OK.value());

success.setMsg(msg);

success.setData(data);

return success;

}


public static ResultVo failure() {

ResultVo failure = new ResultVo();

failure.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());

failure.setMsg("failure");

return failure;

}


public static ResultVo failure(String msg) {

ResultVo failure = new ResultVo();

failure.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());

failure.setMsg(msg);

return failure;

}


public static ResultVo failure(Object data) {

ResultVo failure = new ResultVo();

failure.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());

failure.setMsg("failure");

failure.setData(data);

return failure;

}


public static ResultVo failure(String msg, Object data) {

ResultVo failure = new ResultVo();

failure.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());

failure.setMsg(msg);

failure.setData(data);

return failure;

}

}


6.9 创建UserController

@RestController

@RequestMapping("user")

public class UserController {


@Autowired

private UserService service;


@PostMapping("save")

public ResultVo save(@RequestBody User user) {

System.out.println("user = " + user);

user = service.save(user);

return ResultVo.success("save ok", user);

}

}


6.10 创建启动类

@SpringBootApplication

@MapperScan("com.gao.mapper")

public class App {

public static void main(String[] args) {

SpringApplication.run(App.class, args);

}

}


6.11 SpringBoot配置文件

server:

port: 8080


spring:

datasource:

url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&serverTimeznotallow=Asia/Shanghai

driver-class-name: com.mysql.cj.jdbc.Driver

username: root

password: 123


mybatis:

type-aliases-package: com.gao.entity

此时可以测试了。


6.12 使用Druid数据源

SpringBoot默认使用的是Hikari数据源,我们也可以将其替换为Druid数据源


6.12.1 引入Druid依赖

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.2.4</version>

</dependency>


6.12.2 修改pom.xml

server:

port: 8080


spring:

datasource:

url: jdbc:mysql:///test?serverTimeznotallow=UTC

driver-class-name: com.mysql.cj.jdbc.Driver

username: root

password: 123

type: com.alibaba.druid.pool.DruidDataSource


mybatis:

type-aliases-package: com.gao.entity


7. PostMan的使用

1.  SpringBoot基础篇_xml_14