[TOC]

SpringBoot入门

HelloWorld项目

首先创建maven工程

引入依赖:

1
2
3
4
5
6
7
8
9
10
11
12
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

创建主程序:

1
2
3
4
5
6
7
@SpringBootApplication
public class MainApplication {

public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}

编写业务:

1
2
3
4
5
6
7
8
@RestController
public class HelloController {

@RequestMapping("/")
public String hander01() {
return "Hello Spring Boot !";
}
}

直接运行访问http://localhost:8080/得到结果。


了解自动配置

SpringBoot特点

依赖管理

  • 父项目做依赖管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
依赖管理    
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
</parent>

他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.8.RELEASE</version>
</parent>

几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
  • 开发导入starter场景启动器
1
2
3
4
5
6
7
8
9
10
11
12
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.8.RELEASE</version>
<scope>compile</scope>
</dependency>
  • 无需关注版本号,自动版本仲裁
1
2
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
  • 可以修改默认版本号
1
2
3
4
5
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>

自动配置

  • 自动配好Tomcat
    • 引入Tomcat依赖。
    • 配置Tomcat
1
2
3
4
5
6
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.8.RELEASE</version>
<scope>compile</scope>
</dependency>
  • 自动配好SpringMVC

    • 引入SpringMVC全套组件
    • 自动配好SpringMVC常用组件(功能)
  • 自动配好Web常见功能,如:字符编码问题

    • SpringBoot帮我们配置好了所有web开发的常见场景
  • 默认的包结构

    • 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
    • 无需以前的包扫描配置
    • 想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.kanxz")
      • 或者@ComponentScan 指定扫描路径
1
2
3
4
5
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.kanxz.boot")
  • 各种配置拥有默认值

    • 默认配置最终都是映射到某个类上,如:MultipartProperties
    • 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
  • 按需加载所有自动配置项

    • 非常多的starter
    • 引入了哪些场景这个场景的自动配置才会开启
    • SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面

容器功能

组件添加

@Configuration

Full模式与Lite模式

  • 配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
  • 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#################Configuration使用示例####################
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认。其他Lite模式
*/
@Configuration(proxyBeanMethods = true) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {

/*
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}

@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}


###################@Configuration测试代码如下##########################
@SpringBootApplication
public class MainApplication {

public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}

//3、从容器中获取组件
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:"+(tom01 == tom02));


MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);

//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
//保持组件单实例
User user = bean.user01();
User user1 = bean.user01();
System.out.println(user == user1);


User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);

System.out.println("用户的宠物:"+(user01.getPet() == tom));
}
}

@Import

1
2
3
4
5
6
7
8
 * @Import({User.class, DBHelper.class})
* 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
*/

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}

@Conditional

条件装配:满足Conditional指定的条件,则进行组件注入

详细用法:https://juejin.cn/post/6844903903860015111

原生配置文件引入

@ImportResource

1
2
3
4
5
6
7
8
9
10
11
12
==============beans.xml==============
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="lisi" class="com.kanxz.boot.bean.User">
<property name="name" value="lisi"/>
<property name="age" value="20"/>
</bean>

</beans>
1
2
@ImportResource("classpath:beans.xml")
public class MyConfig {}

配置绑定

使用Java读取到properties文件中的内容,并且把它封装到JavaBean中

application.properties:

1
2
mycar.brand=BYD
mycar.price=100000

@Component + @ConfigurationProperties

1
2
3
4
5
6
7
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
...
}

@EnableConfigurationProperties + @ConfigurationProperties

该方法可注册第三方bean

1
2
3
4
5
6
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
...
}
1
2
3
4
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(Car.class)
public class MyConfig {
}

controller类测试:

1
2
3
4
5
6
7
@Autowired
private Car car;

@RequestMapping("/car")
public String car() {
return car.toString();
}

配置文件

yaml

基本用法

  • key: value;kv之间有空格
  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用tab,只允许空格
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • '#'表示注释
  • 字符串无需加引号,如果要加,’'与""表示字符串内容 会被 转义/不转义

数据类型

  • 字面量:单个的、不可再分的值。
1
k: v
  • 对象:键值对的集合。
