Spring 实战(第四版)
  • Spring 实战(第 4 版)
  • 第一部分 Spring 的核心
  • 第 1 章 Spring 之旅
    • 1.1 简化 Java 开发
      • 1.1.1 激发 POJO 的潜能
      • 1.1.2 依赖注入
      • 1.1.3 应用切面
      • 1.1.4 使用模板消除样式代码
    • 1.2 容纳你的 Bean
      • 1.2.1 使用应用上下文
      • 1.2.2 bean 的生命周期
    • 1.3 俯瞰 Spring 风景线
      • 1.3.1 Spring 模块
      • 1.3.2 Spring Portfolio
    • 1.4 Spring 的新功能
      • 1.4.1 Spring 3.1 新特性
      • 1.4.2 Spring 3.2 新特性
      • 1.4.3 Spring 4.0 新特性
    • 1.5 小结
  • 第 2 章 装配 Bean
    • 2.1 Spring 配置的可选方案
    • 2.2 自动化装配 bean
      • 2.2.1 创建可被发现的 bean
      • 2.2.2 为组件扫描的 bean 命名
      • 2.2.3 设置组件扫描的基础包
      • 2.2.4 通过为 bean 添加注解实现自动装配
      • 2.2.5 验证自动装配
    • 2.3 通过 Java 代码装配 bean
      • 2.3.1 创建配置类
      • 2.3.2 声明简单的 bean
      • 2.3.3 借助 JavaConfig 实现注入
    • 2.4 通过 XML 装配 bean
      • 2.4.1 创建 XML 配置规范
      • 2.4.2 声明一个简单的 <bean>
      • 2.4.3 借助构造器注入初始化 bean
      • 2.4.4 设置属性
    • 2.5 导入和混合配置
      • 2.5.1 在 JavaConfig 中引用 XML 配置
      • 2.5.2 在 XML 配置中引用 JavaConfig
    • 2.6 小结
  • 第 3 章 高级装配
    • 3.1 环境与 profile
      • 3.1.1 配置 profile bean
      • 3.1.2 激活 profile
    • 3.2 条件化的 bean
    • 3.3 处理自动装配的歧义性
      • 3.3.1 标示首选的 bean
      • 3.3.2 限定自动装配的 bean
    • 3.4 bean 的作用域
      • 3.4.1 使用会话和请求作用域
      • 3.4.2 在 XML 中声明作用域代理
    • 3.5 运行时值注入
      • 3.5.1 注入外部的值
      • 3.5.2 使用 Spring 表达式语言进行装配
    • 3.6 小结
  • 第 4 章 面向切面的 Spring
    • 4.1 什么是面向切面编程
      • 4.1.1 定义 AOP 术语
      • 4.1.2 Spring 对 AOP 的支持
    • 4.2 通过切点来选择连接点
      • 4.2.1 编写切点
      • 4.2.2 在切点中选择 bean
    • 4.3 使用注解创建切面
      • 4.3.1 定义切面
      • 4.3.2 创建环绕通知
      • 4.3.3 处理通知中的参数
      • 4.3.4 通过注解引入新功能
    • 4.4 在 XML 中声明切面
      • 4.4.1 声明前置和后置通知
      • 4.4.2 声明环绕通知
      • 4.4.3 为通知传递参数
      • 4.4.4 通过切面引入新的功能
    • 4.5 注入 AspectJ 切面
    • 4.6 小结
  • 第二部分 Web 中的 Spring
  • 第 5 章 构建 Spring Web 应用程序
    • 5.1 Spring MVC 起步
      • 5.1.1 跟踪 Spring MVC 的请求
      • 5.1.2 搭建 Spring MVC
      • 5.1.3 Spittr 应用简介
    • 5.2 编写基本的控制器
      • 5.2.1 测试控制器
      • 5.2.2 定义类级别的请求处理
      • 5.2.3 传递模型数据到视图中
    • 5.3 接受请求的输入
      • 5.3.1 处理查询参数
      • 5.3.2 通过路径参数接受输入
    • 5.4 处理表单
      • 5.4.1 编写处理表单的控制器
      • 5.4.2 校验表单
    • 5.5 小结
  • 第 6 章 渲染 Web 视图
    • 6.1 理解视图解析
    • 6.2 创建 JSP 视图
      • 6.2.1 配置适用于 JSP 的视图解析器
      • 6.2.2 使用 Spring 的 JSP 库
    • 6.3 使用 Apache Tiles 视图定义布局
      • 6.3.1 配置 Tiles 视图解析器
    • 6.4 使用 Thymeleaf
      • 6.4.1 配置 Thymeleaf 视图解析器
      • 6.4.2 定义 Thymeleaf 模板
    • 6.5 小结
  • 第 7 章 Spring MVC 的高级技术
    • 7.1 Spring MVC 配置的替代方案
      • 7.1.1 自定义 DispatcherServlet 配置
      • 7.1.2 添加其他的 Servlet 和 Filter
      • 7.1.3 在 web.xml 中声明 DispatcherServlet
    • 7.2 处理 multipart 形式的数据
      • 7.2.1 配置 multipart 解析器
      • 7.2.2 处理 multipart 请求
    • 7.3 处理异常
      • 7.3.1 将异常映射为 HTTP 状态码
      • 7.3.2 编写异常处理的方法
    • 7.4 为控制器添加通知
    • 7.5 跨重定向请求传递数据
      • 7.5.1 通过 URL 模板进行重定向
      • 7.5.2 使用 flash 属性
    • 7.6 小结
  • 第 8 章 使用 Spring Web Flow
    • 8.1 在 Spring 中配置 Web Flow
      • 8.1.1 装配流程执行器
      • 8.1.2 配置流程注册表
      • 8.1.3 处理流程请求
    • 8.2 流程的组件
      • 8.2.1 状态
      • 8.2.2 转移
      • 8.2.3 流程数据
    • 8.3 组合起来:披萨流程
      • 8.3.1 定义基本流程
      • 8.3.2 收集顾客信息
      • 8.3.3 构建订单
      • 8.3.4 支付
    • 8.4 保护 Web 流程
    • 8.5 小结
  • 第 9 章 保护 Web 应用
    • 9.1 Spring Security 简介
      • 9.1.1 理解 Spring Security 的模块
      • 9.1.2 过滤 Web 请求
      • 9.1.3 编写简单的安全性配置
    • 9.2 选择查询用户详细信息的服务
      • 9.2.1 使用基于内存的用户存储
      • 9.2.2 基于数据库表进行认证
      • 9.2.3 基于 LDAP 进行认证
      • 9.2.4 配置自定义的用户服务
    • 9.3 拦截请求
      • 9.3.1 使用 Spring 表达式进行安全保护
      • 9.3.2 强制通道的安全性
      • 9.3.3 防止跨站请求伪造
    • 9.4 认证用户
      • 9.4.1 添加自定义的登录页
      • 9.4.2 启用 HTTP Basic 认证
      • 9.4.3 启用 Remember-me 功能
      • 9.4.4 退出
    • 9.5 保护视图
      • 9.5.1 使用 Spring Security 的 JSP 标签库
      • 9.5.2 使用 Thymeleaf 的 Spring Security 方言
    • 9.6 小结
  • 第三部分 后端中的 Spring
  • 第 10 章 通过 Spring 和 JDBC 征服数据库
    • 10.1 Spring 的数据访问哲学
      • 10.1.1 了解 Spring 的数据访问异常体系
      • 10.1.2 数据访问模板化
    • 10.2 配置数据源
      • 10.2.1 使用 JNDI 数据源
      • 10.2.2 使用数据源连接池
      • 10.2.3 基于 JDBC 驱动的数据源
      • 10.2.4 使用嵌入式的数据源
      • 10.2.5 使用 profile 选择数据源
    • 10.3 在 Spring 中使用 JDBC
      • 10.3.1 应对失控的 JDBC 代码
      • 10.3.2 使用 JDBC 模板
    • 10.4 小结
  • 第 11 章 使用对象-关系映射持久化数据
    • 11.1 在 Spring 中集成 Hibernate
      • 11.1.1 声明 Hibernate 的 Session 工厂
      • 11.1.2 构建不依赖于 Spring 的 Hibernate 代码
    • 11.2 Spring 与 Java 持久化 API
      • 11.2.1 配置实体管理器工厂
      • 11.2.2 编写基于 JPA 的 Repository
    • 11.3 借助 Spring Data 实现自动化的 JPARepository
      • 11.3.1 定义查询方法
      • 11.3.2 声明自定义查询
      • 11.3.3 混合自定义的功能
    • 11.4 小结
  • 第 12 章 使用 NoSQL 数据库
    • 12.1 使用 MongoDB 持久化文档数据
      • 12.1.1 启用 MongoDB
      • 12.1.2 为模型添加注解,实现 MongoDB 持久化
      • 12.1.3 使用 MongoTemplate 访问 MongoDB
      • 12.1.4 编写 MongoDB Repository
    • 12.2 使用 Neo4j 操作图数据
      • 12.2.1 配置 Spring Data Neo4j
      • 12.2.2 使用注解标注图实体
      • 12.2.3 使用 Neo4jTemplate
      • 12.2.4 创建自动化的 Neo4j Repository
    • 12.3 使用 Redis 操作 key-value 数据
      • 12.3.1 连接到 Redis
      • 12.3.2 使用 Redis Template
      • 12.3.3 使用 key 和 value 的序列化器
    • 12.4 小结
  • 第 13 章 缓存数据
    • 13.1 启用对缓存的支持
      • 13.1.1 配置缓存管理器
    • 13.2 为方法添加注解以支持缓存
      • 13.2.1 填充缓存
      • 13.2.2 移除缓存条目
    • 13.3 使用 XML 声明缓存
    • 13.4 小结
  • 第 14 章 保护方法应用
    • 14.1 使用注解保护方法
      • 14.1.1 使用 @Secured 注解限制方法调用
      • 14.1.2 在 Spring Security 中使用 JSR-250 的 @RolesAllowed 注解
    • 14.2 使用表达式实现方法级别的安全性
      • 14.2.1 表述方法访问规则
      • 14.2.2 过滤方法的输入和输出
    • 14.3 小结
  • 第四部分 Spring 集成
  • 第 15 章 使用远程服务
    • 15.1 Spring 远程调用概览
    • 15.2 使用 RMI
      • 15.2.1 导出 RMI 服务
      • 15.2.2 装配 RMI 服务
    • 15.3 使用 Hessian 和 Burlap 发布远程服务
      • 15.3.1 使用 Hessian 和 Burlap 导出 bean 的功能
      • 15.3.2 访问 Hessian/Burlap 服务
    • 15.4 使用 Spring 的 HttpInvoker
      • 15.4.1 将 bean 导出为 HTTP 服务
      • 15.4.2 通过 HTTP 访问服务
    • 15.5 发布和使用 Web 服务
      • 15.5.1 创建基于 Spring 的 JAX-WS 端点
      • 15.5.2 在客户端代理 JAX-WS 服务
    • 15.6 小结
  • 第 16 章 使用 Spring MVC 创建 REST API
    • 16.1 了解 REST
      • 16.1.1 REST 的基础知识
      • 16.1.2 Spring 是如何支持 REST 的
    • 16.2 创建第一个 REST 端点
      • 16.2.1 协商资源表述
      • 16.2.2 使用 HTTP 信息转换器
    • 16.3 提供资源之外的其他内容
      • 16.3.1 发送错误信息到客户端
      • 16.3.2 在响应中设置头部信息
    • 16.4 编写 REST 客户端
      • 16.4.1 了解 RestTemplate 的操作
      • 16.4.2 GET 资源
      • 16.4.3 检索资源
      • 16.4.4 抽取响应的元数据
      • 16.4.5 PUT 资源
      • 16.4.6 DELETE 资源
      • 16.4.7 POST 资源数据
      • 16.4.8 在 POST 请求中获取响应对象
      • 16.4.9 在 POST 请求后获取资源位置
      • 16.4.10 交换资源
    • 16.5 小结
  • 第 17 章 Spring 消息
    • 17.1 异步消息简介
      • 17.1.1 发送消息
      • 17.1.2 评估异步消息的优点
    • 17.2 使用 JMS 发送消息
      • 17.2.1 在 Spring 中搭建消息代理
      • 17.2.2 使用 Spring 的 JMS 模板
      • 17.2.3 创建消息驱动的 POJO
      • 17.2.4 使用基于消息的 RPC
    • 17.3 使用 AMQP 实现消息功能
      • 17.3.1 AMQP 简介
      • 17.3.2 配置 Spring 支持 AMQP 消息
      • 17.3.3 使用 RabbitTemplate 发送消息
      • 17.3.4 接收 AMQP 消息
    • 17.4 小结
  • 第 18 章 使用 WebSocket 和 STOMP 实现消息功能
    • 18.1 使用 Spring 的低层级 WebSocket API
    • 18.2 应对不支持 WebSocket 的场景
    • 18.3 使用 STOMP 消息
      • 18.3.1 启用 STOMP 消息功能
      • 18.3.2 处理来自客户端的 STOMP 消息
      • 18.3.3 发送消息到客户端
    • 18.4 为目标用户发送消息
      • 18.4.1 在控制器中处理用户的消息
      • 18.4.2 为指定用户发送消息
    • 18.5 处理消息异常
    • 18.6 小结
  • 第 19 章 使用 Spring 发送 Email
    • 19.1 配置 Spring 发送邮件
      • 19.1.1 配置邮件发送器
      • 19.1.2 装配和使用邮件发送器
    • 19.2 构建丰富内容的 Email 消息
      • 19.2.1 添加附件
      • 19.2.2 发送富文本内容的 Email
    • 19.3 使用模板生成 Email
      • 19.3.1 使用 Velocity 构建 Email 消息
      • 19.3.2 使用 Thymeleaf 构建 Email 消息
    • 19.4 小结
  • 第 20 章 使用 JMX 管理 SpringBean
    • 20.1 将 Spring bean 导出为 MBean
      • 20.1.1 通过名称暴露方法
      • 20.1.2 使用接口定义 MBean 的操作和属性
      • 20.1.3 使用注解驱动的 MBean
      • 20.1.4 处理 MBean 冲突
    • 20.2 远程 MBean
      • 20.2.1 暴露远程 MBean
      • 20.2.2 访问远程 MBean
      • 20.2.3 代理 MBean
    • 20.3 处理通知
      • 20.3.1 监听通知
    • 20.4 小结
  • 第 21 章 借助 Spring Boot 简化 Spring 开发
    • 21.1 Spring Boot 简介
      • 21.1.1 添加 Starter 依赖
      • 21.1.2 自动配置
      • 21.1.3 Spring Boot CLI
      • 21.1.4 Actuator
    • 21.2 使用 Spring Boot 构建应用
      • 21.2.1 处理请求
      • 21.2.2 创建视图
      • 21.2.3 添加静态内容
      • 21.2.4 持久化数据
      • 21.2.5 尝试运行
    • 21.3 组合使用 Groovy 与 Spring Boot CLI
      • 21.3.1 编写 Groovy 控制器
      • 21.3.2 使用 Groovy Repository 实现数据持久化
      • 21.3.3 运行 Spring Boot CLI
    • 21.4 通过 Actuator 获取了解应用内部状况
    • 21.5 小结
