SpringBoot(powernode)
目录
- SpringBoot(powernode)
 - 一、第一个SpringBoot项目
 - 二、打jar包启动测试
 - 三、个性化banner
 - 四、常用注解
 - 4.1回顾spring和java的注解
 - 4.1.1 spring标注类的注解:
 - 4.1.2 spring标注方法的注解:
 - 4.1.3 spring标注参数的注解:
 - 4.1.4 spring标注属性的注解:
 
- 4.2 相关注解说明
 - 4.2.1 @Configuration
 - 4.2.2 @Bean
 - 配置类
 - 测试类
 
- 4.2.3 @Qualifier注解
 - 配置类2
 - 测试类2.1
 - 测试类 2.2
 - 配置类3
 - HelloController.java①
 - HelloController.java②
 
- 4.2.4 @Primary 主候选的
 - 4.2.5 @Import注解
 - 4.2.6 @ComponentScan("com.bjpowernode")配置扫描
 
- 五、Spring Boot热部署
 - 5.1 什么是热部署
 - 5.2 添加依赖
 - 5.3 配置idea的启动面板
 
- 六、Spring Boot的配置文件语法
 - 6.1 首先引入依赖
 - 6.2 创建Weapon类
 - 6.3 properties文件的形式
 - 6.3.1创建Hero类
 - 6.3.1.0 @ConfigurationProperties(prefix = XXX)注解
 
- 6.3.2 ①properties方式
 
- 6.4 yml文件的形式
 - 6.4.1 创建Enemy类
 - 6.4.1.0 @ConfigurationProperties("XXX")注解
 
- 6.4.2 ②yml方式
 
- 七、@Value读取配置文件
 - 7.1 @Value读取properties文件
 - 7.1.1 application.properties
 - 7.1.2 javaBean(Hero2)
 - 7.1.3 测试类
 - 7.1.4 测试结果
 
- 7.2 @Value读取yml文件
 - 7.2.1 application.yml
 - 7.2.2 javaBean(Enemy2)
 - 7.2.3 测试类
 - 7.2.4 测试结果
 
- 7.3 测试结果对比
 
- 八、@Value和@ConfigurationProperties取值比较
 - 九、注解验证(JSR303数据校验)
 - 9.1 引入依赖
 - 9.2 javaBean
 - 9.3修改application.yml文件
 - 9.4 测试
 - 9.5 常用的验证注解
 
- 十、@PropertySource和@ImportResource的使用
 - 10.1 @PropertySource
 - 10.1.1 为什么要用@PropertiesSource
 - 10.1.2 注入优先级的问题
 - 案例实操
 - javabean
 - person.properties
 - 测试类
 - 测试结果
 
- 10.2 @ImportResource
 - 10.2.1 为什么要用@ImportResource
 - 10.2.2 javabean
 - 10.2.3 applicationContext.xml
 - 10.2.4 启动类添加@ImportResource注解
 - 10.2.5 测试类
 - 10.2.6 测试结果
 
- 十一、Profile配置文件详解
 - 11.1为什么要使用profiles
 - 11.2 创建application-dev.yml
 - 11.3 创建application-pro.yml
 - 11.4 修改application.yml
 - 11.5 启动测试
 - 11.6 打jar包部署运行测试
 
- 十二、配置文件加载优先级和外部配置文件
 - 12.1 项目内部配置文件
 - 12.1.1 配置文件可以放的位置和优先级
 
- 12.2 外部的配置文件
 
- 十三、编码格式(编码过滤器)(server.servlet.encoding)
 - 十四、如何查看自动配置类生效(debug:true)
 - 十五、整合logback
 - 15.1 概述
 - 15.2创建模块
 - 15.3 创建logback-spring.xml
 - 15.4 修改启动类测试
 - 15.5 查看本地日志
 
- 十六、AOP开发
 - 16.1 概述
 - 16.2使用方法
 - 16.3创建项目并添加maven依赖
 - 16.4 创建Javabean测试类
 - 16.5 创建切面
 - 16.6 测试类
 - 16.7 测试结果
 - 16.8 结论
 - 16.9 三种方式的写法(参考博客)
 - 16.10 代理方式的切换
 - 16.10.1 设计一个接口ManInterface
 - 16.10.2 javaBean目标类Man实现ManInterface接口
 - 16.10.3 修改application.yml文件的切换方式代理方式
 - 16.10.4 测试类
 - 16.10.5 测试结果
 
- 十七、WEB静态资源访问规则
 - 17.1 springboot访问静态资源的几种方式
 - 17.2 自定义静态资源访问方式
 - 17.2.1自定义方式1配置文件方式yml
 - 17.2.2 Java类方式
 
- 17.3 webjars的访问规则
 - 17.3.1什么是webjars
 - 17.3.2 引入依赖
 - 17.3.3启动访问
 
- 十八.Thymeleaf模板的使用
 - 18.1Thymeleaf概述
 - 18.2创建项目添加thymeleaf的依赖
 - 18.3Spring Boot项目Thymeleaf模板页面存放位置
 - 18.4 通过Controller跳转到Thymeleaf的页面
 - 18.4.1在src/main/resources/templates下创建hello.html
 - 18.4.2 创建RouteController类
 - 18.4.3测试访问
 
- 18.5Thymeleaf的相关语法
 - 18.6Thymeleaf读取Model里面的对象
 - 18.6.1创建Hero类
 - 18.6.2在RouteController增加一个方法跳转
 - 18.6.3创建showHero页面
 - 18.6.4测试访问
 
- 18.7Thymeleaf读取Model里面的集合
 - 18.7.1在RouteController增加一个方法跳转
 - 18.7.2创建showHeroList页面
 - 18.7.3测试访问
 
- 18.8ThymeleafObjects的使用
 - 18.8.1在RouteController增加一个方法跳转
 - 18.8.2创建showObj页面
 - 18.8.3测试访问
 
- 18.9Thymeleaf在js中取值
 - 18.9.1在RouteController增加一个方法跳转
 - 18.9.2 js.html
 - 18.9.3 运行效果
 
- 18.10Thymeleaf链接接传值
 - 18.10.1在RouteController增加一个方法跳转
 - 18.10.2 href.html
 - 18.10.3 在RouteController增加一个方法跳转
 - 18.10.4 运行效果
 
- 十九、SpringBoot自动管理MVC
 - 19.2具体查看视图解析
 - 19.3具体查看文件上传
 - 案例实操
 
- 19.4具体查看格式化【接收页面参数并转化】
 - 19.5欢迎页面自动配置
 
- 二十、扩展MVC的组件【掌握】
 - 20.1自定义视图控制器【熟悉】
 - 20.2 SpringBoot 自定义拦截器
 - 一、自定义拦截器
 - 二、编写控制器
 - 三、添加拦截器对象,注入到容器的配置类中
 - 另一种写法
 
- 四、最后application运行
 
- 二十一、注册Web三大组件【重点】
 - 21.1注册自己的Servlet
 - 21.1.1注册自己的Servlet(案例实操一)
 - 21.1.1.1 创建MyServlet
 - 21.1.1.2在配置类注册自己的servlet
 - 21.1.1.3 运行效果
 
- 21.1.2注册自己的Servlet(案例实操二)
 - 21.1.2.1创建UserServlet
 - 21.1.2.2在配置类注册自己的servlet
 - 21.1.2.3 运行效果
 
- 21.2SpringBoot 注册自己的Servlet(三种方式)
 - 21.3 注册自己的Filter
 - 21.4 注册自己的Listener
 - 21.4.1创建MyListener
 - 21.4.2在配置类里面注册自己的监听器
 - 21.4.3 测试
 
- 二十二.使用外部tomcat【了解】
 - 22.1创建项目,选择打包方式为war包
 - 22.2选择依赖
 - 22.3配置pom.xml
 - 22.4添加IDEA配置
 - 22.5配置外部tomcat
 - 22.6创建controller(返回JSON字符串)
 - 22.7 测试
 
- 22.8创建Controller(返回jsp页面)
 - 22.9创建页面
 - 22.10修改配置文件
 - 22.11 启动访问
 
- 二十三.数据源配置和自动管理【重中之中】
 - 23.1创建项目选择依赖
 - 23.2使用DriverManagerDataSource
 - 23.2.1修改配置文件
 - 23.2.2 测试类
 - 23.2.3 测试效果
 
- 23.4使用Druid数据源【官方starter】
 - 23.4.1导入依赖
 - 23.4.2 application.yml
 - 23.4.3 测试类不变 和 测试效果
 - 23.4.4 换成启动器依赖`druid-spring-boot-starter`
 - 23.4.5 application.yml
 - 23.4.6 测试
 
- 23.5使用Druid数据源【自己配置】(powernode CD2206)
 - 23.5.1 步骤说明
 - 23.5.2 创建项目
 - 23.5.3 添加durid的依赖
 - 23.5.4.application.yml
 - 23.5.5 添加MyDruidProperties配置文件类
 - 23.5.6.添加MyDruidAutoConfiguration自动配置类
 - 23.5.7 测试类
 - 23.5.8 配置druid数据源的监控功能
 - 23.5.8.1 application.yml
 - 23.5.8.2 读取druid配置文件的类MyDruidProperties.java
 - 23.5.8.3 修改MyDruidAutoConfiguration类
 - 23.5.9 测试
 
- 二十四、 集成Mybatis
 - 24.1说明
 - 24.2 pom.xml
 - 24.3 application.yml
 - 24.4 启动类
 - 24.5 javabean(User类)
 - 24.6 UserMapper.java接口
 - 24.7 UserMapper.xml配置文件
 - 24.8 service层接口
 - 24.9 测试类
 - 24.10 配置PageHelper插件分页
 - 24.10.1 pom.xml依赖pageHelper的starter
 - 24.10.2 service层接口
 - 24.10.3 service层实现类
 - 24.10.4 测试类
 
- 24.11 事务管理
 - 24.11.1 service层接口类
 - 24.11.2 service层实现类
 - 24.11.3 mapper接口类
 - 24.11.4 mapper.xml配置文件类
 - 24.11.5 测试类
 
- 二十五、集成swagger【熟悉】
 - 二十六 Spring Boot定时任务
 - 26.1概述
 - 26.2最佳实践
 - 26.2.1 创建一个SpringBoot项目
 - 26.2.2 开启定时任务
 - 26.2.3 执行任务
 - 26.2.4 运行测试
 - 26.2.5 阿里云Cron表达式官网
 
- 二十七 SpringBoot 邮件发送
 
一、第一个SpringBoot项目

选择Spring Initializer
 勾选Custom,里面填https://start.aliyun.com/
 

 Spring Boot DevTools 热部署
 Spring Configuration Processor 我们在自己写配置文件的时候,没有提示。如果想有提示
 
 
 
 生成的pom.xml
