SpringMVC总结
Spring MVC
Spring MVC 的理解
谈到这个问题,提到之前 Model1 和 Model2 这两个没有 Spring MVC 的时代。
Model1 时代: 学 Java 后端比较晚的人可能并没有接触过 Model1 模式下的 JavaWeb 应用开发。在 Model1 模式下,整个 Web 应用几乎全部用 JSP 页面组成,只用少量的 JavaBean 来处理数据库连接、访问等操作。这个模式下 JSP 即是控制层又是表现层。显而易见,这种模式存在很多问题。
(1)将控制逻辑和表现逻辑混杂在一起,导致代码重用率极低;
(2)前端和后端相互依赖,难以进行测试并且开发效率极低。
Model2 时代:学过 Servlet 并做过相关 Demo 的朋友应该了解”Java Bean(Model) + JSP(View) + Servlet(Controller)”这种开发模式。这就是早期的 JavaWeb MVC 开发模式。
Model: 系统涉及的数据,也就是 dao 和 bean。
View:展示模型中的数据,只是用来展示。
Controller:处理用户请求都发送给 ,返回数据给 JSP 并展示给用户。
Model2 模式下还存在很多问题,Model2的抽象和封装程度还远远不够,使用 Model2 进行开发时不可避免地会重复造轮子,这就大大降低了程序的可维护性和复用性。于是很多 JavaWeb 开发相关的 MVC 框架应运而生,比如Struts2,但是 Struts2 比较笨重。随着 Spring 轻量级开发框架的流行,Spring 生态圈出现了 Spring MVC 框架,Spring MVC 是当前最优秀的 MVC 框架。相比于 Struts2,Spring MVC 使用更加简单和方便,开发效率更高,并且 Spring MVC 运行速度更快。
MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的 Web 层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)。
Spring MVC 的工作原理
流程说明:
(1)客户端(浏览器)发送请求,直接请求到 DispatcherServlet。
(2)DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。
(3)解析到对应的 Handler(Controller)后,开始由 HandlerAdapter 适配器处理。
(4)HandlerAdapter 会根据 Handler 来调用处理器处理请求,并处理相应的业务逻辑。
(5)处理器处理完业务后,会返回一个 ModelAndView 对象,Model 是返回的数据对象,View 是个逻辑上的 View。
(6)ViewResolver 会根据逻辑 View 查找实际的 View。
(7)DispaterServlet 把返回的 Model 传给 View(视图渲染)。
(8)把 View 返回给请求者(浏览器)。
Spring 框架中用到的设计模式
工厂模式: Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
单例模式: Spring 中的 Bean 默认都是单例的。
代理模式: Spring AOP 功能的实现。
模板方法模式: Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
适配器模式: Spring AOP 的增强或通知(Advice)使用到了适配器模式、Spring MVC 中也用到了适配器模式适配Controller。
装饰模式: 我们的项目需要连接多个数据库 DataSource,而且不同的客户在每次访问中根据需要访问不同的数据库。这种模式让我们可以根据客户的需求动态切换不同的数据源。
Spring 事务
Spring 管理事务的方式
声明式事务,在配置文件中配置(推荐使用)
编程式事务,在代码中硬编码。(不推荐使用)
声明式事务又分为两种:基于XML的声明式事务、基于注解的声明式事务
Spring 事务的隔离级别
TransactionDefinition 接口中定义了五个常量(表示隔离级别):
TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别。Mysql 默认采用的 REPEATABLE_READ 隔离级别,Oracle 默认采用的 READ_COMMITTED 隔离级别。
TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别。允许读取未提交的数据,可能会导致脏读、不可重复读、幻读。
TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取已经提交的数据,可以防止脏读,可能会导致不可重复读、幻读。
TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以防止脏读、不可重复读,但可能会导致幻读。
TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,可以防止脏读、不可重复读、幻读。但是这将严重影响程序的性能。通常也不会用到该级别。
Spring 事务的传播行为
支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
不支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
其他情况:
TransactionDefinition.PROPAGATION_NESTED:
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;
如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
JPA
JPA是Java Persistence API的简称,中文名Java持久层API。
让secrect 这个字段不被持久化,以采用下面几种方法:
static String transient1; // not persistent because of static
final String transient2 = “Satish”; // not persistent because of final
transient String transient3; // not persistent because of transient
@Transient
String transient4; // not persistent because of @Transient
一般使用后面两种方式比较多。