Powered by GitBook
On this page

Was this helpful?

  1. 第 10 章 通过 Spring 和 JDBC 征服数据库
  2. 10.1 Spring 的数据访问哲学

10.1.1 了解 Spring 的数据访问异常体系

这里有一个关于跳伞运动员的经典笑话,这个运动员被风吹离正常路线后降落在树上并高高地挂在那里。后来,有人路过,跳伞运动员就问他自己在什么地方。过路人回答说:“你在离地大约 20 尺的空中。” 跳伞运动员说:“你一定是个软件分析师。” 过路人回应说:“你说对了。你是怎么知道的呢?” “因为你跟我说的话百分百正确,但丝毫 用处都没有。”

这个故事已经听过很多遍了,每次过路人的职业或国籍都会有所不 同。但是这个故事使我想起了 JDBC 中的 SQLException。如果你曾经编写过 JDBC 代码(不使用 Spring),你肯定会意识到如果不强制捕获 SQLException 的话,几乎无法使用 JDBC 做任何事情。SQLException 表示在尝试访问数据库的时出现了问题,但是这个异常却没有告诉你哪里出错了以及如何进行处理。

可能导致抛出 SQLException 的常见问题包括:

  • 应用程序无法连接数据库;

  • 要执行的查询存在语法错误;

  • 查询中所使用的表或列不存在;

  • 试图插入或更新的数据违反了数据库约束。