<?xml version="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:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.11</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.bjpowernode</groupId>
    <artifactId>springboot01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot01</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--用来热部署的工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--支持解析配置文件的工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
 

 点击运行
 
 浏览器访问
 
二、打jar包启动测试


 把打好的jar包拷贝到桌面上来
 
 
 
 
三、个性化banner
启动时查看控制台的输出会发现有一个banner图案,这个banner图案是可以自定义的
 
 修改为自己的banner
 在src/main/resources目录下面创建一个banner.txt文件,并且输入想要的内容即可
banner.txt
${AnsiColor.BRIGHT_YELLOW}
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O  =  /O                              //
//                      ____/`---'\____                           //
//                    .'  \|     |//  `.                         //
//                   /  \|||  :  |||//                          //
//                  /  _||||| -:- |||||-                         //
//                  |   | \  -  /// |   |                       //
//                  | \_|  ''---/''  |   |                       //
//                    .-\__  `-`  ___/-. /                       //
//                ___`. .'  /--.--  `. . ___                     //
//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
//            | | :  `- \`.;` _ /`;.`/ - ` : | |                 //
//               `-.   \_ __ /__ _/   .-` /  /                 //
//      ========`-.____`-.___\_____/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//            佛祖保佑       永不宕机      永无BUG                //
 
启动查看
四、常用注解
4.1回顾spring和java的注解
4.1.1 spring标注类的注解:
| 注解 | 说明 | 
|---|---|
| @Controller | 控制器 | 
| @RestController | 返回json的控制器 | 
| @Service | 标记服务接口 | 
| @Respority | 标记仓库接口 | 
| @Component | 标记组件 | 
| @RequestMapping | 请求映射 (也可在方法上) | 
| @ControllerAdvice | 统一异常处理拦截 | 
| @RestControllerAdvice | 统一异常处理拦截,并返回JSON | 
| @CrossOrigin | 跨域问题 | 
4.1.2 spring标注方法的注解:
| 注解 | 说明 | 
|---|---|
| @RequestMapping | 请求映射 | 
| @GetMapping | GET请求 | 
| @PostMapping | POST请求 | 
| @DeleteMapping | DELETE请求 | 
| @PutMapping | PUT请求 | 
| @PatchMapping | PATCH请求 | 
| @ResponseBody | 返回JSON对象 | 
| @ExceptionHandler | 统一异常处理拦截 | 
| @CrossOrigin | 跨域问题 | 
4.1.3 spring标注参数的注解:
| 注解 | 说明 | 
|---|---|
| @RequestBody | 入参是JSON对象 | 
| @PathVariable | 将路径上面的参数映射到入参里面 | 
| @RequestParam | 将请求参数绑定到你控制器的方法参数上 | 
4.1.4 spring标注属性的注解:
| 注解 | 说明 | 
|---|---|
| @Autowried | 自动注入(首选按照类型) byType byName | 
| @Resource | 自动注入(首选按照名字) | 
| @Value | 动态给属性赋值 | 
4.2 相关注解说明
4.2.1 @Configuration
作用于类上,被标注的类就相当于spring的xml配置文件
 |–application-dao.xml
4.2.2 @Bean
作用于方法上,相当于xml配置文件中的
 被标注的方法的返回值对象会交给ioc容器管理
配置类

com.bjpowernode.springboot01.config
 SpringConfig.java
package com.bjpowernode.springboot01.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
/*
*当前类被@Configuration注解标注,所以当前类就是spring的配置类
* 作用与spring的xml配置文件完全一致
*/
@Configuration
public class SpringConfig {
    /*
    *此方法被@Bean注解标注,所以此方法就是将指定的javabean对象交给ioc容器管理
    * 作用与<bean>标签一致
    * 方法名默认就是该javaBean的名称
    */
    @Bean
    public Date date(){
        return new Date();
    }
}
 
测试类

package com.bjpowernode.springboot01;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
class Springboot01ApplicationTests {
    /*
    *在springboot的测试类中可以直接注入ioc容器中的对象
    * 说明springboot在测试方法之前会自动帮我们读取ioc容器
    */
    @Autowired
    private Date date;
    @Test
   public void test1(){
        System.out.println(date);
   }
 }
 
4.2.3 @Qualifier注解
qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,需要注意的是@Qualifier的参数名称必须为我们之前定义@Bean注解的名称之一
配置类2

package com.bjpowernode.springboot01.config;
import com.bjpowernode.springboot01.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
    @Bean(value = "user1")
    public User user1(){
        return new User(1,"赵一","武汉");
    }
    @Bean(value = "user2")
    public User user2(){
        return new User(2,"王二","成都");
    }
    @Bean("user3")
    public User user3(@Qualifier("user1") User user){
        return user;
    }
}
 
测试类2.1

package com.bjpowernode.springboot01;
import com.bjpowernode.springboot01.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.Date;
@SpringBootTest
class Springboot01ApplicationTests {
    /*
    *在springboot的测试类中可以直接注入ioc容器中的对象
    * 说明springboot在测试方法之前会自动帮我们读取ioc容器
    */
//    @Autowired
//    @Qualifier("user3")
    @Resource(name = "user3")
    private User user;
   @Test
    public void test2(){
       System.out.println("user = " + user);
   }
}
 
测试类 2.2

配置类3

HelloController.java①

HelloController.java②

4.2.4 @Primary 主候选的
当IOC容器里面有多个同类型的对象时,就会发生冲突,标注了该注解的就作为主候选对象
4.2.5 @Import注解
@Import(类名.class)
 
在创建配置文件之后可以引入其它的配置文件
 相当于
|--<import resource="classpath:application-dao.xml"/>
 
新创建一个配置文件SpringConfig2.java
 
 将SpringConfig2.java这个文件挂载到SpringConfig1.java里面
 
 测试类的代码
 
 运行结果
 
4.2.6 @ComponentScan(“com.bjpowernode”)配置扫描
相当于
|--<context:component-scan base-package="com.bjpowernode.*.mapper"/>
 
五、Spring Boot热部署
5.1 什么是热部署
spring为开发者提供了一个名为spring-boot-devtools的模块来使springboot应用支持热部署,提高开发的效率,修改代码后无需重启应用
5.2 添加依赖
<!--添加热部署的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <!--运行时生效-->
    <scope>runtime</scope>
    <!--依赖是否会传递,为true则不会传递-->
    <optional>true</optional>
</dependency>
 
5.3 配置idea的启动面板
如果不配置面板,那么可直接使用ctrl+F9去刷新,配置 以后,当我们修改代码,光标失去idea的焦点以后,就出触发自动部署
 
六、Spring Boot的配置文件语法
读取配置文件的内容为指定javabean的属性赋值
6.1 首先引入依赖
<!-- 配置文件拓展依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
 
6.2 创建Weapon类
package com.bjpowernode.springboot02.javabean;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class Weapon {
    private String name;
    private Double harm;
}
 
6.3 properties文件的形式
6.3.1创建Hero类
6.3.1.0 @ConfigurationProperties(prefix = XXX)注解
package com.bjpowernode.springboot02.javabean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@Component
/*
*指定使用配置文件(启动项目会自动去读取的配置文件application.properties)中指定前缀的数据为当前对象的属性赋值
* 匹配的规律:配置文件中数据的名称 与 对象的属性名相等 就匹配
* prefix匹配前缀为hero的
*/
@ConfigurationProperties(prefix = "hero")
public class Hero {
    private Integer id;
    private Integer age;
    private String name;
    private Date birth;
    private String[] hobby;
    private List<String> list;
    private Set<String> set;
    private Map<String, String> map;
    private Weapon weapon;
}
 
springboot支持两种形式的配置文件:properties与yaml
 Yaml:是一种全新的配置文件的格式
 优点:文件结构很简洁
 支持配置复杂的内容结构
 缺点:基本没有
语法1:
Key1: value1
 
语法2:
Key1: value1
  Key2: value2
 
注意:冒号后面一定要跟一个空格再跟value
6.3.2 ①properties方式
application.properties
# 应用名称
spring.application.name=springboot02
# 应用服务 WEB 访问端口
server.port=8080
#
hero.id=9527
hero.age=25
hero.name=jay zhou
hero.birth=1999/03/04
hero.hobby=sing,dance,rap,basketball
hero.list=list1,list2
hero.set=set1,set2
hero.map.key1=value1
hero.map.key2=value2 
hero.weapon.name=ak47
hero.weapon.harm=500
 
测试类
 
6.4 yml文件的形式
6.4.1 创建Enemy类
6.4.1.0 @ConfigurationProperties(“XXX”)注解
package com.bjpowernode.springboot02.javabean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@Component
/*
 *指定使用配置文件(启动项目会自动去读取的配置文件application.yml)中指定前缀的数据为当前对象的属性赋值
 * 匹配的规律:配置文件中数据的名称 与 对象的属性名相等 就匹配
 * prefix匹配前缀为hero的
 */
@ConfigurationProperties("enemy")
public class Enemy {
    private Integer id;
    private Integer age;
    private String name;
    private Date birth;
    private String[] hobby;
    private List<String> list;
    private Set<String> set;
    private Map<String, String> map;
    private Weapon weapon;
}
 
6.4.2 ②yml方式
enemy:
  age:
    id: 4399
      name: uncle
      age: 26
      birth: 1998/03/26
      hobby:
        - sing
        - dance
        - rap
        - basketball
      list:
        - list1
        - list2
      set:
        - set1
        - set2
      map:
        k1: v1
        k2: v2
      weapon:
        name: hk416
        harm: 5
 
测试类
 
 总结:
 项目启动时,会自动的读取application.properties以及application.yml
 如果两个配置文件的内容不一致,则项目读取到了这两个文件中的所有内容
 如果两个配置文件有相同的内容key,则以properties中的内容为准
 真实开发中:最好是就使用一种配置文件
 如果使用两种,就只能人为的注意不要写冲突,一般将项目的默认配置文件是properties,自定义的在yml文件中
七、@Value读取配置文件
7.1 @Value读取properties文件
7.1.1 application.properties
# 应用名称
spring.application.name=springboot02
# 应用服务 WEB 访问端口
server.port=8080
#
hero.id=9527
hero.age=25
hero.name=jay zhou
hero.birth=1999/03/04
hero.hobby=sing,dance,rap,basketball
hero.list=list1,list2
hero.set=set1,set2
hero.map.key1=value1
hero.map.key2=value2 
hero.weapon.name=ak47
hero.weapon.harm=500
hero.className=CD2207
 
7.1.2 javaBean(Hero2)
Hero2.java
package com.bjpowernode.springboot02.javabean;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@Component
public class Hero2 {
    @Value("123")
    private Integer id;
    @Value("${hero.age}")
    private Integer age;
    @Value("${hero.name}")
    private String name;
    @Value("${hero.birth}")
    private Date birth;
    @Value("${hero.hobby}")
    private String[] hobby;
    @Value("${hero.list}")
    private List<String> list;
    @Value("${hero.set}")
    private Set<String> set;
//    @Value("${hero.map}")
//    private Map<String, String> map;
//    @Value("${hero.weapon}")
//    private Weapon weapon;
    @Value("${hero.className}")
    private String className1;
    @Value("${hero.class-name}")
    private String className2;
}
 
