202108《SpringBoot》学习笔记

写于

狂神,B站,2021年8月

微服务阶段

整个Java学习路线

JavaSE:OOP、 MySQL:持久化 Html+css+js+jquery+框架:前端,视图,框架,css学不精通 JavaWeb:独立开发MVC三层架构的网站了,原始 SSM:框架,简化了我们的开发流程,配置开始较为复杂 War:tomcat运行 Spring再简化:SpringBoot,变成jar包,内嵌tomcat;微服务架构 服务越来越多,后面学SpringCloud,整理服务 阶段六: SpringBoot-是什么-配置如何编写yaml-自动装配原理(重要,面试谈资)-集成web开发:业务核心-集成数据库druid-分布式开发:Dubbo与zookeeper-swagger:接口文档-任务调度-SpringSecurity:Shiro(6天) SpringCloud-微服务-SpringCloud入门-Restful-Eureka-负载均衡Ribbon-Feign-HyStrix-Zuul路由网关-SpringCloud config:git(2天半) Linux:2天 JVM机制:2天 image1 基础是为了以后看源码方便 框架是为了整合更简约 PS:从这里的第一次课老师介绍可以听出,他(狂神)仅是培训机构的一员培训师,而非网上所传的那些。(原话:在我没来之前,去年那个老师讲的深度……)。总结而言:培训机构为了打造所谓的名人、大牛,肆意造假编故事坑蒙学员。而且在这节课的介绍中,也是一个套路,说他的课怎么好,加了什么好的内容,别的老师、机构不负责任……

1.什么是Spring?

老师: 培训讲师:面向面试培训,教你如何使用,快速上手。 做教育的:如何学习新东西,如何持续学习,如何关注这个行业;来龙去脉,历史,理论,谈资 SpringBoot就是一个JavaWeb的开发框架,简化开发,约定大于配置,you can “just run” Java企业级应用-J2EE-Spring-SpringBoot的过程 SpringBoot的主要优点: 1.为所有Spring开发者更快的入门 2.开箱即用,提供各种默认配置来简化项目配置 3.内嵌式容器,简化web项目 4.没有冗余代码生成和xml配置的要求 程序=数据结构+算法(集合框架),程序猿:创造性 程序=面向对象+框架,码农:重复性

2.什么是微服务

MVC三层结构,MVVM,微服务架构 业务:service,userService-模块 Springmvc,controller 提供接口

04113.第一个SpringBoot程序

Jdk1.8 Maven 3.6.1 Springboot:最新版 Idea 官方:提供了一个快速生成的网站,idea集成了这个网站 可以直接在官网下载,导入idea开发 直接使用idea创建一个springboot项目 Springboot banner工具生成特殊文本

4.SpringBoot自动装配原理

1.自动配置 Pom.xml Spring-boot-dependencies:核心依赖在父工程中 我们在写或引入SpringBoot依赖的时候,不需要指定版本,因为有版本仓库 启动器:SpringBoot的启动场景

<dependency>**

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

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

</dependency>

如spring-boot-starter-web,会自动导入web环境所有的依赖 Springboot会将所有的功能场景都变成一个个的启动器 如果需要使用什么功能,只需要找到一个个的启动器 主程序

**package** com.fei;

**import** org.springframework.boot.SpringApplication;

**import** org.springframework.boot.autoconfigure.SpringBootApplication;

//SpringBootApplication :标注这个类是一个SpringBoot的应用

@SpringBootApplication(scanBasePackages = "fei")

**public** **class** Springboot01HelloworldApplication {

**public** **static** **void** main(String[] args) {

SpringApplication.run(Springboot01HelloworldApplication.**class**, args);

}

}

Springboot的所有自动配置都是在启动的时候扫描并加载的,但是不一定生效,要判断条件是否成立 。需要导入相应的start 1.springboot在启动时,从类路径下获取指定的值 2.将这些自动配置类导入容器,自动配置就会生效 3.springboot会将所有需要导入的组合,以类名的方式导入 4.有了自动配置类,免去了手动编写代码 关于SpringBoot:自动装配、run

5.SpringBoot配置

注意:SpringBoot生成的自带class:application要在其他包的前端,否则会出现赋值为null的情况 Application.yaml

person:

name: xiaofei${random.int}

age: ${random.int(30)}

birth: 1990-4-1

happy: true

maps: {k1:v2 , k2:v2}

lists:

- code

- music

- girl

dog:

name: ${person.hello:hello}_旺财

age: 3

Person代码

package com.example.pojo;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.PropertySource;

import org.springframework.stereotype.Component;

import java.util.Date;

import java.util.List;

import java.util.Map;

