• 1. Spring & O/R mapping
  • 2. 内容Spring O/R Mapping MVC 实例开发
  • 3. Spring
  • 4. 具体描述 Spring: 轻量级:Spring 是非侵入性的 - 基于 Spring 开发的应用中的对象可以不依赖于 Spring 的 API 依赖注入(DI --- dependency injection、IOC) 面向切面编程(AOP --- aspect oriented programming) 容器: Spring 是一个容器, 因为它包含并且管理应用对象的生命周期 框架: Spring 实现了使用简单的组件配置组合成一个复杂的应用. 在 Spring 中可以使用 XML 和 Java 注解组合这些对象 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库 (实际上 Spring 自身也提供了展现层的 SpringMVC 和 持久层的 Spring JDBC)
  • 5. Spring 模块
  • 6. Spring 容器 Spring 上下文 Spring IoC Spring AOP Spring ORM Spring DAO Spring MVC Spring 缓存
  • 7. Spring 容器ApplicationContext(应用上下文)建立在BeanFactory之上,提供了更多面向应用的功能,更易于创建实际应用,有时在web开发中为了方便也称ApplicationContext为Spring容器。 WebApplicationContext是专门为Web应用准备的,它允许从相对于Web根目录的路径中装载配置文件完成初始化工作。以便Web应用环境可以访问Spring引用上下文。
  • 8. 搭建 Spring 开发环境
  • 9. 建立 Spring 项目HelloWorld.javaapplicationContext.xml
  • 10. 建立 Spring 项目
  • 11. Spring 中的 Bean 配置
  • 12. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动转配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 13. IOC 和 DIIOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式 DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接
  • 14. ABclass A{} class B{ private A a; public void setA(A a){ this.a = a; } }容器需求:从容器中获取 B 对象,并使 B 对象的 a 属性被赋值为容器中 A 对象的引用A a = getA(); B b = getB(); b.setA(a);ABIOC容器B b = getB();
  • 15. IOC 前生 --- 分离接口与实现需求: 生成 HTML 或 PDF 格式的不同类型的报表.
  • 16. IOC 前生 --- 采用工厂设计模式
  • 17. IOC --- 采用反转控制
  • 18. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动转配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 19. 在 Spring 的 IOC 容器里配置 Bean在 xml 文件中通过 bean 节点来配置 bean id:Bean 的名称 在 IOC 容器中必须是唯一的 若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字 id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
  • 20. Spring 容器在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用. Spring 提供了两种类型的 IOC 容器实现. BeanFactory: IOC 容器的基本实现. ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口. BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory 无论使用何种方式, 配置文件时相同的.
  • 21. ApplicationContextApplicationContext 的主要实现类: ClassPathXmlApplicationContext:从 类路径下加载配置文件 FileSystemXmlApplicationContext: 从文件系统中加载配置文件 ConfigurableApplicationContext 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力 ApplicationContext 在初始化上下文时就实例化所有单例的 Bean。 WebApplicationContext 是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中完成初始化工作
  • 22. 从 IOC 容器中获取 Bean调用 ApplicationContext 的 getBean() 方法
  • 23. 依赖注入的方式Spring 支持 3 种依赖注入的方式 属性注入 构造器注入 工厂方法注入(很少使用,不推荐)
  • 24. 属性注入属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象 属性注入使用 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 子节点指定属性值 属性注入是实际应用中最常用的注入方式
  • 25. 构造方法注入通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。 构造器注入在 元素里声明属性, 中没有 name 属性
  • 26. 构造方法注入按索引匹配入参: 按类型匹配入参: 26
  • 27. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动转配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 28. 字面值字面值:可用字符串表示的值,可以通过 元素标签或 value 属性进行注入。 基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式 若字面值中包含特殊字符,可以使用 把字面值包裹起来。
  • 29. 引用其它 Bean组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 要使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用 在 Bean 的配置文件中, 可以通过 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用. 也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean
  • 30. (本页无文本内容)
  • 31. 内部 Bean当 Bean 实例仅仅给一个特定的属性使用时, 可以将其声明为内部 Bean. 内部 Bean 声明直接包含在 元素里, 不需要设置任何 id 或 name 属性 内部 Bean 不能使用在任何其他地方
  • 32. 集合属性在 Spring中可以通过一组内置的 xml 标签(例如: , ) 来配置集合属性. 配置 java.util.List 类型的属性, 需要指定 标签, 在标签里包含一些元素. 这些标签可以通过 指定简单的常量值, 通过 指定对其他 Bean 的引用. 通过 指定内置 Bean 定义. 通过 指定空元素. 甚至可以内嵌其他集合. 数组的定义和 List 一样, 都使用 配置 java.util.Set 需要使用 标签, 定义元素的方法与 List 一样.
  • 33. 集合属性Java.util.Map 通过 标签定义, 标签里可以使用多个 作为子标签. 每个条目包含一个键和一个值. 必须在 标签里定义键 因为键和值的类型没有限制, 所以可以自由地为它们指定 , , 元素. 可以将 Map 的键和值作为 的属性定义: 简单常量使用 key 和 value 来定义; Bean 引用通过 key-ref 和 value-ref 属性定义 使用 定义 java.util.Properties, 该标签使用多个 作为子标签. 每个 标签必须定义 key 属性.
  • 34. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动装配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 35. XML 配置里的 Bean 自动装配Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 的 autowire 属性里指定自动装配的模式 byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配. byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同. constructor(通过构造器自动装配): 当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用
  • 36. XML 配置里的 Bean 自动装配的缺点在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性. 然而, 若只希望装配个别属性时, autowire 属性就不够灵活了. autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之. 一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些36
  • 37. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动装配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 38. 继承 Bean 配置Spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 Bean 的 Bean 称为子 Bean 子 Bean 从父 Bean 中继承配置, 包括 Bean 的属性配置 子 Bean 也可以覆盖从父 Bean 继承过来的配置 父 Bean 可以作为配置模板, 也可以作为 Bean 实例. 若只想把父 Bean 作为模板, 可以设置 的abstract 属性为 true, 这样 Spring 将不会实例化这个 Bean 并不是 元素里的所有属性都会被继承. 比如: autowire, abstract 等. 也可以忽略父 Bean 的 class 属性, 让子 Bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true
  • 39. 依赖 Bean 配置Spring 允许用户通过 depends-on 属性设定 Bean 前置依赖的Bean,前置依赖的 Bean 会在本 Bean 实例化之前创建好 如果前置依赖于多个 Bean,则可以通过逗号或空格的方式配置 Bean 的名称
  • 40. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动装配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 41. Bean 的作用域在 Spring 中, 可以在 元素的 scope 属性里设置 Bean 的作用域. 默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实例, 整个 IOC 容器范围内都能共享该实例:所有后续的 getBean() 调用和 Bean 引用都将返回这个唯一的 Bean 实例.该作用域被称为 singleton, 它是所有 Bean 的默认作用域.
  • 42. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动装配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 43. 使用外部属性文件在配置文件里配置 Bean 时, 有时需要在 Bean 的配置里混入系统部署的细节信息(例如: 文件路径, 数据源配置信息等). 而这些部署细节实际上需要和 Bean 配置相分离 Spring 提供了一个 PropertyPlaceholderConfigurer 的 BeanFactory 后置处理器, 这个处理器允许用户将 Bean 配置的部分内容外移到属性文件中. 可以在 Bean 配置文件里使用形式为 ${var} 的变量, PropertyPlaceholderConfigurer 从属性文件里加载属性, 并使用这些属性来替换变量. Spring 还允许在属性文件中使用 ${propName},以实现属性之间的相互引用。
  • 44. 注册 PropertyPlaceholderConfigurer Spring 2.0: Spring 2.5 之后: 可通过 元素简化: 中添加 context Schema 定义 在配置文件中加入如下配置: 44
  • 45. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动装配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 SpEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 46. Spring表达式语言:SpELSpring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。 语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpEL SpEL 为 bean 的属性进行动态赋值提供了便利 通过 SpEL 可以实现: 通过 bean 的 id 对 bean 进行引用 调用方法以及引用对象中的属性 计算表达式的值 正则表达式的匹配
  • 47. SpEL:字面量字面量的表示: 整数: 小数: 科学计数法: String可以使用单引号或者双引号作为字符串的定界符号: Boolean:
  • 48. SpEL:引用 Bean、属性和方法(1)引用其他对象: 引用其他对象的属性 调用其他方法,还可以链式操作
  • 49. SpEL支持的运算符号(1)算数运算符:+, -, *, /, %, ^: 加号还可以用作字符串连接: 比较运算符: <, >, ==, <=, >=, lt, gt, eq, le, ge
  • 50. SpEL支持的运算符号(2)逻辑运算符号: and, or, not, | if-else 运算符:?: (ternary), ?: (Elvis) if-else 的变体 正则表达式:matches
  • 51. SpEL:引用 Bean、属性和方法(2)调用静态方法或静态属性:通过 T() 调用一个类的静态方法,它将返回一个 Class Object,然后再调用相应的方法或属性:
  • 52. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动装配 bean 之间的关系:继承;依赖 bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 53. IOC 容器中 Bean 的生命周期方法Spring IOC 容器可以管理 Bean 的生命周期, Spring 允许在 Bean 生命周期的特定点执行定制的任务. Spring IOC 容器对 Bean 的生命周期进行管理的过程: 通过构造器或工厂方法创建 Bean 实例 为 Bean 的属性设置值和对其他 Bean 的引用 调用 Bean 的初始化方法 Bean 可以使用了 当容器关闭时, 调用 Bean 的销毁方法 在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.
  • 54. 创建 Bean 后置处理器Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理. Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例. 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性. 对Bean 后置处理器而言, 需要实现 接口. 在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给上述接口的以下两个方法:
  • 55. 添加 Bean 后置处理器后 Bean 的生命周期Spring IOC 容器对 Bean 的生命周期进行管理的过程: 通过构造器或工厂方法创建 Bean 实例 为 Bean 的属性设置值和对其他 Bean 的引用 将 Bean 实例传递给 Bean 后置处理器的 postProcessBeforeInitialization 方法 调用 Bean 的初始化方法 将 Bean 实例传递给 Bean 后置处理器的 postProcessAfterInitialization方法 Bean 可以使用了 当容器关闭时, 调用 Bean 的销毁方法
  • 56. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式; Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节(bean 之间的关联关系) 自动装配 bean 之间的关系:继承;依赖; bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 57. 通过调用静态工厂方法创建 Bean调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节. 要声明通过静态方法创建的 Bean, 需要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 元素为该方法传递方法参数.
  • 58. 通过调用实例工厂方法创建 Bean实例工厂方法: 将对象的创建过程封装到另外一个对象实例的方法里. 当客户端需要请求对象时, 只需要简单的调用该实例方法而不需要关心对象的创建细节. 要声明通过实例工厂方法创建的 Bean 在 bean 的 factory-bean 属性里指定拥有该工厂方法的 Bean 在 factory-method 属性里指定该工厂方法的名称 使用 construtor-arg 元素为工厂方法传递方法参数
  • 59. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式; Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入 注入属性值细节 自动转配 bean 之间的关系:继承;依赖; bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 60. 实现 FactoryBean 接口在 Spring IOC 容器中配置 BeanSpring 中有两种类型的 Bean, 一种是普通Bean, 另一种是工厂Bean, 即FactoryBean. 工厂 Bean 跟普通Bean不同, 其返回的对象不是指定类的一个实例, 其返回的是该工厂 Bean 的 getObject 方法所返回的对象
  • 61. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式(基于注解配置 Bean;基于注解来装配 Bean 的属性) Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入;工厂方法注入 注入属性值细节 自动转配 bean 之间的关系:继承;依赖; bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 62. 在 classpath 中扫描组件组件扫描(component scanning): Spring 能够从 classpath 下自动扫描, 侦测和实例化具有特定注解的组件. 特定组件包括: @Component: 基本注解, 标识了一个受 Spring 管理的组件 @Respository: 标识持久层组件 @Service: 标识服务层(业务层)组件 @Controller: 标识表现层组件 对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写. 也可以在注解中通过 value 属性值标识组件的名称
  • 63. 在 classpath 中扫描组件当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明 : base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类. 当需要扫描多个包时, 可以使用逗号分隔. 如果仅希望扫描特定的类而非基包下的所有类,可使用 resource-pattern 属性过滤特定的类,示例: 子节点表示要包含的目标类 子节点表示要排除在外的目标类 下可以拥有若干个 子节点
  • 64. 在 classpath 中扫描组件 子节点支持多种类型的过滤表达式:
  • 65. 组件装配 元素还会自动注册 AutowiredAnnotationBeanPostProcessor 实例, 该实例可以自动装配具有 @Autowired 和 @Resource 、@Inject注解的属性.
  • 66. 使用 @Autowired 自动装配 Bean@Autowired 注解自动装配具有兼容类型的单个 Bean属性 构造器, 普通字段(即使是非 public), 一切具有参数的方法都可以应用@Authwired 注解 默认情况下, 所有使用 @Authwired 注解的属性都需要被设置. 当 Spring 找不到匹配的 Bean 装配属性时, 会抛出异常, 若某一属性允许不被设置, 可以设置 @Authwired 注解的 required 属性为 false 默认情况下, 当 IOC 容器里存在多个类型兼容的 Bean 时, 通过类型的自动装配将无法工作. 此时可以在 @Qualifier 注解里提供 Bean 的名称. Spring 允许对方法的入参标注 @Qualifiter 已指定注入 Bean 的名称 @Authwired 注解也可以应用在数组类型的属性上, 此时 Spring 将会把所有匹配的 Bean 进行自动装配. @Authwired 注解也可以应用在集合属性上, 此时 Spring 读取该集合的类型信息, 然后自动装配所有与之兼容的 Bean. @Authwired 注解用在 java.util.Map 上时, 若该 Map 的键值为 String, 那么 Spring 将自动装配与之 Map 值类型兼容的 Bean, 此时 Bean 的名称作为键值
  • 67. 使用 @Resource 或 @Inject 自动装配 BeanSpring 还支持 @Resource 和 @Inject 注解,这两个注解和 @Autowired 注解的功用类似 @Resource 注解要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为 Bean 的名称 @Inject 和 @Autowired 注解一样也是按类型匹配注入的 Bean, 但没有 reqired 属性 建议使用 @Autowired 注解
  • 68. 内容提要IOC & DI 概述 配置 bean 配置形式:基于 XML 文件的方式;基于注解的方式 Bean 的配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean IOC 容器 BeanFactory & ApplicationContext 概述 依赖注入的方式:属性注入;构造器注入;工厂方法注入 注入属性值细节 自动转配 bean 之间的关系:继承;依赖; bean 的作用域:singleton;prototype;WEB 环境作用域 使用外部属性文件 spEL IOC 容器中 Bean 的生命周期 Spring 4.x 新特性:泛型依赖注入
  • 69. 泛型依赖注入Spring 4.x 中可以为子类注入子类对应的泛型类型的成员变量的引用
  • 70. 整合多个配置文件Spring 允许通过 将多个配置文件引入到一个文件中,进行配置文件的集成。这样在启动 Spring 容器时,仅需要指定这个合并好的配置文件就可以。 import 元素的 resource 属性支持 Spring 的标准的路径资源
  • 71. Spring AOP
  • 72. AOP 前奏需求1-日志:在程序执行期间追踪正在发生的活动 需求2-验证:希望计算器只能处理正数的运算WHY AOP ?
  • 73. 代码实现片段73
  • 74. 问题代码混乱:越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀. 每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点. 代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块(方法)里多次重复相同的日志代码. 如果日志需求发生变化, 必须修改所有模块.
  • 75. 使用动态代理解决上述问题代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.调用者计算器日志代理验证代理参数验证方法日志开始方法日志结束
  • 76. CalculatorLoggingHandler
  • 77. CalculatorValidationHandler
  • 78. 测试代码
  • 79. AOP 简介AOP(Aspect-Oriented Programming, 面向切面编程): 是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充. AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点. 在应用 AOP 编程时, 仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受影响的类. 这样一来横切关注点就被模块化到特殊的对象(切面)里. AOP 的好处: 每个事物逻辑位于一个位置, 代码不分散, 便于维护和升级 业务模块更简洁, 只包含核心业务代码.
  • 80. AOP验证参数前置日志add()后置日志验证参数前置日志mul()后置日志验证参数前置日志sub()后置日志验证参数前置日志div()后置日志业务逻辑add()sub()mul()业务逻辑验证div()日志验证参数前置日志后置日志抽取横切关注点AOP切面目标对象代理对象
  • 81. AOP 术语切面(Aspect): 横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象 通知(Advice): 切面必须要完成的工作 目标(Target): 被通知的对象 代理(Proxy): 向目标对象应用通知之后创建的对象 连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位。例如 ArithmethicCalculator#add() 方法执行前的连接点,执行点为 ArithmethicCalculator#add(); 方位为该方法执行前的位置 切点(pointcut):每个类都拥有多个连接点:例如 ArithmethicCalculator 的所有方法实际上都是连接点,即连接点是程序类中客观存在的事务。AOP 通过切点定位到特定的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。
  • 82. Spring AOPAspectJ:Java 社区里最完整最流行的 AOP 框架. 在 Spring2.0 以上版本中, 可以使用基于 AspectJ 注解或基于 XML 配置的 AOP
  • 83. 在 Spring 中启用 AspectJ 注解支持要在 Spring 应用中使用 AspectJ 注解, 必须在 classpath 下包含 AspectJ 类库: aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar 将 aop Schema 添加到 根元素中. 要在 Spring IOC 容器中启用 AspectJ 注解支持, 只要在 Bean 配置文件中定义一个空的 XML 元素 当 Spring IOC 容器侦测到 Bean 配置文件中的 元素时, 会自动为与 AspectJ 切面匹配的 Bean 创建代理.
  • 84. 用 AspectJ 注解声明切面要在 Spring 中声明 AspectJ 切面, 只需要在 IOC 容器中将切面声明为 Bean 实例. 当在 Spring IOC 容器中初始化 AspectJ 切面之后, Spring IOC 容器就会为那些与 AspectJ 切面相匹配的 Bean 创建代理. 在 AspectJ 注解中, 切面只是一个带有 @Aspect 注解的 Java 类. 通知是标注有某种注解的简单的 Java 方法. AspectJ 支持 5 种类型的通知注解: @Before: 前置通知, 在方法执行之前执行 @After: 后置通知, 在方法执行之后执行 @AfterRunning: 返回通知, 在方法返回结果之后执行 @AfterThrowing: 异常通知, 在方法抛出异常之后 @Around: 环绕通知, 围绕着方法执行
  • 85. 前置通知前置通知:在方法执行之前执行的通知 前置通知使用 @Before 注解, 并将切入点表达式的值作为注解值. 标识这个类是一个切面标识这个方法是个前置通知, 切点表达式表示执行 ArithmeticCalculator 接口的 add() 方法. * 代表匹配任意修饰符及任意返回值, 参数列表中的 .. 匹配任意数量的参数
  • 86. 利用方法签名编写 AspectJ 切入点表达式最典型的切入点表达式时根据方法的签名来匹配各种方法: execution * com.atguigu.spring.ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 中声明的所有方法,第一个 * 代表任意修饰符及任意返回值. 第二个 * 代表任意方法. .. 匹配任意数量的参数. 若目标类与接口与该切面在同一个包中, 可以省略包名. execution public * ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 接口的所有公有方法. execution public double ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 中返回 double 类型数值的方法 execution public double ArithmeticCalculator.*(double, ..): 匹配第一个参数为 double 类型的方法, .. 匹配任意数量任意类型的参数 execution public double ArithmeticCalculator.*(double, double): 匹配参数类型为 double, double 类型的方法.
  • 87. 合并切入点表达式在 AspectJ 中, 切入点表达式可以通过操作符 &&, ||, ! 结合起来.
  • 88. 让通知访问当前连接点的细节可以在通知方法中声明一个类型为 JoinPoint 的参数. 然后就能访问链接细节. 如方法名称和参数值. 标识这个方法是个前置通知, 切点表达式表示执行任意类的任意方法. 第 一个 * 代表匹配任意修饰符及任意返回值, 第二个 * 代表任意类的对象, 第三个 * 代表任意方法, 参数列表中的 .. 匹配任意数量的参数
  • 89. 后置通知后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 下面的后置通知记录了方法的终止. 一个切面可以包括一个或者多个通知.
  • 90. 返回通知无论连接点是正常返回还是抛出异常, 后置通知都会执行. 如果只想在连接点返回的时候记录日志, 应使用返回通知代替后置通知.
  • 91. 在返回通知中访问连接点的返回值在返回通知中, 只要将 returning 属性添加到 @AfterReturning 注解中, 就可以访问连接点的返回值. 该属性的值即为用来传入返回值的参数名称. 必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值. 原始的切点表达式需要出现在 pointcut 属性中
  • 92. 异常通知只在连接点抛出异常时才执行异常通知 将 throwing 属性添加到 @AfterThrowing 注解中, 也可以访问连接点抛出的异常. Throwable 是所有错误和异常类的超类. 所以在异常通知方法可以捕获到任何错误和异常. 如果只对某种特殊的异常类型感兴趣, 可以将参数声明为其他异常的参数类型. 然后通知就只在抛出这个类型及其子类的异常时才被执行.
  • 93. 环绕通知环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点. 对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint . 它是 JoinPoint 的子接口, 允许控制何时执行, 是否执行连接点. 在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行. 注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常
  • 94. 环绕通知示例代码
  • 95. 指定切面的优先级在同一个连接点上应用不止一个切面时, 除非明确指定, 否则它们的优先级是不确定的. 切面的优先级可以通过实现 Ordered 接口或利用 @Order 注解指定. 实现 Ordered 接口, getOrder() 方法的返回值越小, 优先级越高. 若使用 @Order 注解, 序号出现在注解中
  • 96. 重用切入点定义在编写 AspectJ 切面时, 可以直接在通知注解中书写切入点表达式. 但同一个切点表达式可能会在多个通知中重复出现. 在 AspectJ 切面中, 可以通过 @Pointcut 注解将一个切入点声明成简单的方法. 切入点的方法体通常是空的, 因为将切入点定义与应用程序逻辑混在一起是不合理的. 切入点方法的访问控制符同时也控制着这个切入点的可见性. 如果切入点要在多个切面中共用, 最好将它们集中在一个公共的类中. 在这种情况下, 它们必须被声明为 public. 在引入这个切入点时, 必须将类名也包括在内. 如果类没有与这个切面放在同一个包中, 还必须包含包名. 其他通知可以通过方法名称引入该切入点.
  • 97. 重用切入点定义示例代码
  • 98. 用基于 XML 的配置声明切面除了使用 AspectJ 注解声明切面, Spring 也支持在 Bean 配置文件中声明切面. 这种声明是通过 aop schema 中的 XML 元素完成的. 正常情况下, 基于注解的声明要优先于基于 XML 的声明. 通过 AspectJ 注解, 切面可以与 AspectJ 兼容, 而基于 XML 的配置则是 Spring 专有的. 由于 AspectJ 得到越来越多的 AOP 框架支持, 所以以注解风格编写的切面将会有更多重用的机会.
  • 99. 基于 XML ---- 声明切面当使用 XML 声明切面时, 需要在 根元素中导入 aop Schema 在 Bean 配置文件中, 所有的 Spring AOP 配置都必须定义在 元素内部. 对于每个切面而言, 都要创建一个 元素来为具体的切面实现引用后端 Bean 实例. 切面 Bean 必须有一个标示符, 供 元素引用
  • 100. 声明切面的实例代码
  • 101. 基于 XML ---- 声明切入点切入点使用 元素声明 切入点必须定义在 元素下, 或者直接定义在 元素下. 定义在 元素下: 只对当前切面有效 定义在 元素下: 对所有切面都有效 基于 XML 的 AOP 配置不允许在切入点表达式中用名称引用其他切入点.
  • 102. 声明切入点的示例代码
  • 103. 基于 XML ---- 声明通知在 aop Schema 中, 每种通知类型都对应一个特定的 XML 元素. 通知元素需要使用 来引用切入点, 或用 直接嵌入切入点表达式. method 属性指定切面类中通知方法的名称.
  • 104. 声明通知示例代码
  • 105. 声明引入可以利用 元素在切面内部声明引入
  • 106. O/R MappingHibernate MyBatis
  • 107. Hibernate
  • 108. hibernate内容介绍: 1.hibernate是什么 2.为什么有hibernate 3.hibernate的原理 4.第一个hibernate项目
  • 109. 学习目标① 了解hibernate的基本概念 ② 明白使用hibernate的优点和必要性 ③ 搞清hibernate基本原理 ④ 会简单使用hibernate
  • 110. ■ 请看一段对话 客户马大凡:小刘,你们上次给我公司开发悠悠办公系统用的是sql 2000吧,我现在要用mysql 数据库,给换一下吧。 经理刘一手: 可以呀,不过换数据库很费时间,我们要重写业务层, 给加10w元吧! 客户马大凡:要吃人呀,我告你去。 要是用hibernate框架问题就好解决啦。 为什么需要hibernate--一个应用场景
  • 111. ■ 使用hibernate的好处 ①引入hibernate可以使工作人员角色细化,让程序员更关心业务流 程。让数据库人员关注数据库相关的各种操作。 ②分层更清晰,耦合性更小。 ③通用性强:可以更轻松的从一个数据库平台转移到别的平台。 ④对象化:把关系数据库变成了Java的对象,更加方便操作。 ⑤性能保证:hibernate可能按不同的数据库,处理不同的操作是用 最优化的SQL语句,不用我们去想,对于分等算法,在hibernate中会显 得更简单,可靠。 ⑥增加了程序的鲁棒性! 为什么需要hibernate--使用hibernate的好处
  • 112. hibernate基本原理--示意图表现层业务逻辑层2000db (数据层)表现层业务逻辑层mysql (数据层)数据持久层操作数据库 1.Configuration 2.SessionFactory 3.Session 4.Transaction Hibernate API Hibernate 配置文件,对象关系映射文件 注意: hibernate对jdbc做了轻量级的封装oracle (数据层)操作数据库 1.Connecion 2.DriverManger 3.PreparedStatement 4.ResultSet
  • 113. ■ hibernate创始人 Gavin King,Hibernate的创始人 ,EJB专家委员会成员,JBoss核心开 发人员;目前,Gavin就职于RebHat, 负责JBoss Hibernate和CMP引擎的开 发。他的传奇是,在开发Hibernate 这个Java领域最流行的数据持久化框 架之前只是一名普通Java程序员,那 时,他对SQL和数据库一窍不通。hibernate是什么--hibernate创始人
  • 114. ■ hibernate的基本概念 hibernate是 轻量级的 ORM 框架, ORM全称object/relation mapping [对象/关系 映射]。hibernate是什么-hibernate的概念
  • 115. ■ orm是什么 对象关系映射(Object Relation Mapping,简称ORM)是一种 为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据, 将java程序中的对象自动持久化到关系数据库中。本质上就是将数 据从一种形式转换到另外一种形式。 结论:使用orm技术(hibernate是其 中最为流行的)可以在java程序以类和 对象的方式去操控数据库表和记录.hibernate是什么-hibernate的概念hibernate 从入门到精通
  • 116. hibernte原理--orm示意图■ java类(pojo/domain object)映射关系型数据库的表 ■ 一个对象映射表中的一条记录 Users类(domain object) private int id private String name private String passwdUsers某个对象users1 id=2,name=“吴用” passwd=“xxx”idnamepasswd1宋江xxx2吴用xxxUsers表
  • 117. ■ 项目说明 ①该项目旨在说明hibernate原理,剖析hibernate框架结构,并 演示hibernate开发流程. ②项目完成的功能非常简单,就演示如何使用hibernate完成 crud的操作(增,删,改,查 load) hibernate第一个项目hibernate开发方式的三种方式: 1由Domain object -> mapping->db。(官方推荐) 2由DB开始,用工具生成mapping和Domain object。(使用较多) 3由映射文件开始。http://www.hibernate.org 下载开发包
  • 118. ■ 项目说明 ③项目框架图如下所示: hibernate第一个项目TestMain.java 测试类Employee.java 这是一个POJO类/javabean/domain 与users表对应数据持久层(Hibernate框架) 1.hibernate.cfg.xml(配置文件) 2.users.hbm.xml(对象映射文件) 3.hibernate core库,api...users表开发hibernate流程 (手写版) 1.建库建表 2.引入hiberate的包 3.配置hibernate.cfg.xml 4.编写POJO类(Users类) 5.编写对象映射文件 6.编写测试类,并测试.
  • 119. ■ hibernate依赖(需要)的其它库 怎么理解hibernate还需要其它的库这个问题?hibernate原理--hibernate依赖的库
  • 120. ■ 什么是POJO 在使用hibernate时,要求和数据库的某张表相互映射的那个java类, 是一个POJO类,一般放在com.xxx.domain包下,POJO类翻译过来就是: 简单的Java对象(Plain Ordinary Java Objects)实际就是普通 JavaBeans,使用POJO名称是为了避免和EJB混淆起来。一个POJO类应当 具有: ①有一个主键属性,用于唯一标识该对象。 (这就是为什么hibernate设计者建议要映射的表需要一个主键) ②有其它的属性 ③有对各个属性操作的get/set方法 ④属性一般是private修饰. ⑤一定有一个无参的构造函数(用于hibernate框架反射用.)hibernate原理--POJO介绍
  • 121. ■ 什么是POJO 在POJO有一些private的参数作为对象的属性。然后针对每 个参数定义了get和set方法作为访问的接口。例如:  public class User {   private long id;   private String name;   public void setId(long id) {   this.id = id;   }   public void setName(String name) {   this.name=name;   }   public long getId() {   return id;   }   public String getName() {   return name;   }   }  POJO对象有时也被称为Data对象,大量应用于表现现实中的对象。hibernate原理--POJO介绍
  • 122. ■ hibernate产品介绍--hibernate产品
  • 123. ■ hibernate部分产品介绍 ①Hibernate Core 即平时所说的Hibernate,它可为应用程序提供强大、高性能的对象 -关系映射以及查询服务。Hibernate使用(HQL)检索方式进行查询,也可 以使用本地SQL语言,还可以使用Query by Criteria(QBC)检索方式或 者Query by Example(QBE)检索方式。Hibernate可以帮助开发者节省 持久层编码时间,有助于面向对象应用程序的设计实现。 ②Hibernate标注(Hibernate Annotations) 从Hebernate3.2开始,Hibernate Annotations提供了JDK 5.0 关于对 象-关系映射的标注。通过使用Hibernate标注,可以减少XML描述符的使 用,在编译期进行校验,以及减少配置和维护工作等。 ③Hibernate EntityManager Hibernate EntityManager在Hibernate Core的强大功能基础上实现了 符合JPA规范Java持久化提供者(Hibernate Java Persistence)。 Hibernate EntityManager可以应用于任何Java EE5应用服务器中或 EJB3.0容器中,也可以被使用在Java SE应用中。--hibernate产品
  • 124. hibernate核心类和接口--一览图
  • 125. ■ Configuraion类 ①负责管理hibernate的配置信息 ②读取hibernate.cfg.xml ③加载hibernate.cfg.xml配置文件中 配置的驱动,url,用户名,密码,连接池. ④管理 *.hbm.xml对象关系文件. 示意代码: Configuration cf=new Configuration().configure(); 该类的其它方法见hibernate api javadoc文档. hibernate核心类和接口--Configuration类
  • 126. ■ hibernate.cfg.xml文件 ①该文件主要用于指定各个参数,是hibernate核心文件 ②默认放在src目录下,也可以放在别的目录下。 ③指定连接数据库的驱动、用户名、密码、url、连接池.. ④指定对象关系映射文件的位置. ⑤也可使用hibernate.properties文件来替代该文件.(推荐使用 hibernate.cfg.xml)。 hibernate核心类和接口--hibernate.cfg.xml
  • 127. ■ hibernate.cfg.xml文件 一个具体的实例,请参看hibernate.cfg.xml文件 hibernate核心类和接口--hibernate.cfg.xml
  • 128. ■ hibernate.properties文件 作用和hibernate.cfg.xml一致. 一个具体的实例,请参看hibernate.properties文件 hibernate核心类和接口hibernate.properties
  • 129. ■ 对象关系映射文件(*.hbm.xml) ①该文件主要作用是建立表和类的映射关系,是不可或缺的重要文件. ②一般放在其映射的类同一个目录下,但不是必须的。 ③命名方式一般是 类名.hbm.xml,但不是必须的。 ④示意图: hibernate核心类和接口--*.hbm.xml文件表*.hbm.xml某个类
  • 130. ■ SessionFactory(会话工厂)接口 ①缓存sql语句和某些数据 ②在应用程序初始化的时候创建,是一个重量级的类(吃内存),一般 用单例模式保证一个应用中只需要一个 SessionFactory实例. ③如果某个应用访问多个数据库,则要创建多个会话工厂实例,一般 是一个数据库一个会话工厂实例. ④通过SessionFactory接口可以获得Session(会话)实例. 示意代码: Configuration cf=new Configuration().configure(); SessionFactory sf=cf.buildSessionFactory(); Session s=sf.getCurrentSession(); //或者是: Session s=sf.openSession(); 它的其它方法见 hibernate api javadoc文件hibernate核心类和接口--SessionFactory(会话工厂)接口
  • 131. ■ SessionFactory(会话工厂)接口的理解 示意图:java se应用 如果是 java ee应用(web应用) 则会话工厂在应用服务器那头..hibernate核心类和接口--SessionFactory(会话工厂)接口java程序 db会话 工厂session
  • 132. ■ Session(会话)接口 ①Session一个实例代表与数据库的一次操作 (当然一次操作可以是crud组合) ②Session实例通过SessionFactory获取,用完 需要关闭。 ③Session是线程不同步的(不安全),因此要保证 在同一线程中使用,可以用getCurrentSessiong()。 ④Session可以看做是持久化管理器,它是与持久 化操作相关的接口 示意代码: Configuration cf=new Configuration().configure(); SessionFactory sf=cf.buildSessionFactory(); Session s=sf.getCurrentSession(); //或者是: Session s=sf.openSession();hibernate核心类和接口--Session(会话)接口
  • 133. ■ Session(会话)接口的理解 示意图:java se应用 如果是 java ee应用(web应用) 则会话工厂在应用服务器那头..hibernate核心类和接口java程序 db会话 工厂--Session(会话)接口
  • 134. ■ Session(会话)接口的几个重要方法 Session一般以对象的形式来操作,这里 给大家演示一下吧! ①保存一个对象(记录)—save方法 ②删除一个对象(记录)—delete方法 ③查询一个对象(记录)—get/load方法 ④修改一个对象(记录)—update方法 hibernate核心类和接口java程序 db会话 工厂--Session(会话)接口
  • 135. ■ get()和load()区别 1、get()方法直接返回实体类,如果查不到数据则返回null。load()会 返回一个实体代理对象(当前这个对象可以自动转化为实体对象), 但当代理对象被调用时,如果没有数据不存在,就会抛出个 org.hibernate.ObjectNotFoundException异常 2.load先到缓存(session缓存/二级缓存)中去查,如果没有则返回一个 代理对象(不马上到DB中去找),等后面使用这个代理对象操作的时 候,才到DB中查询,这就是我们常说的 load在默认情况下支持延迟加 载(lazy) 3. get先到缓存(session缓存/二级缓存)中去查,如果没有就到DB中去 查(即马上发出sql)。总之,如果你确定DB中有这个对象就用 load(),不确定就用get()(这样效率高) hibernate核心类和接口--Session(会话)接口如何配置让load不使用lazy加载?
  • 136. hibernate核心类和接口--Session(会话)接口■ openSession()和 getCurrentSession()区别 ①采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()创建的session则不会 ②采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()创建的session必须手动关闭. ③使用getCurrentSession()需要在hibernate.cfg.xml文件中加入 如下配置: * 如果使用的是本地事务(jdbc事务) thread * 如果使用的是全局事务(jta事务) jta 简单解释一下jdbc事务和jta事务的区别吧!
  • 137. hibernate核心类和接口--Session(会话)接口■ openSession()和 getCurrentSession()联系 深入探讨: 在 SessionFactory启动的时候,Hibernate 会根据配置创建相应的 CurrentSessionContext,在getCurrentSession()被调用的时候,实际被执行的方法是 CurrentSessionContext.currentSession()。在 currentSession()执行时,如果当前Session为空,currentSession会调用SessionFactory的openSession。
  • 138. ■ openSession()和 getCurrentSession()究竟选谁? 原则: ①如果需要在同一线程中,保证使用同一个Session 则,使用getCurrentSession() ②如果在一个线程中,需要使用不同的Session,则 使用opentSession()hibernate核心类和接口--Session(会话)接口
  • 139. hibernate核心类和接口--Session(会话)接口■ openSession()和 getCurrentSession()联系 用ThreadLocal模式 (线程局部变量模式) 管理Session,代码如下: public class HibernateUtil { public static final ThreadLocal session =new ThreadLocal(); public static final SessionFactory sessionFactory; static { try { sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public static Session currentSession() throws HibernateException { Session s = session.get(); if(s == null) { s = sessionFactory.openSession();session.set(s);} return s;} public static void closeSession() throws HibernateException { Session s = session.get(); if(s != null) { s.close();} session.set(null); }}
  • 140. ■ Transaction(事务)接口 这里我们简单给大家说明一下什么是事务。我们通过一个网上转账的 案例来说明. 事务简单的说,就是一组对数据库的操作集合,它们要么全部成功,要 么全部失败.这个可以保证数据的一致性,事务具有原子性。 ①Transaction是底层的事物实现中抽象出来的接口 ②可能是一个jdbc或者jta的事务,这样有利于hibernate在不同执行 环境的移植。 ③hibernate要求显示的调用事务(如果仅仅是查询可以不调用.) Transaction ts=s.beginTransaction(); ... ts.commit();s.close(); 发生异常需要ts.rollback()回滚.hibernate核心类和接口--Transaction(事务)接口
  • 141. ■ Query接口 Query接口类型的对象可以对数据库操作,它可以使用Hql,Qbc,Qbe 和原生SQL(native Sql)对数据库操作.官方推荐使用Hql语句。 这里我们给大家举例简单说明,Query接口查询出来的结果是一个 List接口类型的对象。 hibernate核心类和接口--Query接口举例说明吧!
  • 142. ■ Criteria接口 Criteria接口也可用于面向对象方式的查询,关于它的具体用法我们 这里先不做介绍,简单看几个案例. 最简单案例:返回50条记录 Criteria crit = sess.createCriteria(Cat.class); crit.setMaxResults(50); List cats = crit.list(); 限制结果集内容 List cats = sess.createCriteria(Cat.class) .add( Restrictions.like("name", "Fritz%") ) .add( Restrictions.between("weight", minWeight, maxWeight) ) .list(); hibernate核心类和接口Criteria接口
  • 143. ■ 使用eclipse开发hibernate项目[看看eclipse如何自动完成映射] 用eclipse开发hibernate
  • 144. ■ 使用eclipse开发hibernate项目 配合下页ppt-项目框架图演示开发流程. ①建库建表 ②创建一个项目 ③使用myeclipse自带的db browser连接到数据库 ④引入hibernate支持(框架)【这里会自动创建hibernate.cfg.xml】 ⑤使用hibernate反向工程创建POJO类和对象映射文件 ⑥对各配置文件作相应的修改【稍稍改改就可用】 ⑦编写测试类。用eclipse开发hibernate
  • 145. MyBatis
  • 146. 什么是MyBatisMyBatis是一个运用于持久层的数据操作框架 MyBatis是从iBatis升级而来 使用MyBatis提供的ORM机制,业务逻辑层实现人员操作的是JAVA对象,该层面与Hibernate机制中的相同。对于具体的数据库操作而言,Hibernate会自动生成SQL并执行,而MyBatis要求开发人员具体编写SQL语句。MyBatis在数据库移植性和SQL开发工作量上进行了让步,从而提升了系统设计的灵活性,扩展了其自由空间。
  • 147. 为什么需要MyBatis(1)系统的部分或全部数据来自现有数据库,出于安全性的考虑,只为开发团队提供几条Select SQL(或存储过程)以获取所需数据,具体的表结构不予公开。   (2)开发规范中要求,所有牵涉到业务逻辑部分的数据库操作,必须在数据库层由存储过程实现(对于金融行业而言,工商银行、中国银行和交通银行,都在开发规范中严格指定)。   (3)系统数据处理量巨大,性能要求极为苛刻,这通常意味着我们必须由经过高度优化的SQL语句(或存储过程)才能达到系统性能设计指标。
  • 148. MyBatis的优势支持ORM 支持动态SQL 外部化SQL语句 封装SQL语句
  • 149. MyBatis使用入门准备软件开发环境 MyBatis的源代码、所需的jar文件以及学习文档可以在http://code.google.com/p/mybatis网站上下载,推荐下载mybatis-3.1.1-bundle.zip文件/文件夹说明mybatis-3.1.1.jarmybatis的核心jar包lib文件夹Lib文件夹中包含mybatis所依赖的其他jar文件mybatis-3.1.1.pdfmybatis的用户指南Mybatis-3.1.1-javadoc.jarMybatis的API文档Mybatis-3.1.1-sources.jarMybatis的源代码
  • 150. MyBatis使用入门准备数据 列名类型说明约束USER_IDint用户ID主键标识列(自动增长)USER_NAMEvarchar用户名不能为空USER_PASSWORDvarchar用户密码不能为空USER_BIRTHdate用户生日USER_ADDRESSvarchar用户地址USER_PHONEvarchar用户电话USER_STATUSint用户类型0为禁用;1为普通用户(默认);2为管理员
  • 151. 使用mybatis操作数据库操作步骤 创建项目-导入jar包 创建mybatis配置文件 创建实体类 创建实体类对应的映射器及其配置文件 操作数据 测试操作
  • 152. 创建mybatis配置文件创建mybatis-config.xml文件 配置数据源
  • 153. 创建实体类public class User implements Serializable {   private static final long serialVersionUID = 1L; //属性字段 private int userId; private String userName; private String userPassword; private Date userBirth; private String userAddress; private String userPhone; private int userStatus; //无参数的构造函数 //getter和setter }
  • 154. 创建映射器及其配置文件public interface UserMapper { //新增用户 public void insertUser(User user); //根据用户名和密码查询用户 public User selectUserByNameAndPassword(User user); //查询所有的用户 public List selectAllUsers(); }
  • 155. 创建映射器的配置文件 SQL语句
  • 156. 创建映射器的配置文件namespace表示该配置文件对于映射器(UserMapper)接口的完全路径。 insert 映射插入语句 Id表示在命名空间中唯一的标识符,可以被用于引用该语句,与映射器接口中的方法一致时,会在该方法中使用该语句。 parameterType表示将会传入该语句的参数类的完全限定名或别名。 useGeneratedKeys表示使用JDBC的getGeneratedKeys方法取出由数据库内部生成的主键(实现标识列自动增长)。 select 映射查询语句 Id表示在命名空间中唯一的标识符,可以被用于引用该语句,与映射器接口中的方法一致时会在该方法中使用该语句。 parameterType表示将会传入该语句的参数类的完全限定名或别名。 resultType表示从这条语句中返回的期望类型的类的完全限定名或别名,如果返回的是集合,则应是集合中包含元素的类型,而并非集合本身。
  • 157. 操作数据步骤 读取并解析配置文件,创建SqlSessionFactory。 从SqlSessionFactory中获取SqlSession对象。 使用SqlSession对象操作数据。 提交事务(回滚事务)。 关闭SqlSession对象。
  • 158. 创建SqlSessionFactory//配置文件的路径(在src下) String resource = "mybatis-config.xml"; //读取配置文件 Reader reader = Resources.getResourceAsReader(resource); //创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //解析配置,构建SqlSessionFactory对象 SqlSessionFactory factory = builder.build(reader);
  • 159. 获取SqlSession对象SqlSession sqlSession = factory.openSession(); SqlSession的方法 T selectOne(String statement, Object parameter) List selectList(String statement, Object parameter) Map selectMap(String statement, Object parameter, String mapKey) int insert(String statement, Object parameter) int update(String statement, Object parameter) int delete(String statement, Object parameter)
  • 160. 使用SqlSession对象操作数据SqlSession对象封装了对数据的各种增加、删除、修改和查询操作 User user = new User("汤姆", "tom", new Date(), "湖北武汉", "18688889999", 1); sqlSession.insert("insertUser", user); 使用映射器接口(推荐) User user = new User("汤姆", "tom", new Date(), "湖北武汉", "18688889999", 1); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.insertUser(user );
  • 161. 事务处理提交事务(回滚事务)。 sqlSession.commit(); (sqlSession.rollback();) 关闭SqlSession对象。 sqlSession.close();
  • 162. 测试数据创建工具类: public class MyBatisUtil { private final static SqlSessionFactory sqlSessionFactory; static { String resource = "mybatis-config.xml"; Reader reader = null; try { reader = Resources.getResourceAsReader(resource); } catch (IOException e) { System.out.println(e.getMessage()); } sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } public static SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } }
  • 163. 增加用户@Test public void testInsertUser() { SqlSessionFactory factory = MyBatisUtil.getSqlSessionFactory(); SqlSession sqlSession = factory.openSession(); //构建SqlSession User user = new User("杰克", "jack", new Date(), "湖北省武汉光谷xx号", "18688889999", 1); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.insertUser(user); //插入用户 sqlSession.commit(); //提交 sqlSession.close(); }
  • 164. 查询用户 @Test public void testSelectUsers() { SqlSessionFactory factory = MyBatisUtil.getSqlSessionFactory(); SqlSession sqlSession = factory.openSession(); //构建SqlSession UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //查询所有用户信息 List users = userMapper.selectAllUsers(); //输出结果 System.out.println("所有用户的名字是:"); for (User user : users) { System.out.println(user.getUserId()+"\t"+user.getUserName()); } sqlSession.close(); }
  • 165. 总结在项目开发中,为了提高项目的可扩张性和可维护性,将项目分为三层 持久层与持久化的区别包括: (1)“持久化”仅指将域对象永久保存至数据库中。 (2)“持久层”是指在系统逻辑层面上,专注于实现数据持久化的一个相对独立的领域。 MyBatis是一个数据持久化的框架,其操作数据的基本步骤是: (1)读取并解析配置文件,创建SqlSessionFactory。 (2)从SqlSessionFactory中获取SqlSession对象。 (3)使用SqlSession对象操作数据。 (4)提交事务(回滚事务)。 (5)关闭SqlSession对象。
  • 166. Spring MVC
  • 167. Spring MVC框架简介1HTTP请求地址映射2HTTP请求数据的绑定3数据转换、格式化、校验4数据模型控制5视图及解析器6
  • 168. 支持REST风格的URL 添加更多注解,可完全注解驱动 引入HTTP输入输出转换器(HttpMessageConverter) 和数据转换、格式化、验证框架无缝集成 对静态资源处理提供特殊支持 更加灵活的控制器方法签名,可完全独立于Servlet API
  • 169. Spring MVC框架结构DispatcherServletHandlerMappingHandlerAdapterHandlerView
 (JSP/XML/PDF,...)23ModelAndView54ViewResolver6Model781
  • 170. 框架的实现者DispatcherServletDefaultAnnotation HandlerMappingAnnotationMethod HandlerAdapterUserControllerregister.jsp23ModelAndView "user/register"54InternalResource ViewResolver6Model781
  • 171. Spring MVC框架结构package com.baobaotao.web; ... @Controller ① 将UserController变成一个Handler @RequestMapping(“/user”) ②指定控制器映射的URL public class UserController { @RequestMapping(value = “/register”) ③处理方法对应的URL,相对于 ②处的URL public String register() { return “user/register”; ④返回逻辑视图名 } }
  • 172. Spring MVC框架简介1HTTP请求地址映射2HTTP请求数据的绑定3数据转换、格式化、校验4数据模型控制5视图及解析器6
  • 173. HTTP请求映射原理HTTP请求报文Handler 处理方法Spring MVC 框架WEB容器
  • 174. Spring MVC进行映射的依据
  • 175. 通过URL限定:URL表达式 @RequestMapping不但支持标准的URL,还支持Ant风格(即?、*和**的字符,参见3.3.2节的内容)的和带{xxx}占位符的URL。以下URL都是合法的: /user/*/createUser 匹配/user/aaa/createUser、/user/bbb/createUser等URL。 /user/**/createUser 匹配/user/createUser、/user/aaa/bbb/createUser等URL。 /user/createUser?? 匹配/user/createUseraa、/user/createUserbb等URL。 /user/{userId} 匹配user/123、user/abc等URL。 /user/**/{userId} 匹配user/aaa/bbb/123、user/aaa/456等URL。 company/{companyId}/user/{userId}/detail 匹配company/123/user/456/detail等的URL。
  • 176. 通过URL限定:绑定{xxx}中的值@RequestMapping("/{userId}") public ModelAndView showDetail(@PathVariable("userId") String userId){ ModelAndView mav = new ModelAndView(); mav.setViewName("user/showDetail"); mav.addObject("user", userService.getUserById(userId)); return mav; }@Controller @RequestMapping("/owners/{ownerId}") public class RelativePathUriTemplateController { @RequestMapping("/pets/{petId}") public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) { … } }URL中的{xxx}占位符可以通过@PathVariable("xxx")绑定到操作方法的入参中。如果@PathVariable不指定参数名,只有在编译时打开debug开关(javac -debug=no)时才可行!!(不建议)参考《Spring 3.x企业应用开发实战》
  • 177. 通过请求方法限定:请求方法序号请求方法说明1GET使用GET方法检索一个表述(representation)——也就是对资源的描述。多次执行同一GET请求,不会对系统造成影响,GET方法具有幂等性[指多个相同请求返回相同的结果]。GET请求可以充分使用客户端的缓存。2POSTPOST方法,通常表示“创建一个新资源”,但它既不安全也不具有幂等性(多次操作会产生多个新资源)。3DELETEDELETE,表示删除一个资源,你也可以一遍又一遍地操作它,直到得出结果:删除不存在的东西没有任何问题4PUT幂等性同样适用于PUT(基本的含义是“更新资源数据,如果资源不存在的话,则根据此URI创建一个新的资源”) 请求方法,在HTTP中这被叫做动词(verb),除了两个大家熟知的(GET和POST)之外,标准方法集合中还包含PUT、DELETE、HEAD和OPTIONS。这些方法的含义连同行为许诺都一起定义在HTTP规范之中。一般浏览器只支持GET和POST方法。
  • 178. 通过请求方法限定:代码示例示例1: @RequestMapping(value=“/delete”) public String test1(@RequestParam("userId") String userId){ return "user/test1"; } 所有URL为/delete的请求由test1处理(任何请求方法) 示例2: @RequestMapping(value="/delete",method=RequestMethod.POST) public String test1(@RequestParam("userId") String userId){ return "user/test1"; } 所有URL为/delete 且请求方法为POST 的请求由test1处理
  • 179. 通过请求/请求头参数限定:更多 params和headers分别通过请求参数及报文头属性进行映射,它们支持简单的表达式,下面以params表达式为例说明,headers可以参照params进行理解之。 "param1":表示请求必须包含名为param1的请求参数。 "!param1":表示请求不能包含名为param1的请求参数。 "param1!=value1":表示请求包含名为param1的请求参数,但其值不能为value1。 {"param1=value1","param2"}:请求必须包含名为param1和param2的两个请求参数,且param1参数的值必须为value1。 参考《Spring 3.x企业应用开发实战》
  • 180. 通过请求/请求头参数限定:示例@RequestMapping(value="/delete", params="userId") public String test1(@RequestParam("userId") String userId){ ... }@RequestMapping(value="/show",headers="content-type=text/*")② public String test2(@RequestParam("userId") String userId){ ... }通过请求参数限定:通过请求头参数限定:参考《Spring 3.x企业应用开发实战》
  • 181. 目录Spring MVC框架简介1HTTP请求地址映射2HTTP请求数据的绑定3数据转换、格式化、校验4数据模型控制5视图及解析器6
  • 182. 通过注解绑定:示意图public String handle1(...)@RequestParam绑定请求参数@RequestHeader绑定请求头参数@CookieValue绑定Cookie的值@PathVariable绑定URL中的变量
  • 183. 通过注解绑定:示例@RequestMapping(value="/handle1") public String handle1(@RequestParam("userName") String userName, @RequestParam("password") String password, @RequestParam("realName") String realName){ ... }@RequestMapping(value="/handle2") public String handle2(@CookieValue("JSESSIONID") String sessionId, @RequestHeader("Accept-Language") String accpetLanguage){ ... }
  • 184. 通过注解绑定:小心抛出异常@RequestParam有以下三个参数。 value:参数名。 required:是否必需,默认为true,表示请求中必须包含对应的参数名,如果不存在将抛出异常。 defaultValue:默认参数名,设置该参数时,自动将required设为false。极少情况需要使用该参数,也不推荐使用该参数。@RequestMapping(value="/handle1") public String handle1(@RequestParam("userName") String userName,){ ... } 上面的处理方法 ,如果HTTP请求不包含“userName”参数时,将产生异常!! 因此,如果不能保证存在”userName”的参数,必须使用: @RequestParam(value = "userName", required = false)
  • 185. 使用命令/表单对象绑定 所谓命令/表单对象并不需要实现任何接口,仅是一个拥有若干属性的POJO。Spring MVC按: “HTTP请求参数名 = 命令/表单对象的属性名” 的规则,自动绑定请求数据,支持“级联属性名”,自动进行基本类型数据转换。 @RequestMapping(value = "/handle14") public String handle14(User user) { … }userName=xxx&password=yyyclass User{ private String userName; private String password; }
  • 186. 使用Servlet API对象作为入参 在Spring MVC中,控制器类可以不依赖任何Servlet API对象,但是Spring MVC并不阻止我们使用Servlet API的类作为处理方法的入参。值得注意的是,如果处理方法自行使用HttpServletResponse返回响应,则处理方法的返回值设置成void即可。 @RequestMapping(value = "/handle21") public void handle21(HttpServletRequest request,HttpServletResponse response) { String userName = WebUtils.findParameterValue(request, "userName"); response.addCookie(new Cookie("userName", userName)); }public String handle23(HttpSession session) { session.setAttribute("sessionId", 1234); return "success"; }public String handle24(HttpServletRequest request, @RequestParam("userName")String userName) { … return "success"; }
  • 187. 使用Spring的Servlet API代理类 Spring MVC在org.springframework.web.context.request包中定义了若干个可代理Servlet原生API类的接口,如WebRequest和NativeWebRequest,它们也允许作为处理类的入参,通过这些代理类可访问请求对象的任何信息。@RequestMapping(value = "/handle25") public String handle25(WebRequest request) { String userName = request.getParameter("userName"); return "success"; }
  • 188. 使用IO对象作为入参Spring MVC允许控制器的处理方法使用java.io.InputStream/java.io.Reader及java.io.OutputStream/java.io.Writer作为方法的入参@RequestMapping(value = "/handle31") public void handle31(OutputStream os) throws IOException{ Resource res = new ClassPathResource("/image.jpg");//读取类路径下的图片文件 FileCopyUtils.copy(res.getInputStream(), os);//将图片写到输出流中 }Spring MVC将获取ServletRequest的InputStream/Reader或ServletResponse的OutputStream/Writer,然后按类型匹配的方式,传递给控制器的处理方法入参。
  • 189. 其他类型的参数 控制器处理方法的入参除支持以上类型的参数以外,还支持java.util.Locale、java.security.Principal,可以通过Servlet的HttpServletRequest 的getLocale()及getUserPrincipal()得到相应的值。如果处理方法的入参类型为Locale或Principal,Spring MVC自动从请求对象中获取相应的对象并传递给处理方法的入参。@RequestMapping(value = "/handle32") public void handle31(Locale locale) throws IOException{ ... }
  • 190. HttpMessageConverterHttpServletRequestHttpServletRequest@RequestBody/ HttpEntity@ResponseBody/ ResponseEntityHttpMessageConverterHTTP请求报文HTTP请求报文
  • 191. HttpMessageConverter实现类AnnotationMethodHandlerAdapter 实现类: StringHttpMessageConverter FormHttpMessageConverter XmlAwareFormHttpMessageConverter ResourceHttpMessageConverter BufferedImageHttpMessageConverter ByteArrayHttpMessageConverter SourceHttpMessageConverter MarshallingHttpMessageConverter Jaxb2RootElementHttpMessageConverter MappingJacksonHttpMessageConverter RssChannelHttpMessageConverter AtomFeedHttpMessageConverter注册到...HttpMessageConverter 接口方法 T read(HttpInputMessage httpInputMessage) void write(T t,HttpOutputMessage httpOutputMessage)
  • 192. 使用@RequestBody/@ResponseBody 将HttpServletRequest的getInputStream()内容绑定到入参,将处理方法返回值写入到HttpServletResponse的getOutputStream()中。@RequestMapping(value = "/handle41") public String handle41(@RequestBody String requestBody ) { System.out.println(requestBody); return "success"; }@ResponseBody @RequestMapping(value = "/handle42/{imageId}") public byte[] handle42(@PathVariable("imageId") String imageId) throws IOException { System.out.println("load image of "+imageId); Resource res = new ClassPathResource("/image.jpg"); byte[] fileData =FileCopyUtils.copyToByteArray(res.getInputStream()); return fileData; }优点:处理方法签名灵活不受限 缺点:只能访问报文体,不能访问报文头
  • 193. 使用HttpEntity/ResponseEntity@RequestMapping(value = "/handle43") public String handle43(HttpEntity httpEntity){ long contentLen = httpEntity.getHeaders().getContentLength(); System.out.println(httpEntity.getBody()); return "success"; }@RequestMapping(params = "method=login") public ResponseEntity doFirst(){ HttpHeaders headers = new HttpHeaders(); MediaType mt=new MediaType("text","html",Charset.forName(“UTF-8")); headers.setContentType(mt); ResponseEntity re=null; String return = new String("test"); re=new ResponseEntity(return,headers, HttpStatus.OK); return re; }优点:处理方法签名受限 缺点:不但可以访问报文体,还能访问报文头
  • 194. 输出XML和JSON处理XML转换处理JSON转换
  • 195. 使用HttpEntity/ResponseEntity@RequestMapping(value = "/handle51") public ResponseEntity handle51(HttpEntity requestEntity){ User user = requestEntity.getBody(); user.setUserId("1000"); return new ResponseEntity(user,HttpStatus.OK); } 对于服务端的处理方法而言,除使用@RequestBody/@ResponseBody或HttpEntity /ResponseEntity进行方法签名外,不需要进行任何额外的处理,借由Spring MVC中装配的HttpMessageConverter,它即拥有了处理XML及JSON的能力了。
  • 196. 目录Spring MVC框架简介1HTTP请求地址映射2HTTP请求数据的绑定3数据转换、格式化、校验4数据模型控制5视图及解析器6
  • 197. 数据绑定机理DataBinderConversionServiceValidator34BindingResult51ServletRequest处理方法入参对象集处理方法的签名2数据类型转换/格式化数据校验
  • 198. 数据类型转换 低版本的Spring 只支持标准的PropertyEditor类型体系,不过PropertyEditor存在以下缺陷: 只能用于字符串和Java对象的转换,不适用于任意两个Java类型之间的转换; 对源对象及目标对象所在的上下文信息(如注解、所在宿主类的结构等)不敏感,在类型转换时不能利用这些上下文信息实施高级转换逻辑。 有鉴于此,Spring 3.0在核心模型中添加了一个通用的类型转换模块, ConversionService是Spring类型转换体系的核心接口。 Spring 3.0同时支持PropertyEditor和ConversionService 进行类型转换,在Bean配置、Spring MVC处理方法入参绑定中使用类型转换体系进行工作。
  • 199. PropertyEditor依然有效 对于简单的类型转换,依然建议使用PropertyEditor。按照PropertyEditor的协议,会自动查找Bean类相同类包是否存在Editor.class,如果存在会使用它作为Bean的编辑器。com.book.core.cache.expired |_CacheSpace.java |_ CacheSpaceEditor.java comBookSpace:com/comBook/** bookSpace:com/book/**:100 companySpace:com/company/**
  • 200. 强大的ConversionService,让很多梦想成真 由于ConversionService在进行类型转换时,可以使用到Bean所在宿主类的上下文信息(包括类结构,注解信息),所以可以实施更加高级的类型转换,如注解驱动的格式化等功能。public class User { @DateTimeFormat(pattern="yyyy-MM-dd") private Date birthday; } 以上User类,通过一个@DateTimeFormat注解,为类型转换提供了一些“额外”的信息,即代表日期的“源字符器”格式是“yyyy-MM-dd”
  • 201. 基于ConversionService体系,定义自定义的类型转换器ConverterStringToUserConverterorg.springframework.core.convert.converter.Converter 注册自定义转换器:定义自定义转换器:
  • 202. 格式化:带格式字符串内部对象 相互转换FormatterPrinterParserFormattingConversionServiceFactoryBeanConversionService注册内置的格式化器
  • 203. 使用支持格式化的转换器 值得注解的是,标签内部默认创建的ConversionService实例就是一个FormattingConversionServiceFactoryBean,自动支持如下的格式化注解: @NumberFormatter:用于数字类型对象的格式化。 @CurrencyFormatter:用于货币类型对象的格式化。 @PercentFormatter:用于百分数数字类型对象的格式化。 >>参见testhandle82()
  • 204. 数据校验框架 Spring 3.0拥有自己独立的数据校验框架,同时支持JSR 303标准的校验框架。Spring 的DataBinder在进行数据绑定时,可同时调用校验框架完成数据校验工作。在Spring MVC中,则可直接通过注解驱动的方式进行数据校验。 Spring的org.springframework.validation是校验框架所在的包
  • 205. JSR 303 JSR 303是Java为Bean数据合法性校验所提供的标准框架,它已经包含在Java EE 6.0中。JSR 303通过在Bean属性上标注类似于@NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证。 你可以通过http://jcp.org/en/jsr/detail?id=303了解JSR 303的详细内容。注 解功能说明@Null 被注释的元素必须为 null@NotNull 被注释的元素必须不为 null@AssertTrue 被注释的元素必须为 true@AssertFalse 被注释的元素必须为 false@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值@Size(max, min) 被注释的元素的大小必须在指定的范围内@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内@Past 被注释的元素必须是一个过去的日期@Future 被注释的元素必须是一个将来的日期
  • 206. 数据校验框架 会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参上标注@Valid注解即可让Spring MVC在完成数据绑定后执行数据校验的工作。public class User { @Pattern(regexp="w{4,30}") private String userName; @Length(min=2,max=100) private String realName; @Past @DateTimeFormat(pattern="yyyy-MM-dd") private Date birthday; @DecimalMin(value="1000.00") @DecimalMax(value="100000.00") @NumberFormat(pattern="#,###.##") private long salary; } 注意:Spring本身没有提供JSR 303的实现,所以必须将JSR 303的实现者(如Hibernate Validator)的jar文件放到类路径下,Spring将自动加载并装配好JSR 303的实现者。
  • 207. 如何使用注解驱动的校验@Controller @RequestMapping("/user") public class UserController { @RequestMapping(value = "/handle91") public String handle91(@Valid User user, BindingResult bindingResult){ if(bindingResult.hasErrors()){ return "/user/register3"; }else{ return "/user/showUser"; } } } 在已经标注了JSR 303注解的表单/命令对象前标注一个@Valid,Spring MVC框架在将请求数据绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验。
  • 208. 使用校验功能时,处理方法要如何签名?? Spring MVC是通过对处理方法签名的规约来保存校验结果的:前一个表单/命令对象的校验结果保存在其后的入参中,这个保存校验结果的入参必须是BindingResult或Errors类型,这两个类都位于org.springframework.validation包中。
  • 209. 校验错误信息存放在什么地方??4.Spring MVC将HttpServletRequest对象数据绑定到处理方法的入参对象中(表单/命令对象); 5.将绑定错误信息、检验错误信息都保存到隐含模型中; 6.本次请求的对应隐含模型数据存放到HttpServletRequest的属性列表中,暴露给视图对象。
  • 210. 页面如何显示错误信息<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 注册用户
    用户名:
  • 211. 如何对错误信息进行国际化(1)public class User { @Pattern(regexp=“w{4,30}”)假设发生错误 private String userName; } 一个属性发生校验错误时,Spring MVC会产生一系列对应的错误码键:Pattern.user.userName Pattern.userName Pattern.String Pattern 如果userName的@Pattern校验规则未通过,则会在“隐含模型”中产生如下的错误键,这些错误键可以作为“国际化消息”的属性键。
  • 212. 如何对错误信息进行国际化(2) 我们在conf/i18n/下添加基名为messages的国际化资源,一个是默认的messages. properties,另一个是对应中国大陆的messages_zh_CN.properties。来看一下messages_zh_ CN.properties资源文件的内容:
  • 213. 目录Spring MVC框架简介1HTTP请求地址映射2HTTP请求数据的绑定3数据转换、格式化、校验4数据模型控制5视图及解析器6
  • 214. 数据模型访问结构数据模型 key1=value1 key2=value2 ...接收请求处理请求请求响应@ModelAttribute("user")@SessionAttributesModelAndView,Map及Model视图对象暴露给...
  • 215. 访问数据模型:ModelAndView@RequestMapping(method = RequestMethod.POST) public ModelAndView createUser(User user) { userService.createUser(user); ModelAndView mav = new ModelAndView(); mav.setViewName("user/createSuccess"); mav.addObject("user", user); return mav; } 通过ModelAndView
  • 216. 访问数据模型:@ModelAttribute@RequestMapping(value = "/handle61") public String handle61(@ModelAttribute("user") User user){ user.setUserId("1000"); return "/user/createSuccess"; }1.使用方式一  Spring MVC将HTTP请求数据绑定到user入参中,然后再将user对象添加到数据模型中。@ModelAttribute("user") public User getUser(){ User user = new User(); user.setUserId("1001"); return user; } @RequestMapping(value = "/handle62") public String handle62(@ModelAttribute("user") User user){ user.setUserName("tom"); return "/user/showUser"; }2.使用方式二访问UserController中任何一个请求处理方法前,Spring MVC先执行该方法,并将返回值以user为键添加到模型中在此,模型数据会赋给User的入参,然后再根据HTTP请求消息进一步填充覆盖user对象
  • 217. 访问数据模型:Map及Model@RequestMapping(value = "/handle63") public String handle63(ModelMap modelMap){ modelMap.addAttribute("testAttr","value1"); User user = (User)modelMap.get("user"); user.setUserName("tom"); return "/user/showUser"; }org.springframework.ui.Model和java.util.Map: Spring MVC一旦发现处理方法有Map或Model类型的入参,就会将请求内在的隐含模型对象的引用传给这些入参。
  • 218. 访问数据模型:@SessionAttributes@Controller @RequestMapping("/user") @SessionAttributes(“user”)① public class UserController { @RequestMapping(value = "/handle71") public String handle71(@ModelAttribute(“user”) User user){② user.setUserName("John"); return "redirect:/user/handle72.html"; } @RequestMapping(value = "/handle72") public String handle72(ModelMap modelMap,SessionStatus sessionStatus){ User user = (User)modelMap.get(“user”);③ if(user != null){ user.setUserName("Jetty"); sessionStatus.setComplete();④ } return "/user/showUser"; } } 如果希望在多个请求之间共用某个模型属性数据,则可以在控制器类标注一个@SessionAttributes,Spring MVC会将模型中对应的属性暂存到HttpSession中:将②处的模型属性自动保存到HttpSession中读取模型中的数据让Spring MVC清除本处理器对应的会话属性
  • 219. 一场由@SessionAttributes引发的血案...  org.springframework.web.HttpSessionRequiredException: Session attribute 'user' required - not found in session... 对入参标注@ModelAttribute(“xxx”)的处理方法,Spring MVC按如下流程处理(handle71(@ModelAttribute(“user”) User user)): 如果隐含模型拥有名为xxx的属性,将其赋给该入参,再用请求消息填充该入参对象直接返回,否则到2步 。 如果xxx是会话属性,即在处理类定义处标注了@SessionAttributes("xxx"),则尝试从会话中获取该属性,并将其赋给该入参,然后再用请求消息填充该入参对象。如果在会话中找不到对应的属性,则抛出HttpSessionRequiredException异常。否则到 3。 如果隐含模型不存在xxx属性,且xxx也不是会话属性,则创建入参的对象实例,再用请求消息填充该入参。
  • 220. 如何避免@SessionAttributes引发的血案@Controller @RequestMapping("/user") @SessionAttributes(“user”) public class UserController { @ModelAttribute("user") public User getUser(){ User user = new User(); return user; } @RequestMapping(value = "/handle71") public String handle71(@ModelAttribute(“user”) User user){ ... } @RequestMapping(value = "/handle72") public String handle72(ModelMap modelMap,SessionStatus sessionStatus){ ... } }该方法会往隐含模型中添加一个名为user的模型属性
  • 221. Spring MVC框架简介1HTTP请求地址映射2HTTP请求数据的绑定3数据转换、格式化、校验4数据模型控制5视图及解析器6
  • 222. Spring MVC如何解析视图ViewResolver视图对象 JSP/JSTL/PDF...StringModelAndViewModelAndViewViewModelMap请求处理方法返回值类型
  • 223. 视图解析器类型InternalResourceViewResolver FreeMarkerViewResolver BeanNameViewResolver XmlViewResolver ...完成单一解析逻辑的视图解析器:基于协商的视图解析器:ContentNegotiatingViewResolver 该解析器是Spring 3.0新增的,它不负责具体的视图解析,而是作为一个中间人的角色根据请求所要求的MIME类型,从上下文中选择一个适合的视图解析器,再将视图解析工作委托其负责
  • 224. 基于协商的视图解析器 例子:http://localhost:9080/user/showUserListMix
  • 225. Spring MVC框架简介1HTTP请求地址映射2HTTP请求数据的绑定3数据转换、格式化、校验4数据模型控制5视图及解析器6
  • 226. 本地化:基础原理 一般情况下,Web应用根据客户端浏览器的设置判断客户端的本地化类型,用户可以通过IE菜单:工具→Internet选项...→语言...在打开的“语言首选项”对话框中选择本地化类型。 浏览器中设置的本地化类型会包含在HTML请求报文头中发送给Web服务器,确切地说是通过报文头的Accept-Language参数将“语言首选项”对话框中选择的语言发送到服务器,成为服务器判别客户端本地化类型的依据。TcpTrace实例...
  • 227. 静态资源处理Spring MVC 3.0提供的最强大的功能之一!!! 1.静态资源处理方式 2.静态资源映射
  • 228. 静态资源处理:使REST风格的URL成为实现 优雅REST风格的资源URL不希望带.html或.do等后缀,以下是几个优雅的URL。  /blog/tom:用户tom的blog资源。  /forum/java:java论坛板块资源。  /order/4321:订单号为4321的订单资源;
  • 229. 静态资源处理:原理Spring MVC所有 请求应用服务器默认ServletSpring MVC容器静态资源非静态资源
  • 230. 静态资源处理:如何配置第一步:web.xml让所有请求都由Spring MVC处理 springServlet org.springframework.web.servlet.DispatcherServlet 1 springServlet /
  • 231. 静态资源处理:如何配置?第二步:springServlet-servlet.xml 让Web应用服务器处理静态资源获取应用服务器的默认Servlet,大多数应用服务器的Servlet的名称都是“default”,如果默认不是“default”则使用"/>
  • 232. 物理静态资源路径映射逻辑资源路径<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 静态资源测试页面
  • 233. 允许利用浏览器的缓存且避免不同步 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 静态资源测试 ... public class ResourcePathExposer implements ServletContextAware { public void init() { String version = "1.2.1"; resourceRoot = "/resources-" + version; getServletContext().setAttribute("resourceRoot", getServletContext().getContextPath()+resourceRoot); } }
  • 234. 实例开发使用Spring MVC/Hibernate /MyBatis 实现用户数据的增、删、改、查