7.1.3 测试类


7.1.4 测试结果
Hero2(id=123, age=25, name=jay zhou, birth=Thu Mar 04 00:00:00 CST 1999, hobby=[sing, dance, rap, basketball], list=[list1, list2], set=[set1, set2], className1=CD2207, className2=CD2207)
 
7.2 @Value读取yml文件
7.2.1 application.yml
enemy:
  id: 4399
  name: uncle
  age: 26
  birth: 1998/03/26
  hobby:
    - sing
    - dance
    - rap
    - basketball
  list:
    - list1
    - list2
  set:
    - set1
    - set2
  map:
    k1: v1
    k2: v2
  weapon:
    name: hk416
    harm: 5
  className: CGB2110
  array: LOL,DNF
 
7.2.2 javaBean(Enemy2)
Enemy2.java
package com.bjpowernode.springboot02.javabean;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@Component
/*
 *指定使用配置文件(启动项目会自动去读取的配置文件application.yml)中指定前缀的数据为当前对象的属性赋值
 * 匹配的规律:配置文件中数据的名称 与 对象的属性名相等 就匹配
 * prefix匹配前缀为hero的
 */
public class Enemy2 {
    @Value("008")
    private Integer id;
    @Value("${enemy.age}")
    private Integer age;
    @Value("${enemy.name}")
    private String name;
    @Value("${enemy.birth}")
    private Date birth;
//    @Value("${enemy.hobby}")
    private String[] hobby;
//    @Value("${enemy.list}")
    private List<String> list;
//    @Value("${enemy.set}")
    private Set<String> set;
//    @Value("${enemy.map}")
    private Map<String, String> map;
//    @Value("${enemy.weapon}")
//    private Weapon weapon;
    @Value("${enemy.className}")
    private String className1;
    @Value("${enemy.class-name}")
    private String className2;
    @Value("${enemy.array}")
    public String[] array;
}
 
7.2.3 测试类


7.2.4 测试结果
Enemy2(id=8, age=26, name=uncle, birth=Thu Mar 26 00:00:00 CST 1998, hobby=null, list=null, set=null, map=null, className1=CGB2110, className2=CGB2110, array=[LOL, DNF])
 
7.3 测试结果对比
@Value读取properties文件
Hero2(id=123, age=25, name=jay zhou, birth=Thu Mar 04 00:00:00 CST 1999, hobby=[sing, dance, rap, basketball], list=[list1, list2], set=[set1, set2], className1=CD2207, className2=CD2207)
 
@Value读取yml文件
Enemy2(id=8, age=26, name=uncle, birth=Thu Mar 26 00:00:00 CST 1998, hobby=null, list=null, set=null, map=null, className1=CGB2110, className2=CGB2110, array=[LOL, DNF])
 
小结:
 @Value可以给普通类型的属性赋值
 赋值的方式:
 1.将字面量赋值给属性
 2.读取配置文件的内容赋值给属性
1,@Value只能注入普通的属性[也就是基本数据类型和String] 其它的复杂类型是不能取到值的[如果yaml配置是array:LOL,DNF]这样的配置是可以取。
 但是如果是配置在properties文件中,则可以读取数组、list、set集合类型的数据
2,如果属性是使用驼峰命名法则可以使用属性名注入,使用@Value("${hero.className}")来取值,也可以使用@Value("${hero.class-name}")来取值。
八、@Value和@ConfigurationProperties取值比较

九、注解验证(JSR303数据校验)
当我们读取配置文件的内容给属性赋值时,有可能我们的属性的值是有约束的
数据校验:
读取的值如果满足了属性的约束,则正常赋值
读取的值如果不满足属性的约束,则赋值失败(项目启动失败)
 
1.为指定的属性指定约束
 需要程序员指定:使用注解的方式指定
 2.使用约束对对应的值进行判断
 使用校验的工具自动的进行判断
9.1 引入依赖
Springboot2.3.x以后,需要单独引入依赖,之前在web-starter里面包含
<!--引入注解验证的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
 
9.2 javaBean
People.java
package com.bjpowernode.springboot03jsr303.javabean;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.*;
@Data
@Component
@ConfigurationProperties(prefix = "people")
@Validated//声明当前类的属性需要校验
public class People {
    /*
    * 指定当前类的属性值不能为null
    */
    @NotNull
    private Integer id;
    @NotNull
    private String id1;
    /*
    * 指定当前属性的值不能为null,也不能为" "
    */
    @NotEmpty
    private  String id2;
    /*
    *指定当前属性的值不能为null,也不能为"",也不能为内容只有空格的字符串
    */
    @NotBlank
    private String id3;
//    @Min(value = 0)
//    @Max(100)
    @Range(min = 0,max = 100)
    private Integer age;
    /*
    *指定当前属性的长度范围
    */
    @Size(min=3,max = 6)
    private String name;
    /*
    * 指定当前属性必须符合我们自定义的正则表达式的规则
    * 规则:
    * 必须以字母开头
    * 跟至少1个字母或者数字或者_
    * 跟@符号
    * 跟至少1个字母或者数字或者_
    * 跟.
    * 跟至少1个字母或者数字或者_
    */
    @Pattern(regexp = "[a-zA-Z][A-Za-z0-9_]+@[A-Za-z0-9_]+\\.[A-Za-z0-9_]+")
    //@Email(message = "邮箱不合法")
    private String email;
}
 
9.3修改application.yml文件
people:
  id: 123
  id1: ""
  id2: " "
  id3: " s"
  age: 25
  name: abc
  email: H541434135@qq.com
 

9.4 测试
测试类
package com.bjpowernode.springboot03jsr303;
import com.bjpowernode.springboot03jsr303.javabean.People;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot03Jsr303ApplicationTests {
    @Autowired
    private People people;
    @Test
    void contextLoads() {
        System.out.println(people);
    }
}
 

9.5 常用的验证注解
@NotNull --不能为null,但可以空着不写 (name:)
 @NotEmpty --不能为空,也不能为null,但可以是空格 “ ”
 @NotBlank --不能为空格,也不能为null,也不能为空格
 @Min 最小值,只针对数字属性
 @Max 最大值, 只针对数字属性
 @Size(min = 1, max = 6) 长度限制,只针对字符串
 @Range(min = 1,max = 2) 范围限制
 @Pattern(regexp"[0,1]{1}") 正则限制
十、@PropertySource和@ImportResource的使用
10.1 @PropertySource
10.1.1 为什么要用@PropertiesSource
上面的注入,所有的配置都是写在appliaction.properties或application.yml文件里,那么如果不想写在这里面怎么处理呢,使用@PropertySource可以解决
10.1.2 注入优先级的问题
所在的配置都是优先注入appliaction.properties或application.yml里面的数据
 如果要不一样,必须修改配置文件引入的前缀
案例实操
javabean
package com.bjpowernode.springboot04propertysource_and_importresource.javabean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Data
@Component
/*
*声明主动读取person.properties
* 注意:主动读取这一配置文件与springboot自动读取主配置文件不冲突
* 所以:相当于让springboot读取三个配置文件
*/
@PropertySource("classpath:person.properties")
@ConfigurationProperties("person")
public class Person {
    private Integer id;
    private String name;
}
 
person.properties
person.id=123
person.name=jay
 
测试类
package com.bjpowernode.springboot04propertysource_and_importresource;
import com.bjpowernode.springboot04propertysource_and_importresource.javabean.Person;
import com.sun.imageio.plugins.jpeg.JPEGImageReaderResources;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot04PropertysourceAndImportresourceApplicationTests {
    @Autowired
    private Person person;
    @Test
    void contextLoads() {
        System.out.println(person);
    }
}
 
测试结果

10.2 @ImportResource
10.2.1 为什么要用@ImportResource
从上面所有的配置中可以看出我们没有使用以前的spring的xml的配置方法,如果还是要使用spring里面的xml的配置方式怎么办理,使用@ImportResource
10.2.2 javabean
package com.bjpowernode.springboot04propertysource_and_importresource.javabean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Data
public class Person {
    private Integer id;
    private String name;
}
 
10.2.3 applicationContext.xml
resources资源文件夹下
 applicationContext.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="person" class="com.bjpowernode.springboot04propertysource_and_importresource.javabean.Person">
        <property name="id" value="1"/>
        <property name="name" value="后羿"/>
    </bean>
</beans>
 
10.2.4 启动类添加@ImportResource注解
package com.bjpowernode.springboot04propertysource_and_importresource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("classpath:applicationContext.xml")
public class Springboot04PropertysourceAndImportresourceApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot04PropertysourceAndImportresourceApplication.class, args);
    }
}
 
10.2.5 测试类
package com.bjpowernode.springboot04propertysource_and_importresource;
import com.bjpowernode.springboot04propertysource_and_importresource.javabean.Person;
import com.sun.imageio.plugins.jpeg.JPEGImageReaderResources;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ImportResource;
@SpringBootTest
class Springboot04PropertysourceAndImportresourceApplicationTests {
    @Autowired
    private Person person;
    @Test
    public void testAtImportResourceAnno(){
        System.out.println(person);
    }
}
 
10.2.6 测试结果

十一、Profile配置文件详解
11.1为什么要使用profiles
在开发中,一般有两种环境
 1,生产环境 [项目上线,客户在使用中,就是生产环境]
 2,开发环境 [就是开发环境,自己开发测试的环境]
有时候开发环境和生产环境的配置方法是不一样的,那么如何快速的切换呢,这里就要使用profiles文件
实现的方式:
 1.为不同的环境创建不同的配置文件,配置文件的名称:application-Xxx.properties/application-Xxx.yml
 2.在主配置文件中
spring:
	profiles:
		active: Xxx
 
11.2 创建application-dev.yml

11.3 创建application-pro.yml

11.4 修改application.yml
在application.yml的主配置文件中,激活哪个配置文件,就会使用该配置文件进行运行
 
11.5 启动测试

11.6 打jar包部署运行测试

 
cd target 
java -jar jar包名称 --spring.profiles.active=dev
 

java -jar jar包名称 --spring.profiles.active=pro
 

十二、配置文件加载优先级和外部配置文件
12.1 项目内部配置文件
spring boot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
 其中同一目标下的properties文件的优先级大于yml文件
注意:实际开发中建议都直接放在resources目录中
12.1.1 配置文件可以放的位置和优先级
| 路径 | 目录 | 优先级 | 
|---|---|---|
| classpath:/ | resources目录 | 优先级4 | 
| classpath:/config/ | resources目录下的config目录 | 优先级3 | 
| file:./ | 项目根目录 | 优先级2 | 
| file:./config/ | 项目根目录下的config目录 | 优先级1 | 

