mvc框架
是为了解决传统mvc模式问题而出现的问题
- 所有的servlet和servlet映射都要配置web.xml中,如果项目太大,web.xml文件就太大,并且不能实现模块化管理
- servlet主要的功能就是接收参数,调用逻辑,跳转界面,比如像其他字符编码,文件上传等功能也要写在servlet中,不能让servlet功能单一,
- 接收参数比较麻烦,不能通过model接收,只能单个接收,接收完成后转换封装成model
- 跳转页面方式比较单一(forward,redirect)并且当我的页面名称方法发生改变时需要修改servlet源代码
综上,现在比较常用的mvc框架有:struts2,springMVC
简单讲一下struts2 的流程
- 客户端发送请求
- 这个请求经过一系列的过滤器(filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对与struts2和其他框架的集成很有帮助,例如sitemesh plugin)
- 接着strutsPrepareandExecuteFilter被调用,strutsPrepareAndExecuteFilter询问ActionMapper,来决定这个请求是否需要调用某个Action
- 如果 ActionMapper决定需要调用某个Action,StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy;
- ActionProxy 通过configurationManager 询问框架的配置文件,找到需要调用的Action类
- ActionProxy创建一个ActionInvocation的实例
- ActionInvocation实例使用命名模式调用,在调用Action的过程前后,涉及到相关拦截器Interceptor的调用
- 一旦Action执行完毕,ActionINvocation负责处理struts.xml中的配置找到对应的返回结果,返回结果通常是一个需要贝表示的jsp或者freeMarker的模版,在表示的过程中可以使用struts2框架中继承的标签,在这个过程中需要设计ActionMapper
综上总结:
- 浏览器发送请求,经过一系列的过滤器后,到达核心过滤器strutsPrepareAndExecuteFilter
- 核心过滤器strutsPrepareAndExecuteFilter通过ActionMapper判断当前的请求是否需要某个action处理,如果不需要,则放过,走原来的流程,如果需要,则第三步
- 核心过滤器就会strutsPrepareAndExecuteFilter把这个请求交给ActionProxy来处理,ActionProxy通过configurationManager和struts配置文件来找到Action类
- ActionProxy创建一个ActionInvocation实例,来调用Action的对应方法,来获取结果集的name,在调动前后会执行相关拦截器
- 通过结果集的name,知道对应的结果集来对浏览器进行相应。
拦截—判断—寻找—执行—响应
struts2中的拦截器
java里的烂机器是动态拦截Action调用的对象,他提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码
也可以在一个action执行前阻止其执行,同时提供了一种可以提取action中可重用部分的方式
在AOP中拦截器用于某个方法或字段被访问之前,进行拦截后在之前或之后加入一些操作
总结,通过动态配置方式,可以在执行Action的方法前后,struts2中的功能(参数处理,文件上传,字符编码)都是通过系统拦截器实现的,我们可以自定义拦截器加入相关逻辑完成业务
使用场景:
- 用户登录判断,在执行Action的前面判断是否已经登录,如果没有登录,则跳转到登录页面。
- 用户权限判断,在执行Action的前面判断是否具有权限,如果没有权限给出提示信息
- 操作日志,。。。
SpringMVC的流程分析
- 用户想服务器发送请求,请求被前端控制器Servvlet disPatcherServlet 捕获
- DispatcherServlet对请求url进行解析,得到请求资源标识符uri,然后 根据URI,调用handllerMapping胡哦哦的改Handler配置的所有相关的对象,包括Handler对象以及Handler对应的拦截器,最后一HandlerExecutionChain对象的形式返回:
DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter,提取request中的数据模型,填充Handler入参,开始执行Handler,Handler执行完成后,想DispatcherServlet返回一个ModelAndView对象 - DispatcherServlet根据返回的ModelAndView对象,返回一个合适的ViewResolver,必须是已经注册到Spring容器总的ViewResolver
- 通过哦ViewResolver结合Model和 View,来渲染视图,DispatcherServlet将渲染结果返回客户端
综上: 核心控制器捕获请求—查找Handler—执行Handler—选择合适ViewResolver—通过ViewResolver渲染视图并返回
说一下Struts2和SpringMVC有什么不同
- 核心控制器不同 struts2 的控制器是filter,springmvc的控制器是servlet
- SpringMvc是基于方法设计,struts2是基于对象,每次发送一次请求就都会实例一个action
- SpringMVC对于Spring的集成更好
- 参数传递,struts2中提供多种参数接收,其实就是通过值栈(valueStack)进行传递和赋值,而springMVC是通过方法的参数进行接收
- Struts2更加很多新的知识点,比如拦截器,值栈以及OGNL表达式,学习成本较高,SpringMVC学习相对简单
- 拦截器interceptor的实现机器,struts中有自己的拦截器机制,SpringMVC用的是独立的AOP方式
- SpringMVC处理ajax请求直接返回数据,方法中使用注解@ResponseBody,SpringMVC自动帮我们把对象转换为JSON数据,而struts是通过插件的方式进行处理
综上,springmvc比struts2相对来说比较流行。
Spring介绍
Spring是轻量级的IOC和AOP的容器框架,主要针对JavaBean的声明周期进行管理的轻量级容器,可以单独使用,也可以集成struts2和mybatis等框架
IOC:控制反转,对象的创建交给Spring容器进行管理,控制权从类中反转给了Spring容器, 核心原理:工厂模式+反射+配置文件
AOP:面向切面编程。
核心原理:使用动态代理的设计模式在执行方法前后或者出现异常前后做相关逻辑操作,
我们主要使用AOP来做
1.事务处理
2.权限判断
3.日志记录
AOP的使用场景
核心原理:使用动态代理的设计模式在方法执行前后或者出现异常前后做相关逻辑操作,
1.事务处理,执行方法前开启事务,执行完毕后,关闭事务,出现异常后回滚事务
2.权限判断,在执行方法前,判断是否具有权限
3.日志记录,在执行前进行日志处理。
Spring的事务传播特性
多个事务存在时的处理策略
1-3 存在一个事务
4-6 不管事务存不存在,总是。。。。。
- propagation_required:如果存在一个事务,则支持当前事务,如果没有事务则开启一个新事务(需要)
- propagation_supports:如果存在一个事务,支持当前事务,如果没有事务,则以非事务的方式执行(支持)
- propagation_mandatory: 如果已经存在一个事务,支持当前事务,如果没有一个活动的事务,则抛出异常(必要的)
- propagation_requires_new:总是开启一个新的事务,如果一个事务已经存在,则将存在的事务挂起(总是开启一个新的)
- propagation_not_supported:总是非事务的方式执行,并挂起任何存在的事务(总是非事务)
- propagation_never :总是非事务的凡是执行,如果存在一个事务,则抛出异常(绝不)
- propagation_nested: 如果一个活动的事务存在,则运行在一个嵌套的事务中,如果没有活动事务,则按TransactionDefinition.Propagation_Required属性执行(嵌套的,有就嵌套,没有就开启事务)
spring事务:
什么是事务:
事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败.
事务特性(4种):
原子性 (atomicity):强调事务的不可分割.
一致性 (consistency):事务的执行的前后数据的完整性保持一致.
隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
持久性(durability) :事务一旦结束,数据就持久到数据库
如果不考虑隔离性引发安全性问题:
脏读 :一个事务读到了另一个事务的未提交的数据
不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致.
虚幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致.
解决读问题: 设置事务隔离级别(5种)
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生
已提交读 (read commited):避免脏读。但是不可重复读和虚读有可能发生
可重复读 (repeatable read) :避免脏读和不可重复读.但是虚读有可能发生.
串行化的 (serializable) :避免以上所有读问题.
Mysql 默认:可重复读
Oracle 默认:读已提交
read uncommited:是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
read commited:保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。
repeatable read:这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。
serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读(避免三种)。
事务的传播行为
PROPAGION_XXX :事务的传播行为
- 保证同一个事务中
PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常 - 保证没有在同一个事务中
PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
参考地址:https://blog.csdn.net/weixin_38070406/article/details/78157603
hibernate映射对象的状态
- 临时状态(transient):刚刚使用new语句创建,没有被持久化,无id,不处于session中(没有使用session的方法去操作临时对象,和session没有关系)
- 持久化状态(persistent):已经被持久化,加入到session的缓存中,session是没有关闭该状态的对象为持久化对象
- 游离状态(detached):已经被持久化,但是不处于session中,改状态的对象为游离对象
- 删除状态(removed):对象有关联的ID,并且在session的管理下,但是已经被计划删除(事务提交的时候commit),如果没有事务,就不能删除。
相互转换:
hibernate的缓存
为了降低应用程序对物理数据库源访问的频次,从而提高应用程序的运行性能。
缓存内的数据是对物理数据源中数据的复制,应用程序在运行时从缓存中读写数据,在特定的时刻或时间会同步缓存和物理数据源的数据
综上:为了提供访问速度,把磁盘或数据库访问变成内存访问。
hibernate的缓存分为一级缓存和二级缓存
- 一级缓存(Session缓存):session缓存内置不能被卸载,Session的缓存是事务范围的缓存,(Session对象的生命周期常常对应一个数据库事务或者一个应用事务),一级缓存中,持久化类的每个实例都具有唯一的OID
- 二级缓存(SessionFactory缓存):由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,从应用启动到应用结束有效,有可能出现并发问题。因此需要采用是当的并发访问策略,该策略为被缓存的数据提供了数据隔离级别。
二级缓存是可选的,是一个可配置的插件,默认下SessionFactory不会启用这个插件,Hibernate提供了org.hibernate.cache.CachePorvider接口,它充当缓存插件与Hibernate之间的适配器。
保存数据库后,在内存中保存一份,如果更新了数据库,就要同步更细缓存
放在二级缓存中数据应具备什么条件 - 很少被修改的数据(修改数据库,就要修改缓存很麻烦) 例如:最后回复时间等变量信息
- 经常被查询的数据(查询速度快)例如:电商的地点等常量信息。
- 不是很重复的数据,允许出现偶尔并发的数据
- 不会被并发访问的数据
- 常量数据
扩展: hibernate的二级缓存默认是不支持分布式缓存的
解决方法:使用memcache,redis等中央缓存来代替二级缓存
简单介绍下WebService使用场景
webService是一个SOA(面向服务编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用。通过Internet进行http协议的网络应用间的交互
- 异构系统(不同语言)的整合
- 不同客户端的整合,浏览器,手机端,微信端,pc端等终端访问
实例:
天气预报,通过实现webService客户端调用远程天气服务
单点登录:一个服务是所有系统的登录