// 加载指定的配置文件

@PropertySource(value = "classpath:application.properties")

@Component

@ConfigurationProperties(prefix = "person")

public class Person {

//spel表达式取出配置文件的值

@Value("${name}")

private String name;

private Integer age;

private Boolean happy;

private Date bitrh;

private Map<String,Object> maps;

private List<Object> lists;

private Dog dog;

public Person() {

}

public Person(String name, Integer age, Boolean happy, Date bitrh, Map<String, Object> maps, List<Object> lists, Dog dog) {

this.name = name;

this.age = age;

this.happy = happy;

this.bitrh = bitrh;

this.maps = maps;

this.lists = lists;

this.dog = dog;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

public Boolean getHappy() {

return happy;

}

public void setHappy(Boolean happy) {

this.happy = happy;

}

public Date getBitrh() {

return bitrh;

}

public void setBitrh(Date bitrh) {

this.bitrh = bitrh;

}

public Map<String, Object> getMaps() {

return maps;

}

public void setMaps(Map<String, Object> maps) {

this.maps = maps;

}

public List<Object> getLists() {

return lists;

}

public void setLists(List<Object> lists) {

this.lists = lists;

}

public Dog getDog() {

return dog;

}

public void setDog(Dog dog) {

this.dog = dog;

}

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age=" + age +

", happy=" + happy +

", bitrh=" + bitrh +

", maps=" + maps +

", lists=" + lists +

", dog=" + dog +

'}';

}

}

测试代码

package com.example;

import com.example.pojo.Dog;

import com.example.pojo.Person;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest

class Springboot02ConfigApplicationTests {

@Autowired

private Person person;

@Test

void contextLoads() {

System.out.println(person);

}

}

JRS303校验 image2 可以通过debug=true来判断哪些class没有生效

SpringBoot Web开发

自动装配 Springboot到底帮我们配置了什么?我们能不能进行修改?能修改哪些东西?能不能扩展? XxxxAutoConfiguration,向容器中自动配置组件 XxxProperties:自动配置类,装配配置文件中自定义的一些内容 要解决的问题: 导入静态资源 首页 Jsp,模板引擎Thymeleaf 装配扩展SpringMVC 增删改查 拦截器 国际化

静态资源

