1 框架
1.1 什么是框架?
它是一个半成品软件,将所有公共的、重复的功能解决掉,帮助程序员快速高效的进行开发,它是可复用、可扩展的。是软件开发中的一套解决方案,不同的框架解决的是不同的问题。
使用框架的好处:
框架封装了很多的细节,使开发者可以使用极简的方式实现功能,大大提高开发效率。
1.2 三层架构
各层之间的调用顺序固定,不允许跨层访问:
界面层<------->业务逻辑层<-------->数据访问层
表现层(界面层):用于展示数据
用来接收客户端的输入,调用业务逻辑层进行功能处理,返回结果给客户端。(servlet就是界面层的功能)
业务层(业务逻辑层):处理业务需求
用来进行整个项目的业务逻辑处理,向上为界面层提供处理结果,向下向数据访问层要数据。
持久层(数据访问层):和数据交互
专门用于数据库的增删改查操作,向上为业务逻辑层提供数据。
持久层技术解决方案
JDBC技术:Connection、PrepareddStatement、ResultSet(规范)
Spring的JdbcTemplate:Spring中对JDBC技术的封装(工具类)
Apache的DBUtils:类似Spring的JdbcTemplate,也是对jdbc的简单封装(工具类)
2 代理模式
2.1 代理模式
目标对象不可访问,通过代理对象增强功能访问。
2.2 代理模式作用
- 控制目标对象访问;
- 增强功能
2.3 代理分类
- 静态代理
- 动态代理
- JDK动态代理
- CGLib动态代理
2.3.1 静态代理
静态代理特点
- 目标对象和代理对象实现同一个业务接口;
- 目标对象必须实现接口;
- 代理对象在程序运行前就已经存在;
- 静态代理能够灵活的进行目标对象的切换,但无法进行功能的灵活处理(使用动态代理解决此问题)。
2.3.2 动态代理
代理对象在程序运行过程中动态在内存中构建,可以灵活的进行业务功能的切换。
2.3.2.1 JDK动态代理
JDK动态代理特点
- 目标对象必须实现业务接口;
- 代理对象不需要实现业务接口;
- JDK动态代理的对象在程序运行前不存在,在程序运行过程中动态的在内存中构建;
- JDK动态代理可以灵活的进行业务功能的切换;
- 本类中的方法(非接口)不能被代理。
JDK动态代理用到的类和接口
它是使用现在的工具类完成JDK动态实现
- Proxy类(java.lang.reflect.Proxy)
它有一个方法newProxyInstance(…)专门用来生成动态代理对象 - Method类
反射用的类,用来进行目标对象的方法的反射调用。 - InvocationHandler接口
它是实现代理和业务功能的,我们在调用时使用匿名内部类实现。
2.3.2.2 CGLib动态代理
CGLib动态代理特点
- 又称为子类代理,通过动态在内存中构建子类对象,重写父类的方法进行代理功能的增强;
如果目标对象没有实现接口,则只能通过CGLib子类代理来进行功能增强
;- 子类代理是对象字节码框架ASM来实现的;
- 被代理的类不能为final;
- 目标方法的对象不能为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法。
面向接口编程:
- 类中的成员变量设计为接口
- 方法的参数设计为接口
- 方法的返回值设计为接口
- 使用时使接口指向实现类
3 mybatis框架
mybatis是一个持久层框架,用java编写。它完成了数据访问层的优化,专注于SQL语句,简化了过去JDBC繁琐的访问机制。它封装了jdbc操作的很多细节,使开发者只需要关注SQL语句本身,而无需关注注册驱动、创建连接等繁杂过程。它使用ORM思想实现了结果集的封装。
ORM:
Object Relational Mapping,对象关系映射
就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就实现操作数据库表。
3.1 mybatis框架结构
3.2 mybatis对象分析
- Resources类
解析SqlMapConfig.xml文件,创建相应的对象
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
- SqlSessionFactory接口
使用ctrl+h快捷键查看本接口的子接口和实现类
DefaultSqlSessionFactory是实现类
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
- SqlSession接口
DefaultSqlSession是实现类
SqlSession sqlSession = factory.openSession();
3.3 Mybatis动态代理
动态代理存在的意义:
在三层架构中,业务逻辑层要通过接口访问数据访问层的功能,动态代理可以实现。
MyBatis框架使用动态代理的方式来进行数据库的访问。
Mapper接口的开发相当于是过去的Dao接口的开发。由MyBatis框架根据接口定义创建动态代理对象,代理对象的方法体同Dao接口实现类的方法。
3.3.1 动态代理实现规范
- Mapper接口与Mapper.xml文件在同一个目录下。
- Mapper接口与Mapper.xml文件名必须一致,后缀不管。
- Mapper接口方法名称与Mapper.xml中的标签的statement的ID完全相同。
- Mapper接口方法的
输入参数类型
与Mapper.xml的每个sql的parameterType的类 型相同。 - Mapper接口方法的输出参数与Mapper.xml的每个sql的resultType的类型相同。
- Mapper文件中的namespace的值是接口的完全限定名称。
- 在SqlMapConfig.xml文件中注册时,使用class属性=接口的完全限定名。
3.3.2 动态代理访问步骤
- 建表
- 新建maven工程,刷新可视化
- 修改目录
- 修改pom.xml文件,添加依赖
- 添加jdbc.properties文件到resources目录下
- 添加SqlMapConfig.xml文件
- 添加实体类
- 添加mapper文件夹,新建Mapper接口
- 在mapper文件夹下,新建Mapper.xml文件,完成增删改查功能
- 添加测试类,测试功能
3.3.3 #{}和${}
#{}是对非字符串拼接的参数的占位符
,如果入参是简单数据类型(8种基本数据类型(封装)+ String),则#{}里可以任意写,但是如果入参是对象类型,则#{}里必须是对象的成员变量的名称(严格区分大小写),#{}可以有效防止sql注入
。
${}主要是针对字符串拼接替换
,存在sql注入风险,尽量少用。如果入参是基本数据类型,${}里3.5.1以前可以随便写,之后必须是value,但是如果入参是对象类型,则${}里必须是对象的成员变量的名称
(现在已经很少用)。
${}还可以替换列名和表名
3.3.4 UUID
3.3.4.1 UUID
全球唯一字符串,UUID 是由一组32位数的16进制数字所构成。
UUID可以让分布式系统中的所有元素都能有唯一的识别信息,而不需要通过中央控制端来做辨识信息的指定。如此一来,每个人都可以创建不与其它人冲突的UUID。在这样的情况下,就不需考虑数据库创建时的名称重复问题。
3.3.4.2 UUID组成
UUID由以下几部分的组合:
- 当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
- 时钟序列。
- 全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
3.3.4.3 UUID 特点
经由一定的算法机器生成
为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。UUID的复杂特性在保证了其唯一性的同时,意味着只能由计算机生成。
非人工指定,非人工识别
UUID是不能人工指定的,除非你冒着UUID重复的风险。UUID的复杂性决定了“一般人“不能直接从一个UUID知道哪个对象和它关联。
在特定的范围内重复的可能性极小
UUID的生成规范定义的算法主要目的就是要保证其唯一性。但这个唯一性是有限的,只在特定的范围内才能得到保证,这和UUID的类型有关(参见UUID的版本)。
3.3.4.4 应用
- 数据库表总会有一个主键,可以使用自增的数字作为主键,加快查询效率,但是有时会分库分表,像淘宝、京东等订单表会非常大,自增主键可能会不够用,另一个场景就是在做系统集成或者数据迁移的的时候id有可能会重复。
- 文件上传时可能出现上传的文件放在同一个文件夹,导致后上传的会覆盖先上传的文件的问题,可以使用UUID来解决。
4.Mybatis中的缓存
缓存:
内存中临时存在的数据。
缓存的好处:
减少直接操作数据库的次数。
缓存场景:
- 适用:
经常查询,不常改变;
查询结果正确与否影响不大; - 不适用:
不经常查询,或经常改变;
查询结果正确与否对结果影响很大,比如银行账户,股市等
一级缓存与二级缓存
-
一级缓存
-
二级缓存