12.2 外部的配置文件
在E盘放一个application.yml文件 端口指定为8085
 打包后使用命令行运行并且指定
 
cd target
java -jar jar包 --spring.config.location = 配置文件存放全路径(E:/application.yml)
 

十三、编码格式(编码过滤器)(server.servlet.encoding)
application.yml
server:
  servlet:
    encoding:
      enabled: true # 使用指定编码设置 编码过滤器 默认就是true
      charset: UTF-8 # 手动的设置servlet的编码格式
 
十四、如何查看自动配置类生效(debug:true)
我们可以通过启用debug=true属性(在配置文件配置);来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;
在yaml文件中配置debug: true,就能够在控制台打印出那些自动配置类生效、那些自动配置类没有生效,进行查看。
 
 
十五、整合logback
15.1 概述
在搭建新的系统时候必不可少的是需要日志的,日志的作用就不用多说了吧,可以用来调试程序,记录程序运行的状态,最重要的是可以用来排查线上的问题。
 那我们该如何在项目中使用日志呢?
 SpringBoot内部集成了LogBack日志依赖,SpringBoot默认使用LogBack记录日志信息,默认根据base.xml配置内容来输出到控制台和文件之中,不过这些默认的配置不能达到企业级项目的要求
我们可以设置控制日志格式的配置文件
15.2创建模块

15.3 创建logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="10 seconds">
    <!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="D:/mylogs/" />
    <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最低级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!--输出到文件-->
    <!-- 时间滚动输出 level为 DEBUG 日志 -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_debug.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_info.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 时间滚动输出 level为 WARN 日志 -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_warn.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_error.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender>。<logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true。
    -->
    <!--<logger name="org.springframework.web" level="info"/>-->
    <!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
    <!--
        使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
        第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
        第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
     -->
    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->
    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <logger name="com.nmys.view" level="debug"/>
    </springProfile>
    <root level="info">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="DEBUG_FILE" />
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="WARN_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>
    <!--生产环境:输出到文件-->
    <!--<springProfile name="pro">-->
    <!--<root level="info">-->
    <!--<appender-ref ref="CONSOLE" />-->
    <!--<appender-ref ref="DEBUG_FILE" />-->
    <!--<appender-ref ref="INFO_FILE" />-->
    <!--<appender-ref ref="ERROR_FILE" />-->
    <!--<appender-ref ref="WARN_FILE" />-->
    <!--</root>-->
    <!--</springProfile>-->
</configuration>
 
15.4 修改启动类测试

15.5 查看本地日志
D:\mylogs文件夹下
 
十六、AOP开发
16.1 概述
aop是spring的两大功能模块之一,功能非常强大,为解耦提供了非常优秀的解决方案。SpringBoot集成aop是非常方便的,下面使用aop来拦截业务组件的方法
Aop的作用:在不修改源代码的情况下,对类里面的方法进行增强(前置,后置,环绕,异常)
Aop的关键点:
 切入点: 被增强的方法
 通知/增强: 就是具体增强的代码
16.2使用方法
使用springboot操作aop 与 直接使用spring的注解方式操作aop方式是一致的
16.3创建项目并添加maven依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
 
16.4 创建Javabean测试类
javabean
Man.java
package com.bjpowernode.springboot07.javabean;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class Man {
    public void eat(String foodName){
        System.out.println(foodName+"真好吃");
    }
}
 
16.5 创建切面
package com.bjpowernode.springboot07.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class ManAspect {
    @Before("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))")
    public void beforeAdvice(){
        System.out.println("ManAspect.beforeAdvice");
    }
    @After("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))")
    public void afterAdvice(){
        System.out.println("ManAspect.afterAdvice");
    }
    @Around("execution(* com.bjpowernode.springboot07.javabean.Man.eat(..))")
    public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("ManAspect.aroundAdvice--start");
        proceedingJoinPoint.proceed();
        System.out.println("ManAspect.aroundAdvice--end");
    }
}
 
16.6 测试类
package com.bjpowernode.springboot07;
import com.bjpowernode.springboot07.javabean.Man;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot07ApplicationTests {
    @Autowired
    private Man man;
    @Test
    public void testAop(){
        System.out.println(man.getClass().getName());
        man.eat("油条");
    }
}
 
16.7 测试结果

16.8 结论
springboot aop 默认的动态代理方式为cglib
 SpringBoot 2.x开始,AOP为了解决使用JDK动态代理可能导致的类型转换异常,而使用CGLIB。
16.9 三种方式的写法(参考博客)
详见我的博客《SpringBoot AOP》https://blog.csdn.net/weixin_46411355/article/details/128579076
16.10 代理方式的切换
使用JDK动态代理的方式
16.10.1 设计一个接口ManInterface
package com.bjpowernode.springboot07.javabean;
public interface ManInterface {
    void eat(String foodName);
}
 
16.10.2 javaBean目标类Man实现ManInterface接口

package com.bjpowernode.springboot07.javabean;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class Man implements ManInterface{
    public void eat(String foodName){
        System.out.println(foodName+"真好吃");
    }
}
 
从springBoot2.x以后,切换代理方式需要在配置文件中配置,使用注解切换的方式失效了
 
16.10.3 修改application.yml文件的切换方式代理方式
spring:
    aop:
        proxy-target-class: false # false表示使用JDK代理  true表示使用CGLIB代理,SpringBoot2.x以后默认使用CGLIB代理
 
16.10.4 测试类
需要改为注入接口
 package com.bjpowernode.springboot07;
import com.bjpowernode.springboot07.javabean.Man;
import com.bjpowernode.springboot07.javabean.ManInterface;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot07ApplicationTests {
    @Autowired
    private ManInterface man;
    @Test
    public void testAop(){
        System.out.println(man.getClass().getName());
        man.eat("油条");
    }
}
 
16.10.5 测试结果

十七、WEB静态资源访问规则
17.1 springboot访问静态资源的几种方式
查看WebMvcAutoConfiguration里面的静态类WebMvcAutoConfigurationAdapter
 关于资源管的方法addResourceHandlers

 点进去看一下静态资源可以存放的位置
 
 如果这四个目录下面都有相同的文件,那么访问的优先级为:
 META-INF/resources>resources>static>public
建议都放在static目录下
17.2 自定义静态资源访问方式
17.2.1自定义方式1配置文件方式yml
spring:
    web:
        resources:
            static-locations: classpath:/mystatic/  # 静态资源存放的目录
    mvc:
        static-path-pattern: /static/** # 访问mvc的路径映射
 

17.2.2 Java类方式
com.bjpowernode.springboot10staticresource.config
MyWebMvcResourceHandler.java
package com.bjpowernode.springboot10staticresource.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
 * 自己写配置类去实现WebMvc的配置,并且重写
 */
@Configuration
public class MyWebMvcResourceHandler implements WebMvcConfigurer {
    /**
     * 重写静态资源配置的方法
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")//设置自定义的映射路径
                .addResourceLocations("classpath:/mystatic/");//设置自定义的访问路径 注意/不能省略
    }
}
 
17.3 webjars的访问规则
17.3.1什么是webjars
WebJars是打包到JAR(Java Archive)文件中的客户端Web库(例如jQuery和Bootstrap)。
 在基于JVM的Web应用程序中显式轻松地管理客户端依赖项
 使用基于JVM的构建工具(例如Maven,Gradle,sbt,…)来下载客户端依赖项
 了解您正在使用的客户端依赖项
 传递依赖关系会自动解析,并可选择通过RequireJS加载
 官网:https://www.webjars.org/
17.3.2 引入依赖
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.6.0</version>
</dependency>
 
17.3.3启动访问

 在浏览器中访问以下路径
http://localhost:8080/webjars/jquery/3.6.0/jquery.js 
 

 在static目录下,创建webjars.html文件
 
 
 webjars.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--  引入webjars 的 jQuery  -->
    <script src="webjars/jquery/3.6.0/jquery.js"></script>
    <script>
        $(function (){
            alert("hello webjars!");
        })
    </script>
</head>
<body>
</body>
</html>
 
浏览器访问测试
 
十八.Thymeleaf模板的使用
18.1Thymeleaf概述
就是由后端使用response的输出流对象向前端写html格式的内容,写的过程中将后端某些动态的数据添加到html内容中去
18.2创建项目添加thymeleaf的依赖

 
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
 
18.3Spring Boot项目Thymeleaf模板页面存放位置
查看Thymeleaf的自动配置类
 
 
 当然我们也可以自己修改他的位置,只需要在yml文件中修改即可,一般不做修改
 
 案例实操
 pom.xml
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
 
Controller
 
package com.bjpowernode.springboot14thymeleafpagelocation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ThyController {
    @RequestMapping("/mytemplates/hello")
    public String mytemplatesHello(){
        return "myhello";
    }
}
 
myhello.html
 
 application.properties
 
# 应用名称
spring.application.name=springboot14-thymeleaf-pagelocation
# 应用服务 WEB 访问端口
server.port=8080
# THYMELEAF (ThymeleafAutoConfiguration)
# 开启模板缓存(默认值: true )
spring.thymeleaf.cache=true
# 检查模板是否存在,然后再呈现
spring.thymeleaf.check-template=true
# 检查模板位置是否正确(默认值 :true )
spring.thymeleaf.check-template-location=true
#Content-Type 的值(默认值: text/html )
spring.thymeleaf.content-type=text/html
# 开启 MVC Thymeleaf 视图解析(默认值: true )
spring.thymeleaf.enabled=true
# 模板编码
spring.thymeleaf.encoding=UTF-8
# 要被排除在解析之外的视图名称列表,⽤逗号分隔
spring.thymeleaf.excluded-view-names=
# 要运⽤于模板之上的模板模式。另⻅ StandardTemplate-ModeHandlers( 默认值: HTML5)
spring.thymeleaf.mode=HTML5
# 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ )
spring.thymeleaf.prefix=classpath:/mytemplates/
# 在构建 URL 时添加到视图名称后的后缀(默认值: .html )
spring.thymeleaf.suffix=.html
 
application.yml
spring:
  thymeleaf:
    enabled: true # 开启thymeleaf 默认是开启的
    prefix: classpath:/mytemplates/ # 指定页面存放位置
    suffix: .html # 指定页面后缀
    cache: false # 开发时禁用缓存
 
18.4 通过Controller跳转到Thymeleaf的页面
18.4.1在src/main/resources/templates下创建hello.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hello</title>
</head>
<body>
<h1>hello Thymeleaf</h1>
<h1>我是classpath:/templates/hello.html</h1>
</body>
</html>
 
18.4.2 创建RouteController类
@Controller
public class RouteController {
    @RequestMapping("/hello")
    public String hello(){
        /*设置访问当前方法后,当前方法自动的转发到template/hello.html
        * 原理:返回值会被 视图处理器先处理 然后进行转发
        * 视图处理器处理的方式:将返回值 使用指定的前缀与后缀进行拼接,封装为View对象
        * 拼接的方式:前缀+返回值+后缀          当前方法拼接的View对象的路径:classpath:/templates/hello.html
        * 然后使用转发的方式访问该路径对应的文件,最后将该文件的内容解析之后写给浏览器
        */
        return "hello";
    }
}
 
