Spring
Spring是一个开源框架,是于2003 年兴起的一个轻量级的Java 开发框架,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。
Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地`new`一个对象,而是让Spring框架帮你来完成这一切。
IOC:Invert of control,控制反转,也称为DI(依赖注入)。依赖对象的创建和维护交给了spring容器来管理,应用程序本身不需要负责依赖对象的创建和维护,简单理解就是把原本应该我们去new对象这个操作转到spring容器中执行
AOP:面向切面编程,本质就是拦截器,比如项目中的事务和日志就是很好的体现了AOP。比如:操作数据库的增删改之前,都需要开启事务,增删改之后,都需要提交事务,这样我们就可以写一个拦截器,底层就是采用动态代理实现前置通知和后置通知,在前置通知中开启事务,在后置通知中提交事务,在spring.xml中配置通知即可,spring的事务管理底层就用到了AOP
(1)Spring是什么及Spring的优点
①. Spring是一个轻量级的IOC和AOP容器框架
②. Spring是非侵入式的,基于Spring开发的应用一般不依赖于Spring的类(非侵入式:自己的东西可以直接用,不需要依赖别人的东西 )
③. Spring是个容器,因为它包含并且管理应用对象的生命周期和配置,比如对象的创建、销毁、回调等
④. Spring提供对事务的管理
⑤. Spring对主流的框架提供了很好的集成支持,比如和hibernate SpringMVC等框架的集成
(2)Spring的注入方式有哪些?
①. setter注入:对于习惯了传统的JavaBean开发的程序员来说,通过setter方法注入属性值是熟悉的、直观的和自然的。如果依赖关系比较复杂,那么构造方法注入方式会导致构造方法相当庞大,此时使用设值方式更为简洁
②. 构造注入:构造方法注入很好的响应了Java设计原则之一,在构造期间即可创建一个完整、合法的对象;避免了繁琐的setter方法的编写,所有的依赖关系均在构造方法中设定,依赖关系集中体现;
③. 接口注入:接口注入因具备侵入性,它要求组件必须与特定的接口相关联,因此这种注入方式基本上已经被遗弃了。
(3)如何定义bean的作用域,作用域之间的区别
定义bean的作用域,在<bean>中与一个scope的属性,取值有5中
①. singleton:单例模式(默认),也就是说这种范围不管接收到多少个请求,每个容器中之后一个bean的实例。
②. prototype:原型模式,和单例模式相反,为每一个bean请求提供一个实例。
③. request:针对每一次HTTP请求都会产生一个新的bean,并且该bean仅在当前request内有效,请求完成以后,bean会失效并被垃圾回收器回收
④. session:针对每一次HTTP请求都会产生一个新的bean,并且该bean仅在当前session内有效,session过期后,bean也会随之失效
⑤. Global session:global session和portlet应用相关,当你的应用部署在Portlet容器中工作时,如果你想让所有的portlet共用全局存储变量的话,就需要存储到global session中
(4) 什么是spring的自动装配?并解释一下自动装配的各种模式
Spring的自动装配:无须在Spring配置文件中描述javabean之间的依赖关系,IOC容器会自动建立JavaBean之间的关联关系。
①. 根据属性名称自动装配autowire=”byName”
②. 根据数据类型自动装配autowire=”byType”
③. 根据构造方法自动装配autowire=”constructor”
(5) 如何在spring中注入null或者空字符串
注入null值:<property name=”email”><null/></property>
注入空字符串:<property name=”email” value=””></property>
(6)spring的事务管理
首先搞清楚事务是干什么的,比如ATM取钱100,有两个步骤,账户余额扣掉100,ATM机出来100。这两给步骤要么都执行要么都不执行,如果有一个步骤失败了,整个取钱的过程都能会回滚,也就是完全取消所有操作,事务就是用来解决类似的问题。
事务最重要的两个特性是事务的传播级别和数据隔离级别
传播级别:定义的是事务的控制范围,常用的就是PROPAGATION_REQUIRED
事务的隔离级别:定义的是事务在数据库读写方面的控制范围
事务的配置有两种方式:注解式事务和声明式事务
(7)Spring如何配置数据库驱动
①. 可以使用c3p0数据库连接池技术
②. 使用DriverManagerDataSource数据源来配置数据库驱动
SpringMVC
(1)SpringMVC的工作流程
①. SpringMVC将所有的请求都提交给DispatcherServlet
②. DispatcherServlet收到请求调用HandlerMapping处理映射器
③. 处理映射器找到具体的处理器,生成处理器对象返回给DispatcherServlet
④. DispatcherServlet调用HandlerAdapter处理器适配器
⑤. HandlerAdapter经过适配调用具体的处理器Controller
⑥. Controller进行业务逻辑处理后,会返回一个ModelAndView
⑦. HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
⑧. DispatcherServlet将ModelAndView传给ViewResolver视图解析器
⑨. ViewResolver解析后返回具体的View
⑩. DispatcherServlet根据View进行渲染视图并响应用户
(2)springmvc怎么防止SQL注入
使用SpringMVC的拦截器实现防止SQL注入
MyBatis
(1)mybatis的缓存机制
MyBatis提供了查询缓存来缓存数据,以提高查询的性能,MyBatis的缓存分为一级缓存和二级缓存。
一级缓存:SqlSession级别的缓存,基于HashMap本地缓存,当同一个sqlSession执行两次相同的SQL语句时,第一次执行完后会将数据库中查询到的结果写到缓存,第二次查询时直接从缓冲中读取不经过数据库了。一级缓存默认时开启的
二级缓存:mapper级别的缓存,也是基于hashmap本地缓存,不同的sqlSession两次执行相同的namespace下的sql语句,第二次查询就不会进行数据库了。
(2)#{}和${}区别是什么
#{}是预编译处理,mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值,最后注入进去是带引号的。使用#{}可以有效的防止SQL注入,提高系统安全性。
${}是字符串替换,mybatis在处理${}时,就是把${}替换成变量的值。
例如:
#是将传入的值当做字符串的形式,eg:select id,name,age from student where id =#{id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id ='1'.
$是将传入的数据直接显示生成sql语句,eg:select id,name,age from student where id =${id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id = 1.
(1)$符号一般用来当作占位符,常使用Linux脚本的人应该对此有更深的体会吧。既然是占位符,当然就是被用来替换的。知道了这点就能很容易区分$和#,从而不容易记错了。
(2)预编译的机制。预编译是提前对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。我们知道,SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作。而预编译机制则可以很好的防止SQL注入。
Struts2
(1)Struts2的工作流程
①. 请求发送给StrutsPrepareAndExecuteFilter
②. StrutsPrepareAndExecuteFilter判定该请求是否是一个Struts2请求
③. 若该请求是一个Struts2请求,则StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy
④. ActionProxy创建一个ActionInvocation的实例,并进行初始化
⑤. ActionInvocation实例在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用
⑥. Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到相对应的返回结果,调用结果的execute方法。
⑦. 执行各个拦截器invocation.invoke()之后的代码
⑧. 把结果发送到客户端
(2)Struts2优点
①. 基于MVC架构,框架结构清晰
②. 使用OGNL:OGNL可以快速的访问值栈中的数据、调用值栈中对象的方法
③. 拦截器:struts2中的很多特性都是通过拦截器实现的,例如异常处理、文件上传、验证等。拦截器时可配置与重用的
④. 多种表现层技术,如:JSP、FreeMarker、Velocity等
(3)Struts2拦截器和过滤器的区别
①. 过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器
②. Struts2拦截器只能对Action请求起作用,而过滤器则可以对几乎所有的请求起作用
③. 拦截器可以访问Action上下文(ActionContext),而过滤器不行
④. 在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次
(4)谈谈ValueStack
①. ValueStack贯穿整个Action的生命周期,保存在request域中,所以ValueStack和request的生命周期时一样的.
②. ValueStack是多实例的,因为Action是多实例的(Servlet是单例的),每个Action都有一个对应的值栈,Action对象默认保存在栈顶
③. ValueStack本质上就是一个ArrayList
④. 使用OGNL访问值栈内容是,不需要#号,而访问作用域中的值时,需要#号
⑤. Struts2重写了request的getAttribute方法,所以可以用EL直接访问值栈中的内容
Hibernate
(1)Hibernate的工作原理
①. 通过Configuration读取并解析hibernate.cfg.xml配置文件
②. 由hibernate.cfg.xml中的<mapping resource>读取并解析映射文件
③. 通过config.buildSessionFactory创建sessionFactory
④. 通过sessionFactory.openSession获取session
⑤. 通过session.beginTransaction开启事务
⑥. 操作数据
⑦. 提交事务
⑧. 关闭session和sessionFactory
(2)Hibernate的优缺点
优点:
①. 对JDBC访问数据库的代码进行了封装,简化了数据库访问层繁琐的重复性代码
②. 映射的灵活性,它支持各种关系数据库,从一对一到多对多的各种复杂关系
③. 非侵入性、移植性会好
④. 缓存机制:提供一级缓存和二级缓存
缺点:
①. 无法对SQL进行优化
②. 框架中使用ORM原则,导致配置过于复杂
③. 执行效率和原生的JDBC相比偏差:特别是在批量数据处理的时候
④. 不支持批量修改、删除