SpringBoot(powernode)(内含教学视频+源代码)
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 | 请求映射 |
| @GetMapping | GET请求 |
| @PostMapping | POST请求 |
| @DeleteMapping | DELETE请求 |
| @PutMapping | PUT请求 |
| @PatchMapping | PATCH请求 |
| @ResponseBody | 返回JSON对象 |
| @ExceptionHandler | 统一异常处理拦截 |
| @CrossOrigin | 跨域问题 |
4.1.3 spring标注参数的注解:
| 注解 | 说明 |
|---|---|
| @RequestBody | 入参是JSON对象 |
| @PathVariable | 将路径上面的参数映射到入参里面 |
| @RequestParam | 将请求参数绑定到你控制器的方法参数上 |
4.1.4 spring标注属性的注解:
| 注解 | 说明 |
|---|---|
| @Autowried | 自动注入(首选按照类型) byType byName |
| @Resource | 自动注入(首选按照名字) |
| @Value | 动态给属性赋值 |
4.2 相关注解说明
4.2.1 @Configuration
作用于类上,被标注的类就相当于spring的xml配置文件
|–application-dao.xml
4.2.2 @Bean
作用于方法上,相当于xml配置文件中的
被标注的方法的返回值对象会交给ioc容器管理
配置类

com.bjpowernode.springboot01.config
SpringConfig.java
package com.bjpowernode.springboot01.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Date;/*
*当前类被@Configuration注解标注,所以当前类就是spring的配置类
* 作用与spring的xml配置文件完全一致
*/
@Configuration
public class SpringConfig {/**此方法被@Bean注解标注,所以此方法就是将指定的javabean对象交给ioc容器管理* 作用与<bean>标签一致* 方法名默认就是该javaBean的名称*/@Beanpublic 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容器*/@Autowiredprivate Date date;@Testpublic 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;@Testpublic 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: value1Key2: 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: 4399name: uncleage: 26birth: 1998/03/26hobby:- sing- dance- rap- basketballlist:- list1- list2set:- set1- set2map:k1: v1k2: v2weapon:name: hk416harm: 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=500hero.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: 4399name: uncleage: 26birth: 1998/03/26hobby:- sing- dance- rap- basketballlist:- list1- list2set:- set1- set2map:k1: v1k2: v2weapon:name: hk416harm: 5className: CGB2110array: 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*/@NotNullprivate Integer id;@NotNullprivate String id1;/** 指定当前属性的值不能为null,也不能为" "*/@NotEmptyprivate String id2;/**指定当前属性的值不能为null,也不能为"",也不能为内容只有空格的字符串*/@NotBlankprivate 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: 123id1: ""id2: " "id3: " s"age: 25name: abcemail: 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 {@Autowiredprivate People people;@Testvoid 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 {@Autowiredprivate Person person;@Testvoid 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 {@Autowiredprivate Person person;@Testpublic 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 # 使用指定编码设置 编码过滤器 默认就是truecharset: 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 {@Autowiredprivate Man man;@Testpublic 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 {@Autowiredprivate ManInterface man;@Testpublic 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*/@Overridepublic 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")@ResponseBodypublic 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 # 设置是否开启文件上传功能 默认就是truemax-file-size: 9999999MB #设置上传文件最大的大小 可以使用MB GB TBmax-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*/@Overridepublic 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*/@Overridepublic 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")@ResponseBodypublic String userAccount(){return "访问user/userAccount";}@RequestMapping("/user/userLogin")@ResponseBodypublic 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 {@Overridepublic 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 {@Overrideprotected 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 {@Autowiredprivate MyServlet myServlet;/**注册自定义的Servlet*/@Beanpublic 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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req, resp);}@Overrideprotected 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 {@Autowiredprivate UserServlet userServlet;@Beanpublic 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*/@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("MyListener.contextInitialized");}/*** 这个方法会在ServletContext被销毁的时候,自动的触发* @param sce*/@Overridepublic 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 {@Autowiredprivate MyListener myListener;/** 注册自定义的Listener*/@Beanpublic 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.Driverurl: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: 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 {@Autowiredprivate DataSource dataSource;@Testvoid 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.Driverurl: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: 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.Driverurl: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: root# 设置使用druid数据源,pom.xml中导入的是com.alibaba的druid依赖type: com.alibaba.druid.pool.DruidDataSource#以下内容,pom.xml导入的是com.alibaba的启动器依赖druid-spring-boot-starterdruid:min-idle: 3 # 最小的连接数max-active: 15#druid提供了数据源的监控功能#它是提供了一个servlet让我们去访问,访问这个Servlet,就返回一个资源,这个资源可以看到数据源的状态stat-view-servlet: #设置druid提供的数据源的监控Servletlogin-username: HHH # 设置访问此Servlet时登录的用户名login-password: 123456 # 设置访问此Servlet是登录的密码deny: #设置访问此Servlet的黑名单allow: #设置访问此Servlet的白名单url-pattern: /druid/* #设置访问此Servlet的url-patternenabled: 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.Driverurl: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: rootmin-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 {@Autowiredprivate 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 {@Autowiredprivate DataSource dataSource;@Testvoid 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.Driverurl: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: rootmin-idle: 3 # 最小的连接数max-active: 15 # 最大连接数validation-query: select 'a'my-stat-view-servlet: #设置druid提供的数据源的监控Servletlogin-username: HHH # 设置访问此Servlet时登录的用户名login-password: 123456 # 设置访问此Servlet是登录的密码url-pattern: /druid/* #设置访问此Servlet的url-patternenabled: 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;@Datastatic 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*/@Beanpublic 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 {@Autowiredprivate 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*/@Beanpublic 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.扫描mapperspring:# 配置数据源datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:13306/ssm_power_edu?useSSL=false&characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: rootdruid:min-idle: 3max-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 mapperPUBLIC "-//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 {@Autowiredprivate UserMapper userMapper;@Overridepublic 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 {@Autowiredprivate UserService userService;@Testvoid 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 {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> findAllUser() {return userMapper.selectAllUser();}@Overridepublic 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 {@Autowiredprivate UserService userService;@Testvoid contextLoads() {List<User> users = userService.findAllUser();System.out.println(users);}@Testpublic 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 {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> findAllUser() {return userMapper.selectAllUser();}@Overridepublic 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@Overridepublic 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 mapperPUBLIC "-//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 {@Autowiredprivate UserService userService;@Testvoid contextLoads() {List<User> users = userService.findAllUser();System.out.println(users);}@Testpublic void testPageHelper(){PageInfo<User> pageInfo = userService.findAllUserByPageHelper(1, 3);List<User> list = pageInfo.getList();System.out.println(list);}@Testvoid 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
相关文章:
SpringBoot(powernode)(内含教学视频+源代码)
SpringBoot(powernode)(内含教学视频源代码) 教学视频源代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87484637 目录SpringBoot(powernode)(内含教学视频…...
TEMU联盟计划用意何在?做推广达人真的能收入满满吗?
据东哥近期了解,Temu在北美市场表现十分火爆,甚至冲上了AppStore下载榜第一名。Temu在美国市场上采用了类似PDD的病毒式传播策略,以实惠的产品和折扣吸引消费者并动员普通人大量传播链接和App下载,所以有了TEMU联盟计划࿰…...
【概念辨析】二维数组传参的集中可能性
一、二维数组传参竟然不是用二级指针进行接收? 今天进行再一次的二级指针学习时,发现了一条以前没怎么注意过的知识点:二维数组进行传参只能用二维数组(不能省略列)进行接收或者是数组指针。 问题复现代码如下…...
Photon Vectorized Engine 学习记录
Photon Hash Aggregation Vectorization Photon Hash Join 的向量化的要点是:使用开放地址法。步骤: 向量化计算 hash 值基于 hash 向量化计算 bucket 下标,得到 bucket index 向量基于 bucket index 向量中记录的下标找到 bucketÿ…...
webRTC学习-基础知识
webRTC学习1、webRTC简介1.1什么是webRTC?1.2、作用2、webRTC通信原理2.1、媒体协商(SDP)2.2、网络协商(candidate)2.2.1、STUN2.2.2、TURN2.3、媒体协商网络协商数据的交换通道webRTC官网1、webRTC简介 1.1什么是web…...
MySQL数据库——JDBC编程
文章目录一、什么是Java的JDBC二、JDBC编程三、代码整体展示一、什么是Java的JDBC JDBC,即Java Database Connectivity。意思是java数据库连接。是一种用来执行 SQL 语句的 JavaAPI,是Java中数据库的连接规范。这个 API 由 java.sql* 和 javax.sql* 包中…...
【面向小白】你见过这样讲解队列的吗?(阅此文可学会用纯C手撕一个队列)
目录 0.前言 1.什么是队列 2.选择什么结构实现队列 3.用C语言实现队列 3.1用什么可以封装代表一个队列 3.2队列接口的设计 3.3 队列的初始化 3.4 队列的销毁 3.5* 队列的状态分析 3.6 队列的插入 3.7 队列的删除 3.8 队列的大小(有效元素的数目ÿ…...
[element plus] 对话框组件再封装使用 - vue
学习关键语句: 饿了么组件dialog组件使用 dialog组件二次封装 vue3中封住的组件使用update触发更新 vue3中封装组件使用v-model:属性值来传值 写在前面 这是我遇到的一个页面需求 , 其中一个对话框的内容是很常用的 , 所以我将它封装出来才写的一篇文章 现在给出如下需求: 封…...
Markdown基本语法简介
前言:当你在git平台创建一个仓库时,平台会自动创建一个README.md文件,并将它的内容展现在web端页面,方面其他读者查阅。README.md实则是一个适用Markdown语法的文本文件,从他的后缀md即可看出它是Markdown的缩写。在gi…...
分布式服务的接口幂等性如何设计
1.1 概述 所谓幂等: 多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致。 基于RESTful API的角度对部分常见类型请求的幂等性特点进行分析 举个例子: 假如你有个某多多 有个服务 服务提供一个接口,结果这个服务部署在…...
视频流截取保存到本地路径(打包jar包CMD运行)
需求:现在有一批https的监控视频流URL,需要对视频流进行每三秒截屏一次,并保存到本地路径,png格式,以当前时间命名。代码:import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Fra…...
mysql索引失效的几种情况
失效的几种情况 1、select * from xxx 2、索引列上有计算 3、索引列上有函数 4、like左边包含‘%’ 5、使用or关键字 6、not in和not exists 7、order by 8、不满足最左匹配原则 给code、age和name这3个字段建好联合索引:idx_code_age_name。 该索引字段的顺…...
Windows下载安装Redis的详细步骤
目录 一、概述 1.redis的版本维护介绍 2.msi安装包和压缩包的优点和缺点 二、操作步骤 三、测试是否安装成功(查看版本) 四、获取资源 一、概述 1.redis的版本维护介绍 Redis的官网只提供Linux系统的下载。但是微软的技术团队长期开发和维护着这…...
【蓝桥杯每日一题】差分算法
🍎 博客主页:🌙披星戴月的贾维斯 🍎 欢迎关注:👍点赞🍃收藏🔥留言 🍇系列专栏:🌙 蓝桥杯 🌙我与杀戮之中绽放,亦如黎明的花…...
MyBatis Plus 数据库字段加密处理
目录1.场景介绍2.Maven依赖2.AESUtil.java 加解密工具类3.字段处理类4.修改 MyBatis Plus 查询4.1 修改表对应实体类4.2 修改加密字段对应属性4.3 修改 xml 使用 ResultMap4.4 修改 xml 中 el 表达式5.测试结果6.MyBatis Plus 缺陷补充:测试实例1 查询测试1.1 查询信…...
openpose在win下环境配置
1.下载OpenPose库 以下二选一进行下载源码 (1)git进行下载 打开GitHub Desktop或者Powershell git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose cd openpose/ git submodule update --init --recursive --remote(2)在github上手动下载 由于下载环境问…...
【剑指offer-C++】JZ16:数值的整数次方
【剑指offer】JZ16:数值的整数次方题目描述解题思路题目描述 描述:实现函数 double Power(double base, int exponent),求base的exponent次方。 注意: 1.保证base和exponent不同时为0。 2.不得使用库函数,同时不需要…...
了解Axios及其运用方式
Axios简介 axios框架全称(ajax – I/O – system): 基于promise用于浏览器和node.js的http客户端,因此可以使用Promise API 一、axios是干啥的 说到axios我们就不得不说下Ajax。在旧浏览器页面在向服务器请求数据时,…...
【LeetCode】剑指 Offer(7)
目录 写在前面: 题目剑指 Offer 17. 打印从1到最大的n位数 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 题目:剑指 Offer 18. 删除链表的节…...
Python:try except 异常处理整理
目录 一、try except异常处理的语句格式 二、获取相关异常信息 (1)sys.exec_info() 三、traceback模块的常用方式 (1)traceback.print_tb(tb, limitNone, fileNone) 打印指定堆栈异常信息 (2)tracebac…...
4道高频面试题,吃透时间复杂度(递归_堆_贪心_快排)
4道高频面试题,吃透时间复杂度(递归/堆/贪心/快排) 前言:时间复杂度是算法面试的“必考题”,也是区分初级与中级开发者的核心考点。很多开发者能写出正确的算法代码,却无法清晰、严谨地分析其时间复杂度&am…...
Coze 智能体开发标准流程
在 Coze(扣子)平台上开发 AI 智能体(Agent)的流程可以概括为 “创建 - 编排 - 调试 - 发布” 四个核心阶段。无论你是使用国内版 (coze.cn) 还是国际版 (coze.com),其逻辑架构基本一致。1. 创建智能体 (Create)这是项目…...
2025届必备的AI辅助论文平台解析与推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 于学术写作范畴之内,AI工具已然明显地提升了研究效率,目前主流的论文…...
2026 RAG 全景落地教程(非常详细),从大模型基座到 Agent 记忆从入门到精通,收藏这一篇就够了!
这是一份让你看完就能动手,少走半年弯路的实战指南。 为什么你必须搞懂 RAG 2023 年是大模型“百模大战”年,所有人都在刷榜单、比参数。2024 年起,战场转移了——谁能把大模型真正用起来,谁才有价值。 而检索增强生成…...
告别虚拟机!在Win10上为ARM开发板(如TI AM62x)搭建Qt Widgets开发环境全记录
告别虚拟机!在Win10上为ARM开发板搭建Qt Widgets开发环境全记录 嵌入式开发工程师们对这样的场景一定不陌生:为了给ARM平台开发Qt应用,不得不启动笨重的Linux虚拟机,在两种操作系统间频繁切换。这不仅消耗系统资源,更…...
实测踩坑:用Vibe Coding重写Calendly后,我看清了它的3大致命局限
作为一名常年和调度类工具打交道的开发者,最近被Vibe Coding的“自然语言转代码”噱头狠狠吸引——只需描述需求,AI就能快速生成可用代码,号称能大幅降低开发成本、提升原型落地效率。抱着“省时间、少踩坑”的心态,我决定用它重写…...
比迪丽AI绘画LaTeX集成:学术论文插图自动生成
比迪丽AI绘画LaTeX集成:学术论文插图自动生成 学术写作中,插图制作往往耗时费力,比迪丽AI绘画与LaTeX的集成让这一过程变得智能高效 1. 学术插图制作的痛点与需求 写论文的研究生们都有过这样的经历:花几天时间做实验,…...
W25Q256JWEIQ 1.8V 低功耗大容量串行 NOR Flash存储器——华邦电子 全新原装芯片IC
W25Q256JWEIQ:1.8V 低功耗大容量串行 NOR Flash——华邦 SpiFlash 系列,为嵌入式系统注入节能存储芯动力 Winbond(华邦电子)推出的 W25Q256JWEIQ 256Mbit 串行 NOR Flash-存储器, 1.7V ~ 1.95V 的低电压供电、133MHz …...
AWPortrait-Z WebUI可访问性:键盘导航/屏幕阅读器/高对比度支持
AWPortrait-Z WebUI可访问性:键盘导航/屏幕阅读器/高对比度支持 1. 为什么需要关注WebUI可访问性 当我们谈论AI图像生成工具时,很多人首先想到的是功能和效果,但有一个同样重要的方面经常被忽视——可访问性。AWPortrait-Z作为一款基于Z-Im…...
3个简单步骤:让Windows 11完美运行经典老游戏的终极DDrawCompat方案
3个简单步骤:让Windows 11完美运行经典老游戏的终极DDrawCompat方案 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirr…...