18.4.3测试访问
浏览器访问:http://localhost:8080/hello
 
18.5Thymeleaf的相关语法
官网:https://www.thymeleaf.org/
 表达式
 ${…} 取作用域里面的值 request session applicationContext
 #{…} 取IOC容器中的值
 @{…} URL表达式 th:href=”@{/test(name=’abc’,pwd=’123’)}”
 th:text 标签中取字面值
 th:each 遍历
表达式基本对象
 #locale 本地环境
 #httpServletRequest HttpServletRquest对象
 #httpSession HttpSession对象
 #servletContext servletContext对象
常用工具对象
 #numbers 格式化数字对象的实用方法
 #strings 字符串对象的实用方法:包含startsWith,将/附加等
 #dates java.util的实用方法。对象:日期格式、组件提取等
 #objects:实用方法的对象。
 #bools:布尔评价的实用方法。
 #arrays:数组的实用方法。
 #lists:list集合。
 #sets:set集合。
 #maps:map集合。
 #aggregates:实用程序方法用于创建聚集在数组或集合.
 #ids:实用程序方法来处理可能重复的id属性(例如,由于迭代)。
18.6Thymeleaf读取Model里面的对象
18.6.1创建Hero类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hero {
    private Integer id;
    private String name;
    private String sex;
    private Integer age;
    private String country;
    private String phone;
    private Date birth;
    private Double salary;
}
 
18.6.2在RouteController增加一个方法跳转
@GetMapping("helloHero")
public String helloHero(Model model) {
    Hero hero = new Hero(1, "后羿", "男", 18, "中国", "110", new Date(), 3150D);
    model.addAttribute("hero", hero);
    return "showHero";
}
 
18.6.3创建showHero页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>英雄面板</h1>
<span>英雄id</span> <span th:text="${hero.id}"></span> <br>
<span>英雄名字</span> <span th:text="${hero.name}"></span> <br>
<span>英雄性别</span> <span th:text="${hero.sex}"></span> <br>
<span>英雄年龄</span> <span th:text="${hero.age}"></span> <br>
<span>英雄年龄</span> <span th:text="${#numbers.formatDecimal(hero.age,0,2)}"></span> <br>
<span>英雄国家</span> <span th:text="${hero.country}"></span> <br>
<span>英雄电话</span> <span th:text="${hero.phone}"></span> <br>
<span>英雄生日</span> <span th:text="${hero.birth}"></span> <br>
<span>英雄生日</span> <span th:text="${#dates.format(hero.birth,'yyyy-MM-dd')}"></span> <br>
<span>英雄存款</span> <span th:text="${hero.salary}"></span> <br>
</body>
</html>
 
18.6.4测试访问
http://localhost:8080/helloHero
 
18.7Thymeleaf读取Model里面的集合
18.7.1在RouteController增加一个方法跳转
@GetMapping("helloHeroList")
public String helloHeroList(Model model) {
    ArrayList<Hero> heroes = new ArrayList<>();
    for (int i = 1; i <= 3; i++) {
        heroes.add(new Hero(i, "后裔" + i, "男", 18 + i, "华夏", "110" + i, new Date(), 3150D + i));
    }
    model.addAttribute("heros", heroes);
    return "showHeroList";
}
 
18.7.2创建showHeroList页面
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div th:each="hero: ${heros}">
    <div>
        <span>英雄id</span> <span th:text="${hero.id}"></span> <br>
        <span>英雄名字</span> <span th:text="${hero.name}"></span> <br>
        <span>英雄性别</span> <span th:text="${hero.sex}"></span> <br>
        <span>英雄年龄</span> <span th:text="${hero.age}"></span> <br>
        <span>英雄年龄</span> <span th:text="${#numbers.formatDecimal(hero.age,0,2)}"></span> <br>
        <span>英雄国家</span> <span th:text="${hero.country}"></span> <br>
        <span>英雄电话</span> <span th:text="${hero.phone}"></span> <br>
        <span>英雄生日</span> <span th:text="${hero.birth}"></span> <br>
        <span>英雄生日</span> <span th:text="${#dates.format(hero.birth,'yyyy-MM-dd')}"></span> <br>
        <span>英雄存款</span> <span th:text="${hero.salary}"></span> <br>
    </div>
    <hr>
</div>
</body>
</html>
 
18.7.3测试访问
http://localhost:8080/helloHeroList
 
18.8ThymeleafObjects的使用
18.8.1在RouteController增加一个方法跳转
@GetMapping("thymeleafObject")
public String thymeleafObject(Model model, HttpServletRequest request){
    model.addAttribute("name","超人");
    request.setAttribute("age",22);
    HttpSession session = request.getSession();
    session.setAttribute("address","武汉");
    request.getServletContext().setAttribute("hobby","编码");
    return "showObj";
}
 
18.8.2创建showObj页面
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div>
    model: <span th:text="${name}"></span>
    <hr>
    request: <span th:text="${#httpServletRequest.getAttribute('age')}"></span>
    <hr>
    session: <span th:text="${#httpSession.getAttribute('address')}"></span>
    <hr>
    servletContext: <span th:text="${#servletContext.getAttribute('hobby')}"> </span>
    <hr>
    <div>
        <span th:text="${#locale.getCountry()}"></span>
        <span th:text="${#locale.getLanguage()}"></span>
    </div>
</div>
</body>
</html>
 
18.8.3测试访问
http://localhost:8080/thymeleafObject
 
18.9Thymeleaf在js中取值
18.9.1在RouteController增加一个方法跳转
 @RequestMapping("/js")
    public String jsReadValue(Model model){
        model.addAttribute("name","HHH");
        model.addAttribute("age",24);
        return "js";
    }
 
18.9.2 js.html
src/main/resources/templates

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    // 字符串需要引号
    let name = "[[${name}]]"
    // 数字类型不需要引号
    let age = [[${age}]]
    console.log(name)
    console.log(age)
</script>
</body>
</html>
 
18.9.3 运行效果

18.10Thymeleaf链接接传值
18.10.1在RouteController增加一个方法跳转
   /**
     * 用来转发到测试a标签的页面
     * @return
     */
    @GetMapping("/toHref")
    public String toHref(){
        return "href";
    }
 
18.10.2 href.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a th:href="@{/href(username='jay',password='123456')}">点我呀</a>
</body>
</html>
 
18.10.3 在RouteController增加一个方法跳转
 /**
     * 测试th:href的请求数据的
     * @param username
     * @param password
     * @return
     */
    @GetMapping("/href")
    @ResponseBody
    public String href(String username,String password){
        System.out.println(username+"."+password);
        return "success";
    }
 
18.10.4 运行效果

 
 
十九、SpringBoot自动管理MVC
19.2具体查看视图解析
1.必须是视图解析器 只要实现了ViewResolver都认为是视图解析
 2.被ioc容器管理
19.3具体查看文件上传
直接使用spring:
 1.在springmvc的配置文件中配置文件上传解析器
 2.在controller方法中设置MultipartFile类型的参数,用来接收前端上传文件的所有信息
 3.从MultipartFile对象取出文件的所有内容,读出来再写到服务端的磁盘上,完成上传
使用springboot:
 1.在controller方法中设置MultipartFile类型的参数,用来接收前端上传文件的所有信息
 2.从MultipartFile对象取出文件的所有内容,读出来再写到服务端的磁盘上,完成上传
总结:springboot其实就是帮我们自动的配置了文件上传解析器,使用的方式与直接使用spring是一致的
MultipartAutoConfiguration中帮我们自动配置了
 
案例实操
src/main/resources/static
 Upload.html
 
 controller层
package com.bjpowernode.springboot20fileupload.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@RestController
public class FileController {
    @PostMapping("/upload")
    public String upload(MultipartFile file) throws IOException {
        file.transferTo(new File("D:/"+file.getOriginalFilename()));
        return "success";
    }
}
 
测试结果
 
 
 
 MultipartProperties配置文件中可以设定参数,可以的yml文件里面配置
 
application.yml
spring:
  servlet:
    # 设置文件上传的相关属性
    multipart:
      enabled: true # 设置是否开启文件上传功能 默认就是true
      max-file-size: 9999999MB #设置上传文件最大的大小 可以使用MB GB TB
      max-request-size: 99999999MB #设置上传所有的文件的最大的大小
 
19.4具体查看格式化【接收页面参数并转化】
我们也可以配置文件中自己配置
 application.yml
spring:
  mvc:
    format:
      date: yyyy-MM-dd HH:mm:ss #设置String->Date的转换器的格式
 
版本说明
 format.date ----java.utils.Date
 format.date-time —java.time.LocalDateTime
src/main/resources/static
 convert.html
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="get" action="/convert">
    <input type="text" name="date">
    <input type="submit">
</form>
</body>
</html>
 
controller层
package com.bjpowernode.springboot21format.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
public class ConvertController {
    @GetMapping("/convert")
    public Date convert(Date date){
        return date;
    }
}
 
运行结果
 
 
19.5欢迎页面自动配置
在任意一个静态资源路径中添加index.html 就是当前项目的欢迎页面
 
 运行项目
 
二十、扩展MVC的组件【掌握】
组件:视图控制器、拦截器(Interceptor) 、 servlet 、 过滤器(Filter) 、监听器(Listener)
20.1自定义视图控制器【熟悉】
视图控制器:一个请求进来后,控制响应的视图的工具
 创建一个配置类实现WebMvcConfigurer重写之前的方法即可实现自定义拓展
src/main/resources/templates
 hello.html
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
hello......................................
</body>
</html>
 
之前写Controller
package com.bjpowernode.springboot23viewcontroller.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
    @GetMapping("/test")
    public String test(){
        return "hello";
    }
}
 
运行效果
 
这样我们就不需要写controller
 
src/main/java/com/bjpowernode/springboot23viewcontroller/config
 MyWebMvcConfiger.java