1.在springboot中,我们可以使用以下方式处理静态资源 Webjars, localhost:8080/webjars/ Public,static,/**,resourcesn localhost:8080/ 2.优先级:resources>static()>public

首页如何定制

模板引擎

前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。jsp支持非常强大的功能,包括能写Java代码,但是呢,我们现在的这种情况SpringBoot这个项目首先是以jar的方式,不是war,像第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的。 那不支持jsp,如果我们直接用纯静态页面的方式,那给我们开发会带来非常大的麻烦,那怎么办呢,SpringBoot推荐你可以来使用模板引擎。那么这模板引擎,我们其实大家听到很多,其实jsp就是一个模板引擎,还有以用的比较多的freemarker,包括SpringBoot给我们推荐的Thymeleaf,模板引擎有非常多,但再多的模板引擎,他们的思想都是一样的,什么样一个思想呢我们来看一下这张图。

image4 模板引擎的作用是写一个页面模板,比如有些值是动态的,可以写成是一个表达式。而这个值可以根据组装的数据来找到,然后把这个模板和数据交给模板引擎,它会按照数据解析表达式、填充到指定位置,然后生成最终的内容。 SpringBoot推荐Thymeleaf模板引擎,是一个高级语言的模板引擎,语法简单,功能强大。 使用thymeleaf,只需要导入相应的依赖便可

<dependency>

<groupId>org.thymeleaf</groupId>

<artifactId>thymeleaf-spring5</artifactId>

</dependency>

<dependency>

<groupId>org.thymeleaf.extras</groupId>

<artifactId>thymeleaf-extras-java8time</artifactId>

</dependency>

将html放到templates目录下即可

员工管理系统

POJO模块

Department代码

  1. ``` package spring02web.pojo;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

//部门表

@Data

@AllArgsConstructor

@NoArgsConstructor

public class Department {

private Integer id;

private String departmentName;

} ```

Employee代码

  1. ``` package spring02web.pojo;

import lombok.Data;

import lombok.NoArgsConstructor;

import java.util.Date;

//员工表

@Data

@NoArgsConstructor

public class Employee {

   private Integer id;

   private String lastName;

   private String email;

   private Integer gender; //0:女 1:男

   private Department department;

   private Date birth;

   public Employee(Integer id, String lastName, String email, Integer gender, Department department) {

       this.id = id;

       this.lastName = lastName;

       this.email = email;

       this.gender = gender;

       this.department = department;

       this.birth = new Date(); //默认的创建日期

}

} ```

Dao模块

DepartmentDao代码

package spring02web.dao;

import spring02web.pojo.Department;

import org.springframework.stereotype.Repository;

import java.util.Collection;

import java.util.HashMap;

import java.util.Map;

//部门dao

@Repository

public class DepartmentDao {

//模拟数据库中的数据

private static Map<Integer, Department> departments = null;

static{

    departments = new HashMap<Integer,Department>();

    departments.put(101,new Department(101,"教学部"));

    departments.put(102,new Department(102,"市场部"));

    departments.put(103,new Department(103,"教研部"));

    departments.put(104,new Department(104,"运营部"));

    departments.put(105,new Department(105,"后勤部"));

}

//获得所有部门信息

public Collection<Department> getDepartment(){

    return departments.values();

}

//通过id获得部门

public Department getDepartmentById(Integer id){

    return departments.get(id);

}

}

EmpolyeeDao

package spring02web.dao;

import spring02web.pojo.Department;

import spring02web.pojo.Employee;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;

import java.util.HashMap;

import java.util.Map;

//员工Dao

public class EmployeeDao {

//模拟数据库中的数据

private static Map<Integer, Employee> employees = null;

//员工所属部门

@Autowired

private DepartmentDao departmentDao;

static {

employees = new HashMap<Integer, Employee>();//创建一个部门表

employees.put(1001,new Employee(1001,"张三","4***@qq.com",1,new Department(101,"教育部")));

employees.put(1002,new Employee(1002,"李四","4***@qq.com",0,new Department(101,"教育部")));

employees.put(1003,new Employee(1003,"张四","4***@qq.com",1,new Department(103,"教研部")));

employees.put(1004,new Employee(1004,"张五","4***@qq.com",0,new Department(102,"市场部")));

employees.put(1005,new Employee(1005,"李六","4***@qq.com",1,new Department(101,"教育部")));

}

//主键自增

private static Integer initId = 1006;

//增加一个员工

public void save(Employee employee){

if (employee.getId() == null){

employee.setId(initId++);

}

employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));

employees.put(employee.getId(),employee);

}

//查询全部员工信息

public Collection<Employee> getAll(){

return employees.values();

}

//通过id查询员工

public Employee getEmployeeById(Integer id){

return employees.get(id);

}

//通过id删除员工

public void delete(Integer id){

employees.remove(id);

}

}

Controller模块

IndexController代码

package spring02web.controller;

import org.springframework.stereotype.Controller;

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

@Controller

public class IndexController {

@RequestMapping({"/","/index.html"})

public String index(){

return "index";

}

}

<dependency>

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

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

</dependency>

如何写一个网站

1.前端: 模板:别人写好的,我们拿来自己修改 框架:组件,自己手动组合拼接,Bootsrap,Layui,semanti-ui 栅格系统,导航栏,侧边栏, 2.设计数据库(数据库设计) 3.前端自动运行,独立化工程 4.数据接口对口对接:json,对象,all in one 5.前后端联调测试 1.要有一套自己熟悉的后台模板,x-admin,bootstrap 2.前端界面:至少自己能够通过前端框架,组合出来一个网站页面

  • index
  • about
  • blog
  • post

user 3.能够让网站自己独立运行

SpringBoot项目课程

B站,黑马程序员 前期Spring,SpringMVC,MyBatis 后期Spring Cloud,各种解决方案

image5

SpringBoot概述

快速使用Spring的方式,约定优于配置

Spring缺点

1.配置繁琐 2.依赖繁琐

Spring功能

1.自动配置 2.起步依赖 定义了其他库的传递依赖 3.辅助功能 提供了大型项目中常见的非功能性特性,如嵌入式服务器、安全、健康检测 SpringBoot并不是对Spring项目的功能增强,而是提供快速开发

SpringBoot快速入门

案例:需求

搭建SpringBoot工程,定义HelloController.hello()方法

步骤:

1.创建Maven项目 2.导入SpringBoot起步依赖

<!-- springboot工程需要继承的父工程 -->

<parent>

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

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

<version>2.5.2</version>

</parent>

<dependencies>

<dependency>

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

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

</dependency>

</dependencies>

3.定义Controller

package com.controller;

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

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

@RestController

public class HelloController {

@RequestMapping("/hello")

public String hello(){

return "hello Spring Boot";

}

}

4.编写引导类

package com;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

//引导类。理解为SpringBoot项目的入口

@SpringBootApplication

public class HelloApplication {

public static void main(String[] args) {

SpringApplication.run(HelloApplication.class,args);

}

}

5.启动测试

小结

SpringBoot在创建项目时,使用jar的打包方式 SpringBoot的引导类,是项目入口 ,运行main方法就可以启动项目 使用SpringBoot和Spring构建的项目,业务代码编写方式完全一样 方法二:直接通过IDEA构建 方法三:通过网址start.spring.io 或start.aliyun.io构建

SpringBoot起步依赖原理分析

起步依赖原理分析

(1)在Spring-boot-parent中定义了各种技术的版本信息,组合了一套最优搭建的技术版本 (2)在各种starter中,定义了完成该功能需要的坐标合集,其中大部分版本信息来自于父工程 (3)我们的工程继承parent,引入starter后,通过依赖传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突等问题

SpringBoot配置

配置文件分类

SpringBoot是基于约定的,所以很多配置都有默认值,如果想要自己配置,可以使用application.properties或application.yaml(yml)进行配置 默认配置文件名称:application Properties:

Server.port=8080 Yml: Server: Port: 8080 //注意要冒号后加空格 如果在同一级目录配置了这3个文件,则加载顺序为:peoperties->yml->yaml

Yaml

一、概述 YAML Ain’t Markup Language,是一种直观的能够被电脑识别的数据序列化格式语言 Yaml文件是以数据为核心,比传统的xml方式更加简洁 Yaml文件的扩展名可以使用.yaml或.yml

image-20250505191702472

因此,yaml简洁,以数据为核心 二、基本语法: 1.大小写敏感 2.数据值前边必须有空格,作为分隔符 3.使用缩进符表示层级关系 4.缩进时不允许使用Tab键,只允许使用空格(各个系统Tab对应的空格数目不同,导致层次混乱) 5.缩进的空格数目不重要,只要相同层级的元素左侧对齐 6.# 表示注释 三、数据格式 1.对象(map):键值对的集合

image-20250505191724219

空格不要忘记 2.数值:一组按次序排列的值

image-20250505191735114

3.纯量:单个的、不可再分的值 image-20250505191751733 四、参数引用 ${key} Application.yml

server:
port: 8081
name: abc

对象格式

person:
name: zhangsan
age: 20

对象的行内写法

person2: {name: zhangsan, age: 20}

数组

  • address: - beijing - shanghai

数组的行内写法

address2: [beijing,shanghai]

纯量

msg1: 'hello \n world' # 不会识别转义字符,原样输出
msg2: "hello \n world" # 能识别转义字符

读取配置文件内容

@value

Environment

@ConfigurationProperties
在pom.xml中加入

<dependency>

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

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

<optional>true</optional>

</dependency>

能够取消代码过程中顶行的红色提醒,也能在yml提示相应信息 Controller中Person代码

package com.controller;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component

@ConfigurationProperties(prefix = "person")

public class Person {

private String name;

private int age;

private String[] address;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String[] getAddress() {

return address;

}

public void setAddress(String[] address) {

this.address = address;

}

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

Controller中HelloController代码

package com.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.core.env.Environment;

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

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

@RestController

public class HelloController {

@Value("${name}")

private String name;

@Value("${person.name}")

private String personName;

@Value("${person.age}")

private int age;

@Value("${address[0]}")

private String address;

@Value("${msg1}")

private String msg1;

@Value("${msg2}")

private String msg2;

@Autowired

private Environment env;

@Autowired

private Person person;

@RequestMapping("/hello")

public String helloName(){

System.out.println(name);

System.out.println(personName);

System.out.println(age);

System.out.println(address);

System.out.println(msg1);

System.out.println(msg2);

System.out.println("---------------------------");

System.out.println(env.getProperty("person.name"));

System.out.println(env.getProperty("address[0]"));

System.out.println("---------------------------");

System.out.println(person);

String[] address = person.getAddress();

for (String s : address) {

System.out.println(s);

}

return "hello spring boot name!";

}

@RequestMapping("")

public String hello(){

return "hello spring boot 222!";

}

}

Profile

我们在开发SpringBoot应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址、服务器端口等配置都不同时,如果每次打包都要修改配置文件,则非常麻烦。Profile功能就是来进行动态配置切换的 1)profile配置方式

  • 多profile文件方式
  • yml多文档方式
--

server:

port: 8081

spring:

profiles: dev

--

server:

port: 8082

spring:

profiles: test

--

server:

port: 8083

spring:

profiles: pro

--

spring:

profiles:

active: pro

2)profile激活方式

  • 配置文件

  • 虚拟机参数

image10

  • Dspring.profiles.active=test
  • 命令行参数
  • -spring.profiles.active=pro

image12

image13

内部配置加载顺序

外部配置加载顺序

SpringBoot整合其他框架