Spring+Mybatis
企业级项目环境搭建
Spring整合MyBatis
-
导包
-
创建WEB项目,并导入如下开发包
- 数据库驱动包、连接池包、MyBatis开发包
- Spring开发包
- JSTL开发包
- Spring整合MyBatis开发包
-
导入之后,项目的包结构如下图
-
-
配置applicationContext.xml
-
在src下创建applicationContext.xml,并配置如下内容
- 配置数据源
- 配置SqlSessionactory
- 配置MyBatis注解(该注解需要自定义)
-
-
阶段性测试
-
写出查询全部的员工数据的案例,测试项目环境
- 创建员工DAO接口EmpDao,增加查询全部数据的方法,并使用@MyBatisRepository注解标识该接口。
- 创建员工表的MyBatis映射文件EmpMapper.xml,并实现查询全部员工数据。
- 创建Junit测试类,并增加测试方法,测试查询全部员工数据的方法。
-
应用Spring MVC
-
配置web.xml
- 配置DispatcherServlet,充当Spring的前端控制器,用于分发请求
- 配置一个Filter,用于处理中文参数的乱码问题
- 解决中文乱码Filter的配置代码如下
-
配置applicationContext.xml
-
在applicationContext.xml中追加如下配置
- 开启注解扫描
- 开启RequestMapping注解
- 配置ViewResolver,处理请求转发
-
-
阶段性测试
-
完成员工查询功能,测试项目环境
- 创建员工模板业务控制器EmpController,并增加查询方法,调用EmpDao查询全部员工数据,并发送至员工列表页面。
- 创建员工列表页面emo_list.jsp,并将EmpController发送过来的全部员工数据循环输出在表格中。
-
MyBatis动态SQL
动态SQL简介
-
动态SQL是MyBatis框架中强大特性之一。在一些组合查询页面,需要根据用户输入的查询条件生成不同的查询SQL,这在JDBC或其他相似框架中需要在代码中拼写SQL,经常容易出错,但是在MyBatis中可以解决这种问题。
-
使用动态SQL元素与JSTL相似,它允许我们在XML中构建不同的SQL语句。常用的元素如下
- 判断元素:if,choose
- 关键字元素:where,set,trim
- 循环元素:foreach
进行判断
-
if元素
- if元素是简单的条件判断逻辑,满足指定条件时追加if元素内的SQL,不满足条件时不追加。使用格式如下
- if元素最常见的使用是在where子句部分,根据不同情况追加不同的SQL条件。示例代码如下
-
choose元素
- choose元素的作用就相当于Java中的switch语句,基本上跟JSTL中的choose的作用和用法是一样的,通常与when和otherwise搭配使用。choose使用格式如下
- choose元素的使用示例代码如下:
拼关键字
-
where元素
- where元素主要是用于简化查询语句中where部分的条件判断。where元素可以在where>元素所在位置输出一个where关键字,而且还可以将后面条件多余的and或or关键字去除。
- where使用格式如下
- where元素的使用示例代码如下
-
set元素
- set元素主要是用在更新操作的时候,它的主要功能和where元素相似,主要是在set>元素所在位置输出一个set关键字,而且还可以去除内容结尾中无关的逗号。有了set元素我们就可以动态的更新那些修改了的字段。
- set使用格式如下
- set元素的使用示例代码如下
-
trim元素
-
trim元素的主要更能如下
- 可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;
- 可以把包含内容的首部某些内容过滤,即忽略,也可以把尾部的某些内容过滤,对应的属性是prefixOverrides和suffixOverrides;
- 正因为trim有上述功能,所以我们也可以非常简单的利用trim来代替where和set元素的功能
- trim元素的应用示例如下
-
进行循环
-
foreach元素
- foreach元素实现了循环逻辑,可以进行一个集合的迭代,主要用在构建in条件中。foreach使用示例如下
- foreach元素非常强大,它允许指定一个集合,声明集合项和索引变量,这些变量可以用在元素体内。它也允许指定开放和关闭的字符串,在迭代之间放置分隔符。
- foreach元素的使用示例代码如下
Spring与Ajax
Ajax简介
-
Asynchronous JavaScript and Xml 异步的JavaScript和Xml
-
AJAX是一种用来改善用户体验的技术,具有异步处理和刷新部分页面内容的特点
-
Ajax技术在应用时,需要客户端JavaScript处理和服务器端处理两部分。
-
使用Ajax技术时,需要以下工作
- 编写JavaScript程序,发送Ajax请求
- 编写服务器处理,返回处理结果(常用json格式)
- 编写JavaScript程序,获取服务器结果,刷新部分页面
Spring对Ajax的支持
- 为了便于接受和处理Ajax请求,Spring MVC提供了JSON响应支持,可以很方便地将数据自动转成JSON格式字符串给客户端JavaScript返回。
- 在Spring MVC中,与JSON响应相关的注解为@ ResponseBody
@ ResponseBody应用
-
@ ResponseBode注解主要用于Controller组件的处理方法前,具体使用方法如下:
- 引入jackson开发包,后面示例采用的是jackson-annotations-2.4.1.jar、jackson-core-2.4.1.jar、jackson-databind-2.4.1.jar
- 在Spring配置文件中定义mvc:annotation-driven/>,开启对@ ResponseBody应用的支持
- 在Controller处理方法前定义@ ResponseBody注解
-
使用@ ResponseBody,返回单个值的示例如下
-
使用@ ResponseBody,返回多个值的示例如下
-
使用@ ResponseBody,返回List结果的示例如下
-
使用@ ResponseBody,返回对象结果的示例如下
-
使用@ ResponseBody,返回对象集合结果的示例如下
MyBatis关联映射
主键映射
-
主键映射作用
-
在使用MyBatis做插入操作时,可以有MyBatis负责主键生成,主键字段部分的映射可以分成以下两种情况。
- 数据库支持自动递增,例如MySQL、SQLServer
- 数据库不支持自动递增,例如Oracle
-
-
自动递增
- MySQL、SQLServer数据库都支持字段自动递增功能,在设计表时,可以为主键字段指定自动递增。这样在添加操作时,主键值数据库会自动生成,不需要指定。
- 在使用MyBatis时,有时需要返回MySQL和SQLServer数据库自动增长的主键值,可以采用下面方法定义
- 在insert>元素指定了自动递增属性设置后,MyBatis会在插入操作后将自动生成的主键值给keyProperty指定的属性赋值。
-
非自动递增
- 在使用Oracle数据库时,由于不支持自动递增,经常采用序列生成主键值
- Oracle基于序列生成主键的映射方法如下
- 在insert>元素指定了selectKey>设置后,MyBatis会在插入操作前先执行selectKey>获取主键值的SQL,然后在执行插入的SQL。
关联映射
-
关联映射作用
-
在查询时经常需要获取两个或两个以上关联表的数据,通过关联映射可以由一个对象获取相关联对象的数据。例如查询一个Emp员工对象,可通过关联映射获取员工所在部门的Dept对象信息。
-
MyBatis的关联映射有以下两种不同的实现形式:
- 嵌套查询:通过执行另外一个SQL映射语句来返回关联数据结果(查两次)。
- 嵌套结果:执行一个表关联查询SQL,然后将查询结果映射成关联对象(查一次)。
-
-
嵌套查询映射
- 嵌套查询映射的应用示例如下
- 上面映射信息,当利用findById查询EMP时,会只查询EMP表返回一个Emp对象,当访问Emp对象的dept属性时,会调用selectDept查询操作获取DEPT表相关的记录
-
嵌套结果映射
- 嵌套结果映射的应用示例
- 上面resultMap属性指定的empMap的映射如下
- 上面映射信息,当利用findById查询时,会执行定义的关联查询SQL,然后MyBatis负责将结果数据提取,EMP字段值封装成Emp对象,DEPT字段值封装成Dept对象,然后将Dept对象给Emp对象的dept属性赋值。
集合映射
-
集合映射作用
-
当查询某个表的记录信息时,如果关联表有多条相关记录,此时就可以使用集合映射。例如查询某个Dept部门对象信息,通过集合映射可以获取该部门中所有的Emp员工对象信息。
-
MyBatis的集合映射有以下两种不同的实现形式
- 嵌套查询:通过执行另外一个SQL映射语句来返回关联数据结果(查两次)。
- 嵌套结果:执行一个表关联查询SQL,然后将查询结果映射成关联对象(查一次)。
-
-
嵌套查询映射
- 前天查询映射的应用示例如下
- 上面映射信息,当利用findById查询DEPT时,会只查询DEPT表返回一个Dept对象,当访问Dept对象的emps属性时,会调用selectEmps查询操作获取EMP表相关的记录
-
嵌套结果映射
- 嵌套结果映射的应用示例如下
- 上面resultMap属性指定的deptEmpsResult的映射如下
- 上面映射信息,当利用findById查询时,会执行定义的关联查询SQL,然后MyBatis负责将结果数据提取,DEPT字段值封装成Dept对象,EMP字段值封装成Emp对象集合,然后将Emp对象集合给Dept对象的emps属性赋值。
鉴别器
-
鉴别器的作用
- 有时一个单独的数据库查询也许返回很多不同类型的结果集。例如表储存了单选题和多选题,查询时需要返回单选题对象和多选题对象。鉴别器就是用来处理这个情况的。鉴别器元素很像Java语言中的switch分支语句的结构。
-
鉴别器的使用
- 鉴别器的应用示例如下
- 上面映射信息,当利用findAll查询时,会查询T_CAR表所有记录,然后MyBatis会根据鉴别器type字段值分别封装成Truck对象和Car对象放入返回的结果集中。
Spring AOP
AOP介绍
-
AOP概念及优点
- AOP为Aspect Oriented Programming的缩写,被称为面向切面编程。
- AOP主要用于处理共通逻辑,例如日志记录,性能统计,安全控制,事务处理,异常处理等等。AOP可以将这些共通逻辑从普通业务逻辑代码中分离出来,这样在日后修改这些逻辑的时候就不会影响普通业务逻辑的代码。
- 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
- AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。
- OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
- AOP这是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
- AOP需要以OOP为前提和基础。
-
什么是方面
- 方面是指封装共通处理的组件,该组件被作用到其他目标组件方法上。
-
什么是目标
- 目标是指被一个或多个方面所作用的对象。
-
什么是切入点
-
切入点是用于指定哪些组件和方法使用方面功能,在Spring中利用一个表达式指定切入目标。
-
Spring提供了以下常用的切入点表达式
-
方法限定表达式
- execution(修饰符?返回类型 方法名(参数)throws 异常类型?)
-
类型限定表达式
- within(包名.类型)
-
Bean名称限定表达式
- bean(“Bean的id或name属性值”)
-
-
-
什么是通知
-
通知是用于指定方面组件和目标组件作用的时机。例如方面功能在目标方法之前或之后执行等时机。
-
Spring框架提供以下几种类型的通知:
- 前置通知:先执行方面功能再执行目标功能
- 后置通知:先执行目标功能再执行方面功能(目标无异常才执行方面)
- 最终通知:先执行目标功能再执行方面功能(目标有无异常都执行方面)
- 异常通知:先执行目标,抛出后执行方面
- 环绕通知:先执行方面前置部分,然后执行目标,最后再执行方面后置部分
-
Spring框架提供5种通知,可以按下面try-catch-finally结构理解
-
-
AOP实现原理
-
Spring AOP实现主要是基于动态代理技术。当Spring采用AOP配置后,Spring容器返回的目标对象,实质上是Spring利用动态代理技术生成一个代理类型。代理类重写了原目标组件方法的功能,在代理类中调用方面对象功能和目标对象功能。
-
Spring框架采用了两种动态代理实现:
-
利用cglib工具包
- 目标没有接口时采用此方法,代理类时利用继承方法生成一个目标子类。
-
利用JDK Proxy API
- 目标有接口时采用此方法,代理类时采用实现目标接口方法生成一个类。
-
-
XML配置实现AOP
-
开发步骤
-
创建方面组件
- 创建一个类,充当方面组件,实现通用业务逻辑
-
声明方面组件
- 在applicationContext.xml中,声明方面组件
-
使用方面组件
- 在applicationContext.xml中,将方面组件作用到目标组件的方法上,并设置通知类型以确认方面组件调用的时机。
-
-
前置通知
- 使用前置通知,方面组件中方法格式如下
- applicationContext.xml中配置代码如下
- 后置通知、最终通知使用方式与前置通知一致,只需将配置代码中的aop:before改为aop:after-returning、after即可。
-
环绕通知
- 使用环绕通知,方面组件中方法格式如下
- applicationContext.xml中配置代码如下
-
异常通知
- 使用异常通知,方面组件中方法格式如下
- applicationContext.xml中配置代码如下
注解实现AOP
-
开发步骤
-
创建方面组件
- 创建一个类,充当方面组件,实现通用业务逻辑
-
声明方法组件
-
在applicationContext.xml中开启AOP注解扫描:
- aop:aspectj-autoproxy proxy-target-class=“true”/>
-
使用@ component注解标识这个类,将其声明为组件
-
使用@Aspect注解标识这个类,将其声明为方面组件
-
-
使用方法组件
- 在组件的方法上,使用注解将方面组件作用到目标组件的方法上,并设置通知类型以确认方面组件调用的时机。
-
-
前置通知
- 使用前置通知,在方面组件方法上增加注解:
- 后置通知、最终通知使用方式与前置通知一致,只需将注解改为@ AfterReturning、@ After即可
-
环绕通知
- 使用环绕通知,在方面组件方法上增加注解:
-
异常通知
- 使用异常通知,在方面组件方法上增加注解:
Spring事务处理
Spring事务介绍
-
Spring事务介绍
-
Spring框架引入的重要因素之一是它全面的事务支持
-
Spring框架提供了一致的事务管理方式,给程序带来以下好处:
- 提供简单易用的编程式事务管理API
- 支持声明式事务管理
- 便于Spring整合各种数据访问技术
-
-
编程式事务
-
使用编程式事务时,Spring提供了以下两种事务管理的API
- 使用TransactionTemplate
- 直接使用一个PlatformTransactionManager实现
-
如果采用改编式事务管理,推荐使用TransactionTemplate
-
TransactionTemplate与Spring中JdbcTemplate等模板类使用风格相似它也使用回调机制,将事务代码和业务代码分离,这样便于开发者把精力集中在具体的业务编程上。
-
TransactionTemplate应用的示例代码如下
-
如果不需要返回值,可以创建一个TransactionCallbackWithoutResult的匿名类,示例代码如下:
-
-
声明式事务
- Spring的声明式事务管理是通过Spring AOP实现的。使用时不需要修改原有的业务代码,只需通过简单配置就可以追加事务控制功能。
- 大多数Spring用户选择证明事务管理。这是对程序代码影响最小的选择,因此也最符合非侵入式的理念。
声明事务
-
注解实现声明式事务
-
步骤一,在applicationContext.xml中声明事务组件,开启事务注解扫描,示例代码如下
-
transaction-manager指定的事务管理器txManager,需要根据数据库访问技术不同选择不同的实现。例如JDBC、MyBatis技术选用DataSourceTransactionManager,而Hibernate技术则选用HibernateTransactionManager。
-
步骤二,使用@ Transactional注解声明事务,使用方法如下:
-
@ Transactional注解标记可以用在类定义和方法定义前,方法的事务设置将优先于类级别注解的事务设置
-
@ Transactional注解标记有以下属性,在使用时可以根据需要做特殊设定。
- propagation:设置事务传播
- isolation:设置实物隔离级别
- readOnly:设置为只读,还是可读写
- rollbackFor:设置遇到哪些异常必须回滚
- noRollbackFor:设置遇到哪些异常不回滚
-
@ Transactional注解属性默认设置如下
- 事务传播设置是PROPAGATION_REQUIRED
- 事务隔离级别是ISOLATION_DEFAULT
- 事务是读/写
- 事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
- 任何RuntimeException将触发事务回滚,但是任何Checked Exception将不出发事务回滚
-
-
XML配置实现声明式事务
- 在applicationContext.xml中声明事务组件,配置事务作用的范围及类型,示例代码如下
Spring事务控制
-
事务回滚
- @ Transactional默认情况下RuntimeException异常将触发事务回滚,但是任何Checked Exception将不触发事务回滚
- 常见的RuntimeException和Checked Exception如下表所示:
- 对于Checked Exception,需要手动指定异常类型,才能实现事务回滚。
- 使用注解实现声明事务时,按如下方式指定异常:
- 使用XML配置实现声明式事务时,按如下方式指定异常:
- 当使用自定义异常时,异常类必须从RuntimeException继承才能自动回滚事务,否则需要指定事务回滚的异常类型
-
事务传播
- 事务传播是指一个方法调用了另一个带有事务控制的方法,这种复杂情况就需要指定事务传播的处理方案
- Spring中事务的传播类型有以下几种:
- 利用@ Transactional注解的propagation属性可以控制事务的传播行为,示例代码如下:
-
事务隔离级别
- 在读取数据库的过程中,如果两个事务并发执行,那么彼此之间的数据会发生影响。为了避免这种并发冲突需要见过两个事务隔离开,根据隔离成都不同分为以下几种级别:
- 利用@ Transactional注解的isolation属性可以控制事务的隔离级别,示例代码如下
Spring与RESTful
RESTful简介
-
什么是REST?
-
REST是英文Representational State Transfer的缩写,中文翻译为“表述形状转移”,它是由Roy Thomas Fielding博士在他的论文中提出的一个术语。
-
REST本身只是为分布式超媒体系统设计的一种架构风格,适合开发Web Service服务,并没有任何技术和语言上的限制。
-
REST软件架构之所以适合超媒体系统,是因为它可以把网络所有资源进行唯一的URL定位,资源类型没有限制,例如图片、Word文件、视频文件、txt文件、xml文件、html文件等。
-
REST架构师一个抽象的概念,目前主要是基于HTTP协议实现,其目的是为了提高系统的可伸缩性、降低应用之间的耦合度、便于架构分布式处理程序。
-
REST主要对以下两个方面进行规范
-
定位资源的URL风格,例如
- http://tarena.com/customers/1234
- http://tarena.com/orders/2007/10/776654
-
如何对资源操作
- 采用HTTP协议规定的GET、POST、PUT、DELETE动作处理资源的增删改查操作
-
-
-
什么是RESTful?
- 符合REST约束风格和原则的应用程序或设计就是RESTful
Spring对RESTful的支持
-
Spring MVC对RESTful应用提供了以下支持
- 利用@ RequestMapping指定要处理请求的URI模板和HTTP请求的动作类型
- 利用@ PathVariable将URI请求模板中的变量映射到处理方法的参数上
- 利用Ajax,在客户端发出PUT、DELETE动作的请求
@ RequestMapping应用
- @ RequestMapping可以定义在Controller类前和处理方法前,主要用于指定Controller的方法处理哪些请求。
- 在RESTful应用中,@ RequestMapping可以采用以下使用格式
@ PathVariable应用
- @ PathVariable作用是将URI请求模板中的变量解析出来,映射到处理方法的参数上,使用示例如下:
- 上述URI请求模板匹配/emp/1、emp/2等格式请求
客户端发送PUT、DELETE请求
- 可以采用Ajax方式发送PUT和DELETE请求,示例如下
静态资源访问处理
-
采用RESTful架构后,需要将web.xml中控制器拦截的请求设置为/,这样会将css,js等静态资源进行拦截,发送404错误。
-
解决上述问题的方法如下:
-
配置mvc:resources/>,使用示例如下
- mvc:resources mapping="请求URI"location=“资源位置”/>
-
配置mvc:default-servlet-handler/>,使用示例如下
- mvc:default-servlet-handler/>
-