SpringBoot(powernode)(内含教学视频+源代码)

news2024/11/26 16:36:24

SpringBoot(powernode)(内含教学视频+源代码)

教学视频+源代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87484637

目录

  • SpringBoot(powernode)(内含教学视频+源代码)
  • `教学视频+源代码下载链接地址:`[https://download.csdn.net/download/weixin_46411355/87484637](https://download.csdn.net/download/weixin_46411355/87484637)
    • 一、第一个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请求映射
@GetMappingGET请求
@PostMappingPOST请求
@DeleteMappingDELETE请求
@PutMappingPUT请求
@PatchMappingPATCH请求
@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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/364924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AcWing3490.小平方——学习笔记

目录 题目 代码 AC结果 思路 题目 3490. 小平方 - AcWing题库https://www.acwing.com/problem/content/3493/ 代码 import java.util.Scanner;public class Main {public static void main(String[] args){Scanner input new Scanner(System.in);int target input.nextI…

Python 自动化测试必会技能板块—unittest框架

说到 Python 的单元测试框架&#xff0c;想必接触过 Python 的朋友脑袋里第一个想到的就是 unittest。的确&#xff0c;作为 Python 的标准库&#xff0c;它很优秀&#xff0c;并被广泛应用于各个项目。但其实在 Python 众多项目中&#xff0c;主流的单元测试框架远不止这一个。…

谷歌seo关键词怎么做?Google如何优化关键词

本文主要分享谷歌seo关键词怎么去操盘才能更好的提升排名&#xff0c;我们立刻来学习一下。 本文由光算创作&#xff0c;有可能会被剽窃和修改&#xff0c;我们佛系对待这种行为吧。 谷歌seo关键词如何优化&#xff1f;这里我们提供一个谷歌seo优化的公式 答案是&#xff1a…

Vue基础15之消息订阅与发布、TodoList消息订阅与发布、TodoList编辑功能

Vue基础15消息订阅与发布安装pubsub-js库使用main.jsSchool.vueStudent.vue总结&#xff1a;消息订阅与发布&#xff08;pubsub&#xff09;TodoList-消息的订阅与发布将Item的deleteTodo使用消息订阅与发布App.vueMyItem.vueMyList.vueTodoList-编辑App.vueMyItem.vue完善编辑…

【极海APM32替代笔记】HAL库ADC测量精度提高方案(利用内部参考电压VREFINT计算VDDA来提高精度)

【极海APM32替代笔记】HAL库ADC测量精度提高方案&#xff08;利用内部参考电压VREFINT计算VDDA来提高精度&#xff09; 多数STM32的MCU 都没有内部基准电压 如L496系列 但在外接VDDA时&#xff08;一般与VCC 3.3V连接&#xff09; 有可能VCC不稳定 导致参考电压不确定 从而使A…

【并发编程十八】线程局部存储(TLS)

【并发编程十八】线程局部存储(TLS&#xff09;一、定义二、线程局部存储的实现1、windows系统2、linux系统3、c11三、windows系统1、线程局部存储是分块的&#xff08;TLS_MINIMUM_AVAILABLE&#xff09;2、获得索引3、通过索引&#xff1a;存储数据、取出数据4、释放索引和内…

《计算机网络:自顶向下方法》实验1:协议分析软件的使用

实验1:协议分析软件的使用 实验步骤 启动主机上的web浏览器。 启动Ethereal(或WireShark)。你会看到如图2所示的窗口,只是窗口中没有任何分组列表。 开始分组捕获:选择“capture”下拉菜单中的“Start”命令,会出现如图所示的“Ethereal(或WireShark): Capture Options”…

(02)Cartographer源码无死角解析-(56) 2D后端优化→class MapById、MapById::lower_bound

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文末…

Flink04: Flink核心API之DataSet

DataSet API主要可以分为3块来分析&#xff1a;DataSource、Transformation、Sink。 DataSource是程序的数据源输入。Transformation是具体的操作&#xff0c;它对一个或多个输入数据源进行计算处理&#xff0c;例如map、flatMap、filter等操作。DataSink是程序的输出&#xf…

攻击者查看邮件就被溯源到家?

本文通过分享实际攻防演练中真实案例&#xff0c;防守方在未暴露任何敏感信息的情况下&#xff0c;仅通过邮件往来最终溯源到攻击方相关真实信息。 作为攻击溯源技术的引子&#xff0c;供各位从业和爱好者交流学习。 场景描述 攻击者伪造邮件&#xff0c;称其申请防守方靶标系…

洛谷P5736 【深基7.例2】质数筛 C语言/C++

【深基7.例2】质数筛 题目描述 输入 nnn 个不大于 10510^5105 的正整数。要求全部储存在数组中&#xff0c;去除掉不是质数的数字&#xff0c;依次输出剩余的质数。 输入格式 第一行输入一个正整数 nnn&#xff0c;表示整数个数。 第二行输入 nnn 个正整数 aia_iai​&…

基于 esp-idf SDK ,如何在 .cpp 工程中加入.c 的文件调用?

把外部 .c 文件放到 .cpp 工程下的 main 文件夹然后在 .cpp 工程下声明 .c 文件下的 hello_main 函数同时在 cpp 工程的 CmakeLists.txt 文件下加上 .c 文件最后在 .cpp 工程下调用 hello_main 函数即可 可基于 esp-idf/examples/storage/nvs_rw_value_cxx 例程来测试 &#x…

mysql 8.0.32安装 windows server 超详细

官网下载mysql包&#xff0c;官网地址(中文版)&#xff1a; http://mysql.p2hp.com/cloud/index.html 我是下载的这个(第一个) 内容解压后是这样的&#xff0c;其实windows版本无需安装&#xff0c;只需要配置后启动即可 同时&#xff0c;建议下载下这个Visual Studio&#xf…

Nebula测试

LDBC benchmark 这是官方文档 https://ldbcouncil.org/ldbc_snb_docs/ldbc-snb-specification.pdf 主要有几点 Scale Factors 是生成数据的一个大小&#xff0c;For both workloads, the SF1 data set is 1 GiB, the SF100 is 100 GiB, and the SF10 000 data set is 10 000 G…

关于CSS的简单知识

CSS是什么首先&#xff0c;在之前的html仅仅是写了一个框架&#xff0c;页面并不工整&#xff0c;美观。而CSS正是解决了这一问题。HTML仅仅只是表示页面的结构和内容&#xff0c;而CSS描述的是页面的样式&#xff08;包括大小/位置/字体/颜色/背景等&#xff09;基本语言规范选…

[element plus] 对话框组件再封装使用 - vue

学习关键语句: 饿了么组件dialog组件使用 dialog组件二次封装 vue3中封住的组件使用update触发更新 vue3中封装组件使用v-model:属性值来传值 写在前面 这是我遇到的一个页面需求 , 其中一个对话框的内容是很常用的 , 所以我将它封装出来才写的一篇文章 现在给出如下需求: 封…

Git(分布式版本控制系统)

提到git了&#xff0c;我们先来说一下什么是git? 1、通俗一点&#xff0c;就是一个人工版本控制器 通过人工的复制行为来保存项目的不同阶段的内容&#xff0c;添加适当的一些描述文字加以区分 繁琐、容易出错 产生大量重复数据 2、什么是版本控制&#xff1f; 版本控制是指对…

JVM16命令行

2. JVM 监控及诊断工具-命令行篇 2.1. 概述 简单命令行工具 在我们刚接触 java 学习的时候&#xff0c;大家肯定最先了解的两个命令就是 javac&#xff0c;java&#xff0c;那么除此之外&#xff0c;还有没有其他的命令可以供我们使用呢&#xff1f; 我们进入到安装 jdk 的…

JAVA并发编程面试题合集

1.在Java中守护线程和本地线程的区别&#xff1f; Java中的线程分为两种&#xff1a;守护线程&#xff08;Daemon&#xff09;和用户线程&#xff08;User&#xff09;任何线程都可以设置为守护线程和用户线程&#xff0c;通过方法Thread.setDaemon(boolean)&#xff1b;true表…

框架开发有哪些优势?Java主流框架

什么是框架“框架&#xff08;Framework&#xff09;"一词最早出现在建筑领域&#xff0c;指的是在建造房屋前期构建的建筑骨架。在编程领域&#xff0c;框架就是应用程序的骨架&#xff0c;开发人员可以在这个骨架上加入自己的东西&#xff0c;搭建出符合自己需求的应用系…