SQLException 的问题在于捕获到它的时候该如何处理。事实上,能够触发 SQLException 的问题通常是不能在 catch 代码块中解决的。大多数抛出 SQLException 的情况表明发生了致命性错误。如果应用程序不能连接到数据库,这通常意味着应用不能继续使用了。类似地,如果查询时出现了错误,那在运行时基本上也是无能为力。

如果无法从 SQLException 中恢复,那为什么我们还要强制捕获它呢?

即使对某些 SQLException 有处理方案,我们还是要捕获 SQLException 并查看其属性才能获知问题根源的更多信息。这是因为 SQLException 被视为处理数据访问所有问题的通用异常。对于所有的数据访问问题都会抛出 SQLException,而不是对每种可能的问题都会有不同的异常类型。

一些持久化框架提供了相对丰富的异常体系。例如,Hibernate 提供了二十个左右的异常,分别对应于特定的数据访问问题。这样就可以针对想处理的异常编写 catch 代码块。

即便如此,Hibernate 的异常是其本身所特有的。正如前面所言,我们想将特定的持久化机制独立于数据访问层。如果抛出了 Hibernate 所特有的异常,那我们对 Hibernate 的使用将会渗透到应用程序的其他部分。如果不这样做的话,我们就得捕获持久化平台的异常,然后将其作为平台无关的异常再次抛出。