package com.bjpowernode.springboot23viewcontroller.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfiger implements WebMvcConfigurer {
    /**
     * 声明视图控制器
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //表示如果请求的路径:/test 则响应的视图名称为hello    使用转发的方式跳转到指定的视图
        registry.addViewController("/test").setViewName("hello");
        //使用重定向的方式 为指定的请求url 设置响应的资源
        registry.addRedirectViewController("baidu","http://www.baidu.com");
    }
}
 
运行效果
 
 
 
20.2 SpringBoot 自定义拦截器
一、自定义拦截器
创建登录拦截器
com/bjpowernode/springbootinterceptor02/interceptor
 LoginInterceptor.java
package com.bjpowernode.springbootinterceptor02.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor implements HandlerInterceptor {
    /**
     *
     * @param request
     * @param response
     * @param handler 被拦截器的控制器对象
     * @return boolean
     *  true:请求能被controller处理
     *  false:请求被截断
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("执行了LoginInterceptor的preHandle");
        return true;
    }
}
 
二、编写控制器
com/bjpowernode/springbootinterceptor02/controller
 BootController.java
package com.bjpowernode.springbootinterceptor02.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class BootController {
    @RequestMapping("/user/userAccount")
    @ResponseBody
    public String userAccount(){
        return "访问user/userAccount";
    }
    @RequestMapping("/user/userLogin")
    @ResponseBody
    public String userLogin(){
        return "访问user/userLogin";
    }
}
 
三、添加拦截器对象,注入到容器的配置类中
package com.bjpowernode.springbootinterceptor02.config;
import com.bjpowernode.springbootinterceptor02.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器对象,注入到容器中
        // 可以不采用new的方式直接在登录拦截器中加入@Component注解 在本类中用@Autowired注入
        LoginInterceptor loginInterceptor = new LoginInterceptor();
        //指定拦截的地址
        String path[] = {"/user/**"};
        //指定不拦截的地址
        String excludePath[] = {"/user/userLogin"};
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns(path)
                .excludePathPatterns(excludePath);
    }
}
 
另一种写法
也可以使用@Component注解将LoginController交给Spring容器管理
 
 则在添加拦截器对象,注入到容器的配置类中
 不需要使用new LoginController来创建对象
 直接通过@Autowired注解注入即可
 
四、最后application运行
访问 localhost:8080/user/userLogin,拦截器放行
 
 访问localhost:8080user/userAccount,拦截器生效
 
 控制台输出:
 
二十一、注册Web三大组件【重点】
首先查看注册组件的结构
 
21.1注册自己的Servlet
21.1.1注册自己的Servlet(案例实操一)
我们可以模仿DispatcherServlet的注册方式
21.1.1.1 创建MyServlet
package com.bjpowernode.springboot25servlet.servlet;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
* 自定义的servlet
* springboot中不要使用@WebServlet注册了 因为没效果
*/
//@WebServlet("/myServlet")
@Component
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("MyServlet.doGet");
    }
}
 
21.1.1.2在配置类注册自己的servlet
package com.bjpowernode.springboot25servlet.config;
import com.bjpowernode.springboot25servlet.servlet.MyServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Autowired
    private MyServlet myServlet;
    /*
    *注册自定义的Servlet
    */
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        //1.创建注册器对象
        ServletRegistrationBean<MyServlet> registrationBean = new ServletRegistrationBean<>();
        //2.将我们自定义的servlet对象注册到注册器中
        registrationBean.setServlet(myServlet);
        //3.设置注册的属性
        registrationBean.addUrlMappings("/myServlet");
        registrationBean.setLoadOnStartup(0);
        //4.返回注册器对象
        return registrationBean;
    }
}
 
21.1.1.3 运行效果
浏览器访问:http://localhost:8080/myServlet
 
 控制台输出
 
21.1.2注册自己的Servlet(案例实操二)
我们可以模仿DispatcherServlet的注册方式
21.1.2.1创建UserServlet
package com.bjpowernode.springboot25servlet02.servlet;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Component
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      this.doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("这是我自己的servlet");
        PrintWriter writer = resp.getWriter();
        writer.write("hello");
        writer.flush();
        writer.close();
    }
}
 
21.1.2.2在配置类注册自己的servlet
package com.bjpowernode.springboot25servlet02.config;
import com.bjpowernode.springboot25servlet02.servlet.UserServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyWebConfig {
    @Autowired
    private UserServlet userServlet;
    @Bean
    public ServletRegistrationBean<UserServlet> userServletServletRegistrationBean(){
        ServletRegistrationBean<UserServlet> registrationBean = new ServletRegistrationBean<>();
        registrationBean.setServlet(userServlet);
        registrationBean.addUrlMappings("/user");//相当于@WebServlet(/user)
        return registrationBean;
    }
}
 
21.1.2.3 运行效果

21.2SpringBoot 注册自己的Servlet(三种方式)
详见我的博客《SpringBoot 注册自己的Servlet(三种方式)》https://huanghaoheng.blog.csdn.net/article/details/128703156
21.3 注册自己的Filter
详见我的博客《SpringBoot的filter过滤器》https://huanghaoheng.blog.csdn.net/article/details/128708392
21.4 注册自己的Listener
21.4.1创建MyListener
package com.bjpowernode.springbootfilter.listener;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
 * 自定义的监听器
 * 监听ServletContext的生命周期
 * 也就是说可以监听到ServletContext的初始化 直到 被销毁
 */
@Component
public class MyListener implements ServletContextListener{
    /**
     * 这个方法会在ServletContext被初始化的时候,自动的触发
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("MyListener.contextInitialized");
    }
    /**
     * 这个方法会在ServletContext被销毁的时候,自动的触发
     * @param sce
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("MyListener.contextDestroyed");
    }
}
 
21.4.2在配置类里面注册自己的监听器
package com.bjpowernode.springbootfilter.config;
import com.bjpowernode.springbootfilter.filter.MyFilter;
import com.bjpowernode.springbootfilter.interceptor.MyInterceptor;
import com.bjpowernode.springbootfilter.listener.MyListener;
import com.bjpowernode.springbootfilter.servlet.MyServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.ServletRegistration;
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Autowired
    private MyListener myListener;
    /*
    * 注册自定义的Listener
    */
    @Bean
    public ServletListenerRegistrationBean<MyListener> servletListenerRegistrationBean(){
        //1.创建注册器对象
        ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>();
        //2.将我们自定义的listener对象注册器中
        registrationBean.setListener(myListener);
        return registrationBean;
    }
}
 
21.4.3 测试

 
 
 
二十二.使用外部tomcat【了解】
使用外部tomcat的springboot项目的特点:
 1.打包的方式:war
 2.需要一个SpringBootServletInitializer的子类,来初始化servlet
22.1创建项目,选择打包方式为war包

 https://start.aliyun.com/
 
 
22.2选择依赖

22.3配置pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<!--加入内嵌入tomcat对jsp的支持-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>
<!-- servlet 依赖 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <scope>provided</scope>
</dependency>
<!--jstl的依赖 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.1.2</version>
</dependency>
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>
 
22.4添加IDEA配置

 
 
 点击OK
 
22.5配置外部tomcat

 
 
 找到Tomcat的安装路径
 
 点击OK
 
 点击“+”号,然后点击Artifact

 选择带exploded的那个
 
 
================================================================================
22.6创建controller(返回JSON字符串)
package com.bjpowernode.springboot26tomcat.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}
 
22.7 测试
================================================================================
22.8创建Controller(返回jsp页面)
@Controller
public class TestController {
    @GetMapping("test")
    public String test(){
        return "test";
    }
}
 
22.9创建页面
在webapp->WEB-INF->view路径下创建test.jsp
 
22.10修改配置文件
application.yml
spring:
    mvc:
        view:
            prefix: /WEB-INF/view/
            suffix: .jsp
 
22.11 启动访问
浏览器访问:http://localhost:8080/test
 
二十三.数据源配置和自动管理【重中之中】
23.1创建项目选择依赖

 
 
23.2使用DriverManagerDataSource
23.2.1修改配置文件
application.properties全部注销掉不用
application.yml
spring:
  datasource:
    type: org.springframework.jdbc.datasource.DriverManagerDataSource #使用spring自带的数据源
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
 
23.2.2 测试类
package com.bjpowernode.springboot27datasource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@SpringBootTest
class Springboot27DatasourceApplicationTests {
    @Autowired
    private DataSource dataSource;
    @Test
    void contextLoads() throws SQLException {
        System.out.println(dataSource);
        System.out.println(dataSource.getClass().getName());
        Connection connection = dataSource.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement("select * from user");
        ResultSet resultSet = preparedStatement.executeQuery();
        while(resultSet.next()){
            Object name = resultSet.getObject("name");
            System.out.println(name);
        }
    }
}
 
23.2.3 测试效果

23.4使用Druid数据源【官方starter】
23.4.1导入依赖
pom.xml
 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.5</version>
        </dependency>
 
23.4.2 application.yml
application.properties全部注销掉不用
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
    # 设置使用druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
 
23.4.3 测试类不变 和 测试效果

23.4.4 换成启动器依赖druid-spring-boot-starter
 
把pom.xml刚刚导入的druid的依赖换成启动器druid-spring-boot-starter
   <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>
      
 
注意:换成启动器druid-spring-boot-starter除了导入druid数据源的依赖之外,
 还会引入自动配置类,而自动配置类就会帮我们读取配置文件中的内容,所以现在在application.yml配置文件中可以写其他内容了
23.4.5 application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
    # 设置使用druid数据源,pom.xml中导入的是com.alibaba的druid依赖
    type: com.alibaba.druid.pool.DruidDataSource
    #以下内容,pom.xml导入的是com.alibaba的启动器依赖druid-spring-boot-starter
    druid:
      min-idle: 3 # 最小的连接数
      max-active: 15
      #druid提供了数据源的监控功能
      #它是提供了一个servlet让我们去访问,访问这个Servlet,就返回一个资源,这个资源可以看到数据源的状态
      stat-view-servlet: #设置druid提供的数据源的监控Servlet
        login-username: HHH # 设置访问此Servlet时登录的用户名
        login-password: 123456 # 设置访问此Servlet是登录的密码
        deny: #设置访问此Servlet的黑名单
        allow: #设置访问此Servlet的白名单
        url-pattern: /druid/* #设置访问此Servlet的url-pattern
        enabled: true # 设置启用监控功能
 
23.4.6 测试
启动当前项目 启动启动类
 
 浏览器访问http://localhost:8080/druid
 
 
 输入用户名:HHH
 密码:123456
 
 
 
23.5使用Druid数据源【自己配置】(powernode CD2206)
注意:真实开发中都是用druid官方的启动器,不要手写
就是 只导入druid的依赖(数据源、servlet),然后 自己写自动配置类
23.5.1 步骤说明
1.自动配置类
 1.1 创建数据源对象添加到ioc容器中
 1.2 读取配置文件,为数据源对象属性赋值
 2.配置druid的监控页的servlet
 读取配置文件的内容对servlet的相关属性进行赋值并配置
23.5.2 创建项目

 
 



 pom.xml版本换成2.7.7
 
23.5.3 添加durid的依赖
 <!--
            导入druid数据源
            注意:不是启动器,需要自己实现自动配置类
        -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.15</version>
        </dependency>
 
23.5.4.application.yml
application.properties全部注释掉
myDruid:
  driver-class-name: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC
  username: root
  password: root
  min-idle: 3 # 最小的连接数
  max-active: 15 # 最大连接数
  validation-query: select 'a'
 
23.5.5 添加MyDruidProperties配置文件类
package com.bjpowernode.springboot27datasourcedruidselfconfiguration2206.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
 * 用来读取配置文件中druid相关的内容
 */