1
2
3
4
5
6
行内写法:  k: {k1:v1,k2:v2,k3:v3}
#或
k:
k1: v1
k2: v2
k3: v3
  • 数组:一组按次序排列的值。
1
2
3
4
5
6
行内写法:  k: [v1,v2,v3]
#或者
k:
- v1
- v2
- v3

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Data
public class Person {

private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String, Object> score;
private Set<Double> salary;
private Map<String, List<Pet>> allPets;
}

@Data
public class Pet {
private String name;
private Double weight;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
person:
username: 张三
boss: true
birth: 2002/2/22
age: 18
pet:
name: 大黄
weight: 10
interests: [篮球, 游泳]
animal:
- 小黑
- 小白
score:
english: 90
math: 90
salary: [111, 222]
allPets:
sick:
- {name: tom}
- {name: jerry, weight: 47}
healthy: [{name: mario, weight: 47}]

配置提示

自定义的类和配置文件绑定一般没有提示,需要添加:

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

Web开发

简单功能分析

静态资源目录

只要静态资源放在类路径下: /static (or /public or /resources or /META-INF/resources

访问 : 当前项目根路径/ + 静态资源名

原理: 静态映射/**。

请求进来,先去找Controller看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应404页面

改变默认的静态资源路径

1
2
3
4
5
6
7
8
spring:
#访问:当前项目根路径/res/ + 静态资源名
mvc:
static-path-pattern: /res/**

#静态资源需要放在放在classpath的haha文件夹下
resources:
static-locations: [classpath:/haha/]

欢迎页支持

  • 静态资源路径下 index.html
    • 可以配置静态资源路径
    • 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
1
2
3
4
5
6
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致welcome page功能失效

resources:
static-locations: [classpath:/haha/]
  • controller能处理/index

自定义 Favicon

favicon.ico 放在静态资源目录下即可。

1
2
3
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致 Favicon 功能失效

请求参数处理

普通参数与基本注解

注解

@PathVariable、@RequestHeader、@ModelAttribute、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 路径变量,请求头
@GetMapping("/car/{id}/owner/{username}")
public Map<String, Object> getCar(@PathVariable("id") int id,
@PathVariable("username") String name,
@PathVariable Map<String, String> kv,
@RequestHeader("User-Agent") String userAgent,
@RequestHeader Map<String, String> header) {
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("username", name);
map.put("kv", kv);
map.put("userAgent", userAgent);
map.put("header", header);
return map;
}

请求:http://localhost:8080/car/1/owner/zhangsan 可得到相应结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 请求参数,cookie值
@GetMapping("/user")
public Map<String, Object> getUser(@RequestParam("age") int age,
@RequestParam("name") String name,
@RequestParam("interest") List<String> interest,
@RequestParam Map<String, String> params,
@CookieValue("Idea-90db23ce") Cookie cookie) {
HashMap<String, Object> map = new HashMap<>();
map.put("age", age);
map.put("name", name);
map.put("interest", interest);
map.put("params", params);
System.out.println(cookie.getName() + "--->" + cookie.getValue());
return map;
}

请求:http://localhost:8080/user?age=18&name=zhangsan&interest=ball&interest=music

可以得到:{“interest”:[“ball”,“music”],“name”:“张三”,“params”:{“age”:“18”,“name”:“张三”,“interest”:“ball”},“age”:18}

控制台输出:Idea-90db23ce—>5482e6f3-30e6-4f4e-873b-0aa04d909edc

1
2
3
4
5
6
7
<form action="/save" method="post">
<label for="username">username:</label>
<input type="text" name="username" id="username"><br>
<label for="pd">password:</label>
<input type="password" name="pd" id="pd"><br>
<input type="submit" value="save">
</form>
1
2
3
4
5
6
7
// 请求体
@PostMapping("/save")
public Map<String, String> save(@RequestBody String content) {
HashMap<String, String> map = new HashMap<>();
map.put("content", content);
return map;
}

输入表单内容,点击按钮,可得到结果:{“content”:“username=123456&pd=654321”}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 获取request域属性
@Controller
public class RequestController {

@GetMapping("/go")
public String go(HttpServletRequest servletRequest) {
servletRequest.setAttribute("msg", "success");
servletRequest.setAttribute("code", 200);
return "forward:/msg";
}

@ResponseBody
@GetMapping("/msg")
public Map<String, Object> getMsg(@RequestAttribute("msg") String msg,
@RequestAttribute("code") int code,
HttpServletRequest servletRequest) {
HashMap<String, Object> map = new HashMap<>();
map.put("msg", msg);
map.put("code", code);
System.out.println(servletRequest.getAttribute("msg"));
System.out.println(servletRequest.getAttribute("code"));
return map;
}
}

访问:http://localhost:8080/go,得到:{“msg”:“success”,“code”:200}

控制台输出:
success
200

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 矩阵变量
// 需要手动开启矩阵变量功能,矩阵变量必须有url路径变量才能被解析
@Configuration
public class WebConfig {
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper helper = new UrlPathHelper();
helper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(helper);
}
};
}
}


// /car/sell;low=34;brand=byd,audi,yd
// /car/sell;low=34;brand=byd;brand=audi;brand=yd
@GetMapping("/car/{path}")
public Map<String, Object> carSell(@PathVariable("path") String path,
@MatrixVariable("low") int low,
@MatrixVariable("brand") List<String> brand) {
HashMap<String, Object> map = new HashMap<>();
map.put("path", path);
map.put("low", low);
map.put("brand", brand);
return map;
}
得到结果:{"path":"sell","low":34,"brand":["byd","audi","yd"]}


// /boss/1;age=20/2;age=10
@GetMapping("/boss/{bossId}/{empId}")
public Map<String, Object> bossAge(@PathVariable("bossId") String bossId,
@PathVariable("empId") String empId,
@MatrixVariable(value = "age", pathVar = "bossId") int bossAge,
@MatrixVariable(value = "age", pathVar = "empId") int empAge) {
HashMap<String, Object> map = new HashMap<>();
map.put("bossId", bossId);
map.put("bossAge", bossAge);
map.put("empId", empId);
map.put("empAge", empAge);
return map;
}
得到结果:{"empId":"2","bossAge":20,"bossId":"1","empAge":30}

视图解析与模板引擎

模板引擎-Thymeleaf

官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

基本语法

1、表达式
表达式名字 语法 用途
变量取值 ${…} 获取请求域、session域、对象等值
选择变量 *{…} 获取上下文对象值
消息 #{…} 获取国际化等值
链接 @{…} 生成链接
片段表达式 ~{…} jsp:include 作用,引入公共页面片段
2、字面量

文本值: ‘one text’ , ‘Another one!’ **,…**数字: 0 , 34 , 3.0 , 12.3 **,…**布尔值: true , false

空值: null

变量: one,two,… 变量不能有空格

3、文本操作

字符串拼接: +

变量替换: |The name is ${name}|

4、数学运算

运算符: + , - , * , / , %

5、布尔运算

运算符: and , or

一元运算: ! , not

6、比较运算

比较: > , < , >= , <= ( gt , lt , ge , le )

等式: **== , != ( eq , ne ) **

7、条件运算

If-then: (if) ? (then)

If-then-else: (if) ? (then) : (else)

Default: (value) ?: (defaultvalue)

8、特殊操作

无操作: _

设置属性值-th:attr

设置单个值

1
2
3
4
5
6
<form action="subscribe.html" th:attr="action=@{/subscribe}">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
</fieldset>
</form>

设置多个值

1
<img src="../../images/gtvglogo.png"  th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

以上两个的代替写法 th:xxxx

1
2
<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>
<form action="subscribe.html" th:action="@{/subscribe}">

所有h5兼容的标签写法

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes

迭代

1
2
3
4
5
<tr th:each="prod : ${prods}">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
1
2
3
4
5
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

条件运算

1
2
3
<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}">view</a>
1
2
3
4
5
<div th:switch="${user.role}">
<p th:case="'admin'">User is an administrator</p>
<p th:case="#{roles.manager}">User is a manager</p>
<p th:case="*">User is some other thing</p>
</div>

属性优先级

thymeleaf使用

引入Starter

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

页面开发测试

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<h1 th:text="${msg}">Hello</h1>
<h2>
<a href="www.baidu.com" th:href="${link}">google</a>
</h2>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
@Controller
public class ViewTestController {

@GetMapping("/view")
public String viewTest(HttpServletRequest servletRequest) {
servletRequest.setAttribute("msg", "你好~");
servletRequest.setAttribute("link", "https://www.google.com");
return "hello";
}
}

拦截器

HandlerInterceptor 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* 登录检查
* 1、配置好拦截器要拦截哪些请求
* 2、把这些配置放在容器中
*/
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

/**
* 目标方法执行之前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String requestURI = request.getRequestURI();
log.info("preHandle拦截的请求路径是{}",requestURI);

//登录检查逻辑
HttpSession session = request.getSession();

Object loginUser = session.getAttribute("loginUser");

if(loginUser != null){
//放行
return true;
}

//拦截住。未登录。跳转到登录页
request.setAttribute("msg","请先登录");
request.getRequestDispatcher("/").forward(request,response);
return false;
}

/**
* 目标方法执行完成以后
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle执行{}",modelAndView);
}

/**
* 页面渲染以后
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion执行异常{}",ex);
}
}

配置拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 1、编写一个拦截器实现HandlerInterceptor接口
* 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
* 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】
*/
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //所有请求都被拦截包括静态资源
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求
}
}

