10.8 maven高级 Git入门
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
Maven依赖管理
生命周期和插件
分模块开发
Git基本命令
3.根据概述分章节描述
Maven依赖管理
依赖配置和依赖传递
一个项目可以设置多个依赖
依赖就是平常说的jar包.
依赖传递
依赖是有传递性的 分为直接依赖和间接依赖
1 2 直接依赖:在当前项目中通过依赖配置建立的依赖关系 间接依赖:被资源的资源如果依赖其他资源 当前项目间接依赖其他资源
依赖范围
下面这个表比较重要
标签四种的作用 能解节约资源
依赖范围
传递的时候的影响
生命周期和插件
生命周期
Maven构建生命周期描述的是一次构建过程经历了多少的事件
compile test-compile test package install 类似于这些对 项目处理的功能都是事件
项目构建的生命周期分三套
1 2 3 clean 清洗工作 default 核心工作 编译 测试 打包 部署site 产生报告 发布站点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 default 生命周期比较重要 加#都是重要点列出 validate(校验) 校验项目是否正确并且所有必要的信息可以完成项目的构建过程。 initialize(初始化) 初始化构建状态,比如设置属性值。 generate- sources(生成源代码) 生成包含在编译阶段中的任何源代码。 process- sources(处理源代码) 处理源代码,比如说,过滤任意值。 generate- resources(生成资源文件) 生成将会包含在项目包中的资源文件。 process- resources (处理资源文件) 复制和处理资源到目标目录,为打包阶段最好准备。 #compile(编译) 编译项目的源代码。 process- classes(处理类文件) 处理编译生成的文件,比如说对Java class文件做字节码改善优化。 generate- test- sources(生成测试源代码) 生成包含在编译阶段中的任何测试源代码。 process- test- sources(处理测试源代码) 处理测试源代码,比如说,过滤任意值。generate- test- resources(生成测试资源文件) 为测试创建资源文件。 process- test- resources(处理测试资源文件) 复制和处理测试资源到目标目录。 #test- compile(编译测试源码) 编译测试源代码到测试目标目录. process- test- classes(处理测试类文件) 处理测试源码编译生成的文件。 #test(测试) 使用合适的单元测试框架运行测试(Juint是其中之一)。 prepare - package(准备打包) 在实际打包之前,执行任何的必要的操作为打包做准备。#package(打包) 将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。 pre- integration- test(集成测试前) 在执行集成测试前进行必要的动作。比如说,搭建需要的环境。 integration- test(集成测试) 处理和部署项目到可以运行集成测试环境中。 post- integration- test(集成测试后) 在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境。 verify (验证) 运行任意的检查来验证项目包有效且达到质量标准。 #install(安装) 安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖。 deploy(部署) 将最终的项目包复制到远程仓库中与其他开发者和项目共享。
插件
插件就是该生命周期所能支持的事件
多个插件组成一个生命周期
分模块开发
聚合 多个工程的功能集于一个工程
继承 父工程的坐标以及插件可以给子工程使用
属性
1 2 3 4 5 <properties > <spring.version > 5.1.9.RELEASE</spring.version > <junit.version > 4.12</junit.version > </properties >
可自定义
调用方法如下
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > com.itheima</groupId > <artifactId > ssm_service</artifactId > <version > ${version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > ${spring.version}</version > </dependency >
Git命令
Git的工作原理
分三个区 工作区 暂存区 本地库
1 2 3 工作区:写代码的 暂存区:缓冲点 临时存储 本地库:历史版本 可查可切换
常用命令如下:
黑色只用设置一次
1 2 3 4 5 6 初始化的效果 会生成一个隐藏的.git文件 status查看本地库文件的状态 : 文件在什么区 git add 将文件提交到缓存区 git commit -m "日志信息" 文件名 提交到本地库 git reflog 查看历史记录 git reset
4. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
当时maven的pugin全部报错 之前遇到过找自己的setting.xml文件并没有问题
后面 发现默认的C中.m2的仓库就可以 觉得是仓库的问题 自己的仓库有问题,就把老师资料中的仓库直接覆盖自己 问题解决了
5.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天学习点是git和maven两大以后团队协作做项目很有用的操作,之前都略有接触过,maven都用过很久了,高级部分多看了一下,基础文档过了一眼。git的命令有点像linux,git就是解决团队协作时候,对服务器更改的各种问题。今天大部分都是看文档,安装的时候是跟着视频的,因为哪里没配置好会很麻烦,所以学习进度也很快。有过接触,掌握起来也不难。
10.9 Git分支 SSM框架Bean
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
Git分支
Spring入门
3.根据概述分章节描述
Git分支
分支按我自己的理解就像支线(影分身),各个人负责自己的支线,然后做完了以后,将任务提交到主线中去,能大大提高开发的效率,而且开发失败对主线影响不大,
分支的操作
1 2 3 4 5 git branch 分支名 创建分支 git branch -v 查看分支 git checkout 分支名 切换分支 git checkout -b 分支名 切换分支 分支不存在就创建 git merge 分支名 把指定的分支合并到当前的分支 一般当前分支需要是主分支
注意点
冲突问题
合并的时候,如果主线和分支的同一个文件的同一个位置有两套不同的 修改 Git 就无法为我们决定哪一个 就需要人为 的选择
1 2 编辑有冲突的文件,删除特殊符号,决定要使用的内容 特殊符号:<<<<<<< HEAD 当前分支的代码 = = = = = = = 合并过来的代码 >>>>>>> hot-fix
删除以后 添加暂存区然后提交
Spring相关概念
Spring框架主要的优势是在简化开发
和框架整合
我们平常写的代码中耦合度偏高 都知道低耦合度比较好
因为每次业务层调用数据层的方法,需要在业务层new数据层的对象 ,如果数据层的实现类发生变化,那么业务层的代码也需要跟着改变,发生变更后,都需要进行编译打包和重部署
使用对象时,在程序中不要主动使用new产生对象,转换为由==外部==提供对象
Spring中关于bean的使用
使用spring 需要导入依赖 如下
1 2 3 4 5 6 7 8 9 10 11 12 13 <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 5.2.10.RELEASE</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.12</version > <scope > test</scope > </dependency > </dependencies >
bean基础设置
bean的name属性
环境准备好后,接下来就可以在这个环境的基础上进行bean的别名配置,
1 2 3 4 5 6 7 8 9 10 11 <?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 ="bookService" name ="u7Service bookEbi" class ="com.itheima.service.impl.BookServiceImpl" > <property name ="bookDao" ref ="bookDao" /> </bean > <bean id ="bookDao" name ="dao" class ="com.itheima.dao.impl.BookDaoImpl" scope ="prototype" /> </beans >
bean作用范围scope配置
关于bean的作用范围是bean属性配置的一个==重点==内容。
prototype可以非单例
默认是singleton是单例模式
一般都是设置为单例 提高效率
小总结
生命周期
关于Spring中对bean生命周期控制提供了两种方式:
在配置文件中的bean标签中添加初始化init-method
和销毁destroy-method
属性
类实现InitializingBean
与DisposableBean
接口
1 <bean id ="bookDao" class ="com.itheima.dao.impl.BookDaoImpl" init-method ="init" destroy-method ="destory" />
close关闭容器
上面两种都可以关闭容器 调用xml文件中的destroy-method的方法
4. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
UserDaoFactory 的文件夹命名问题 导致找不到 该类
6.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天学习了git基本操作最后一点的分支和SSM框架前面Spring的基础部分,总体来说难度不是很大,spring文档前面概念性的自己理解起来花费了一些时间,结合文档给的案例,敲代码帮助自己理解起来快很多,xml调用接口的时候出现了点问题,解决起来也蛮快的,一个一个点进去找就行了。文档结合视频加上自己敲,理解起来很通透,这样学习是很不错的。
10.10 Spring
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
依赖注入
核心容器
3.根据概述分章节描述
依赖注入
setter注入
在BookDaoImpl类中声明对应的简单数据类型的属性,并提供对应的setter方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class BookDaoImpl implements BookDao { private String databaseName; private int connectionNum; public void setConnectionNum (int connectionNum) { this .connectionNum = connectionNum; } public void setDatabaseName (String databaseName) { this .databaseName = databaseName; } public void save () { System.out.println("book dao save ..." +databaseName+"," +connectionNum); } }
配置中使用==property==标签==ref==属性注入引用类型对象
配置中使用==property==标签==value==属性注入基本类型对象
1 2 3 4 5 6 7 8 9 10 11 12 <?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 ="bookDao" class ="com.itheima.dao.impl.BookDaoImpl" /> <bean id ="userDao" class ="com.itheima.dao.impl.UserDaoImpl" /> <bean id ="bookService" class ="com.itheima.service.impl.BookServiceImpl" > <property name ="bookDao" ref ="bookDao" /> <property name ="userDao" ref ="userDao" /> </bean > </beans >
构造器注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?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 ="bookDao" class ="com.itheima.dao.impl.BookDaoImpl" > <constructor-arg index ="0" value ="mysql" /> <constructor-arg index ="1" value ="1001" /> </bean > <bean id ="userDao" class ="com.itheima.dao.impl.UserDaoImpl" /> <bean id ="bookService" class ="com.itheima.service.impl.BookServiceImpl" > <constructor-arg name ="bookDao" ref ="bookDao" /> <constructor-arg name ="userDao" ref ="userDao" /> </bean > </beans >
Service使用构造器 传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.itheima.service.impl;import com.itheima.dao.BookDao;import com.itheima.dao.UserDao;import com.itheima.service.BookService;public class BookServiceImpl implements BookService { private BookDao bookDao; private UserDao userDao; public BookServiceImpl (BookDao bookDao, UserDao userDao) { this .bookDao = bookDao; this .userDao = userDao; } public void save () { System.out.println("book service save ..." ); bookDao.save(); userDao.save(); } }
依赖方式的选择
自动注入
前面java文件不变 自动调用set方法
修改配置文件即可
1 2 3 4 5 6 7 8 9 <?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 class ="com.itheima.dao.impl.BookDaoImpl" /> <bean id ="bookService" class ="com.itheima.service.impl.BookServiceImpl" autowire ="byType" /> </beans >
集合注入
一般集合注入都是注入常量 如果需要注入引用类型 加[标签]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public interface BookDao { public void save () ; } public class BookDaoImpl implements BookDao { public class BookDaoImpl implements BookDao { private int [] array; private List<String> list; private Set<String> set; private Map<String,String> map; private Properties properties; public void save () { System.out.println("book dao save ..." ); System.out.println("遍历数组:" + Arrays.toString(array)); System.out.println("遍历List" + list); System.out.println("遍历Set" + set); System.out.println("遍历Map" + map); System.out.println("遍历Properties" + properties); } }
配置文件如下
按照集合名字赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?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 ="bookDao" class ="com.itheima.dao.impl.BookDaoImpl" > <property name ="array" > <array > <value > 100</value > <value > 200</value > <value > 300</value > </array > </property > <property name ="list" > <list > <value > itcast</value > <value > itheima</value > <value > boxuegu</value > <value > chuanzhihui</value > </list > </property > <property name ="set" > <set > <value > itcast</value > <value > itheima</value > <value > boxuegu</value > <value > boxuegu</value > </set > </property > <property name ="map" > <map > <entry key ="country" value ="china" /> <entry key ="province" value ="henan" /> <entry key ="city" value ="kaifeng" /> </map > </property > <property name ="properties" > <props > <prop key ="country" > china</prop > <prop key ="province" > henan</prop > <prop key ="city" > kaifeng</prop > </props > </property > </bean > </beans >
核心容器
因为是之前的源代码了解
小结一下
容器相关
BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
ApplicationContext接口常用初始化类
==ClassPathXmlApplicationContext(常用)==
FileSystemXmlApplicationContext
bean相关
其实整个配置中最常用的就两个属性==id==和==class==。
依赖注入相关
注解开发基础
注解开发分两块内容注解开发定义bean
和纯注解开发
。
注解开发定义bean用的是2.5版提供的注解,纯注解开发用的是3.0版提供的注解。
笔记我主要记纯注解开发
几个常用的注解我都列举出来
@Component等
名称
@Component/@Controller/@Service/@Repository
类型
类注解
位置
类定义上方
作用
设置该类为spring管理的bean
属性
value(默认):定义bean的id
知识点1:@Configuration
名称
@Configuration
类型
类注解
位置
类定义上方
作用
设置该类为spring配置类
属性
value(默认):定义bean的id
知识点2:@ComponentScan
名称
@ComponentScan
类型
类注解
位置
类定义上方
作用
设置spring配置类扫描路径,用于加载使用注解格式定义的bean
属性
value(默认):扫描路径,此路径可以逐层向下扫描
知识点1:@Scope
名称
@Scope
类型
类注解
位置
类定义上方
作用
设置该类创建对象的作用范围 可用于设置创建出的bean是否为单例对象
属性
value(默认):定义bean作用范围, ==默认值singleton(单例),可选值prototype(非单例)==
知识点1:@PostConstruct
名称
@PostConstruct
类型
方法注解
位置
方法上
作用
设置该方法为初始化方法
属性
无
知识点2:@PreDestroy
名称
@PreDestroy
类型
方法注解
位置
方法上
作用
设置该方法为销毁方法
属性
无
1 其实就是把xml 文件中bean标签需要到的属性 利用注解放到java中 就不需要使用xml 配置了
注解开发依赖注入
知识点1:@Autowired
名称
@Autowired
类型
属性注解 或 方法注解(了解) 或 方法形参注解(了解)
位置
属性定义上方 或 标准set方法上方 或 类set方法上方 或 方法形参前面
作用
为引用类型属性设置值
属性
required:true/false,定义该属性是否允许为null
知识点2:@Qualifier
名称
@Qualifier
类型
属性注解 或 方法注解(了解)
位置
属性定义上方 或 标准set方法上方 或 类set方法上方
作用
为引用类型属性指定注入的beanId
属性
value(默认):设置注入的beanId
知识点3:@Value
名称
@Value
类型
属性注解 或 方法注解(了解)
位置
属性定义上方 或 标准set方法上方 或 类set方法上方
作用
为 基本数据类型 或 字符串类型 属性设置值
属性
value(默认):要注入的属性值
知识点4:@PropertySource
名称
@PropertySource
类型
类注解
位置
类定义上方
作用
加载properties文件中的属性值
属性
value(默认):设置加载的properties文件对应的文件名或文件名组成的数组
注解开发管理第三方bean
前面定义bean的时候都是在自己开发的类上面写个注解就完成了 第三方是需要导入jar包的
如果需要管理是要一个新的注解==@Bean==
其实就是建立一个Java类 retrun返回一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class JdbcConfig { @Value("com.mysql.jdbc.Driver") private String driver; @Value("jdbc:mysql://localhost:3306/spring_db") private String url; @Value("root") private String userName; @Value("root") private String password; @Bean public DataSource dataSource (BookDao bookDao) { System.out.println(bookDao); DruidDataSource ds = new DruidDataSource (); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } }
在spring连接的java类中放入注解即可 这时候需要componentScan导入包名扫描
1 2 3 4 5 6 @Configuration @ComponentScan("com.itheima") @Import({JdbcConfig.class}) public class SpringConfig {}
注解开发小总结
图片总结 红色的是以后常用的
4. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
Translation的问题 IDEA中谷歌插件 报错 CSDN搜索解决方法
C:\Windows\System32\drivers\etc 中的hosts 进行修改 添加
要获取ip获取:命令行 ping translate.google.cn 会返回对应的ip,然后加上translate.googleapis.com
1 Hosts 是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP 地址建立一个关联“数据库”
命令如下
6.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天学习的内容比较多的,从依赖注入到容器到重点的注解开发,注解开发是比较重要的,前面的注入和容器什么的,都可以通过注解开发完成,就不需要写xml文件了,这样很方便。过程中没什么问题,但是注解那边需要记很多东西,不然估计不太好打。之前java学注解的时候,没怎么学,现在 算是又看了一遍,也是理解注解的作用了。今天基本都掌握到了,代码量比较多,学习状态也很不错的。
10.11 AOP Spring事务
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
AOP简介
AOP实现步骤
AOP配置管理
3.根据概述分章节描述
AOP简介
AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构。
和面向对象编程一样都是一种编程的思想
AOP作用
在不惊动原始设计的基础上为其进行功能增强,和之前学过的代理模式很像。
如图所实现的功能调用update和delete方法时候 会计算程序执行时间 但是调用select就不会执行
spring实现方式就是 三个方法为三个连接点,需要实现功能增强(通知)的方法 设置切入点
AOP核心概念
总结下:
连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
切入点(Pointcut):匹配连接点的式子
在SpringAOP中,一个切入点可以描述一个具体方法,也可也匹配多个方法
一个具体的方法:如com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
连接点范围要比切入点范围大,是切入点的方法也一定是连接点,但是是连接点的方法就不一定要被增强,所以可能不是切入点。
通知(Advice):在切入点处执行的操作,也就是共性功能
通知类:定义通知的类
切面(Aspect):描述通知与切入点的对应关系。
AOP实现步骤
添加spring依赖
1 2 3 4 5 <dependency > <groupId > org.aspectj</groupId > <artifactId > aspectjweaver</artifactId > <version > 1.9.4</version > </dependency >
实现java类
代码和注解 如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.itheima.aop;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;@Component @Aspect public class MyAdvice { @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt () {} @Before("pt()") public void method () { System.out.println("我是切入点" ); } }
开启注解格式AOP功能
1 2 3 4 5 6 @Configuration @ComponentScan("com.itheima") @EnableAspectJAutoProxy public class SpringConfig {}
所用新注解
知识点1:@EnableAspectJAutoProxy
名称
@EnableAspectJAutoProxy
类型
配置类注解
位置
配置类定义上方
作用
开启注解格式AOP功能
知识点2:@Aspect
名称
@Aspect
类型
类注解
位置
切面类定义上方
作用
设置当前类为AOP切面类
知识点3:@Pointcut
名称
@Pointcut
类型
方法注解
位置
切入点方法定义上方
作用
设置切入点方法
属性
value(默认):切入点表达式
知识点4:@Before
名称
@Before
类型
方法注解
位置
通知方法定义上方
作用
设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行
语法格式
各个关键字解释
1 execution(public User com.itheima.service.UserService.findById(int ))
execution:动作关键字,描述切入点的行为动作,例如execution表示执行到指定切入点
public:访问修饰符,还可以是public,private等,可以省略
User:返回值,写返回值类型
com.itheima.service:包名,多级包使用点连接
UserService:类/接口名称
findById:方法名
int:参数,直接写参数的类型,多个类型用逗号隔开
异常名:方法定义中抛出指定异常,可以省略
通配符
这样使用的话比较单一 肯定是有通配符的 和java中 sql中一样 可以简化配置
*
:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
1 execution(public * com.itheima.*.UserService.find*(*))
匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法
..
:多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写
1 execution(public User com ..UserService.findById(..))
匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法
通知类型
前置通知
后置通知
环绕通知(重点)
环绕通知依赖形参ProceedingJoinPoint才能实现对原始方法的调用
环绕通知可以隔离原始方法的调用执行
环绕通知返回值设置为Object类型
环绕通知中可以对原始方法调用过程中出现的异常进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Component @Aspect public class MyAdvice { @Pointcut("execution(void com.itheima.dao.BookDao.update())") private void pt () {} @Around("pt()") public void around () { System.out.println("around before advice ..." ); pjp.proceed(); System.out.println("around after advice ..." ); } }
返回后通知
抛出异常后通知
通知中获取参数
获取切入点方法的参数,所有的通知类型都可以获取参数
JoinPoint:适用于前置、后置、返回后、抛出异常后通知
ProceedingJoinPoint:适用于环绕通知
5.扩展学习部分
通配符使用练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 u7 execution (void com.itheima.dao.BookDao.update() )匹配接口,能匹配到 execution(void com.itheima.dao.impl.BookDaoImpl.update()) 匹配实现类,能匹配到 execution(* com.itheima.dao.impl.BookDaoImpl.update()) 返回值任意,能匹配到 execution(* com.itheima.dao.impl.BookDaoImpl.update(*)) 返回值任意,但是update方法必须要有一个参数,无法匹配,要想匹配需要在update接口和实现类添加参数 execution(void com.*.*.*.*.update()) 返回值为void ,com包下的任意包三层包下的任意类的update方法,匹配到的是实现类,能匹配 execution(void com.*.*.*.update()) 返回值为void ,com包下的任意两层包下的任意类的update方法,匹配到的是接口,能匹配 execution(void *..update()) 返回值为void ,方法名是update的任意包下的任意类,能匹配 execution(* *..*(..)) 匹配项目中任意类的任意方法,能匹配,但是不建议使用这种方式,影响范围广 execution(* *..u*(..)) 匹配项目中任意包任意类下只要以u开头的方法,update方法能满足,能匹配 execution(* *..*e(..)) 匹配项目中任意包任意类下只要以e结尾的方法,update和save方法能满足,能匹配 execution(void com..*()) 返回值为void ,com包下的任意包任意类任意方法,能匹配,*代表的是方法 execution(* com.itheima.*.*Service.find*(..)) 将项目中所有业务层方法的以find开头的方法匹配 execution(* com.itheima.*.*Service.save*(..)) 将项目中所有业务层方法的以save开头的方法匹配
百度网盘密码数据兼容处理
密码输入最后一个会是空格的问题 比如我密码是 root 但是我打成了root(空格) 这种情况 就可以使用环绕通知解决
代码如下 getArgs获取一个对象数组 一般情况其实是string 但是不严谨 所以要循环找出string类型的 再调用trim()处理掉空格最后将改args返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Component @Aspect public class DataAdvice { @Pointcut("execution(boolean com.itheima.service.*Service.*(*,*))") private void servicePt () {} @Around("DataAdvice.servicePt()") public Object trimStr (ProceedingJoinPoint pjp) throws Throwable { Object[] args = pjp.getArgs(); for (int i = 0 ; i < args.length; i++) { if (args[i].getClass().equals(String.class)) { args[i] = args[i].toString().trim(); } } return pjp.proceed(args); } }
执行结果如上 4是实际读取密码的位数
6.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天是学习的内容是spring中的AOP和简单的事务管理,充分利用好注解来完成spring项目 ,比之前的xml方便很多,今天的学习任务还是很重的,整个的AOP,有很多的代码要敲,AOP从简介到总结,然后是和java差不多的转账的事务管理,比较麻烦的就是AOP后面的环绕通知了,但是很好用,也是花时间去看了一下,今天的学习状态也不错,明天加快进度学MVC了。
10.12 SpringMVC
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
SpringMVC简介
SpringMVC简单使用
PostMan使用
请求和响应
Rest风格
3.根据概述分章节描述
SpringMVC简介
SpringMVC入门案例
java控制器类代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.itheima.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;@Controller public class UserController { @RequestMapping("/save") @ResponseBody public String save () { System.out.println("user save ..." ); return "{'info':'springmvc'}" ; } }
使用到的注解
知识点1:@Controller
名称
@Controller
类型
类注解
位置
SpringMVC控制器类定义上方
作用
设定SpringMVC的核心控制器bean
知识点2:@RequestMapping
名称
@RequestMapping
类型
类注解或方法注解
位置
SpringMVC控制器类或方法定义上方
作用
设置当前控制器方法请求访问路径
相关属性
value(默认),请求访问路径
知识点3:@ResponseBody
名称
@ResponseBody
类型
类注解或方法注解
位置
SpringMVC控制器类或方法定义上方
作用
设置当前控制器方法响应内容为当前返回值,无需解析
使用Tomcat7:run运行
如何排除某个备案 比如排除掉SpringMVC控制的备案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.itheima.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.FilterType;import org.springframework.stereotype.Controller;@Configuration @ComponentScan(value="com.itheima", excludeFilters = @ComponentScan.Filter( //排除 Controller的注解加载 type = FilterType.ANNOTATION, classes = Controller.class ) ) public class SpringConfig {}
原来的Web配置比较麻烦 可以优化的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class []{SpringConfig.class}; } protected Class<?>[] getServletConfigClasses() { return new Class []{SpringMvcConfig.class}; } protected String[] getServletMappings() { return new String []{"/" }; } }
PostMan工具的使用
就是一款功能为网页调试与发送网页HTTP请求的Chrome插件
使用截图
Send可以直接发送 就不需要一次一次浏览器打开,也能很好的判断是否连接。
请求和响应
SpringMVC是web层的框架,那它作用应该是和web一样是接收请求、接收数据、响应结果
请求参数
请求参数的传递与接收是和请求方式有关系的,目前比较常见的两种请求方式为:
五种类型参数传递
GET的时候写入的信息和后台接受参数的设置会有不同,结合情况使用
因为PostMan中自己都写了,就不放入到笔记中去了
知识点1:@RequestParam
名称
@RequestParam
类型
形参注解
位置
SpringMVC控制器方法形参定义前面
作用
绑定请求参数与处理器方法形参间的关系
相关参数
required:是否为必传参数 defaultValue:参数默认值
JSON数据传输参数
现在比较流行的开发方式为异步调用。前后台以异步方式进行交换,传输的数据使用的是==JSON==
对于JSON数据类型,我们常见的有三种:
json普通数组([“value1”,“value2”,“value3”,…])
json对象({key1:value1,key2:value2,…})
json对象数组([{key1:value1,…},{key2:value2,…}])
如何传递
在SpringMVC的配置类中开启SpringMVC的注解支持,这里面就包含了将JSON转换成对象的功能。
1 2 3 4 5 6 @Configuration @ComponentScan("com.itheima.controller") @EnableWebMvc public class SpringMvcConfig {}
参数前添加@RequestBody
1 2 3 4 5 6 7 @RequestMapping("/listParamForJson") @ResponseBody public String listParamForJson (@RequestBody List<String> likes) { System.out.println("list common(json)参数传递 list ==> " +likes); return "{'module':'list common for json param'}" ; }
后面的对象和集合也是差不多的,只要修改类型就就可以了 注意要在pom.xml中导入jackson包
知识点1:@EnableWebMvc
名称
@EnableWebMvc
类型
==配置类注解==
位置
SpringMVC配置类定义上方
作用
开启SpringMVC多项辅助功能
知识点2:@RequestBody
名称
@RequestBody
类型
==形参注解==
位置
SpringMVC控制器方法形参定义前面
作用
将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
==REST==(Representational State Transfer),表现形式状态转换,它是一种软件架构==风格==
当我们想表示一个网络资源的时候,可以使用两种方式:
传统风格资源描述形式
http://localhost/user/getById?id=1
查询id为1的用户信息
http://localhost/user/saveUser
保存用户信息
REST风格描述形式
http://localhost/user/1
http://localhost/user
个人理解:就是简化get post put delete等操作的时候 写路径会很繁琐的这种行为,称之为Rest风格 用这种风格访问就被称为==RESTful==
1 2 3 4 5 * `http:// localhost/users` 查询全部用户信息 GET(查询) * `http:// localhost/users/ 1 ` 查询指定用户信息 GET(查询) * `http:// localhost/users` 添加用户信息 POST(新增/ 保存) * `http:// localhost/users` 修改用户信息 PUT(修改/ 更新) * `http:// localhost/users/ 1 ` 删除用户信息 DELETE(删除)
所用到的注解
知识点1:@PathVariable
名称
@PathVariable
类型
==形参注解==
位置
SpringMVC控制器方法形参定义前面
作用
绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应
原本的get使用REST风格就变成如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Controller public class UserController { @RequestMapping(value = "/users" ,method = RequestMethod.GET) @ResponseBody public String getAll () { System.out.println("user getAll..." ); return "{'module':'user getAll'}" ; } @RequestMapping(value = "/users/{id}" ,method = RequestMethod.GET) @ResponseBody public String getById (@PathVariable Integer id) { System.out.println("user getById..." +id); return "{'module':'user getById'}" ; }
发现有些地方是重复的
解决方案如下 注解是原来的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @RestController @RequestMapping("/books") public class BookController { @PostMapping public String save (@RequestBody Book book) { System.out.println("book save..." + book); return "{'module':'book save'}" ; } @DeleteMapping("/{id}") public String delete (@PathVariable Integer id) { System.out.println("book delete..." + id); return "{'module':'book delete'}" ; } @PutMapping public String update (@RequestBody Book book) { System.out.println("book update..." + book); return "{'module':'book update'}" ; } @GetMapping("/{id}") public String getById (@PathVariable Integer id) { System.out.println("book getById..." + id); return "{'module':'book getById'}" ; } @GetMapping public String getAll () { System.out.println("book getAll..." ); return "{'module':'book getAll'}" ; } }
问题1:每个方法的@RequestMapping注解中都定义了访问路径/books,重复性太高。
1 将@RequestMapping 提到类上面,用来定义所有方法共同的访问路径。
问题2:每个方法的@RequestMapping注解中都要使用method属性定义请求方式,重复性太高。
1 使用@GetMapping @PostMapping @PutMapping @DeleteMapping 代替
问题3:每个方法响应json都需要加上@ResponseBody注解,重复性太高。
1 2 1. 将ResponseBody提到类上面,让所有的方法都有@ResponseBody 的功能2. 使用@RestController 注解替换@Controller 与@ResponseBody 注解,简化书写
使用的注解
知识点1:@RestController
名称
@RestController
类型
==类注解==
位置
基于SpringMVC的RESTful开发控制器类定义上方
作用
设置当前控制器类为RESTful风格, 等同于@Controller与@ResponseBody两个注解组合功能
知识点2:@GetMapping @PostMapping @PutMapping @DeleteMapping
名称
@GetMapping @PostMapping @PutMapping @DeleteMapping
类型
==方法注解==
位置
基于SpringMVC的RESTful开发控制器方法定义上方
作用
设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作, 例如@GetMapping对应GET请求
相关属性
value(默认):请求访问路径
BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
做 REST风格的案例的时候 连接不到html
但是问题是在MVC应该是拦截了前端的数据 导致无法访问
换成下面这种方式就好了 具体原因没有搞清楚 老师示范的代码是上图的 静态资源进行放行
5.扩展学习部分
@RequestBody与@RequestParam区别
区别
@RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
@RequestBody用于接收json数据【application/json】
应用
后期开发中,发送json格式数据为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接收请求参数
6.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天学习状态一般 没怎么睡好,下午还不错,学习的内容是MVC也就是和web框架差不多,前后端连接的点比较多,敲很多代码觉得不错的地方就是比原本的webServlet要快很多,而且我觉得很清楚,代码还简洁,利用注解就能接决连接的情况。做REST风格的案例的时候,稍微出现了一些问题,但是也在同学的帮助下解决了,学了很多的注解了,有些其实都没怎么记住,还是要多敲代码多用,才能更好的去记忆如何使用。
10.13 SSM整合 拦截器
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
3.根据概述分章节描述
SSM整合流程
把前面所学习的三个框架都整合在一起
1 2 3 4 5 6 7 8 9 10 1> >>创建工程 2> >>SSM整合 Spring MyBatis SpringMVC 3> >>功能模块 表和实现类 dao接口 service业务层 controller表现层
入门案例
以后spring 创建项目包结构都可以用这种 单词自己注意下
创建项目包结构
config目录存放的是相关的配置类
controller编写的是Controller类
dao存放的是Dao接口,因为使用的是Mapper接口代理方式,所以没有实现类包
service存的是Service接口,impl存放的是Service实现类
resources:存入的是配置文件,如Jdbc.properties
webapp:目录可以存放静态资源
个人理解:流程可以这样敲
1 2 3 4 SpringConfig -- JdbcConfig -- MybatisConfig -- jdbc.prperties -- SpringMVC --创建Web项目入口配置类 模块开发 模型类 == Dao接口 == Service接口和实现类 == Contorller类
前后台协议统一
在webAPP添加静态资源
因为添加了静态资源所以SpringMVC会拦截的 我们需要放行 在SpringConfig放行
1 2 3 4 5 6 7 8 9 10 @Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Override protected void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**" ).addResourceLocations("/pages/" ); registry.addResourceHandler("/css/**" ).addResourceLocations("/css/" ); registry.addResourceHandler("/js/**" ).addResourceLocations("/js/" ); registry.addResourceHandler("/plugins/**" ).addResourceLocations("/plugins/" ); } }
在SpringMvcConfig中扫描SpringMvcSupport
1 2 3 4 5 @Configuration @ComponentScan({"com.itheima.controller","com.itheima.config"}) @EnableWebMvc public class SpringMvcConfig {}
然后写前端页面完成项目整合
拦截器
可以动态拦截控制器的执行
在指定的方法调用前后执行预先设定的代码
阻止原始方法的执行
总结:拦截器就是用来做增强
拦截器开发
让类实现HandlerInterceptor接口,重写接口中的三个方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Component public class ProjectInterceptor implements HandlerInterceptor { @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle..." ); return true ; } @Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle..." ); } @Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion..." ); } }
**注意:**拦截器类要被SpringMVC容器扫描到。
所以需要再SpringMvcSupport允许通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Autowired private ProjectInterceptor projectInterceptor; @Override protected void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**" ).addResourceLocations("/pages/" ); } @Override protected void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/books" ,"/books/*" ); } }
4. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
@Autowired下面一直冒红 也找不到原因 索性重新打了一遍代码就莫名其妙好了
6.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天学习状态一般,有点太疲劳了,还是内容问题,感觉有点不是很理解,类太多,使用的注解也很多 ,敲过去有些参数不是很理解,调用的方式,但是也没有死磕,大致的过了一下就好了,后面SpringBoot的时候会简单很多,这些到时候在复习一下,拦截器那里没怎么听懂,今天的掌握只有70吧。也没有报错但是就是有点云里雾里。
10.14 Mybatis-Puls
1.头:日期、所学内容出处
【黑马程序员MybatisPlus深入浅出教程,快速上手mybatisplus】 https://www.bilibili.com/video/BV1rE41197jR?p=12&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
了解Mybatis-plus
快速使用
使用sql简单功能实现
3.根据概述分章节描述
什么是Mybatis-plus(MP)
个人理解:之前学过mybatis,连接数据库,利用返回值,以及实现的接口,实现java对mysql的操作。这个Mybatis-plus相当于是把你java对mysql的操作进行封装,这样你开发的时候的代码量等操作就会少很多,提高效率。
快速使用
需要导入插件在Maven中
1 2 3 4 5 6 <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus</artifactId > <version > 3.1.1</version > </dependency >
因为之前学过spring了,而且以后基本也都是使用spring 所以 前面mybatis+MP的代码就不列出来了
Spring+Mybatis+MP
熟悉的流程
实现查询User
1.编写jdbc.properties
1 2 3 4 5 6 jdbc.driver =com.mysql.jdbc.Driver jdbc.url =jdbc:mysql://127.0.0.1:3306/mp? useUnicode =true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL =false jdbc.username =root jdbc.password =root
2.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" ><context:property-placeholder location ="classpath:*.properties" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" destroy-method ="close" ><property name ="url" value ="${jdbc.url}" /> <property name ="username" value ="${jdbc.username}" /> <property name ="password" value ="${jdbc.password}" /> <property name ="driverClassName" value ="${jdbc.driver}" /> <property name ="maxActive" value ="10" /> <property name ="minIdle" value ="5" /> </bean > <bean id ="sqlSessionFactory" class ="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" ><property name ="dataSource" ref ="dataSource" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="cn.itcast.mp.simple.mapper" /> </bean > </beans >
3.UserMapper接口 继承BaseMapper
1 2 3 4 5 package cn.itcast.mp.simple.mapper;import cn.itcast.mp.simple.pojo.User;import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface UserMapper extends BaseMapper <User> {}
4.测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package cn.itcast.mp.simple;import cn.itcast.mp.simple.mapper.UserMapper;import cn.itcast.mp.simple.pojo.User;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.List;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class TestSpringMP {@Autowired private UserMapper userMapper;@Test public void testSelectList () {List<User> users = this .userMapper.selectList(null ); for (User user : users) {System.out.println(user); } } }
通用CRUD
我都放到一个测试类里面了 也有注解 其实就是调用接口中的方法 忘记的话点击去源代码查看 有MP的中文注解的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 package cn.itcast.mp;import cn.itcast.mp.mapper.UserMapper;import cn.itcast.mp.pojo.User;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;@RunWith(SpringRunner.class) @SpringBootTest public class TestUserMapper { @Autowired private UserMapper userMapper; @Test public void testInsert () { User user = new User (); user.setMail("2@itcast.cn" ); user.setAge(301 ); user.setUserName("caocao1" ); user.setName("曹操1" ); user.setPassword("123456" ); user.setAddress("北京" ); int result = this .userMapper.insert(user); System.out.println("result => " + result); System.out.println("id => " + user.getId()); } @Test public void testSelectById () { User user = this .userMapper.selectById(2L ); System.out.println(user); } @Test public void testUpdateById () { User user = new User (); user.setId(1L ); user.setAge(19 ); user.setPassword("666666" ); int result = this .userMapper.updateById(user); System.out.println("result => " + result); } @Test public void testUpdate () { User user = new User (); user.setAge(20 ); user.setPassword("8888888" ); QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("user_name" , "zhangsan" ); int result = this .userMapper.update(user, wrapper); System.out.println("result => " + result); } @Test public void testUpdate2 () { UpdateWrapper<User> wrapper = new UpdateWrapper <>(); wrapper.set("age" , 21 ).set("password" , "999999" ) .eq("user_name" , "zhangsan" ); int result = this .userMapper.update(null , wrapper); System.out.println("result => " + result); } @Test public void testDeleteById () { int result = this .userMapper.deleteById(9L ); System.out.println("result => " + result); } @Test public void testDeleteByMap () { Map<String,Object> map = new HashMap <>(); map.put("user_name" , "zhangsan" ); map.put("password" , "999999" ); int result = this .userMapper.deleteByMap(map); System.out.println("result => " + result); } @Test public void testDelete () { User user = new User (); user.setPassword("123456" ); user.setUserName("caocao" ); QueryWrapper<User> wrapper = new QueryWrapper <>(user); int result = this .userMapper.delete(wrapper); System.out.println("result => " + result); } @Test public void testDeleteBatchIds () { int result = this .userMapper.deleteBatchIds(Arrays.asList(6L , 7L )); System.out.println("result => " + result); } @Test public void testSelectBatchIds () { List<User> users = this .userMapper.selectBatchIds(Arrays.asList(2L , 3L , 4L , 100L )); for (User user : users) { System.out.println(user); } } @Test public void testSelectOne () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("password" , "123456" ); User user = this .userMapper.selectOne(wrapper); System.out.println(user); } @Test public void testSelectCount () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.gt("age" , 20 ); Integer count = this .userMapper.selectCount(wrapper); System.out.println("count => " + count); } @Test public void testSelectList () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.like("email" , "itcast" ); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } @Test public void testSelectPage () { Page<User> page = new Page <>(3 ,1 ); QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.like("email" , "itcast" ); IPage<User> iPage = this .userMapper.selectPage(page, wrapper); System.out.println("数据总条数: " + iPage.getTotal()); System.out.println("数据总页数: " + iPage.getPages()); System.out.println("当前页数: " + iPage.getCurrent()); List<User> records = iPage.getRecords(); for (User record : records) { System.out.println(record); } } @Test public void testFindById () { User user = this .userMapper.findById(2L ); System.out.println(user); } @Test public void testAllEq () { Map<String,Object> params = new HashMap <>(); params.put("name" , "李四" ); params.put("age" , "20" ); params.put("password" , null ); QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.allEq((k, v) -> (k.equals("age" ) || k.equals("id" ) || k.equals("name" )) , params); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } @Test public void testEq () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("password" , "123456" ) .ge("age" , 20 ) .in("name" , "李四" , "王五" , "赵六" ); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } @Test public void testLike () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.likeLeft("name" , "五" ); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } @Test public void testOrderByAgeDesc () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.orderByDesc("age" ); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } @Test public void testOr () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("name" , "王五" ).or().eq("age" , 21 ); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } @Test public void testSelect () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("name" , "王五" ) .or() .eq("age" , 21 ) .select("id" ,"name" ,"age" ); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
6.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天的学习状态不错,看着文档敲了很多代码,MP是中国团队写出来的,也是我现在IDEA点进去,唯一一个注释是中文的Maven插件,一些基本的sql语句,我都是看他源代码和注释,了解用法了的。学习中也没遇到什么BUG,偶尔几次是自己写错了方法名字或者jdbc写错了,难度不是很大,前面基本使用是会了,打算明天看SpringBoot2,遇到使用MP进阶的时候再回头看看。
10.17 SpringBoot
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
简单的入门案例利用SpringBoot 只需要一行就能实现
1 2 3 4 5 6 7 8 9 10 11 @RestController @RequestMapping("/books") public class BookController { @GetMapping public String getById () { System.out.println("springboot is running..." ); return "springboot is running!" ; } }
主程序如下
1 2 3 4 5 6 7 8 9 10 11 12 package com.itheima;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class Springboot0101QuickstartApplication { public static void main (String[] args) { SpringApplication.run(Springboot0101QuickstartApplication.class, args); } }
原来的Spring项目结构如下
SpringBoot项目结构如下
只需要一个java类
个人理解显而易见SpringBoot简单很多 Spring中的配置 在SpringBoot中都给你配好了
还有一个很智能的 pom.xml文件 他能帮你把所有最合适的版本配置好 在IDEA可以直接创建
3.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天的学习内容不是很多,上午考驾照去了,下午先整理了一下前面SSM框架的一些内容,再来看的SpringBoot,只做了一个简单的入门案例,SpringBoot把之前要写Bean都帮你整理好了,这样你只要输入controller文件就好了。暂时没什么难的,就是搞清楚他运行原理的话有点麻烦,学到后面的原理篇再仔细看一下吧。
10.18 SpringBoot基础篇完结
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
SpringBoot基本配置
属性配置
配置文件分类
yaml文件使用
yaml数据读取
SpringBoot实现SSMP整合
3.根据概述分章节描述
SpringBoot基本配置
属性配置
修改application.properties文件 设置服务器端口号 格式如下 IDEA会有自动联想功能会有提示
1 2 3 4 5 server.port =80 spring.main.banner-mode =off logging.level.root =debug
配置文件分类
分三种 默认的是properties 然后是两种yaml和yml
三种格式也不一样
application.properties(properties格式)
仔细看会发现yml式和yaml格式除了文件名后缀不一样,格式完全一样,是这样的,yml和yaml文件格式就是一模一样的,只是文件后缀不同,所以可以合并成一种格式来看。以后企业比较常用的是yml格式的 是yml为重点
配置文件如果有相同的话 优先级来说的话如下 但是配置文件不同会同时起作用
1 2 application.properties > application.yml > application.yaml
yaml文件使用
数据书写格式i如下
1 2 3 4 5 6 7 8 boolean: TRUE float: 3.14 int: 123 null: ~ string: HelloWorld string2: "Hello World" date: 2018-02-17 datetime: 2018-02-17T15:02:31+08:00
也可以表示数组或多维数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 subject: - Java - 前端 - 大数据 enterprise: name: itcast age: 16 subject: - Java - 前端 - 大数据 likes: [王者荣耀 ,刺激战场 ] users: - name: Tom age: 4 - name: Jerry age: 5 users: - name: Tom age: 4 - name: Jerry age: 5 users2: [ { name:Tom , age:4 } , { name:Jerry , age:5 } ]
yaml数据读取
读取单一数据
yaml中保存的单个数据,可以使用Spring中的注解直接读取,使用@Value可以读取单个数据,属性名引用方式:${一级属性名.二级属性名……}
读取全部数据
读取单一数据可以解决读取数据的问题,但是如果定义的数据量过大,这么一个一个书写肯定会累死人的,SpringBoot提供了一个对象,能够把所有的数据都封装到这一个对象中,这个对象叫做Environment,使用自动装配注解可以将所有的yaml数据封装到这个对象中
但是要写env.getProperty太麻烦了
写成对象数据调用会方便很多
读取方式如下
会简单很多 直接输出就是 对象的tostring
4.总结
重点是哪些知识比较重要,难点是你在学习过程中觉得比较繁琐,掌握起来有一点
今天的学习内容是Boot2基础篇差不多结束了,配置方面学习的比较多,算是重点吧,yml感觉是比之前properties的文件要舒服很多,连接数据库的时候,输入也很方便,加上MP的配置,感觉将开发效率提高了很多。今天没什么难点,都是理解为主,文档看看,去实验了一下,明天把SSMP的案例过了,就能去下一个阶段了。
10.19 SSMP案例
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
SSMP步骤
个人理解:
1.pom.xml
配置依赖
2.application.yml
设置数据源 端口 框架
3.dao
继承BaseMapper 设置@Mapper
4.dao测试类
5.service
调用数据层接口或Mybatis-Plus提供的接口快速开发
6.service测试类
7.controller
基于Restful开发 用Postman测试
8.页面
放置resources目录中static静态页面
本人理解原理:
接口各个实现原理
数据层BookDao接口继承mp中的BaseMapper拥有其方法
IBookService业务层接口 继承mp中IService
BookServiceImpl注入BookDao实现对象,业务层方法一目了然知道使用方法,创建对应类然后调用数据层的方法
在表现层BookController写对应请求类所调用的方法 并添加功能
表现层消息一致性
要求是前端请求得到的数据 需要统一
增删改操作结果
查询单个数据操作结果
1 2 3 4 5 6 { "id" : 1 , "type" : "计算机理论" , "name" : "Spring实战 第5版" , "description" : "Spring入门经典教程" }
查询全部数据操作结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [ { "id" : 1 , "type" : "计算机理论" , "name" : "Spring实战 第5版" , "description" : "Spring入门经典教程" } , { "id" : 2 , "type" : "计算机理论" , "name" : "Spring 5核心原理与30个类手写实战" , "description" : "十年沉淀之作" } ]
如上面的几种不同的操作 返回的数据格式都不一样,为了方便前端的开发,可以设计一个类 被称为模型类 用于数据统一的 被称为前后端数据协议
创建R类 写boolean类的flag Object的data 即可 (msg是后面对异常处理添加的)
Object类可以放数据 flag设计是有没有请求到数据 设计好构造方法 这样前端的返回的数据 都是一个flag一个data了
效果如下
1 2 3 4 5 6 7 8 9 { "flag" : true , "data" : { "id" : 1 , "type" : "计算机理论" , "name" : "Spring实战 第5版" , "description" : "Spring入门经典教程" } }
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
4.扩展学习部分
5.总结
今天下午学了车,所以今天主要是做了SSMP的案例,之前讲过学SSM框架的时候的实现效果差不多,但是使用SSMP方便了很多,上次这个案例没怎么做,过了一遍,这次自己尝试去做了一遍,因为没学过vue,在前端实现的部分,就采用了老师的代码,后端开发基本都是自己看完视频以后独立完成,难度不是很大,sql语句也是很简单的,所以MP已经帮你写好了,明天可以进入开发篇中去了。
10.20 SpringBoot运维
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
使用cmd命令行 运行项目jar包
cmd运行jar包命令如下
可以设置临时配置属性 两个–后面跟属性然后设置值 和properties文件格式差不多
1 java -jar xxxxxx.jar --server.port=80 --logging.level.root=debug
下面是有时候端口冲突或者进程冲突时候命令
1 2 3 4 5 6 7 8 9 10 # 查询端口 netstat -ano # 查询指定端口 netstat -ano |findstr "端口号" # 根据进程PID查询进程名称 tasklist |findstr "进程PID号" # 根据PID杀死任务 taskkill /F /PID "进程PID号" # 根据进程名称杀死任务 taskkill -f -t -im "进程名称"
多环境开发
个人理解:在公司中 一些配置是不需要底层的人看到的,所以相当于每个阶层负责的内容不一样。就是说你的电脑上写的程序最终要放到别人的服务器上去运行。每个计算机环境不一样,这就是多环境。常见的多环境开发主要兼顾3种环境设置,开发环境——自己用的,测试环境——自己公司用的,生产环境——甲方爸爸用的。所以一些配置是不一样的,利用不同的文件目录就可以实现
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
4.扩展学习部分
5.总结
今天学习的内容对我比较简单,之前学过一些运维方面的知识,打包什么都很熟悉,在大数据比赛的时候已经如鱼得水了,今天看文档就把运维看完了,然后附带了点后面开发的内容,如热部署什么的。总体来说,今天学习状态也不错,内容比较对口吧。
10.21下午-10.23下午 Spring开发使用篇
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
热部署
热部署相当于你启动完服务器,又修改了java的代码,之前是需要重新运行一次的,现在只要L+一下就好了,不需要再次运行浪费时间和资源了
因为自动和监控比较鸡肋,最常用的还是手动启动热部署,所以就记手动的实现 方式=就行了‘
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-devtools</artifactId > <optional > true</optional > </dependency >
1 <CTR>L+<F9> #IDEA启动热部署快捷键
配置高级
属性绑定时,可能会遇到如下情况,为了进行标准命名,开发者会将属性名严格按照驼峰命名法书写,在yml配置文件中将datasource修改为dataSource,如下:
1 2 dataSource: driverClassName: com.mysql.jdbc.Driver
此时程序可以正常运行,然后又将代码中的前缀datasource修改为dataSource,如下:
1 2 3 4 5 6 @Bean @ConfigurationProperties(prefix = "dataSource") public DruidDataSource datasource () { DruidDataSource ds = new DruidDataSource (); return ds; }
明明确定的目标名是一样的,却无法匹配,就是有关属性名称的宽松绑定,也可以称为宽松绑定。
实际上是springboot进行编程时人性化设计的一种体现,即配置文件中的命名格式与变量名的命名格式可以进行格式上的最大化兼容。可以与下面的配置属性名规则全兼容
1 2 3 4 5 servers: ipAddress: 192.168 .0 .2 ip_address: 192.168 .0 .2 ip-address: 192.168 .0 .2 IP_ADDRESS: 192.168 .0 .2
也可以说,以上4种模式最终都可以匹配到ipAddress这个属性名。不过springboot官方推荐使用烤肉串模式,也就是中划线模式。命名的规范问题。看开始出现的编程错误信息
1 2 3 4 5 6 7 8 Configuration property name 'dataSource' is not valid: Invalid characters: 'S' Bean: datasource Reason : Canonical names should be kebab -case ('-' separated ), lowercase alpha -numeric characters and must start with a letter Action :Modify 'dataSource ' so that it conforms to the canonical names requirements .
其中Reason描述了报错的原因,规范的名称应该是烤肉串(kebab)模式(case),即使用-分隔,使用小写字母数字作为标准字符,且必须以字母开头。
以上规则仅针对springboot中@ConfigurationProperties注解进行属性绑定时有效,对@Value注解进行属性映射无效。
总结
@ConfigurationProperties绑定属性时支持属性名宽松绑定,这个宽松体现在属性名的命名规则上
@Value注解不支持松散绑定规则
绑定前缀名推荐采用烤肉串命名规则,即使用中划线做分隔符
数据层
数据源技术
之前我们用的是druid springboot还有三个内置的数据源技术
HikariCP
Tomcat提供DataSource
Commons DBCP、
HikariCP是默认的 不配置啥数据源的话就是这个
1 2 3 4 5 6 7 spring: datasource: druid: url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root
持久化技术
个人觉得这里比较重要 就提高一个标题等级吧 这里主要是springboot充分发挥其最强辅助的特征,给开发者提供了一套现成的数据层技术,叫做JdbcTemplate。导入坐标完了 可以直接写自定义sql
导入jdbc对应的坐标,记得是starter
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-jdbc</artifactId > </dependency
自动装配JdbcTemplate对象
1 2 3 4 5 6 @SpringBootTest class Springboot15SqlApplicationTests { @Test void testJdbcTemplate (@Autowired JdbcTemplate jdbcTemplate) { } }
使用JdbcTemplate实现查询操作(非实体类封装数据的查询操作)
1 2 3 4 5 6 @Test void testJdbcTemplate (@Autowired JdbcTemplate jdbcTemplate) { String sql = "select * from tbl_book" ; List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql); System.out.println(maps); }
使用JdbcTemplate实现查询操作(实体类封装数据的查询操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Test void testJdbcTemplate (@Autowired JdbcTemplate jdbcTemplate) { String sql = "select * from tbl_book" ; RowMapper<Book> rm = new RowMapper <Book>() { @Override public Book mapRow (ResultSet rs, int rowNum) throws SQLException { Book temp = new Book (); temp.setId(rs.getInt("id" )); temp.setName(rs.getString("name" )); temp.setType(rs.getString("type" )); temp.setDescription(rs.getString("description" )); return temp; } }; List<Book> list = jdbcTemplate.query(sql, rm); System.out.println(list); }
使用JdbcTemplate实现增删改操作
1 2 3 4 5 @Test void testJdbcTemplateSave (@Autowired JdbcTemplate jdbcTemplate) { String sql = "insert into tbl_book values(3,'springboot1','springboot2','springboot3')" ; jdbcTemplate.update(sql); }
个人理解:一些复杂的sql语句可以不依赖于MP,自定义会更好些,而且可以满足需求,想写什么类型的sql语句,写完调用jdbcTemplate中对应的实现方法就行了,查询比较麻烦,非实体类看起来不太方便,可以写一个实体类,封装进去。
数据库技术
讲的都是springboot内置的三个数据库,感觉没什么很大的用处以后,还是mysql居多
NOSQL非关系数据库
讲了三个Redis MongoDB ES 都是比较常用的数据库,跟着安装了一下,然后基本的使用学会了,用SpringBoot整合了一下,没什么难点,也没重点,后面需要用的使用,再局部的复习一下
3. BUG
难点(关键代码或关键配置,BUG截图+解决方案)
自己写的查询方法这里,想用sql来进行分页,报错了,发现这里修改以后,后面的Service业务层没有修改,导致报错
4.扩展学习部分
5.总结
因为上午都有点事情,就把这两天下午的学习内容放一天了,这两天下午的学习内容是有点难度的,而且内容比较多,从热部署,配置,测试,数据层结局问题,和整合第三方技术。在数据层那边难度比较大,重点在数据层和整合第三方技术,,数据层课件分了两部分,SQL和NOSQL,非关系和关系型的数据库,NOSQL比较简单,除了ES是有点难度的打算下次去专门回头看一下,也只讲了基本操作,SQL中数据源和持久化还是很有意思的,利用JdbcTemplate持久化,完成比较复杂的sql语句,也验证了我之前觉得MP虽然智能,但是在复杂的企业项目中,会用到复杂的SQL语句,肯定是有些要自己手敲sql的,学一暑假的MYSQL没白学。下次就结束整合第三方,开发篇也就完结了,就可以去做项目了,数据层还差一个ES没有看。自己试着用数据库技术,用自己之前比赛清洗的数据库清洗代码,放java中运行今天学习状态极佳,内容也比较多,因为自己擅长sql点,学习也有兴趣。
10.24 Spring整合第三方技术
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
缓存
缓存是一种介于数据永久存储介质与应用程序之间的数据临时存储介质,使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能。
内置缓存
就是一些数据可以临时放缓存中,Springboot提供了包
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-cache</artifactId > </dependency >
然后在服务器启动上面
在业务层方法上面注解
1 2 3 4 5 @Override @Cacheable(value="cacheSpace",key="#id") public Book getById (Integer id) { return bookDao.selectById(id); }
ehcache缓存
坐标
1 2 3 4 <dependency > <groupId > net.sf.ehcache</groupId > <artifactId > ehcache</artifactId > </dependency >
外置缓存需要配置的 在yml文件中
1 2 3 4 5 spring: cache: type: ehcache ehcache: config: ehcache.xml
ehcache的配置有独立的配置文件格式,因此还需要指定ehcache的配置文件,以便于读取相应配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?xml version="1.0" encoding="UTF-8" ?> <ehcache xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation ="http://ehcache.org/ehcache.xsd" updateCheck ="false" > <diskStore path ="D:\ehcache" /> <defaultCache eternal ="false" diskPersistent ="false" maxElementsInMemory ="1000" overflowToDisk ="false" timeToIdleSeconds ="60" timeToLiveSeconds ="60" memoryStoreEvictionPolicy ="LRU" /> <cache name ="smsCode" eternal ="false" diskPersistent ="false" maxElementsInMemory ="1000" overflowToDisk ="false" timeToIdleSeconds ="10" timeToLiveSeconds ="10" memoryStoreEvictionPolicy ="LRU" /> </ehcache >
Redis
redis的坐标
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > </dependency >
配置
1 2 3 4 5 6 7 8 9 10 11 spring: redis: host: localhost //本地 port: 6379 cache: type: redis redis: use-key-prefix: false key-prefix: sms_ cache-null-values: false time-to-live: 10s
j2cache缓存
之前还有一种jet的整合方式,我觉得太麻烦,而且只能整合4种,所以就只记j2了。就以整合ehcache和redis
导入三个坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <dependency > <groupId > net.oschina.j2cache</groupId > <artifactId > j2cache-core</artifactId > <version > 2.8.4-release</version > </dependency > <dependency > <groupId > net.oschina.j2cache</groupId > <artifactId > j2cache-spring-boot2-starter</artifactId > <version > 2.8.0-release</version > </dependency > <dependency > <groupId > net.sf.ehcache</groupId > <artifactId > ehcache</artifactId > </dependency >
配置一级与二级缓存,并配置一二级缓存间数据传递方式,配置书写在名称为j2cache.properties的文件中。
1 2 3 4 5 6 7 8 9 10 11 j2cache.L1.provider_class = ehcache ehcache.configXml = ehcache.xml j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider j2cache.L2.config_section = redis redis.hosts = localhost:6379 j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy
j2cache是一个缓存框架,自身不具有缓存功能,它提供多种缓存整合在一起使用的方案
j2cache需要通过复杂的配置设置各级缓存,以及缓存之间数据交换的方式
j2cache操作接口通过CacheChannel实现
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
运行 cache缓存的时候报错,报错点一直没找到,看报错信息是XM,这个没听过,把那两个XM的jar包注释掉也没有用,最后把yml的配置全改了,然后检查数据层的一些注解,把和XM有关的都去掉,BUG解决了,看到后面才知道XM类是外置的一直缓存,需要下载配置才能使用,pom文件中导入不了
4.扩展学习部分
手机验证码案例 自定义校对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Component public class CodeUtils { private String [] patch = {"000000" ,"00000" ,"0000" ,"000" ,"00" ,"0" ,"" }; public String generator (String tele) { int hash = tele.hashCode(); int encryption = 20206666 ; long result = hash ^ encryption; long nowTime = System.currentTimeMillis(); result = result ^ nowTime; long code = result % 1000000 ; code = code < 0 ? -code : code; String codeStr = code + "" ; int len = codeStr.length(); return patch[len] + codeStr; } @Cacheable(value = "smsCode",key="#tele") public String get (String tele) { return null ; } }
5.总结
今天学习的学习内容一般,内容比较多,主要是整合第三方的缓存部分,然后附带了点任务,出了一个小BUG,然后自己手动解决了,基本都是看文档,不知道具体用法的时候看视频去,然后试着敲一下,请求的时候有点云里雾里。跟着老师知道具体的请求,手敲了一遍简单的手机验证码,福袋啦Quartz任务,看了一会视频,还没明白是个什么事,明天就能结束Boot,后天可以做项目了。今天的学习状态不错,比较集中,看文档也看的下去,效率很高。
10.25 开发篇完结
1.头:日期、所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
任务Task
课件中还有一个Quartz,但是感觉很麻烦不太实用,现在主流的好像是Task
也就是定时任务,要做定时任务要容器有这功能,然后定时执行什么任务直接告诉对应的bean什么时间执行就行了
开启定时任务功能,在引导类上开启定时任务功能的开关,使用注解@EnableScheduling
1 2 3 4 5 6 7 8 @SpringBootApplication @EnableScheduling public class Springboot22TaskApplication { public static void main (String[] args) { SpringApplication.run(Springboot22TaskApplication.class, args); } }
步骤② :定义Bean,在对应要定时执行的操作上方,使用注解@Scheduled定义执行的时间,执行时间的描述方式还是cron表达式
1 2 3 4 5 6 7 @Component public class MyBean { @Scheduled(cron = "0/1 * * * * ?") public void print () { System.out.println(Thread.currentThread().getName()+" :spring task run..." ); } }
对定时任务进行相关配置,可以通过配置文件进行
1 2 3 4 5 6 7 8 9 spring: task: scheduling: pool: size: 1 thread-name-prefix: ssm_ shutdown: await-termination: false await-termination-period: 10s
总结
spring task需要使用注解@EnableScheduling开启定时任务功能
为定时执行的的任务设置执行周期,描述方式cron表达式
邮件
发邮件是java程序的基本操作,springboot整合javamail其实就是简化开发。发送邮件方是需要配置的,需要在自己的邮箱设置中找到密码SMTP的。收件方只需要一个邮箱地址就行了
消息
消息和之前用java做过的一个交互差不多,现在主要是异步消息,同步消息作用不大。
现在比较主流的RocketMQ,只要给要发送消息的方法挂上ROcketMQ的注解就可以了,还是比较简单的,步骤就不列出来了。
springboot整合RocketMQ使用RocketMQTemplate对象作为客户端操作消息队列
操作RocketMQ需要配置RocketMQ服务器地址,默认端口9876
企业开发时通常使用监听器来处理消息队列中的消息,设置监听器使用注解@RocketMQMessageListener
监控
监控这边比较重要的是可视化监控平台
需要先看开启服务器 加入配置
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > de.codecentric</groupId > <artifactId > spring-boot-admin-starter-server</artifactId > <version > 2.5.4</version > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency >
在引导类上添加注解@EnableAdminServer,声明当前应用启动后作为SpringBootAdmin的服务器使用
1 2 3 4 5 6 7 @SpringBootApplication @EnableAdminServer public class Springboot25AdminServerApplication { public static void main (String[] args) { SpringApplication.run(Springboot25AdminServerApplication.class, args); } }
这样就能进去admin的页面了
然后就是开启一个自己的客户端 客户端比较简单导入坐标
导入springboot admin对应的starter,版本与当前使用的springboot版本保持一致,并将其配置成web工程
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > de.codecentric</groupId > <artifactId > spring-boot-admin-starter-client</artifactId > <version > 2.5.4</version > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency >
然后需要在yml配置信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server: port: 80 spring: boot: admin: client: url: http://localhost:8080 management: endpoint: health: show-details: always endpoints: web: exposure: include: "*"
页面大致内容如下 功能很多 回头可以详细的一个一个功能的使用
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
一直报错检查代码也没什么问题,提示是什么命名原因,但是自己根本没有dataSource这个名字, 后面重新开了一个模块,代码没改变没有报错信息了。之前的Spring是快速模块,现在换成2.4.1了,应该是模块的原因阿吧
发送消息如下
4.扩展学习部分
发送邮件和附件 超链接和图片
导入springboot整合javamail的starter
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-mail</artifactId > </dependency >
步骤② :配置邮箱的登录信息 这里是发送方 发送方邮箱需要开启服务 一般都在设置中
1 2 3 4 5 6 7 8 9 10 11 12 spring: mail: host: smtp.163.com username: asrl825067@163.com password: EPEKPEWBZXLAMCYL
写一个业务层的代码就好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Service public class SendMailServiceImpl2 implements SendMailService { private String from = "2272917904@qq.com" ; private String to = "asrl825067@163.com" ; private String subject = "测试邮件" ; private String context = "<img src='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.soogif.com%2FV2a5qLlX2gFNIHXSvMrmUjyWxHdb4XXQ.gif&refer=http%3A%2F%2Fimg.soogif.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1669274278&t=7f8449969831195ab78eea7408740099'/><a href='https://www.itcast.cn'>点开有惊喜</a>" ;; @Autowired private JavaMailSender javaMailSender; @Override public void sendMail () { try { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper message = new MimeMessageHelper (mimeMessage,true ); message.setFrom(to+"(u7u7)" ); message.setTo(from); message.setSubject(subject); message.setText(context,true ); File f2 = new File ("D:\\CC\\SpringBootCode\\springboot_mail_test\\src\\main\\resources\\cc.png" ); message.addAttachment("最zz的cc.png" ,f2); javaMailSender.send(mimeMessage); }catch (Exception e){ e.printStackTrace(); } } }
测试点一直调用接口的sendMail的方法就行了需要注入的
5.总结
今天的内容算是一个结尾吧,然后把前面开发篇的部分又复习了一遍,开发实用篇到这里就暂时完结了,在开发实用篇中 都是大量的第三方技术的整合方案,选择的方案都是市面上比较流行的常用方案。今天也是把整个Boot篇做了个小总结吧,哪些注解哪些东西常用的也都记住了,明天开始做瑞吉外卖的项目,今天自己修改了一下用javamail发消息的代码, 能循环发消息和附件,但是会被官方拉黑。也明白平常的一些垃圾邮件是怎么发送的,利用随机值,发垃圾邮件,他们可能有不被官方拉黑的方法。监控那里的服务器还是很有意思的,能看页面的请求和次数还有自己代码的类啥的,功能很强,使用起来也方便,开启一个服务器,给自己要监控的代码,导入一个坐标,复制一个spring配置就好了。
10.26 瑞吉外卖 DAY1
1.头 所学内容出处
【黑马程序员2022新版SSM框架教程_Spring+SpringMVC+Maven高级+SpringBoot+MyBatisPlus企业实用开发技术】 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=31&share_source=copy_web&vd_source=c8ae4150b2286ee39a13a79bbe12b843
2.所学内容概述
了解软件开发整体介绍
开发环境的搭建
数据库环境的搭建
课件提供了sql文件,可以直接source 导入mysql中 早就习以为常了
Maven项目创建
也很简单,普通的maven项目,复习导入坐标和yaml文件,因为不是直接创建的springBoot 项目,所以要创建Boot程序入口
后台登录开发
先创建一个实体类和mapper以及service
再封装一个R作为返回的结果类
将登录方法 以及返回值写入controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @Slf4j @RestController @RequestMapping("/employee") public class EmployeeController { @Autowired private EmployeeService employeeService; @PostMapping("/login") public R<Employee> login (HttpServletRequest request, @RequestBody Employee employee) { String password = employee.getPassword(); password = DigestUtils.md5DigestAsHex(password.getBytes()); LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper <>(); queryWrapper.eq(Employee::getUsername,employee.getUsername()); Employee emp = employeeService.getOne(queryWrapper); if (emp == null ){ return R.error("用户不存在" ); } if (! emp.getPassword().equals(password)){ return R.error("密码错误" ); } if (emp.getStatus() == 0 ){ return R.error("用户已被禁用" ); } request.getSession().setAttribute("employee" ,emp.getId()); return R.success(emp); } @PostMapping("logout") public R<String> logout (HttpServletRequest request) { request.getSession().removeAttribute("employee" ); return R.success("退出成功" ); } }
后台系统退出功能
这个比较简单 点击按钮退出到登陆页面就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 @PostMapping("/logout") public R<String> logout (HttpServletRequest request) { request.getSession().removeAttribute("employee" ); return R.success("退出成功" ); }
3. BUG点
难点(关键代码或关键配置,BUG截图+解决方案)
之前的登陆功能是有个bug的,像之前web的一个登陆案例,直接输入地址的话,就可以跳过登录页面,达到不登录就能进入需要登录的 页面,之前web是用过滤器的,现在用拦截器解决这个小bug
要先在启动项上面加入@ServletComponentScan注解 识别bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 @WebFilter(filterName = "LongCheckFilter", urlPatterns = "/*") @Slf4j public class LoginCheckFilter implements Filter { public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher (); @Override public void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String requestURI = request.getRequestURI(); String[] urls = new String []{ "/employee/login" , "/employee/logout" , "/backend/**" , "/front/**" }; log.info("拦截到的请求:{}" ,requestURI); boolean check = check(urls, requestURI); if (check){ filterChain.doFilter(request,response); return ; } Object employee = request.getSession().getAttribute("employee" ); if (employee != null ){ log.info("用户已登录,用户id为:{}" ,employee); filterChain.doFilter(request,response); return ; } log.info("用户未登录" ); response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN" ))); } public boolean check (String[] urls, String requestURI) { for (String url: urls){ boolean match = PATH_MATCHER.match(url, requestURI); if (match){ return true ; } } return false ; } }
4.扩展学习部分
5.总结
刚进入瑞吉外卖,下载了一些资料,没找到老师的官方的ppt文档,就CSDN去搜的,第一天的任务不是很难,主要是帮助回看一下springboot的部分,算是小复习,就做了一个登录和退出,还有个登录的小BUG,基本都是后台的代码,前端的一些功能都做好了,后端加bean,调用一下响应和请求就好了,比较基础的还是。学习方法就是看老师过一遍功能如何实现,如何测试,然后就自己试着去敲,慢慢做出来,这样学,进度可能会有些慢,但是能搞清楚每一块是干嘛的,每个注解和类的作用和功能。