@Component
//@ConfigurationProperties("mydruid")
@ConfigurationProperties("my-druid")
@Data
public class MyDruidProperties {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private int minIdle;
    private int maxActive;
    private String validationQuery;
}
 
注意:@ConfigurationProperties()注解中的参数一定要全小写
23.5.6.添加MyDruidAutoConfiguration自动配置类
package com.bjpowernode.springboot27datasourcedruidselfconfiguration2206.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
 * 自定义的druid数据源的自动配置类
 * 需要做的事情
 * 1.创建Druid数据源对象交给ioc容器管理
 * 2.读取配置文件的内容为数据源对象属性赋值
 *
 * 3.创建StatViewServlet对象并注册
 * 4.读取配置文件的内容为Servlet属性赋值
 */
@Configuration
//2.读取配置文件的内容
//指定MyDruidProperties类读取配置文件中druid中相关的内容
@EnableConfigurationProperties(MyDruidProperties.class)
public class MyDruidAutoConfiguration {
    @Autowired
    private MyDruidProperties myDruidProperties;
    /**
     * 创建数据源对象 交给IOC容器管理
     * @return
     */
    @Bean(initMethod = "init",destroyMethod = "close")
    public DruidDataSource druidDataSource(){
        //1.创建Druid数据源对象交给ioc容器管理
        DruidDataSource druidDataSource = new DruidDataSource();
        //2.为数据源对象属性赋值
        druidDataSource.setDriverClassName(myDruidProperties.getDriverClassName());
        druidDataSource.setUrl(myDruidProperties.getUrl());
        druidDataSource.setUsername(myDruidProperties.getUsername());
        druidDataSource.setPassword(myDruidProperties.getPassword());
        druidDataSource.setMinIdle(myDruidProperties.getMinIdle());
        druidDataSource.setMaxActive(myDruidProperties.getMaxActive());
        druidDataSource.setValidationQuery(myDruidProperties.getValidationQuery());
        //返回数据源对象
        return druidDataSource;
    }
   
}
 
23.5.7 测试类
package com.bjpowernode.springboot27datasourcedruidselfconfiguration2206;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootTest
class Springboot27DatasourceDruidSelfconfiguration2206ApplicationTests {
    @Autowired
    private DataSource dataSource;
    @Test
    void contextLoads() throws SQLException {
        System.out.println("dataSource = " + dataSource);
        Connection connection = dataSource.getConnection();
        System.out.println("connection = " + connection);
    }
}
 
23.5.8 配置druid数据源的监控功能
配置druid提供的数据源的监控功能,它是提供了一个servlet让我们去访问,访问这个Servlet,就返回一个资源,这个资源可以看到数据源的状态
23.5.8.1 application.yml
配置文件加上如下内容
 
application.yml
myDruid:
  driver-class-name: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC
  username: root
  password: root
  min-idle: 3 # 最小的连接数
  max-active: 15 # 最大连接数
  validation-query: select 'a'
  my-stat-view-servlet: #设置druid提供的数据源的监控Servlet
    login-username: HHH # 设置访问此Servlet时登录的用户名
    login-password: 123456 # 设置访问此Servlet是登录的密码
    url-pattern: /druid/* #设置访问此Servlet的url-pattern
    enabled: true # 设置启用监控功能
 
23.5.8.2 读取druid配置文件的类MyDruidProperties.java
MyDruidProperties加入如下内容

 MyDruidProperties.java
package com.bjpowernode.springboot27datasourcedruidselfconfiguration2206.config;
import com.alibaba.druid.support.http.StatViewServlet;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
 * 用来读取配置文件中druid相关的内容
 */
@Component
@ConfigurationProperties("mydruid")
//@ConfigurationProperties("my-druid")
@Data
public class MyDruidProperties {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private int minIdle;
    private int maxActive;
    private String validationQuery;
    /*
    * 此属性不是普通属性 是javabean类型
    * 所以会将配置文件中对应的数据的子数据作为此对象的属性进行匹配与赋值
    */
    private MyStatViewServlet myStatViewServlet;
    @Data
    static class MyStatViewServlet{
        private String loginUsername;
        private String loginPassword;
        private String urlPattern;
        private String enabled;
    }
}
 
因为在application.yml的层级关系是嵌套关系,所以在MyDruidProperties类中以内部类的形式展现
23.5.8.3 修改MyDruidAutoConfiguration类
MyDruidAutoConfiguration类中创建StatViewServlet对象 交给IOC容器管理
 
 添加的代码
 /**
     *创建StatViewServlet对象 交给IOC容器管理
     * @return
     */
    @Bean
    public ServletRegistrationBean<StatViewServlet> servletRegistrationBean(){
        ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<>();
        StatViewServlet statViewServlet = new StatViewServlet();
        servletRegistrationBean.setServlet(statViewServlet);
        //给StatViewServlet的属性赋值
        servletRegistrationBean.addUrlMappings(this.myDruidProperties.getMyStatViewServlet().getUrlPattern());
        /*
        * loginUsername 并不是servlet的通用属性
        * 所以servletRegistrationBean并没有设计为这个属性赋值的方法
        * 只能通过为该servle添加初始化参数的方式进行绑定
        */
        servletRegistrationBean.addInitParameter("loginUsername",this.myDruidProperties.getMyStatViewServlet().getLoginUsername());
        servletRegistrationBean.addInitParameter("loginPassword",this.myDruidProperties.getMyStatViewServlet().getLoginPassword());
        servletRegistrationBean.addInitParameter("enable",this.myDruidProperties.getMyStatViewServlet().getEnabled());
        return servletRegistrationBean;
    }
 
MyDruidAutoConfiguration类全部代码
 MyDruidAutoConfiguration.java
package com.bjpowernode.springboot27datasourcedruidselfconfiguration2206.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
 * 自定义的druid数据源的自动配置类
 * 需要做的事情
 * 1.创建Druid数据源对象交给ioc容器管理
 * 2.读取配置文件的内容为数据源对象属性赋值
 *
 * 3.创建StatViewServlet对象并注册
 * 4.读取配置文件的内容为Servlet属性赋值
 */
@Configuration
//2.读取配置文件的内容
//指定MyDruidProperties类读取配置文件中druid中相关的内容
@EnableConfigurationProperties(MyDruidProperties.class)
public class MyDruidAutoConfiguration {
    @Autowired
    private MyDruidProperties myDruidProperties;
    /**
     * 创建数据源对象 交给IOC容器管理
     * @return
     */
    @Bean(initMethod = "init",destroyMethod = "close")
    public DruidDataSource druidDataSource(){
        //1.创建Druid数据源对象交给ioc容器管理
        DruidDataSource druidDataSource = new DruidDataSource();
        //2.为数据源对象属性赋值
        druidDataSource.setDriverClassName(myDruidProperties.getDriverClassName());
        druidDataSource.setUrl(myDruidProperties.getUrl());
        druidDataSource.setUsername(myDruidProperties.getUsername());
        druidDataSource.setPassword(myDruidProperties.getPassword());
        druidDataSource.setMinIdle(myDruidProperties.getMinIdle());
        druidDataSource.setMaxActive(myDruidProperties.getMaxActive());
        druidDataSource.setValidationQuery(myDruidProperties.getValidationQuery());
        //返回数据源对象
        return druidDataSource;
    }
    /**
     *创建StatViewServlet对象 交给IOC容器管理
     * @return
     */
    @Bean
    public ServletRegistrationBean<StatViewServlet> servletRegistrationBean(){
        ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<>();
        StatViewServlet statViewServlet = new StatViewServlet();
        servletRegistrationBean.setServlet(statViewServlet);
        //给StatViewServlet的属性赋值
        servletRegistrationBean.addUrlMappings(this.myDruidProperties.getMyStatViewServlet().getUrlPattern());
        /*
        * loginUsername 并不是servlet的通用属性
        * 所以servletRegistrationBean并没有设计为这个属性赋值的方法
        * 只能通过为该servle添加初始化参数的方式进行绑定
        */
        servletRegistrationBean.addInitParameter("loginUsername",this.myDruidProperties.getMyStatViewServlet().getLoginUsername());
        servletRegistrationBean.addInitParameter("loginPassword",this.myDruidProperties.getMyStatViewServlet().getLoginPassword());
        servletRegistrationBean.addInitParameter("enable",this.myDruidProperties.getMyStatViewServlet().getEnabled());
        return servletRegistrationBean;
    }
}
 
23.5.9 测试
启动当前项目 启动启动类
 
浏览器访问http://localhost:8080/druid
 
 
 输入用户名:HHH
 密码:123456
 
 
 
二十四、 集成Mybatis
24.1说明
之前手动配置Mybatis步骤
 1.配置数据源
 2.配置SqlSessionFactoryBean:引入Mybatis核心配置文件
 3.扫描mapper包
springboot整合Mybatis步骤
 1.配置数据源
 2.配置mybatis的核心信息
 3.扫描mapper
 
24.2 pom.xml
pom.xml导入druid的启动器依赖
 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.6</version>
        </dependency>
 
24.3 application.yml
# 配置mybatis 之前手动配置:1.配置数据源  2.配置SqlSessionFactoryBean:引入Mybatis核心配置文件 3.扫描mapper包
# springboot整合mybatis 1.配置数据源 2.配置mybatis的核心信息  3.扫描mapper
spring:
  # 配置数据源
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
    druid:
      min-idle: 3
      max-active: 15
# 配置mybatis
mybatis:
  mapper-locations: classpath:mapper/*.xml #配置读取映射配置文件的路径
  type-handlers-package: com.bjpowernode.springboot28mybatis.domain # 读取指定包中的所有类并取别名
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 设置mybatis的日志的具体实现
 
24.4 启动类
package com.bjpowernode.springboot28mybatispagehelper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = "com.bjpowernode.springboot28mybatispagehelper.mapper")//扫描mapper包
@SpringBootApplication
public class Springboot28MybatisPagehelperApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot28MybatisPagehelperApplication.class, args);
    }
}
 
24.5 javabean(User类)
User.java
package com.bjpowernode.springboot28mybatispagehelper.domain;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
 * @TableName user
 */
@Data
public class User implements Serializable {
    private Integer id;
    private String name;
    private String portrait;
    private String phone;
    private String password;
    private String regIp;
    private Boolean accountNonExpired;
    private Boolean credentialsNonExpired;
    private Boolean accountNonLocked;
    private String status;
    private Boolean isDel;
    private Date createTime;
    private Date updateTime;
    private static final long serialVersionUID = 1L;
}
 
