目录
■ 如何解决 get 和 post 乱码问题?
■ 简单介绍一下 Spring bean 的生命周期(11步)
■ 如何构建一个线程安全的SqlSession
■ SpringMVC 的工作原理
首先:读取配置文件
1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)
4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
5. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
6. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
7. ViewResolver 结合Model和View,来渲染视图
8. 将渲染结果返回给客户端。
■ 谈谈你对SpringMVC的理解
1. 是一个基于MVC的web框架
2. SpringMVC是Spring的一个模块,是Spring的子容器,子容器可以拿父容器的东西,但是父容器不能拿子容器的东西
3. SpringMVC的前端控制器DispatcherServlet,用于分发请求,使开发变得简单
4. SpringMVC流程(重点)
5. SpringMVC三大组件
1)HandlerMapping:处理器映射器
用户请求路径到Controller方法的映射
2)HandlerAdapter:处理器适配器
根据handler(controlelr类)的开发方式(注解开发/其他开发) 方式的不同去寻找不同的处理器适配器
3)ViewResolver:视图解析器
可以解析JSP/freemarkerr/pdf等
■ SpringMVC 常用注解都有哪些?
1. @Controller,使用它标记的类就是一个SpringMVC Controller 对象
2. @RequestMapping,处理请求映射地址
3. @PathVariable,用于对应restful风格url中的参数
@RequestMapping(value="/happy/{dayid}")
findPet(@PathVariable String dayid)
4. @RequestParam,将请求的参数绑定到方法中的参数上
@RequestParam(value = "name", required = false) String name
5. @ResponseBody,将返回类型直接输入到http response body中
6. @RequestBody,方法参数直接被绑定到http request body中
7. @ModelAttribute和@SessionAttributes,用来传递和保存数据,有很多的坑,不建议使用
■ Spring 的常用注解
1. 控制反转
@Component,标注为一个普通的bean
@Service,@Repository
2. 依赖注入
@Autowired
@Qulifier
@Resource
@Value
3. 全局
@Configuration,代替配置文件,相当于beans
@ComponentScan,配置扫描包
@Scope,配置bean的生命周期
■ 如何开启注解处理器和适配器?
<mvc:annontation-driven/>
■ 如何解决 get 和 post 乱码问题?
1. get乱码,手动转换
首先:
String name = new String(xx.getBytes(“iso-8859-1”),”utf-8”);
不行的化,再:
在server.xml中,修改编码和工程编码一致
2. post乱码,在web.xml中配置字符过滤的filter,采用的类是Spring的CharacterEncodingFilter
-
<filter>
-
<filter-name>CharacterEncodingFilter</filter-name>
-
<filter-class>
-
org.springframework.web.filter.CharacterEncodingFilter
-
</filter-class>
-
<init-param>
-
<param-name>encoding</param-name>
-
<param-value>utf-8</param-value>
-
</init-param>
-
</filter>
-
<filter-mapping>
-
<filter-name>CharacterEncodingFilter</filter-name>
-
<url-pattern>/*</url-pattern>
-
</filter-mapping>
原因:
使用注解@RequestBody和@ResponseBody时,request.setCharactorEncoding(“utf-8”),不起作用。
■ 谈谈你对 Spring 的理解
1. 是一个容器框架
2. 非侵入式框架,框架不会影响或者改变我们原有的编码过程
3. 是一个轻量级框架,可以*选择Spring框架的全部或一部分
4. 是一个一站式框架,提供了各种各样的模块,支持开发
5. 提供了对于持久层的支持
6. 提供了Web MVC框架
7. IOC/DI,控制反转/依赖注入(解释一下)
控制反转
不是一种技术,而是一个面向对象编程的法则,“好莱坞法则”,即“don’t call us,we’ll call you”,“别找我,我回来找你”。
控制反转是从容器的角度来说的,以前对象都是应用程序new出来的,对象之间的依赖也是应用程序自己创建的,从而导致类与类之间高耦合,难于测试。现在,由Spring管理bean的生命周期以及bean之间的关系,降低了业务对象替换的复杂性,提高了组件之间的解耦。
对资源进行集中管理,实现了资源的可配置和易管理;
隐藏细节,不用自己组装,我们只负责调用。
依赖注入
是从应用程序的角度来说的,即,应用程序依赖Spring管理的bean以及bean之间的关系。Spring容器中有很多bean的实例,它会将符合依赖关系的对象通过注入的方式进行关联,建立bean与bean之间的联系。
常见注入方式有:属性注入,构造器注入,数组注入,集合注入。
8. AOP,面向切面编程(解释一下)
利用一种称为“横切”的技术,支持将公共业务提取出来(例如:安全/事务/日志)进行集中管理,面向核心业务编程,只需要关注业务本身,而不用去关注公共业务。使用AOP可以将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
Spring中实现AOP的方式有三种,分别为,基于AspectJ注解方式实现、基于Schema的xml配置、基于ProxyFactoryBean代理实现,但是底层都是基于动态代理实现的,动态代理有JDK动态代理和CGLIB动态代理,AOP默认使用的是JDK动态代理,当目标类没有接口时,使用CGLIB动态代理,也可以在配置文件中配置proxy-target-class=true,只使用CGLIB动态代理。
■ Spring 中的设计模式(解释)
Spring*用到9种设计模式:
工厂模式,单例模式,代理模式,包装器模式,适配器模式,简单工厂模式,观察者模式,策略模式,模板方法模式
1. 工厂模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
Spring中FactoryBean就是典型的工厂方法模式
2. 单例模式
保证一个类只有一个实例,并提供一个访问它的全局访问点。
Spring的单例模式完成了后半句化,即提供了全局的访问点BeanFactory
3. 包装器模式
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
Spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。
4. 代理模式
为其他对象提供一种代理以控制对这个对象的访问。
Spring的Proxy模式在aop中有体现,比如JdkDynamicAopProxy和Cglib2AopProxy。
5. 适配器模式,HandlerAdapter
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
Spring中在对于AOP的处理中有Adapter模式的例子,见如下图:
由于Advisor链需要的是MethodInterceptor(拦截器)对象,所以每一个Advisor中的Advice都要适配成对应的MethodInterceptor对象。
6. 简单工厂模式
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
BeanFactory,根据传入一个唯一的标识来获得bean对象,但不属于23种GOF设计模式之一。
■ 简单介绍一下 Spring bean 的生命周期(11步)
前提是实体类实现了相应的接口
spring上下文中的bean的生命周期:
1.实例化bean对象
2.注入bean的所有属性
3.设置bean的id
调用BeanNameAware接口的setBeanName(String)方法
4.设置bean工厂
调用BeanFactoryAware接口的setBeanFactory()方法
5.设置实例所在的上下文空间
调用ApplicationContextAware接口的setApplicationContext()方法,传入Spring上下文
6.调用后置处理器的预初始化方法
调用BeanPostProcessor接口的postProcessorBeforeInitialization()方法
7.执行InitializingBean的afterPropertiesSet()
8.调用使用init-method配置的自定义初始化方法
9.调用后置处理器的后初始化方法
调用BeanPostProcessor接口的postProcessorAfterInitialization()方法
10.调用DisPosableBean接口的destory()方法
11.调用使用destroy-method配置的自定义销毁由方法
由BeanFactroy创建的bean
没有第五步
■ 如何构建一个线程安全的SqlSession
请参看我的另外一篇博客:https://blog.csdn.net/qq_41541619/article/details/82528871
目录
■ 什么是 Spring IOC 容器,IOC 的优点是什么?
■ Spring 支持的几种 bean 的作用域
■ 使用 MyBatis 的 mapper 接口调用时有哪些要求
■ mybatis的缓存机制,一级,二级介绍一下
■ Spring 能帮我们做什么
1. 实例化bean,并且管理bean与bean之间的依赖关系
2. Spring面向切面编程能帮助我们无耦合实现日志记录,性能统计,安全控制等功能
3. Spring能非常简单的帮我们管理数据库事务
4. Spring提供了与第三方框架无缝集成,如:
第三方数据访问框架(mybatis,hibernate,jpa),自身提供了JDBC访问;
第三方web框架(struts,jsf),自己提供了spring mvc进行web创建;
其他第三方框架(如:java mail,任务调度,缓存框架等)
■ 描述一下 Spring 的事务
1. 事务的特性ACID
原子性、一致性、隔离性、持久性
2. 事务是一系列操作的最小单元,在Spring中,一个session对应一个事务,要么全部成功要么全部失败,如果中间有一条出现异常,那么回滚之前的所有操作
3. Spring中有自己的事务管理机制,实现方式共有两种:编程式和声明式。
编程式事务:使用TransactionTemplate,重写execute方法实现事务管理
声明式事务:使用AOP面向切面编程实现,本质就是在目标方法执行前后进行拦截。在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。
实现声明式事务管理又有两种方式:
基于XML配置文件;
基于注解,使用@Transactional注解,将事务规则应用到业务逻辑中
4. 事务最重要的两个特性是事务的传播级别(7种)和数据隔离级别(4种)
传播级别定义的是事务的控制范围。
我使用过的是REQUIRED和SUPPORTS
REQUIRED(增删改):在事务中执行,如果没有事务存在,则会重新创建一个。
SUPPORTS(查):使用当前的环境执行,如果当前存在事务,则使用这个事务;如果当前没有事务,则不使用事务
事务隔离级别定义的是事务在数据库读写方面的控制范围。
未授权读取,授权读取,可重复读取,序列化(隔离级别最高)
事务隔离的实现是基于悲观锁和乐观锁
Mysql默认的隔离级别是可重复读
■ 什么是 Spring IOC 容器,IOC 的优点是什么?
1. IOC容器可以理解为一个创建和管理bean的容器,用于创建bean的实例并且管理bean和bean之间的关系
2. 优点(3点)
1) 以前对象都是应用程序new出来的,对象之间的依赖也是应用程序自己创建的,从而导致类与类之间高耦合,难于测试。现在,由Spring管理bean的生命周期以及bean之间的关系,降低了业务对象替换的复杂性,提高了组件之间的解耦;
2) 对资源进行集中管理,实现了资源的可配置和易管理;
3)隐藏细节,不用自己组装,我们只负责调用。
■ 什么是 Spring 的依赖注入 ,注入方式有哪些?
1. 依赖注入,是IOC的一方面,是一个通常的概念,它有多种解释。这个概念是说我们不用创建对象,而只需要描述它是如何被创建。我们不用在代码里直接组装组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后由IOC容器负责把他们组装起来。
2. 注入方式,实现方式分为两类,基于配置文件和基于注解
属性注入
构造器注入
数组注入
集合注入
List注入
Map注入
■ Spring 支持的几种 bean 的作用域
1. Singleton,单例,每个bean在Spring IOC容器中只有一个实例,缺省作用域
2. Prototype,原型,每次使用的使用,都会创建一个新的实例
3. Session,在一个HttpSession中,一个bean定义对应一个实例
4. Request,每次http请求都会创建一个bean
5. GlobalSession,在一个全局的HttpSession中,一个bean定义对应一个实例
6. Application
7. Socket
■ 简单解释一下 spring 的 AOP
利用一种称为“横切”的技术,支持将公共业务提取出来(例如:安全/事务/日志)进行集中管理,面向核心业务编程,只需要关注业务本身,而不用去关注公共业务。使用AOP可以将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
Spring中实现AOP的方式有三种,分别为,基于AspectJ注解方式实现、基于Schema的xml配置、基于ProxyFactoryBean代理实现,但是底层都是基于动态代理实现的,动态代理有JDK动态代理和CGLIB动态代理,AOP默认使用的是JDK动态代理,当目标类没有接口时,使用CGLIB动态代理,也可以在配置文件中配置proxy-target-class=true,只使用CGLIB动态代理。
Spring切面可以应用五种类型的通知
1. 前置通知
2. 后置通知
3. 环绕通知
4. 返回后通知
5. 异常通知
AOP术语
1. 切面(Aspect):公共功能、交叉功能的描述
2. 通知(Advice):实现切面功能的类,真正做事情的地方
3. 连接点(Joinpoint):静态概念,通知执行的地方
4. 切入点(PointCut):动态概念,运行时执行通知的地方,实现切面功能时,连接点变为切入点
5. 目标对象(Target):被通知的对象,核心关注点对象
6. 代理对象(Proxy):代理的是目标对象,通过代理目标对象就增加了切面功能
7. 引入(Introductions):静态概念,将切面与目标对象关联起来
8. 织入(Weaving):将切面应用到代理对象,是一个过程
■ Mybatis 中#和$的区别?
1. #{}是预编译处理,${}是字符串替换。
2. Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
3. Mybatis在处理${}时,就是把${}替换成变量的值,相当于字符串拼接
4. 使用#{}可以有效的防止SQL注入,提高系统安全性。
■ Mybatis 的使用步骤是什么样的?
1. 读取配置文件
2. 创建SqlSessionFactoty
3. 创建SqlSession
4. 操作数据库
5. 提交事务(增删改)
6. 关闭session
■ 使用 MyBatis 的 mapper 接口调用时有哪些要求
1. namespace命名空间指向一个特定的dao接口(全路径)
2. 每一个sql中的id,唯一标识接口中的一个方法
3. parameterType对应接口方法中的输入参数类型
4. resultType对应接口方法的返回类型
5. 参数多个怎么做
map,索引,注解@Param
■ mybatis的缓存机制,一级,二级介绍一下
1. 一级缓存
默认开启
SqlSession级别的缓存,实现在同一个会话中数据的共享
一级缓存的生命周期和SqlSession一致
当有多个SqlSession或者分布式环境下,数据库写操作会引起脏数据。
2. 二级缓存
默认不开启,需手动开启
SqlSessionFactory级别的缓存,实现不同会话中数据的共享,是一个全局变量
可自定义存储源,如Ehcache
当开启缓存后,数据查询的执行的流程是:二级缓存>一级缓存>数据库
不同于一级缓存,二级缓存可设置是否允许刷新和刷新频率
实现
实体类实现序列化
在mapper文件中开启<cache>
在配置文件中设置cacheEnabled为true
■ 视图解析器本质是什么
转发,隐藏细节
■ 统一解决get乱码
传参之前,将数据序列化