文件上传

页面表单

1
2
3
4
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="file"><br>
<input type="submit" value="提交">
</form>

文件上传代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* MultipartFile 自动封装上传过来的文件
*/
@PostMapping("/upload")
public String upload(
@RequestParam("email") String email,
@RequestParam("username") String username,
@RequestPart("avatar") MultipartFile avatar,
@RequestPart("photos") MultipartFile[] photos) throws IOException {

log.info("\n\temail={}\n\tusername={}\n\tavatar={}\n\tphotos={}", email, username, avatar.getSize(), photos.length);

if (!avatar.isEmpty()) {
String filename = avatar.getOriginalFilename();
avatar.transferTo(new File("C:\\Users\\MI\\Desktop\\test\\" + filename));
}

if (photos.length != 0) {
for (var photo: photos) {
if (!photo.isEmpty()) {
String filename = photo.getOriginalFilename();
photo.transferTo(new File("C:\\Users\\MI\\Desktop\\test\\photos\\" + filename));
}
}
}

return "main";
}

数据访问

SQL

数据源的自动配置-HikariDataSource

导入JDBC场景

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

修改配置项

1
2
3
4
5
6
spring:
datasource:
url: jdbc:mysql://localhost:3306/user_db?serverTimezone=Asia/Shanghai
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver

使用Druid数据源

druid官方github地址

https://github.com/alibaba/druid

引入依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.4</version>
</dependency>

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_account
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver

druid:
aop-patterns: com.atguigu.admin.* #监控SpringBean
filters: stat,wall # 底层开启功能,stat(sql监控),wall(防火墙)

stat-view-servlet: # 配置监控页功能
enabled: true
login-username: admin
login-password: admin
resetEnable: false

web-stat-filter: # 监控web
enabled: true
urlPattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'


filter:
stat: # 对上面filters里面的stat的详细配置
slow-sql-millis: 1000
logSlowSql: true
enabled: true
wall:
enabled: true
config:
drop-table-allow: false

SpringBoot配置示例

https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

配置项列表https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8

MyBatis

https://github.com/mybatis

1
2
3
4
5
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>

使用注解

1
2
3
4
5
6
7
@Mapper
public interface CityMapper {

@Select("select * from city where id=#{id}")
public City getById(Long id);

}

整合 MyBatis-Plus 完成CRUD

mybatis plus 官网

1
2
3
4
5
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>

只需要我们的Mapper继承 BaseMapper 就可以拥有crud能力

NoSQL

Redis

安装教程:

https://www.cnblogs.com/hunanzp/p/12304622.html

导入依赖:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置:

1
2
3
4
redis:
host: 服务器地址
password: 密码
......

测试:

1
2
3
4
5
6
7
8
9
10
@Autowired
StringRedisTemplate redisTemplate;

@Test
public void testRedisTemplate() {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set("Hello", "World");
assertEquals("World", operations.get("Hello"));
log.debug("【Redis】:set 'Hello' -> '{}' ", operations.get("Hello"));
}

学习自: