GAV
packaging---jar/war/pom
Maven中管理3套classpath
1.编译期间的
2.测试期间的
3.运行期间的
<scope>
默认值:compile--所有的的classpath都有效
test---测试范围
runtime---运行期间范围(测试和运行的classpath)
provided----编译和测试的classpath有效
依赖的冲突问题:
1.路径不同:找最短路径
2.路径相同:谁先加载使用谁
在不改变加载的顺序的前提下,想使用后加载中的内容,可以设置排除依赖的方式
如果A设置了pom值,则进行项目之间的管理
聚合关系的描述
<modules>
<module>../B</module>
<module>../C</module>
</modules>
管理的依赖的描述
<dependencyManagement>
<dependencies>
<dependency>
<g>
<a>
<v>
B项目作为A的子项目,需要描述继承关系
<parent>
<g>
<a>
<v>
<relativePath>../A/pom.xml</relativePath>
</parent>
<dependency>
<g>
<a>
在MyBatis的核心配置文件中描述使用的开发环境:事务处理方式和数据源
<environments default="A">
<environment id="A">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="" value="">
<property name="" value="crx_663">
<property name="" value="">
<property name="" value="">
<environment id="B">
MyBatis框架默认情况下变更操作是手动提交的
加载映射文件:加载classpath路径下的映射文件(resources)
<mappers>
<mapper resource="**/***.xml"/>
<mapper/>
<mapper/>
</mappers>
student-----12条记录----12个对象
映射文件
namespace:多个文件中可以重复-----接口模式下,namespace值必须是接口的全名称
id:当前文件中唯一----接口模式下,id值必须是接口中方法的名称
namespace.id:在整个项目中不能重复------>通过该唯一的坐标进行查找要执行的SQL语句
int row = sqlSession.insert(namespace.id)
int row = sqlSession.update(namespace.id)
sqlSession.commit();
映射文件中获取Java代码传递的数据的方式
传递一条记录:Map/Java对象
传递多条记录:数组/集合
传递单个值:基本数据类型/引用数据类型-----因为单个值没有设置KEY和属性名,在获取时直接命名,见名知意即可
#{}:预处理方式,推荐
Map集合或者自定义的Java对象,#{}描述的是Map中的KEY或者是类中的属性
parameterType="java.util.HashMap"
parameterType=".....Student" use....="true" keyProperty="studentId"
delete(10)
parameterType="java.lang.Integer" 其实一个的时候也可以省略不写,为了提高阅读性
where id = #{studentId}
使用注解自定义KEY
update(@Param("id") Integer studentId,@Param("name") String studentName);
update(20,"小明")
一旦接口的方法中的形参个数多余1个的时候,parameterType不建议设置,让框架自动识别
set studentName = #{arg1} where id=#{arg0} 使用系统提供的KEY
set studentName = #{param2} where id=#{param1} 使用系统提供的KEY
set studentName = #{name} where id=#{id} 使用自定义的KEY
${}:Statement的方式,需要自己对传递的数据进行转换,容易造成SQL语句的注入问题
存在即合理,当使用sql标签提取sql语句中公共部分时,一旦需要设置表的别名,只能使用${}才能获取正确的结果
<sql>
student_id,student_name,student_sex,age,birthday
</sql>
<sql>
${alias}.student_id,${alias}.student_name,${alias}.student_sex,${alias}.age,${alias}.birthday
</sql>
单条记录--->Map集合
1.resultType属性:将ResultSet转成Map集合(默认情况下,虚拟表中的字段为集合中的KEY。也可以使用自定义别名的方式作为集合中的KEY)
2.resultMap属性:需要找resultMap标签,建立约定,描述映射的关系。可自定义不同的KEY
type:描述每条结果处理成的类型
单条记录--->自定义类型(Student)
默认情况下,是自动映射的:如果查询的虚拟表中的记录的字段与Java类中属性一致,自动完成映射(赋值)
1.可以采用别名的方式让虚拟表中的字段与Java类中属性一致
2.resultMap标签:建立映射关系
<id> <result>
column:数据表中的字段名称 jdbcType:描述数据表中的数据类型(可以省略)
property:类中的属性名称 javaType:类中属性的数据类型(可以省略)
如果类中的同一个属性被数据表中不同的字段进行重复赋值,那么后面的值会覆盖前面的。
单个值----使用resultType属性:String类型、基本数据类型
多条记录----本质上还是处理单条记录的映射,将其保存到集合中,这是一个重复循环的动作。
1.resultType:表示每一条记录对应的类型--->String、Integer、int 、map,存储在List集合中
2.resultMap:每一条记录对应的类型--->Student、Map,存储在List集合中
动态的SQL语句
1.if标签+恒等式:需要通过test属性判断条件是否成立
2.where标签+if标签:如果where标签中有内容显示,在内容的最前面加入where关键字,是否有内容需要通过if标签的test属性进行判断
如果where标签中有内容显示,则需要检查内容的最前面是否含有AND或OR,如果有则进行去除
3.set标签+if标签:如果set标签中有内容显示,在内容的最前面加入set关键字,是否有内容需要通过if标签的test属性进行判断
如果set标签中有内容显示,则需要检查内容的最后面是否含有逗号,如果有则进行去除
4.trim标签+if标签:该标签中的属性可以自由组合,可以实现where和set的功能,是否有内容需要通过if标签的test属性进行判断
prefix:当标签中有内容显示时,描述内容的最前端加入的信息
suffix:当标签中有内容显示时,描述内容的最末端加入的信息
prefixOverrides:当标签中有内容显示时,检查最前端的内容是否匹配,如果匹配则进行去除
suffixOverrides:当标签中有内容显示时,检查最末端的内容是否匹配,如果匹配则进行去除
一般trim的经典使用:动态的添加操作---->动态添加的字段和数据的顺序必须要保持一致
(String)类中的trim方法的作用是(去除指定字符串的前后端的空格)
5.foreach标签:实现批量的处理-----遍历数组或者集合
collection:必填项,遍历的集合的名称
item:遍历的集合中每个元素需要赋值给该变量
open:在遍历整个集合时,在内容的最前端需要加入的信息
close:在遍历整个集合时,在内容的最末端需要加入的信息
index:索引
separator:用于指定每次遍历的结果之间使用什么进行分隔
如果传递的是数组,不用设置parameterType属性,让MyBatis框架自动进行识别
数组没有进行指定Key,MyBatis框架为传递的数组设置默认的Key:array
集合没有指定key,MyBatis框架为传递的集合设置默认的Key:list
如果传递的是Map集合,需要通过我们自定义的KEY进行获取该集合中存储的数据
如果传递的是自定义类对象,需要通过自定义类中的集合/数组属性名称进行获取(如果该自定义类对象使用了自定义的KEY,语法是:key.类中属性名)
6.choose标签----主要涉及的知识点:小于号和中文的比较
where标签+choose标签+when/otherwise
通过when标签中的test属性进行判断,如果该条件成立,则在最前面添加where关键字,并按照指定的内容进行查询处理
该标签中不支持小于号的使用,需要处理成:<
test='sex == "男"':如果涉及中文判断,外面单引号,里面双引号
支持小于号的写法(CDATA中不会进行转义,并且不支持标签):<![CDATA[ id < 5]]>
复杂的关系映射
一对一关系
没有框架的时候,类与类之间的关联关系,需要程序员自己手动实现,例如:一个学生对应一个班级
如果有框架,可以选择使用select属性方式:通过resultMap标签中的子标签association关联对象(关联一个)
association标签中的属性:
property:必填项,用于描述类中的关联对象的属性名
javaType:可以省略,用于描述关联对象的类型
column:表示传递哪个字段的值,如果使用select属性的方式进行建立关联关系,必须设置该值
select:定义要执行的指定的SQL语句(namespace+id),并且传递column属性中描述的数据
自定义的映射方式:resultMap标签中的子标签association进行关联对象
为表进行设置别名,获取别名的时候,使用${}的方式
可以使用连接查询方式,减少sql语句的执行,提高查询的效率
该情况不再使用select属性指定sql,也不需要传递column属性值,直接进行关联对象的映射处理
需要使用子标签association的resultMap属性进行操作(namespace+id的方式找关联对象的映射文件中的resultMap标签)
多对一关系
如果使用子标签association的select属性方式进行处理,会存在N+1的问题
可以通过懒加载的方式进行解决:fetchType="lazy"(当我们使用关联对象的时候,才会执行对应的SQL语句)
如果使用连接查询方式,不存在N+1的问题的,相对来讲,效率会高一些
一对多的关系
例如:一个班级对应多个学生
使用select属性方式:通过resultMap标签中的子标签collection关联集合对象
collection标签的属性:
property:必填项,用于描述类中的关联对象的属性名
ofType:必填项,用于描述集合中泛型的类型
javaType:可以省略,用于描述关联对象的类型
column:表示传递哪个字段的值,如果使用select属性的方式进行建立关联关系,必须设置该值
select:定义要执行的指定的SQL语句(namespace+id),并且传递column属性中描述的数据
连接查询方式:通过resultMap标签中的子标签collection关联集合对象
1.当id标签存在时,根据id值进行数据的合并
2.当id标签不存在时,比较每条记录中的每个数据(如果比较的字段都不相同,会因为多余1个结果而导致无法合并,报错)
缓存:提高查询的效率
一级缓存:SqlSession 执行sqlSession.close()方法后,一级缓存消失;执行变更语句后,一级缓存消失
二级缓存:<cache></cache> 持久类必须实现序列化接口
当一级缓存通过close()方法进行关闭后,则去二级缓存中进行查找,如果有则直接返回
当执行变更语句后,二级缓存消失
pom.xml
mybatis-config.xml
web.xml---->DispatcherServlet:通过SpringMVC框架中的web文件进行配置前端控制器,该控制器读取默认位置下系统约定名称的核心配置文件
名称:前缀是通过<servlet-name>标签的内容指定 后缀指定为:-servlet
位置:/WEB-INF/
spring-servlet.xml /WEB-INF/spring-servlet.xml
<servlet>
<servlet-name>spring
<servlet-class>
</servlet>
<servlet-mapping>
官方推荐使用/
</servlet-mapping>
@Controller 该注解只能标注在类上 表示这是控制类(Servlet)
value属性:对应的默认的名称是类名的首字母小写 需要保持唯一性
@RequestMapping:可以标注在类上,也可以标注在方法上(控制器)
标注在类上:提取映射路径中的公共部分
标注在方法上:具体注册的映射路径 (注册的映射路径可以是相同的,不需要具有唯一性)
在SpringMVC的核心配置文件中进行启动SpringMVC的功能,指定扫描的位置(Controller类所在的包)
服务端的跳转方式(JSP与Servlet):请求转发和重定向
请求转发:通过HttpServletRequest传递数据
可以访问WEB-INF下的文件
重定向:类似超链接的操作,通过url?的方式拼接字符串传递数据
Controller跳转JSP
注意:请求转发的默认位置是:/WEB-INF/
请求转发:如果调用的setViewName方法中传递的字符串(jsp页面的url)没有设置任何的前缀,默认是请求转发操作
重定向:如果调用的setViewName方法中传递的字符串(jsp页面的url)设置了前缀----redirect:,表示重定向操作
Controller跳转Controller
请求转发:如果调用的setViewName方法中传递的字符串(Controller的映射url)没有设置任何的前缀,默认是请求转发操作
重定向:如果调用的setViewName方法中传递的字符串(Controller的映射url)设置了前缀----redirect:,表示重定向操作
SpringMVC框架针对请求转发到JSP页面提供了视图解析器,可以拼接完整的URL
通过该解析器设置路径中的公共部分
前缀:/WEB-INF/jsp/
后缀:.jsp
配置了视图解析器之后,如果调用的setViewName方法中传递的字符串没有设置前缀,默认都是转发到JSP页面,无法实现转发到Controller中
此时需要设置前缀----forward:,才能实现转发到Controller中
自定义核心配置文件的名称与位置
配置前端控制器时,直接进行指定
<init-param>
<param-name>....Location</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
如果出现相同名称的类,只要存储在不同包下即可
类:Controller,需要设置@Controller注解,该注解的value属性值是默认类名首字母小写,他俩的value值是一样的
此时,启动服务会出现错误,一个value值映射两个不同类
可以通过自定义@Controller注解的value属性值进行区分
@RequestMapping:该注解有value和path属性,具有相同作用,如果只有映射路径时,这两个注解都可以省略不写
如果映射路径是相同的,可以通过请求的方式进行区分 get/post
虽然存在put/patch/delete的其他请求方式,但是HTML页面只支持get和post
此时需要在web.xml文件中配置过滤器,通过该过滤器将页面中发起的post请求处理成你想要的put/delete等其他请求方式
post作为页面中的真正的请求方式
需要传递一个控件(隐藏表单域),控件需要设置name属性,该属性的值必须是:_method------>name="_method" value="put/delete"
控制器中的参数,如果是HttpServletRequest、HttpServletResponse、HttpSession、PrintWriter、ServletContext(该对象不能使用,因为不存在),SpringMVC框架对
其他类型进行了自动实例化处理。
通过@Autowired注解可以对成员变量进行自动的注入(装配):HttpServletRequest、HttpServletResponse、HttpSession、ServletContext
控制器中的参数,如果是Map接口,SpringMVC框架可以对其自动实例化,如果是List、Set接口,不能使用,因为SpringMVC框架没有对其进行实例化处理。
可以使用List、Set的是实现类进行传递数据(ArrayList、HashSet)
如果是自定义类对象,该类无论是私有的还是公有的构造方法都可以进行实例化
控制器返回值的类型:ModelAndView new ModelAndView(url) 对象.setViewName(url) return 对象
String
void:(不太推荐的返回值类型) 默认按照映射路径进行请求转发处理,查找页面
页面输出内容、下载文件、返回Json数据(jackson工具类)
请求转发传递数据:
ModelAndView
传递的数据是以名值对的形式传递的,其中基本数据类型数据默认的KEY是对应的包装类首字母小写,其他引用数据类型就是首字母小写
55 int---Integer--integer requestScope.integer
88.8 double---Double---double ======>由于double是关键字,在页面中通过该KEY进行获取数据时,语法是:requestScope["double"]
cat Cat---cat requestScope.cat.catSex
ModelMap、Map、Model
重定向传递数据:
1.路径传递数据
2.Model、ModelAndView 页面中获取数据的方式:${param.key}
服务端获取客户端的数据:
1.传统方式获取数据----需要程序员自己完成数据格式的转换
2.@RequestParam:该注解作用在方法的形参上
name属性:表示指定传递的参数为形参进行赋值,如果只有一个值,该属性可以省略
required=false表示可以不用传值,默认是true
defaultValue表示设置默认值
注意:如果形参中存在基本数据类型,一定要对该参数进行传递数据,否则出现500错误,表示数据转换的失败
3.@RequestParam:推荐简写的方式----形参的名称与传递的名称一致,可以自动完成转换,省略@RequestParam注解。
4.对象数据的获取:当传递的数据的名称为类中属性的时候,可以自动完成转换
5.关联对象数据的获取:1)自己建立关联关系 2)自动建立关联关系-----通过主类中的关联对象进行传递数据(从关联对象中查询属性)
6.不同对象具有相同属性的形式的获取:需要使用第三类建立不同对象的关联关系,通过对象的属性名进行区分,传递规则类似于第5条中的第2点
7.传递Map数据的规则:1)传统方式传递数据,需要通过@RequestParam注解将其转成Map集合
2)使用占位符的形式传递数据,可以通过@PathVariable将其转成Map集合
3)可以使用第三方类,将Map集合作为主类的关联对象进行传递,需要自定义Map集合中的KEY,主要注意前端页面的写法
8.占位符传递数据:可以支持正则表达式的使用,但是实际开发中使用的较少,大多数情况下只是用来传递简单的数据(注意@PathVariable注解使用的规则)
文件的上传和下载:
前端的准备工作:
必须是POST请求(但是不能使用PUT、DELETE、PATCH)
可以使用Form表单提交数据
可以使用Ajax发送POST请求,需要于FormData对象搭配使用
传递的文件必须设置请求内容的类型(二进制流的形式----multipart/form-data)
文件域(单个文件/多个文件[需要设置multiple属性])
后端的准备工作:
依赖文件上传和下载的jar包:commons-fileupload
SpringMVC针对文件上传进行封装对应的解析器----在核心配置文件中描述该解析器时,id属性值是固定的(前端控制器中有约定)
下载页面容易出现的问题:
因为所有的请求都会被前端控制器进行处理,按照URL找对应的处理器(Controller),但是下载的操作应该是一个静态资源的请求处理,需要对静态资源的访问进行排除
静态资源的排除方式:
1.使用服务器默认的排除方案:静态资源的路径需要程序员写完整的路径
2.静态资源的映射路径(推荐使用的):<mvc:resources mapping="/映射路径/**" location="本地静态资源的位置"/>
Ajax传递数据:
如果涉及到JSON数据格式的传递或者文件上传时,只能使用POST请求方式
1.传递JSON数据格式,可以自己拼接字符串传递到服务端(ajax的get/post函数发起请求),自己在服务端转换数据的类型
2.传递JSON数据格式,前端通过ajax函数发起请求传递数据,服务端可以通过@RequestBody完成自动转换
1)请求方式必须是post的
2)contentType必须是json格式
3)processData设置为false,不需要对数据转成字符串
3.通过JSON的插件,简化前端数据的转换
1)在引入该插件的js文件之前,先引入jquery的js文件
2)先将表单进行序列化,再将序列化的结果转成json的字符串
4.传递FormData数据:
1)获取文件域数据(单个/多个)
2)将获取的数据封装成FormData对象
3)通过ajax函数发送数据
a.请求方式必须是post的
b.contentType值设置为false,表示使用二进制流的方式传递数据
c.processData设置为false,不需要对数据转成字符串
数据转换:(可以使用内置转换器规则,可以使用自定义转换器规则)
1.Converter通用转换器:可以在应用程序的任意层进行使用,转换与被转换的数据类型没有限制
2.格式化Formatter:
如果完成日期的转换,默认情况下,日期可以转成的格式:yyyy/MM/dd HH:mm:ss
如果想处理成自定义的转换格式,需要使用@DateTimeFormat注解,将其作用在类的属性上以及方法的形参上
访问修饰符 返回值类型 方法名(@DateTimeFormat("yyyy-MM-dd")日期参数)
注意:录入的数据格式可以比自定义的规则长(多余部分自动抹除),不能比规则短(400错误)
Formatter是将一种数据类型转成另一种数据类型,但是源类型必须是字符串(Converter可以是任意的类型)
Formatter更适合用于web层(Converter可以使用在任意层)
优先级:自定义的Formatter转换器 > @DateTimeForma > 默认情况
拦截器Interceptor:
对资源的拦截,可以根据自己设置的规则进行拦截或者放行,是一种特殊的过滤器
拦截的是映射路径,拦截的是控制器,不拦截JSP
需要在核心配置文件中配置拦截器,设置拦截的规则
preHandle:访问控制器之前执行,最常用的方法
postHandle:在找到视图资源之前执行
afterCompletion:视图资源加载完毕(渲染完成)之后执行
静态资源可以经过拦截器,但是可以设置排除(排除的也可以是映射路径)
异常处理:
1.可以通过配置web.xml文件处理错误信息,因为以后不再使用web.xml文件,所以该形式不常用,会用即可。
2.简单的统一异常映射(第三优先级)
需要在核心配置文件中进行配置----异常映射的解析器
默认是请求转发操作,所以需要遵循JSP请求转发解析器处理跳转操作
3.自定义全局的异常处理方式(第三优先级)
1)自定义全局异常处理规则,需要实现HandlerExceptionResolver接口
2)启动自定义全局的异常处理,在核心配置文件中进行配置
注意:第2点和第3点中处理方式,属于同一个级别,所以核心配置文件中谁先加载使用谁
4.定义局部的异常处理@ExceptionHandler(第一优先级),该方式不太推荐使用
@Controller
class ***Controller
@ExceptionHandler(value = {异常类,异常类,异常类.....})
访问修饰符 返回值类型 方法名(参数列表....)
5.使用@ControllerAdvice+@ExceptionHandler=自定义全局异常(第二优先级),个人推荐使用的方式
@ControllerAdvice
class ***Controller
@ExceptionHandler(value = {异常类,异常类,异常类.....})
访问修饰符 返回值类型 方法名(参数列表....)
Java创建对象的方式
1.使用new关键字,最常用的方式,可以调用任意的构造方法(调用构造方法不一定会创建对象,子类创建对象时会调用父类的构造方法,但是不会创建父类对象)
2.使用Class类的newInstance方法创建对象,但是该方法只能调用类中的无参构造方法
3.通过反射的方式获取构造方法对象(Constructor),然后使用newInstance方法创建对象,可以调用任意的构造方法
4.使用clone方法克隆,需要有源对象,会创建源对象的副本(一个新的对象),克隆时不会调用任何的构造方法,类必须要实现Cloneable接口,具有克隆的能力,重写clone的方法
5.序列化:当使用序列化和反序列化的方式创建对象时,会创建一个新的对象。反序列化的时候不会调用任何的构造方法,但是类必须实现Serializable接口,具有序列化的能力
实例变量的初始化
在创建对象时,由构造方法进行初始化(也可以通过公开的set方法,进行再次的赋值)
也可以通过反射的方式获取对象的字段,再通过字段的set方法对属性进行重新赋值
Spring是IoC和AOP的容器框架,核心是管理Bean
IoC:控制反转(让别人为我们提供服务,创建和初始化的步骤交给Spring框架)
Spring容器默认情况下创建的对象都是单例模式 可以通过设置scope属性的值,将其改变为多例模式(在容器初始化时,没有调用构造方法,只有在使用时才调用)
核心配置文件中的bean标签具有init-method和destroy-method两个属性,可以初始化和销毁操作
DI:依赖注入(从另一个角度对控制反转的描述)
依赖:描述对象与对象之间的关系,对象和属性之间的关系
注入:就是初始化/赋值的过程,对成员变量的初始化(简单数据或对象[子类对象或实现类对象]),可以使用构造方法的方式或者使用set方法的方式
构造方法方式:如果是无参构造,bean标签中只需要提供class和id属性即可
如果类中没有无参构造方法,上述操作会报错,必须要指定使用的具体的有参构造方法(bean标签中要存在具体内容),构造方法中参数的描述不区分顺序
set方法方式:前提---必须提供无参构造方法,调用无参构造对实例变量进行初始化,然后再调用set方法进行重新赋值。
核心配置文件中bean标签需要有具体内容的描述(使用set方法的过程)
关联对象:简单的关联对象
班级具有班主任 Teacher
班级含有很多学生 List<Student>
复杂的关联对象
抽象类:子类(对象的上转型)
接口:实现类(接口的回调)
开发过程中,可以使用核心配置文件方式(xml版本)管理bean,
也可以使用核心配置类方式(java版本)管理bean
1.使用JavaConfige配置类+Bean注解
2.使用JavaConfige配置类+扫描注解(@Component使用在任意层,不易区分层次,可读性差;@Repository持久层;@Service业务层;@Controller控制层)
IoC注册组件的方式
1.@Bean注解注册组件
2.包扫描+组件标注注解的方式(@ComponentScan(描述要扫描的位置),@Component,@Repository,@Service,@Controller)
3.@Import快速向容器中注册一个组件(描述要导入到容器中的组件,然后容器会对其进行自动注册[id默认值是类名的全名称])
ImportSelector:实现该接口,返回需要导入的组件的类名的全名称数组(通过@Import注解向容器中进行手动注册)
ImportBeanDefinitionRegistrar:实现该接口,通过@Import注解向容器中进行手动注册 具体实现时可以检查是否包含某个注册的组件
4.使用Spring提供的FactoryBean(工厂Bean)------ FactoryBean是一个接口,需要进行实现,通过该方式创建的对象默认是多例模式。
默认获取的对象,调用工厂Bean中的getObject方法创建对象
要获取工厂Bean的本身,需要在ID的前面加入&
DI依赖注入的方式
简单数据的注入:
@PropertySource加载属性文件
@Value注入简单数据(可以获取属性文件中的值进行注入)
@Autowired自动装配(官方推荐的方式)
在自动装配时,如果容器中存在多个同类型组件,此时需要搭配使用@Qualifier注解进行明确的指定
默认情况下,先按照关联属性的类型在容器中进行查找,找到且只有一个就进行注入。如果找到多个同类型的组件,那么再将属性的名称作为Bean的值在容器中进行查找
@Resource先按照名称进行查找,再按照类型进行查找
容器注册组件的过滤
1.使用判断的方式注册组件
2.扫描的过滤规则(排除扫描/指定扫描[必须设置取消默认的过滤规则])
代理模式
1.静态代理
2.Java动态代理:必须存在接口和实现类,代理类必须要实现InvocationHandler接口
3.CgLib动态代理:用类实现代理,对执行目标类动态生成一个子类,子类重写父类中的方法,所以目标类不能使用final进行修饰,因为目标类必须是可以继承的
AOP:面向切面编程,在不改变原来代码的基础上,增加新的功能(通过动态代理方式实现AOP[Java动态代理、CgLib动态代理])
表达式支持匹配的语法:
*:匹配任意数量的字符
..:表示0个或多个项(方法所在类的全路径名称[匹配当前包及其子包],或者匹配0个或多个参数)
+:匹配执行类型的子类类型
术语:
连接点:被进项某种增强的方法被称为连接点
切点:一个切点由多个连接点组成
增强位置:前置、后置、返回/最终、异常、环绕
前置:无论代码是否正确都会织入
后置:无论代码是否正确都会织入
返回/最终:代码正确时才会织入
异常:代码错误时才会织入
切面:切面由通知和切点组合。表示何时在何处完成其功能
目标对象(被代理对象):增强代码的目标类
代理对象:一个类被AOP增强后,产生的一个结果(子类)
事务管理
什么是事务:一个业务功能由多个动作组成,如果有一个动作错误,那么之前所有的动作都不应该起作用
数据库事务:数据库管理系统运行过程中的一个逻辑单位(一次执行多条SQL语句),由一个有限的数据库操作序列(SQL语句执行的顺序)组成。
当其中某条SQL语句执行错误的时候,那么之前涉及到的变更操作都应该进行"回滚"处理。
事务的4个特性:
原子性:要么全部执行,要么全部不执行
一致性:保持所有数据的完整性
隔离性:当多个事务并发执行时,一个事务的执行不应该被其他事务所影响
持久性:一个事务一旦被提交,那么事务的操作便永久保存在数据库中。
什么是事务管理:就是管理事务,为了保持数据的完整性和一致性。
事务的传播性:当一个事务A方法调用另一个事务B方法时,需要检查B方法设置的事务传播性
@Transactional(propagation = Propagation.REQUIRED)
Propagation.REQUIRED:默认值,有则加入,无则新建
Propagation.REQUIRES_NEW:不管有没有(有进行挂起处理),直接创建一个新的事务
Propagation.SUPPORTS:有则加入,没有就不管,非事务运行
Propagation.NOT_SUPPORTED:存在就挂起(以非事务的方式进行执行)
Propagation.MANDATORY:有则加入,无则异常(抛出异常)
Propagation.NEVER:存在就异常(以非事务的方式进行执行)
Propagation.NESTED:存在就在嵌套内执行,没有就找是否存在外面的事务,有则加入,无则新建
事务的隔离级别:
DEFAULT:默认的隔离级别READ_COMMITTED
READ_UNCOMMITTED:最低隔离级别(不推荐使用)会产生脏读、不可重复读和幻读问题
READ_COMMITTED:可以避免脏读的出现,但是可能会出现不可重复读和幻读问题
REPEATABLE_READ:可以避免脏读、不可重复读出问题,但是可能出现幻读问题
SERIALIZABLE:最可靠的事务隔离级别,可以避免所有问题,但是消耗性能太大。
Spring Boot数据注入
@Value注解
普通简单数据(字符串、基本数据类型)
操作系统属性(System)
表达式运行的结果(#{})
其他Bean中的属性(前提:该Bean已经被实例化)
文件资源(输入输出流进行读取)
核心配置文件
自定义文件,需要通过@PropertySource进行加载,但是默认只能加载*.properties的文件。加载多个配置文件时,如果出现相同的KEY,那么只会使用最后加载文件中该KEY对应的值。
URL资源文件(得到访问网址的内容)
@Autowired注解
@Resource注解
SpEL使用规则
${}和#{}的使用方式
${}:必须符合SpEL表达式,通过其可以获取属性文件中指定KEY所对应的值,如果该KEY不存在,则报错,但是可以赋值默认值。
#{}:直接使用Java类或者对应方法
${}和#{}混合使用:#{}必须在外面,${}必须在里面
@ConfigurationProperties和@Value的区别
功能:
批量注入属性到Java类中 只能一个一个属性指定注入
复杂数据类型(对象和数组):
支持 不支持
JSR303数据校验:
支持 不支持
SpEL表达式
不持支 支持
松散语法绑定(自动驼峰式)
支持 不支持
切换环境的方式:
全局的配置文件方式:在核心配置文件中进行指定使用的环境(会破坏核心配置文件,增加修改配置的次数)
设置主程序的启动参数(不会破坏核心配置文件,减少修改配置的次数,方便不同环境之间的切换)
vm options:-Dspring.profile.active=***
program argument:--spring.profile.active=***
active profile:***
注意:上述三个选项认选其一
命令方式:
先打包,然后运行cmd,执行命令
java -jar 路径/****.jar --spring.profile.active=***