一方面,JDBC 的异常体系过于简单了 —— 实际上,它算不上一个体系。另一方面,Hibernate 的异常体系是其本身所独有的。我们需要的数据访问异常要具有描述性而且又与特定的持久化框架无关。

Spring 所提供的平台无关的持久化异常

Spring JDBC 提供的数据访问异常体系解决了以上的两个问题。不同于 JDBC,Spring 提供了多个数据访问异常,分别描述了它们抛出时所对应的问题。表 10.1 对比了 Spring 的部分数据访问异常以及 JDBC 所提供的异常。

从表中可以看出,Spring 为读取和写入数据库的几乎所有错误都提供了异常。Spring 的数据访问异常要比表 10.1 所列的还要多。(在此没有列出所有的异常,因为我不想让 JDBC 显得太寒酸。)

JDBC 的异常

Spring 的数据访问异常

BatchUpdateException DataTruncation SQLException SQLWarning

BadSqlGrammarException CannotAcquireLockException CannotSerializeTransactionException CannotGetJdbcConnectionException CleanupFailureDataAccessException ConcurrencyFailureException DataAccessException DataAccessResourceFailureException DataIntegrityViolationException DataRetrievalFailureException DataSourceLookupApiUsageException DeadlockLoserDataAccessException

DuplicateKeyException EmptyResultDataAccessException IncorrectResultSizeDataAccessException IncorrectUpdateSemanticsDataAccessException InvalidDataAccessApiUsageException InvalidDataAccessResourceUsageException InvalidResultSetAccessException JdbcUpdateAffectedIncorrectNumberOfRowsException LbRetrievalFailureException

