MyBatis
核心接口和类
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession
准备工作
配置MyBatis所需DTD文件
Mybatis.3.2.2.jar解压
Mybatis/org/apache/ibatis/builder/xml
mybatis-3-config.dtd
mybatis-3-mapper.dtd
在Eclipse中添加DTD
Window》Preferences》xml》选中catalog》右击到
在弹出窗口中选择File System...
编写key值
-//mybatis.org//DTD Config 3.0//EN
-//mybatis.org//DTD Mapper 3.0//EN
对应不同的DTD文件
创建XML文件
项目右键New》orhers》XML file》填写名称》选择create XML file from a DTD file》
选择select XML catalog entry》编写System ID: http://mybatis.org/dtd/...
项目运行流程
文件及作用
Jdbc.properties资源文件
作用:用于编写数据库链接信息
Log4j.propreties资源文件
作用:记录日志信息
Mybatis-config.Xml配置文件
作用:加载资源文件链接数据库,设置别名、事务管理、设置访问Mapping等核心
XxxMapping.xml映射文件
作用:实现实体类与关系型数据库字段的关联,执行数据库操作(编写SQL)
SqlSessionUtil.java工具类
作用:加载配置文件创建SqlSession对象
项目文件创建流程(可根据自己特点设计)
创建pojo包,实体类(属性与数据库字段一一对应)
创建util包,SqlSessionUitl工具类(提供打开SqlSession的方法)数据访问层接口
编写mybatis-config.xml文件(编写过程中发现需要引入资源文件)
编写资源文件
创建Mapping文件
创建dao包,实现业务需求的数据访问接口
创建dao.impl包:数据访问层实现(获取util中SqlSessiom对象)
在数据持久化方法中指定要访问的Mapping文件
内容:namespace+id
创建service包:实现业务逻辑处理
创建service.Impl包,业务逻辑层实现(访问数据层访问层获取数据)
创建数据访问层接口对象,调用功能方法
Servlet+jsp
trim在java中去两边空格,xml在配置中mappers里是
注解
优化代码
改@Update
查@Select
曾@Insert
删@Delete
GetMapper()
通过反射机制动态获取类的方法
使用:session对象.getmapper(Dao接口.class).方法();
注意:
Mapping文件中需要将namespace指定到具体的Dao接口
方法名必须与Mapping中的元素id保持一致
@Before 在加载类其他测试之前先加载使用此注解的测试
作用
注:
仅限简单sql语句查询
使用注解时不可以在编写对应的Mapping元素,二者选其一
传递参数是使用@param(“自定义参数名”)
当参数数量过多时可使用实体类对象传参
缓存
分类
一级缓存:基于Sessioin的缓存,默认存在的
二机缓存:全局存在
eviction驱逐测量:LRU最少最近使用(默认),FIFO先进先出,SOFT软引用,WEAK弱引用
flushInterval清楚缓存的间隔参数
size设置最多保持的key值数量最大(1024)
readOnly不写以默认的方式序列化和反序列化
type编写的缓存类
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"></cache>
Mybatis分页
Mybatis自带分页:RowBounds(非物理分页)
new RowBounds(int offset,int limit);
Offset:开始索引
Limit行数
使用selectList(id,参数,rowBunds对象)
Mybatis插件:Pagehelper(物理分页)
Batis-config.xml配置插件信息
<plugins>
<!--导入分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 区分数据库 -->
<property name="helperDialect" value="mysql"/>
</plugins>
使用PageHelper.startPage(int pageNum,int pageSize,boolean count)
pageNum:当前页数
PageSize:每页行数
Count:是否统计总数(默认为:true)
获取分页信息通过new PageInfo(获取到的集合对象)
getPages()获取总页数
getToral()获取总记录数
反射机制
动态反射类的信息以及动态调用类的属性及方法
可以动态获取类的信息以及动态获取类的属性及方法,解决静态语言本身的缺陷,是动态管理类的一种机制
怎么实现
创建自定义类(添加属性及方法)
通过反射加载目标类路径
Class.forName(路径)
要处理:ClassNotFoundException异常
通过指定方法调用获取类的信息、属性及方法
遍历展示信息
常用的反射方法有哪些?
动态获取属性信息:
动态获取类的全部属性
Target.getDeclaredFields();
返回field[]
获取属性的详细信息
field.toString()
获取访问修饰符
Modifier.toString(field.getModifiers())
返回String
获取属性类型
field.getType().getSimpleName();
返回String
获取属性名称
field.getName()
返回String
判断属性是否存在
target.getDeclaredField(属性名称);
返回Field
通过判断返回是否为null,判断是否存在该属性(如果不存在会产生异常)
动态获取方法信息
动态获取类的全部方法
Target.getDeclaredMethods();
返回Methods[]
获取方法详细信息
met.toString();
获取方法访问修饰符
Modifier.toString(met.getModifiers());
获取方法返回类型
met.getReturnType().getSimpleName();
获取方法名称
met.getName();
获取参数信息(jdk1.7以上版本)
getParameters();
返回Parameter[]
获取参数类型
获取类型名称:parameter.getType().getSimpleName();
获取类型详情:parameter.getType().getName();
获取参数名称
Parameter.getName()
参数名称以及参数顺序默认设为:arg0,arg1,...
获取返回值
Method.invoke(targer.nawInsrance(),参数);
参数根据实际方法的参数定义,存则加,没有则省略
获取类的对象
获取类的无参构造
Target.newInstance();
调用类的私有有参构造
调用类的有参方法
Target.getDeclareMethod(“方法名称”,参数类型);
Method.invoke(target.newInstance(),参数列表);
EG:Method method=target.getDeclareMethod(“方法名称”,参数类型);
method.invoke(target.newInstance(),参数列表);
Spring插件
代理(proxy)
共23种代理模式
静态代理:
在编译时就将接口、实现类、代理类全部手动完成(构成代理冗余、浪费时间)
动态代理:
在程序运行期间动态创建代理类及其实例主要运用的是Java反射机制
作用
有效将实现与调用者进行解耦,隐藏具体实现通过面向接口进行编码
代理实现
静态代理
创建接口
创建具体的实现类(被代理者)
创建代理类(代理者)
实现被代理者一致的接口
创建私有Dao接口对象
重新接口中的方法(方法体:通过对象访问被调用者中重写的方法)
创建测试类
创建代理类对象访问方法即可
动态代理
创建接口
创建具体的实现类(被代理者)
创建InvocationHandler接口的代理类(代理者)
实现InvocationHandler接口
创建私用于接收事例的Object对象,通过有参构造赋值
重写invoke(Object,args)方法
创建测试类
创建接口对象
创建动态代理类对象
实现动态代理(强制转换为接口对象)
Proxy.newProxyInstanse(类加载器,接口数组,代理类对象)
类加载器:对应接口名.class.getClassLoader()
接口数组:new Class[]{对应接口ming.class}
代理类对象:方法调用处理器的代理类对象
代理优缺点
静态代理:
优点:
隐藏实现类的实现细节,解耦合
缺点:
重写同一接口中方法造成大量代码重复、多接口的实现增加了代码的维护复杂度
代理对象只服务于一种类型的对象,如果要服务多类性对象都要进行代理
动态代理:
优点:
最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法处理(InvocationHandler.invoke)灵活处理接口中大量方法,类的职责更加单一,复用性更强
Spring核心
Spring设置注入
通过set方法
在<bean>元素中设置<property>元素,通过name属性关联实体类属性,
通过value属性设值,或通过<value>元素设值
Spring容器默认会访问指定名称属性的set方法进行设值
Eg:
<bean id="user" class="com.main.java.bean.userBean">
<property name="userName" value="tom"></property>
<property name="age" value="20"></property>
</bean>
通过构造方法
在<bean>元素中设置<constructor-arg>元素,通过name属性关联实体类属性
通过value属性设值、或通过<value>元素设置
Spring容器默认会访问实体类无参构造创建对象
自定义有参构造后在<bean>元素未设值属性参数时会报错,把对应参数补全解决报错问题
构造注入减少实体类中的set方法的创建,代码整洁,提高安全性
Eg:
<bean id="use" class="com.main.java.bean.userBean">
<constructor-arg name="userName" value="ddd"></constructor-arg>
<constructor-arg name="age" value="15"></constructor-arg>
</bean>
工厂模式
解决紧耦合问题,实现类与类的松耦合
简单工厂
工厂类
抽象工厂
创建一个普通类和一个接口
创建接口的实现(两个以上)
创建抽象工程类
包含返回对应接口类型并带有String参数的静态方法
使用控制语句根据参数不同返回不同的实体类对象
普通类中只声明B接口对象,通过有参构造赋值
在类中调用接口中的方法,
创建普通类对象时通过工厂类获取对应实现类实例
单例模式
保证对象的一致
饿汉式
构造私有化(禁止通过new创建对象)
创建本类对象静态常量私有化(避免通过类名访问对象)
提供静态公共方法返回本类对象
懒汉式
在访问类的方法时指定方法创建实例对象
构造私有化(禁止通过new创建对象)
声明私有成员静态属性
提供静态公共方法返回本类对象
判断空值:真则创建对象给成员属性 赋值,否则直接返回成员属性
注:解决线程安全问题
使用关键字synchronized设置方法同步
在方法中设置同步
If(对象==null){
Synchronize(本类名.class){
if(对象==null){
//实例化对象
}
}
}
(推荐)使用静态内部类
Private static class 类名{
Private static final 单例类型 属性名=new单例类型();
}
构造私有化
Public static final 单例类型 getInstance(){
return 内部类名.属性名
}
IOC:依赖注入
Aop:面向切面编程
日志
公共部分:
日志:前置通知,后置通知
实现正常的核心业务编写
创建用于日志记录的类(LOG4J)
通过配置文件将日志记录类与核心业务关联
测试
权限:
实现正常核心文件的编写
创建用于控制权限的类(power)
Aspectj:MethodIncocationProceedingJoinPoint
自定义方法:
返回类型为Object
参数:JoinPoint
实现权限管理
获取用户的访问方法
强转为MethodIncocationProceedingJoinPoint
调用getSignature().getName()
通过比较方法及用户名称判断是否拥有权限
有则放行进入对应方法:proceed()
否则返回null
将权限管理类与业务类关联
实现一个MethodInterceptor接口
private String who;
public void setWho(String who) {
this.who=who;
}
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
// TODO Auto-generated method stub
String method= arg0.getMethod().getName();
List<String> list=Arrays.asList("show1","find");
if(!(list.contains(method)&&"admin".equals(who))) {
System.err.println("--撒个--");
}else {
System.out.println("--sagfdfag--");
return arg0.proceed();
}
return null;
}
或:创建一个权限类不实现接口
private String who;
public void setWho(String who) {
this.who=who;
}
public Object Invoke(JoinPoint jp) throws Throwable{
//获取用户访问方法
MethodInvocationProceedingJoinPoint point=(MethodInvocationProceedingJoinPoint)jp;
String method =point.getSignature().getName();
List<String> list=Arrays.asList("show","query","findAll");
//判断是否在允许范围内
if(!(list.contains(method)&&"admin".equals(who))) {
//无权限返回
System.out.println("您没有权限访问method方法");
}else {
//有权限放行
System.out.println("欢迎"+who+"访问本系统");
return point.proceed();
}
return null;
}
通过配置文件将权限类与核心类关联
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!-- 权限 -->
<bean id="power" class="com.main.java.aop.powerManager">
<property name="who" value="admin"></property>
</bean>
<bean id="power2" class="com.main.java.aop.Power">
<property name="who" value="admin"></property>
</bean>
<!-- 业务实现类 -->
<bean id="userService" class="com.main.java.service.userServiceImpl"></bean>
<!-- <aop:config>
定义切入点
<aop:pointcut expression="execution(* com.main.java.service.*.*(..))" id="ponint"/>
引入权限管理
<aop:aspect ref="power">
<aop:around method="Invoke" pointcut-ref="ponint"/>
</aop:aspect>
</aop:config> -->
<!-- 引用权限类 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 指定权限管理的bean -->
<property name="interceptorNames">
<list>
<value>power2</value>
</list>
</property>
<!-- 指定需要权限管理的bean -->
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
</bean>
</beans>
测试
事务
核心部分:
数据访问,业务处理功能性接口等
<tx:advice id="advice">
<tx:attributes>
<!-- REQUIRED:当存在事务时使用当前事务,不存在则开启新事务 (百度搜索:7中事务管理策略了解即可)-->
<tx:method name="do*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 将业务与事务关联 -->
<aop:config>
<!-- 定义切入点 -->
<aop:pointcut expression="execution(* com.main.java.service.*.*(..))" id="point"/>
<!-- 将切入点与事务策略关联 -->
<aop:advisor advice-ref="advice" pointcut-ref="point"/>
</aop:config>
注入:
设值注入
通过<property name=“属性名” value=“属性值”>理的类添加@transaction
在具体方法添加@Transaction(propagation=propagation.REQUITED)
非注解实现SpringMVC:
- 1.在web.xml中配置核心控制器
- 1.1 注意: <url-pattern>*.do</url-pattern>
- 1.2 “ *.do ”是自定义的(可变)
- 2.创建Controller类实现Controller接口,并重写handleRequest方法,返回ModelAndView
- 2.1 handleRequest方法返回一个ModelAndView对象由核心控制器解析
- 2.2 通过构造赋值指定目标视图名称:
- 2.2.1 new ModelAndView("视图名称");
- 2.2.2 new ModelAndView("redirect:视图名称.扩展名");
- 2.3 通过方法调用设置传递到视图的对象及目标视图
- 2.3.1 设置对象通过:addObject("key", "value");
- 2.3.2 设置视图名称:setViewName("视图名称");
- 2.3.3 注意:通过这种方式实现重定向时,数据是传递不过去的需要使用session
- 3.在Spring配置文件中实现对象实例的注入并创建Controller代理用于指定Controller的访问名称
- 代理类:org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
- 属性:mappings
- 配置:
<props>
<!-- 注意要有“/”,并且格式要与web.xml中url定义匹配 -->
<prop key="/自定义访问名称.do">控制器<bean>的id属性值</prop>
</props>
- 4.创建JSP文件实现数据交互
-- 注:在配置控制器<bean>时,设置scope属性
- scope属性作用:配置Bean的作用域
- 常用取值:
- Spring 2.0 以前
- singleton:单例(保证Spring IOC容器只存在一个共享实例)
- prototype:多列(每访问一次则创建一个实例,默认作用域)
- Spring 2.0以后新增
- request:HTTP请求域(每个HTTP请求都会创建新实例,作用域范围仅限于本次请求)
- session:HTTP会话域(每个HTTP请求都会创建新实例,作用域范围仅限于本次会话)
- 注:需要在web.xml中配置监听
- <listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>