日分享开始啦,请大家多多指教~
本篇总结 SSM 三大框架相关面试题~
当客户端第一次请求服务器时(请求登录),服务器创建 Session ,然后将登录用户身份信息保存到 Session 中,并将用户身份信息作为 “门卡”,响应回客户端,客户端将服务器响应的 “门卡” 信息保存在本地 Cookie 中。
当下一次客户端再次请求服务器时,这时候就直接将客户端的 Cookie 中存放的 “门卡” 带到服务器端,服务器端从 Session 中拿出数据和 “门卡” 进行对比,判断是否可以同行。
服务端保存大量用户身份标识,增加服务端压力。
客户端请求依赖服务端,多次请求必须访问同一台服务器(如果是集群,相当于启动了多个 Tomcat,这时候无法在多个 Tomcat 直接共享 Session 数据)。
服务器不保存任何客户端用户的登录信息!
客户端的每次请求服务器必须自己具备身份信息标识(jwt),服务器端通过身份信息标识识别客户端身份。
客户端请求不依赖服务端的信息,任何多次请求不需要必须访问到同一台服务器。
减小服务端存储压力。
如何实现无状态登录?
如图所示:
过滤器和拦截器均体现了AOP的编程思想,都可以实现诸如日志记录、登录鉴权等功能,但二者的不同点也是比较多的。
1、实现原理不同
过滤器和拦截器 底层实现方式大不相同,过滤器是基于函数回调的,拦截器则是基于Java的反射机制(动态代理)实现的。
2、使用范围不同
我们看到过滤器实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。
而拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于Application、Swing等程序中。
3、触发时机不同
过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。
拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。
4、拦截的请求范围不同
5、注入Bean情况不同
在实际的业务场景中,应用到过滤器或拦截器,为处理业务逻辑难免会引入一些service服务。
6、控制执行顺序不同
实际开发过程中,会出现多个过滤器或拦截器同时存在的情况,不过,有时我们希望某个过滤器或拦截器能优先执行,就涉及到它们的执行顺序。
① 前端控制器(DispatcherServlet):主要用于接收客户端发送的 HTTP 请求、响应结果给客户端。
② 处理器映射器(HandlerMapping):根据请求的 URL 来定位到对应的处理器(Handler)。
③ 处理器适配器(HandlerAdapter):在编写处理器(Handler)的时候要按照处理器适配器(HandlerAdapter) 要求的规则去编写,通过适配器可以正确地去执行 Handler。
④ 处理器(Handler):就是我们经常写的 Controller 层代码,例如:UserController。
⑤ 视图解析器(ViewResolver):进行视图的解析,将 ModelAndView 对象解析成真正的视图(View)对象返回给前端控制器。
⑥ 视图(View):View 是一个接口, 它的实现类支持不同的视图类型(JSP,FreeMarker,Thymleaf 等)。
① 首先,用户发送 HTTP 请求给 SpringMVC 前端控制器 DispatcherServlet。
② DispatcherServlet 收到请求后,调用HandlerMapping 处理器映射器,根据请求 URL 去定位到具体的处理器 Handler,并将该处理器对象返回给 DispatcherServlet 。
③ 接下来,DispatcherServlet 调用 HandlerAdapter 处理器适配器,通过处理器适配器调用对应的 Handler 处理器处理请求,并向前端控制器返回一个 ModelAndView 对象。
④ 然后,DispatcherServlet 将 ModelAndView 对象交给 ViewResoler 视图解析器去处理,并返回指定的视图 View 给前端控制器。
⑤ DispatcherServlet 对 View 进行渲染(即将模型数据填充至视图中)。View 是一个接口, 它的实现类支持不同的视图类型(JSP,FreeMarker,Thymleaf 等)。
⑥ DispatcherServlet 将页面响应给用户。
一级缓存:作用域是 SqlSession,同一个 SqlSession 中执行相同的 SQL 查询(相同的SQL和参数),第一次会去查询数据库并写在缓存中,第二次会直接从缓存中取。
二级缓存:作用域是 NameSpace 级别,多个 SqlSession 去操作同一个 NameSpace 下的 Mapper 文件的 sql 语句,多个 SqlSession可以共用二级缓存,如果两个 Mapper 的 NameSpace 相同,(即使是两个 Mapper,那么这两个 Mapper 中执行 sql 查询到的数据也将存在相同的二级缓存区域中)。
注意:实现二级缓存的时候,MyBatis 建议返回的 POJO 是可序列化的, 也就是建议实现 Serializable 接口。
如图所示:
当 Mybatis 调用 Dao 层查询数据库时,先查询二级缓存,二级缓存中无对应数据,再去查询一级缓存,一级缓存中也没有,最后去数据库查找。
ORM 是什么?
ORM(Object Relational Mapping),对象关系映射,是一种为了解决关系型数据库数据与简单 Java 对象(POJO)建立映射关系的技术。
为什么说 Mybatis 是半自动ORM映射工具?它与全自动的区别在哪里?
具体流程:
① 加载配置文件:需要加载的配置文件包括全局配置文件(mybatis-config.xml)和 SQL(Mapper.xml) 映射文件,其中全局配置文件配置了Mybatis 的运行环境信息(数据源、事务等),SQL映射文件中配置了与 SQL 执行相关的信息。
② 创建会话工厂:MyBatis通过读取配置文件的信息来构造出会话工厂(SqlSessionFactory),即通过SqlSessionFactoryBuilder 构建 SqlSessionFactory。
③ 创建会话:拥有了会话工厂,MyBatis就可以通过它来创建会话对象(SqlSession)。会话对象是一个接口,该接口中包含了对数据库操作的增删改查方法。
④ 创建执行器:因为会话对象本身不能直接操作数据库,所以它使用了一个叫做数据库执行器(Executor)的接口来帮它执行操作。
⑤ 封装SQL对象:执行器(Executor)将待处理的SQL信息封装到一个对象中(MappedStatement),该对象包括SQL语句、输入参数映射信息(Java简单类型、HashMap或POJO)和输出结果映射信息(Java简单类型、HashMap 或 POJO)。
⑥ 操作数据库:拥有了执行器和SQL信息封装对象就使用它们访问数据库了,最后再返回操作结果,结束流程。
所谓三级缓存,其实就是org.springframework.beans.factory包下DefaultSingletonBeanRegistry类中的三个成员属性:
Key:beanName
Value: Bean实例
private final Map<String, Object> singletonObjects=new ConcurrentHashMap<>(256);
Key:beanName
Value: Bean实例
和一级缓存一样也是保存BeanName和创建bean实例之间的关系,与singletonObjects不同之处在于,当一个单例bean被放在里面后,那么bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来循环检测引用!
private final Map<String, Object> earlySingletonObjects=new ConcurrentHashMap<>(16);
Key:beanName
Value: Bean的工厂
private final Map<String, ObjectFactory<?>> singletonFactories=new HashMap<>(16);
如图所示,除了三级缓存是一个HashMap,其他两个都是ConcurrentHashMap:
Spring之所以引入三级缓存,目的就是为了解决循环依赖问题!
除了上面三个Map集合,还有另一个集合这里也说一下:
用来保存当前所有已注册的Bean
private final Set<String> registeredSingletons=new LinkedHashSet<>(256);
首先,Spring 解决循环依赖有两个前提条件:
本质上解决循环依赖的问题就是依靠三级缓存,通过三级缓存提前拿到未初始化的对象。下面我们来看一个循环依赖的例子:
A 对象的创建过程:
1.创建对象A,实例化的时候把A对象工厂放入三级缓存
2.A 注入属性时,发现依赖 B,转而去实例化 B
3.同样创建对象 B,注入属性时发现依赖 A,一次从一级到三级缓存查询 A,从三级缓存通过对象工厂拿到 A,把 A 放入二级缓存,同时删除三级缓存中的 A,此时,B 已经实例化并且初始化完成,把 B 放入一级缓存。
4.接着继续创建 A,顺利从一级缓存拿到实例化且初始化完成的 B 对象,A 对象创建也完成,删除二级缓存中的 A,同时把 A 放入一级缓存。
5.最后,一级缓存中保存着实例化、初始化都完成的A、B 对象。
从上面5步骤的分析可以看出,三级缓存解决循环依赖是通过把实例化和初始化的流程分开了,所以如果都是用构造器的话,就没法分离这个操作(因为构造器注入实例化和初始是一起进行的)。因此构造器方式注入的话是无法解决循环依赖问题的。
解决循环依赖为什么必须要要三级缓存?二级不行吗?
答案:不可以!
使用三级缓存而非二级缓存并不是因为只有三级缓存才能解决循环引用问题,其实二级缓存同样也能很好解决循环引用问题。
使用三级而非二级缓存并非出于IOC的考虑,而是出于AOP的考虑,即若使用二级缓存,在AOP情形下,往二级缓存中放一个普通的Bean对象,BeanPostProcessor去生成代理对象之后,覆盖掉二级缓存中的普通Bean对象,那么多线程环境下可能取到的对象就不一致了。
单例模式:Spring 中的 Bean 默认情况下都是单例的。无需多说。
工厂模式:工厂模式主要是通过 BeanFactory 和 ApplicationContext 来生产 Bean 对象。
代理模式:最常见的 AOP 的实现方式就是通过代理来实现,Spring主要是使用 JDK 动态代理和 CGLIB 代理。
…
单例模式
单例模式使?场景:
单例模式分类:
单例模式实现步骤:
工厂模式
??模式介绍:它提供了?种创建对象的最佳?式,在创建对象时 不会对客户端暴露创建逻辑,并且是通过使??个共同的接?来指向新创建的对象。
??模式有 3 种不同的实现?式:
① 简单??模式(静态工厂):通过传?相关的类型来返回相应的类,这 种?式?较单 ?,可扩展性相对较差。
② ???法模式:通过实现类实现相应的?法来决定相应的返回结果,这种?式的可扩展性?较强。
③ 抽象??模式:基于上述两种模式的拓展,且?持细化产品。
应?场景:
解耦:分离职责,把复杂对象的创建和使?的过程分开。
复?代码 降低维护成本:如果对象创建复杂且多处需?到,如果每处都进?编写,则很多重复代码,如果业务逻辑发?了改 变,需?四处修改;使???模式统?创建,则只要修改??类即可, 降低成本。
代理模式
代理模式最直观的解释就是,通过代理,将被代理对象 “增强”!(即,扩展被代理对象的功能)
代理模式分为静态代理,和动态代理:动态代理的代理类是动态生成的 , 静态代理的代理类是我们提前写好的逻辑。
Java 中实现动态代理的方式有 2 种:
今日份分享已结束,请大家多多包涵和指点!
下流行的两种企业开发MVC开源框架,是我们Java程序猿必备知识能力。MVC,即模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。框架之所以流行,在于其易复用和简化开发,精髓在思想,掌握了核心思想,我们掌握其他类似框架也不会有问题,建议大家有精力的话读一下框架源码,尤其是Spring。
SSH和SSM定义
SSH 通常指的是 Struts2 做控制器(controller),spring 管理各层的组件,hibernate 负责持久化层。
SSM 则指的是 SpringMVC 做控制器(controller),Spring 管理各层的组件,MyBatis 负责持久化层。
共同点:1.Spring依赖注入DI来管理各层的组件。2.使用面向切面编程AOP管理事物、日志、权限等。
不同点:1.Struts2 和 SpringMVC 控制器(controller)控制视图和模型的交互机制的不同,
Struts2是Action类级别,SpringMVC是方法级别,更容易实现RESTful风格。
SSH 和 SSM 的实现原理
1.Struts2 的实现原理
Struts2框架执行步骤(Struts2使用Filter嵌入):
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6、ActionProxy创建一个ActionInvocation的实例。
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。
9、将处理结果返回给客户端
2.SpringMVC 的实现原理
SpringMVC框架执行步骤(SpringMVC使用Servlet嵌入):
1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.
2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。
3-4、DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。
5、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。
6、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。
7、Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端。
Hibernate 和 MyBatis 两种ORM框架对比
两者的相同点
Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。
Hibernate和MyBatis都支持JDBC和JTA事务处理。
两者各自优势
MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
MyBatis容易掌握,而Hibernate门槛较高。
Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳,更新操作不能指定刷新指定记录,会清空整个表,但是也可以使用第三方缓存。
Hibernate 封装性好,屏蔽了数据库差异,自动生成SQL语句,应对数据库变化能力较弱,SQL语句优化困难。
MyBatis仅实现了SQL语句和对象的映射,需要针对具体的数据库写SQL语句,应对数据库变化能力较强,SQL语句优化较为方便。
总结
SSM和SSH不同主要在MVC实现方式,以及ORM持久化方面不同(Hiibernate与Mybatis)。SSM越来越轻量级配置,将注解开发发挥到极致,且ORM实现更加灵活,SQL优化更简便;而SSH较注重配置开发,其中的Hiibernate对JDBC的完整封装更面向对象,对增删改查的数据维护更自动化,但SQL优化方面较弱,且入门门槛稍高。
附Spring家族:
熟悉当下流行的两种企业开发MVC开源框架,是Java程序猿必备知识。MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写。M是指业务模型,V是指用户界面,C则是控制器。一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。小编在学校的时候学习过SSH,SSM则是去公司后用的。
SSH 通常指的是 Struts2 做前端控制器,Spring 管理各层的组件,Hibernate 负责持久化层。
SSM 则指的是 SpringMVC 做前端控制器,Spring 管理各层的组件,MyBatis 负责持久化层。
1.Struts2 的原理
Struts2框架执行过程:
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action,FilterDispatcher是控制器的核心,就是mvc中c控制层的核心
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6、ActionProxy创建一个ActionInvocation的实例
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版
9、将处理结果返回给客户端
2.SpringMVC 的原理
SpringMVC框架执行过程:
1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet
2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)
3、DispatcherServlet根据HandlerMapping找到对应的Handler,并返回
4、将处理权交给Handler(Handler将具体的处理进行封装),再由具体的处理器适配器(HandlerAdapter)对Handler进行具体的调用
5、处理器适配器执行Handler
6、Handler对数据处理完成以后将返回一个ModelAndView对象给处理器适配器
7、处理器适配器向前端控制器返回ModelAndView
ModelAndView是springmvc框架的一个底层对象,包括Model和View
8、Handler返回的ModelAndView只是一个逻辑视图并不是一个正式的视图,前端控制器请求视图解析器(ViewResolver)去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
9、视图解析器向前端控制器返回View
10、前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域
11、前端控制器向用户响应结果
3.Hibernate 的原理
Hibernate框架执行过程:
1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的读取并解析映射信息
3.通过config.buildSessionFactory();//创建SessionFactory
4.sessionFactory.openSession();//打开Sesssion
5.session.beginTransaction();//创建事务Transation
6.persistent operate持久化操作
7.session.getTransaction().commit();//提交事务
8.关闭Session
9.关闭SesstionFactory
4、MyBatis原理
MyBatis框架执行过程:
1、配置MyBatis的配置文件,SqlMapConfig.xml(名称不固定)
2、通过配置文件,加载MyBatis运行环境,创建SqlSessionFactory会话工厂SqlSessionFactory 在实际使用时按单例方式
3、通过SqlSessionFactory创建SqlSession,SqlSession 是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议sqlSession应用场合在方法体内
4、调用 sqlSession 的方法去操作数据。如果需要提交事务,需要执行 SqlSession 的 commit() 方法
5、释放资源,关闭SqlSession
Struts2和SpringMVC两种框架对比
1.springmvc和struts2都是负责取转发的,但是两者针对request的请求上面区别很大。springmvc是针对于方法级别的请求的,也就是一个方法对应于一个请求,属于方法拦截,请求的数据方法不共享;而struts2则是针对一个Action类来进行请求的,即一个Action类对应于一个请求,所以类拦截,请求的数据类共享
2.springmvc入口是一个servlet前端控制器(DispatcherServlet),struts2入口是一filter过滤器
3.springmvc的配置文件相对struts2来说较为少,容易上手,可以加快软件开发的速度
Hibernate 和 MyBatis 两种框架对比
相同之处
1.Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的
2.Hibernate和MyBatis都支持JDBC和JTA事务处理
不同之处
1.Hibernate是一种O/R关系型,即完成数据库表和持久化类之间的映射,而MyBitas是针对的SQL-Maping,个人理解是一种Hibernate把数据库给封装好以后,可以调用相应的数据库操作语句HQL,而MyBitas则是用的原始的数据库操作语句
2.针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程
3.Hibernate优化起来相对MyBitas较难,而且Hibernate掌握起来相对MyBitas较难,但是Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL
Spring家族:
SSM和SSH相同之处在于都是用Spring依赖注入DI来管理各层的组件,并且都是使用面向切面编程AOP来管理事物、日志、权限等。不同之处在于MVC实现方式,以及ORM持久化方面不同(Hiibernate与Mybatis)。SSM越来越轻量级配置,将注解开发发挥到极致,且ORM实现更加灵活,SQL优化更简便;而SSH较注重配置开发,其中的Hiibernate对JDBC的完整封装更面向对象,对增删改查的数据维护更自动化,但SQL优化方面较弱,且入门门槛稍高。
如果觉得不错有帮助的,可以转发点赞关注一下。谢谢!
*请认真填写需求信息,我们会在24小时内与您取得联系。