24.6 UserMapper.java接口
package com.bjpowernode.springboot28mybatispagehelper.mapper;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author HHH
* @description 针对表【user】的数据库操作Mapper
* @createDate 2023-01-31 20:38:15
* @Entity com.bjpowernode.springboot28mybatispagehelper.domain.User
*/
@Mapper
public interface UserMapper {
    List<User> selectAllUser();
}
 
24.7 UserMapper.xml配置文件
<?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.bjpowernode.springboot28mybatispagehelper.mapper.UserMapper">
    <resultMap id="BaseResultMap" type="com.bjpowernode.springboot28mybatispagehelper.domain.User">
            <id property="id" column="id" jdbcType="INTEGER"/>
            <result property="name" column="name" jdbcType="VARCHAR"/>
            <result property="portrait" column="portrait" jdbcType="VARCHAR"/>
            <result property="phone" column="phone" jdbcType="VARCHAR"/>
            <result property="password" column="password" jdbcType="VARCHAR"/>
            <result property="regIp" column="reg_ip" jdbcType="VARCHAR"/>
            <result property="accountNonExpired" column="account_non_expired" jdbcType="BIT"/>
            <result property="credentialsNonExpired" column="credentials_non_expired" jdbcType="BIT"/>
            <result property="accountNonLocked" column="account_non_locked" jdbcType="BIT"/>
            <result property="status" column="status" jdbcType="VARCHAR"/>
            <result property="isDel" column="is_del" jdbcType="BIT"/>
            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
    </resultMap>
    <sql id="Base_Column_List">
        id,name,portrait,
        phone,password,reg_ip,
        account_non_expired,credentials_non_expired,account_non_locked,
        status,is_del,create_time,
        update_time
    </sql>
    <select id="selectAllUser" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/> from user
    </select>
</mapper>
 
24.8 service层接口
package com.bjpowernode.springboot28mybatispagehelper.service;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import java.util.List;
public interface UserService {
    List<User> findAllUser();
}
 
service层实现类
package com.bjpowernode.springboot28mybatispagehelper.service.impl;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.bjpowernode.springboot28mybatispagehelper.mapper.UserMapper;
import com.bjpowernode.springboot28mybatispagehelper.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public List<User> findAllUser() {
        return userMapper.selectAllUser();
    }
}
 
24.9 测试类
package com.bjpowernode.springboot28mybatispagehelper;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.bjpowernode.springboot28mybatispagehelper.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class Springboot28MybatisPagehelperApplicationTests {
    @Autowired
    private UserService userService;
    @Test
    void contextLoads() {
        List<User> users = userService.findAllUser();
        System.out.println(users);
    }
}
 
24.10 配置PageHelper插件分页
使用的方式没有区别
 但是配置有区别:
 1.之前的配置
 1.1导入pageHelper的依赖
 1.2引用pageHelper插件
2.springboot的配置
 导入pageHelper的启动器
24.10.1 pom.xml依赖pageHelper的starter
   <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>1.4.1</version>
    </dependency>
 
24.10.2 service层接口

package com.bjpowernode.springboot28mybatispagehelper.service;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.github.pagehelper.PageInfo;
import java.util.List;
public interface UserService {
    List<User> findAllUser();
    PageInfo<User> findAllUserByPageHelper(Integer pageNum,Integer pageSize);
}
 
24.10.3 service层实现类

package com.bjpowernode.springboot28mybatispagehelper.service.impl;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.bjpowernode.springboot28mybatispagehelper.mapper.UserMapper;
import com.bjpowernode.springboot28mybatispagehelper.service.UserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public List<User> findAllUser() {
        return userMapper.selectAllUser();
    }
    @Override
    public PageInfo<User> findAllUserByPageHelper(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<User> userList = userMapper.selectAllUser();
        PageInfo<User> pageInfo = new PageInfo<>(userList);
        return pageInfo;
    }
}
 
24.10.4 测试类

package com.bjpowernode.springboot28mybatispagehelper;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.bjpowernode.springboot28mybatispagehelper.service.UserService;
import com.github.pagehelper.PageInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class Springboot28MybatisPagehelperApplicationTests {
    @Autowired
    private UserService userService;
    @Test
    void contextLoads() {
        List<User> users = userService.findAllUser();
        System.out.println(users);
    }
    @Test
    public void testPageHelper(){
        PageInfo<User> pageInfo = userService.findAllUserByPageHelper(1, 3);
        List<User> list = pageInfo.getList();
        System.out.println(list);
    }
}
 
24.11 事务管理
直接在spring中使用事务没有区别
 但有配置区别:
之前的配置
 1.配置事务管理器
 2.通过@Transactional注解为指定的类的所有方法或者为指定单个方法添加事务
现在的配置:
 无配置,直接使用@Transactional
24.11.1 service层接口类

package com.bjpowernode.springboot28mybatispagehelper.service;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.github.pagehelper.PageInfo;
import java.util.List;
public interface UserService {
    List<User> findAllUser();
    PageInfo<User> findAllUserByPageHelper(Integer pageNum,Integer pageSize);
    void addUser(User user);
}
 
24.11.2 service层实现类

package com.bjpowernode.springboot28mybatispagehelper.service.impl;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.bjpowernode.springboot28mybatispagehelper.mapper.UserMapper;
import com.bjpowernode.springboot28mybatispagehelper.service.UserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public List<User> findAllUser() {
        return userMapper.selectAllUser();
    }
    @Override
    public PageInfo<User> findAllUserByPageHelper(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<User> userList = userMapper.selectAllUser();
        PageInfo<User> pageInfo = new PageInfo<>(userList);
        return pageInfo;
    }
    /*
    * 测试事务的使用
    */
    @Transactional
    @Override
    public void addUser(User user) {
        int result = userMapper.insertUser(user);
//        System.out.println(1/0);
        if(result!=1){
            throw new RuntimeException("添加失败");
        }
    }
}
 
24.11.3 mapper接口类

package com.bjpowernode.springboot28mybatispagehelper.mapper;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author HHH
* @description 针对表【user】的数据库操作Mapper
* @createDate 2023-01-31 20:38:15
* @Entity com.bjpowernode.springboot28mybatispagehelper.domain.User
*/
@Mapper
public interface UserMapper {
    List<User> selectAllUser();
    int insertUser(User user);
}
 
24.11.4 mapper.xml配置文件类

<?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.bjpowernode.springboot28mybatis.mapper.UserMapper">
    <resultMap id="BaseResultMap" type="com.bjpowernode.springboot28mybatis.domain.User">
            <id property="id" column="id" jdbcType="INTEGER"/>
            <result property="name" column="name" jdbcType="VARCHAR"/>
            <result property="portrait" column="portrait" jdbcType="VARCHAR"/>
            <result property="phone" column="phone" jdbcType="VARCHAR"/>
            <result property="password" column="password" jdbcType="VARCHAR"/>
            <result property="regIp" column="reg_ip" jdbcType="VARCHAR"/>
            <result property="accountNonExpired" column="account_non_expired" jdbcType="BIT"/>
            <result property="credentialsNonExpired" column="credentials_non_expired" jdbcType="BIT"/>
            <result property="accountNonLocked" column="account_non_locked" jdbcType="BIT"/>
            <result property="status" column="status" jdbcType="VARCHAR"/>
            <result property="isDel" column="is_del" jdbcType="BIT"/>
            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
    </resultMap>
    <sql id="Base_Column_List">
        id,name,portrait,
        phone,password,reg_ip,
        account_non_expired,credentials_non_expired,account_non_locked,
        status,is_del,create_time,
        update_time
    </sql>
    <insert id="insertUser">
        insert into user(id,name) values (#{id},#{name})
    </insert>
    <select id="selectAllUser" resultMap="BaseResultMap">
        select <include refid="Base_Column_List"/> from user
    </select>
</mapper>
 
24.11.5 测试类

package com.bjpowernode.springboot28mybatispagehelper;
import com.bjpowernode.springboot28mybatispagehelper.domain.User;
import com.bjpowernode.springboot28mybatispagehelper.service.UserService;
import com.github.pagehelper.PageInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class Springboot28MybatisPagehelperApplicationTests {
    @Autowired
    private UserService userService;
    @Test
    void contextLoads() {
        List<User> users = userService.findAllUser();
        System.out.println(users);
    }
    @Test
    public void testPageHelper(){
        PageInfo<User> pageInfo = userService.findAllUserByPageHelper(1, 3);
        List<User> list = pageInfo.getList();
        System.out.println(list);
    }
    @Test
    void testTransaction(){
        User user = new User();
        user.setName("jay");
        userService.addUser(user);
    }
}
 
二十五、集成swagger【熟悉】
请查看笔者的博文
 1、《SpringBoot集成swagger3(powernode CD2207)(内含教学视频+源代码)》——https://huanghaoheng.blog.csdn.net/article/details/128966897
 2、《SpringBoot集成Swagger3(powernode document)(内含源代码)》——https://huanghaoheng.blog.csdn.net/article/details/129005812
二十六 Spring Boot定时任务
26.1概述
以控制指定的方法在指定的时间执行,并且还能控制该方法以指定的频率重复执行
- sprignBoot定时任务是与quartz整合,不需要添加任何的依赖
 - 在springBoot的启动类上添加
@EnableScheduling注解开启定时调度 - 在需要定时调度的方法上添加
@Scheduled这个注解即可,其中可以指定cron表达式和其他的定时方式 
26.2最佳实践
26.2.1 创建一个SpringBoot项目

 
26.2.2 开启定时任务

package com.bjpowernode.springboottimedtask;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication//开启定时任务功能
public class SpringbootTimedtaskApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootTimedtaskApplication.class, args);
    }
}
 
26.2.3 执行任务
package com.bjpowernode.springboottimedtask.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyTask {
    /*
    *指定当前方法被定时任务调度
    * 建议使用cron表达式来指定调用的时间以及频率
    * cron表达式的语法:秒 分 时 日 月 星期 年
    * 每一个时间单位的值:
    *       * : 匹配任意时间
    *       纯数字:指定具体的时间点
    *       0/3 : 表示从0秒开始 每隔3秒执行一次
    *       ? 用在日 或者 星期
    */
    @Scheduled(cron = "0/3 * * * * ?")
    public void task1(){
        System.out.println("我是任务一");
    }
}
 
26.2.4 运行测试
.
26.2.5 阿里云Cron表达式官网
https://help.aliyun.com/document_detail/64769.html
二十七 SpringBoot 邮件发送
可以查看笔者的另外2篇博文
 1、Spring Boot邮件发送(powernode document)(内含源代码)——https://huanghaoheng.blog.csdn.net/article/details/129040069
 2、Spring Boot邮件发送(powernode CD2207)(内含教训视频+源代码)——https://huanghaoheng.blog.csdn.net/article/details/129029939














![[qiankun]-多页签缓存](https://img-blog.csdnimg.cn/48dd4bc1aed04385851a296c9b047a6d.png)