BatchUpdateException DataTruncation SQLException SQLWarning

NonTransientDataAccessResourceException OptimisticLockingFailureException PermissionDeniedDataAccessException PessimisticLockingFailureException QueryTimeoutException RecoverableDataAccessException SQLWarningException SqlXmlFeatureNotImplementedException TransientDataAccessException TransientDataAccessResourceException TypeMismatchDataAccessException UncategorizedDataAccessException UncategorizedSQLException

尽管 Spring 的异常体系比 JDBC 简单的 SQLException 丰富得多,但它并没有与特定的持久化方式相关联。这意味着我们可以使用 Spring 抛出一致的异常,而不用关心所选择的持久化方案。这有助于我们将所选择持久化机制与数据访问层隔离开来。

看!不用写 catch 代码块

表 10.1 中没有体现出来的一点就是这些异常都继承自 DataAccessException。DataAccessException 的特殊之处在于它是一个非检查型异常。换句话说,没有必要捕获 Spring 所抛出的数据访问异常(当然,如果你想捕获的话也是完全可以的)。

DataAccessException 只是 Sping 处理检查型异常和非检查型异常哲学的一个范例。Spring 认为触发异常的很多问题是不能在 catch 代码块中修复的。Spring 使用了非检查型异常,而不是强制开发人员编写 catch 代码块(里面经常是空的)。这把是否要捕获异常的权力留给了开发人员。

为了利用 Spring 的数据访问异常,我们必须使用 Spring 所支持的数据访问模板。让我们看一下 Spring 的模板是如何简化数据访问的。

Previous10.1 Spring 的数据访问哲学Next10.1.2 数据访问模板化

Last updated 5 years ago

Was this helpful?