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项目
编写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);
}
}
注意,启动类必须创建在其他包的根目录下:
启动应用,并访问hello/f1端点:
在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页面
2.2 简单复盘HelloWorld案例
1. spring-boot-starter-parent的作用:
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环境的静态资源路径可以设置如下:
访问静态资源:
2.3 打包SpringBoot HelloWorld应用
直接打包SpringBoot应用,然后在控制台上运行jar文件,会发现提示“没有主清单属性”
这是因为在打包好的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;
}
}
访问
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 = "...") 注解,否则会报错!
测试:
使用@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
6. 使用SpringBoot搭建SSM环境
6.1 创建Maven项目
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
修改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的使用