1、Mybatis框架
1.1、谈一谈你对Mybatis框架的理解(了解)
MyBatis 是一款优秀的持久层框架,一个半 ORM(对象关系映射)框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接 口和 Java 的 POJO(Plain OldJavaObjects,普通老式 Java 对象)为数据库中的记录。
1.2、在mybatis中,${} 和 #{} 的区别是什么?(必会)
#{} 是占位符,预编译处理,${}是字符串替换;
Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的set方法来赋值;
Mybatis 在处理${}时,就是把${}替换成变量的值。使用#{}可以有效的防止SQL 注入,提高系统安全性。
1.3、MyBatis编程步骤是什么样的?(了解)
1、 创建 SqlSessionFactory
2、 通过 SqlSessionFactory 创建SqlSession
3、 通过 sqlsession 执行数据库操作
4、 调用 session.commit()提交事务
5、 调用 session.close()关闭会话
1.4、在mybatis中,resultType和ResultMap的区别是什么?(必会)
如果数据库结果集中的列名和要封装实体的属性名完全一致的话用 resultType 属性;
如果数据库结果集中的列名和要封装实体的属性名有不一致的情况用 resultMap属性,通过resultMap 手动建立对象关系映射,resultMap要配置一下表和类的一一对应关系,所以说就算你的字段名和你的实体类的属性名不一样也没关系,都会给你映射出来。
1.5、在Mybatis中你知道的动态SQL的标签有哪些?作用分别是什么?(必会)
1. <if>if 是为了判断传入的值是否符合某种规则,比如是否不为空;
2. <where> where 标签可以用来做动态拼接查询条件,当和 if标签配合的时候,不用显示的声明类型 where 1 = 1 这种无用的条件;
3. <foreach> foreach标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到 sql语句中;
4. <include> include 可以把大量的重复代码整理起来,当使用的时候直接 include 即可,减少重复代码的编写;
5. <set>适用于更新中,当匹配某个条件后,才会对该字段进行跟新操作。
1.6、谈一下你对mybatis缓存机制的理解?(了解)
Mybatis 有两级缓存,一级缓存是 SqlSession级别的,默认开启,无法关闭;二级缓存是 Mapper 级别的,二级缓存默认是没有开启的,但是手动开启。
1. 一级缓存:基础PerpetualCache 的HashMap本地缓存,其存储作用域为Session, 当Session flush或close 之后,Session中的所有 Cache 就将清空;
2. 二级缓存其存储作用域为Mapper(Namespace),使用二级缓存属性类需要实现 Serializable 序列化接口;
3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces) 的进行了C(增加)/U(更新)/D(删除)操作后, 默认该作用域下所有select中的缓存将被clear. 需要在setting 全局参数中配置开启二级缓存,如下conf.xml 配置:

当我们的配置文件配置了cacheEnabled=true 时,就会开启二级缓存,二级缓存是 mapper 级别的,如果你配置了二级缓存,那么查询数据的顺序应该为:二级缓存→一级缓 存→数据库。
2. Spring框架
2.1、Spring的两大核心是什么?谈一谈你对IOC的理解? 谈一谈你对DI的理解?谈一谈你对AOP的理解?(必会)
1.Spring的两大核心是:IOC(控制反转)和 AOP(面向切面编程) DI(依赖注入);
2. IOC的意思是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。最直观的表达就是, IOC让对象的创建不用去 new了,可以由 spring 根据我们提供的配置文件自动生产,我们需要对象的时候,直接从Spring容器中获取即可。
Spring的配置文件中配置了类的字节码位置及信息, 容器生成的时候加载配置文件识 别字节码信息, 通过反射创建类的对象。
Spring的IOC有三种注入方式 :构造器注入, setter 方法注入, 根据注解注入。
3. DI 的意思是依赖注入,和控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖IOC容器来动态注入对象需要的外部资源。
4.AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect).SpringAOP 使用的动态代理,所谓的动态代理就是说 AOP 框 架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
5. Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理:
(1)JDK 动态代理只提供接口代理,不支持类代理,核心 InvocationHandler 接口和 Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起, Proxy 利用 InvocationHandler 动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
(2) 如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
2.2、Spring的生命周期?(高薪常问)
1. 实例化一个Bean,也就是我们通常说的 new;
2. 按照 Spring上下文对实例化的 Bean进行配置,也就是 IOC注入;
3. 如果这个 Bean 实现dao 了 BeanNameAware 接口,会调用它实现的 setBeanName(String beanId)方法,此处传递的是Spring配置文件中Bean 的 ID;
4. 如果这个 Bean 实现了BeanFactoryAware 接口,会调用它实现的 setBeanFactory(),传递的是 Spring 工厂本身(可以用这个方法获取到其他Bean);
5. 如果这个 Bean 实现了ApplicationContextAware 接口,会调用 setApplicationContext(ApplicationContext)方法,传入Spring上下文,该方式同样可以实现步骤4,但比 4更好,以为 ApplicationContext 是BeanFactory的子接口,有更多的实现方法;
6. 如果这个 Bean 关联了BeanPostProcessor 接口,将会调用 postProcessBeforeInitialization(Objectobj, String s)方法,BeanPostProcessor 经常被用作是Bean 内容的更改,并且由于这个是在Bean 初始化结束时调用 After方法,也可用于内存或缓存技术;
7. 如果这个Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法;
8. 如果这个 Bean 关联了BeanPostProcessor 接口,将会调用 postAfterInitialization(Object obj, String s)方法;
注意:以上工作完成以后就可以用这个 Bean了,那这个Bean 是一个 single 的,所以一般情况下我们调用同一个 ID的Bean 会是在内容地址相同的实例
9. 当Bean 不再需要时,会经过清理阶段,如果 Bean 实现了DisposableBean接口,会调用其实现的 destroy方法;
10. 最后,如果这个 Bean 的Spring 配置中配置了destroy-method 属性,会自动调用其配置的销毁方法。
2.3、Spring支持bean的作用域有几种吗? 每种作用域是什么样的?(必会)
Spring支持如下 5种作用域:
(1)singleton:默认作用域,单例bean,每个容器中只有一个 bean 的实例;
(2)prototype:每次请求都会为bean 创建实例;
(3)request:为每一个 request 请求创建一个实例,在请求完成以后,bean 会失效 并被垃圾回收器回收;
(4)session:与 request 范围类似,同一个session会话共享一个实例,不同会话 使用不同的实例;
(5)global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会 话共享的存储变量的话,那么这全局变量需要存储在global-session中。
2.4、BeanFactory和ApplicationContext有什么区别(了解)
BeanFactory:
Spring 最顶层的接口,实现了 Spring 容器的最基础的一些功能, 调用起来比较麻烦, 一般面向 Spring自身使用;
BeanFactory 在启动的时候不会去实例化Bean,从容器中拿Bean 的时候才会去实例化。
ApplicationContext:
是BeanFactory 的子接口,扩展了其功能, 一般面向程序员身使用 ApplicationContext 在启动的时候就把所有的Bean 全部实例化了。
2.5、Spring框架中都用到了哪些设计模式?(必会)
1. 工厂模式:BeanFactory 就是简单工厂模式的体现,用来创建对象的实例;
2. 单例模式:Bean 默认为单例模式;
3. 代理模式:Spring的AOP 功能用到了JDK 的动态代理和 CGLIB字节码生成技术;
4. 模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate;
5. 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如 Spring 中 listener 的实现--ApplicationListener。
2.6、Spring事务的实现方式和实现原理(必会)
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring 是 无法提供事务功能的。真正的数据库层的事务提交和回滚是通过 binlog 或者 redo log 实现的。
spring事务实现主要有两种方法:
1、编程式,beginTransaction()、commit()、rollback()等事务管理相关的方法;
2、声明式,利用注解Transactional 或者 aop配置。
2.7、你知道的Spring的通知类型有哪些,分别在什么时候执行?(了解)
Spring的通知类型有四种,分别为:
前置通知[]before]:在切点运行之前执行;
后置通知[after-returning]:在切点正常结束之后执行;
异常通知[after-throwing]:在切点发生异常的时候执行;
最终通知[after]:在切点的最终执行;
环绕通知:环绕通知运行程序员以编码的方式自己定义通知的位置, 用于解决其他通知时序问题。
2.8、Spring 的对象默认是单例的还是多例的? 单例bean存不存在线程安全问题呢?(必会)
1. 在spring中的对象默认是单例的,但是也可以配置为多例。
2. 单例bean对象对应的类存在可变的成员变量并且其中存在改变这个变量的线程时,多线程操作该 bean对象时会出现线程安全问题。
原因是:多线程操作如果改变成员变量,其他线程无法访问该bean 对象,造成数据混乱。
解决办法:在 bean对象中避免定义可变成员变量;在 bean 对象中定义一个 ThreadLocal 成员变量,将需要的可变成员变量 保存在ThreadLocal 中。
2.9、@Resource和@Autowired依赖注入的区别是什么? @Qualifier使用场景是什么?(了解)
@Resource
只能放在属性上,表示先按照属性名匹配IOC 容器中对象id 给属性注入值若没有成功,会继续根据当前属性的类型匹配IOC 容器中同类型对象来注入值;
若指定了 name属性@Resource(name ="对象id"),则只能按照对象id注入值。
@Autowird
放在属性上:表示先按照类型给属性注入值如果 IOC 容器中存在多个与属性同类型的对象,则会按照属性名注入值;
也可以配合@Qualifier("IOC 容器中对象id")注解直接按照名称注入值。
放在方法上:表示自动执行当前方法,如果方法有参数,会自动从 IOC 容器中寻找同类型的对象给参数传值;
也可以在参数上添加@Qualifier("IOC 容器中对象 id")注解按照名称寻找对象给 参数传值。@Qualifier使用场景:
@Qualifier("IOC 容器中对象 id")可以配合@Autowird 一起使用, 表示根据指定的id在Spring 容器中匹配对象。
2.10、Spring的常用注解(必会)
1. @Component(任何层) @Controller @Service @Repository(dao): 用于实例化对象;
2. @Scope : 设置Spring对象的作用域;
3. @PostConstruct @PreDestroy : 用于设置 Spring 创建对象在对象创建之后和销毁之前要执行的方法;
4. @Value: 简单属性的依赖注入;
5. @Autowired: 对象属性的依赖注入;
6. @Qualifier: 要和@Autowired联合使用,代表在按照类型匹配的基础上,再按照名称匹配;
7. @Resource 按照属性名称依赖注入;
8. @ComponentScan: 组件扫描;
9. @Bean: 表在方法上,用于将方法的返回值对象放入容器;
10. @PropertySource: 用于引入其它的properties 配置文件;
11. @Import: 在一个配置类中导入其它配置类的内容;
12. @Configuration: 被此注解标注的类,会被 Spring 认为是配置类。Spring 在启动的时候会自动扫描并加载所有配置类,然后将配置类中 bean放入容器;
13. @Transactional 此注解可以标在类上,也可以表在方法上,表示当前类中的方法具有事务管理功能。
2.11、Spring的事务传播行为(高薪常问)
spring事务的传播行为说的是,当多个事务同时存在的时候,spring 如何处理这些事务的行为。
备注(方便记忆): propagation传播
require 必须的/suppor 支持/mandatory 强制托管/requires-new 需要新建/ not -supported 不支持/never从不/nested嵌套的
① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED 属性执行。
2.12、Spring中的隔离级别 (高薪常问)
ISOLATION隔离的意思
① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别;
② ISOLATION_READ_UNCOMMITTED:读未提交,允许另外一个事务可以看到这个事务未提交的数据;
③ ISOLATION_READ_COMMITTED:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。解决脏读问题;
④ ISOLATION_REPEATABLE_READ:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。行锁;
⑤ ISOLATION_SERIALIZABLE:一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。表锁。
3、SpringMVC框架
3.1、谈一下你对SpringMVC框架的理解(了解)
SpringMVC是一个基于 Java的实现了 MVC设计模式的请求驱动类型的轻量级Web 框架,通过把 Model,View,Controller 分离,将web 层进行职责解耦,把复杂的web 应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
在我看来,SpringMVC 就是将我们原来开发在 servlet 中的代码拆分了,一部分由 SpringMVC完成,一部分由我们自己完成。
3.2、SpringMVC主要组件(必会)
前端控制器DispatcherServlet:接收请求、响应结果,相当于转发器,有了 DispatcherServlet 就减少了其它组件之间的耦合度;
处理器映射器HandlerMapping:根据请求的 URL来查找Handler;
处理器适配器HandlerAdapter:负责执行 Handler;
处理器Handler:处理业务逻辑的Java类;
视图解析器ViewResolver:进行视图的解析,根据视图逻辑名将ModelAndView解析成真正的视图(view) ;
视图View:View 是一个接口,它的实现类支持不同的视图类型,如jsp, freemarker, pdf等等。
3.3、谈一下SpringMVC的执行流程以及各个组件的作用(必会)

1. 用户发送请求到前端控制器(DispatcherServlet);
2. 前端控 制 器 ( DispatcherServlet ) 收到请求调用处理器映射器 (HandlerMapping),去查找处理器(Handler);
3. 处理器映射器(HandlerMapping)找到具体的处理器(可以根据xml 配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
4. 前端控制器(DispatcherServlet)调用处理器映射器(HandlerMapping);
5. 处理器适配器(HandlerAdapter)去调用自定义的处理器类(Controller,也叫后端控制器);
6.自定义的处理器类(Controller,也叫后端控制器)将得到的参数进行处理并返回结果给处理器映射器(HandlerMapping);
7. 处理器适配器(HandlerAdapter)将得到的结果返回给前端控制器 (DispatcherServlet);
8. DispatcherServlet( 前 端 控 制 器 ) 将 ModelAndView传给视图解析器 (ViewReslover);
9. 视图解析器(ViewReslover)将得到的参数从逻辑视图转换为物理视图并返回给前端控制器(DispatcherServlet);
10. 前端控制器(DispatcherServlet)调用物理视图进行渲染并返回;
11. 前端控制器(DispatcherServlet)将渲染后的结果返回。
3.4、说一下SpringMVC支持的转发和重定向的写法(必会)
1.转发:
forward方式:在返回值前面加"forward:",比如"”"forward:user.do?name=method4"
2.重定向:
redirect方式:在返回值前面加 redirect:, 比如"redirect:http://www.baidu.com"
3.5、SpringMVC的常用注解(必会)
1.@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径;
2.@RequestBody:注解实现接收http请求的json数据,将 json转换为java 对象;
3.@ResponseBody:注解实现将conreoller 方法返回对象转化为json 对象响应给客
户;
4.@PathVariable 用户从 url 路径上获取指定参数,标注在参数前 @PathVariabel(" 要获取的参数名");
5.@RequestParam: 标注在方法参数之前,用于对传入的参数做一些限制,支持三个属性:
- value:默认属性,用于指定前端传入的参数名称;
- required:用于指定此参数是否必传;
- defaultValue:当参数为非必传参数且前端没有传入参数时,指定一个默认值;
6. @ControllerAdvice 标注在一个类上,表示该类是一个全局异常处理的类;
7.@ExceptionHandler(Exception.class) 标注在异常处理类中的方法上,表示该方法可以处理的异常类型。
3.6、谈一下SpringMVC统一异常处理的思想和实现方式(必会)
使用 SpringMVC 之后,代码的调用者是 SpringMVC框架,也就是说最终的异常会抛到框架中,然后由框架指定异常处理类进行统一处理。
方式一: 创建一个自定义异常处理器(实现HandlerExceptionResolver接口),并实现里面的异常处理方法,然后将这个类交给 Spring容器管理;
方式二: 在类上加注解(@ControllerAdvice)表明这是一个全局异常处理类。在方法上加注解(@ExceptionHandler),在 ExceptionHandler 中有一个 value属性,可以指定可以处理的异常类型。
3.7、在SpringMVC中, 如果想通过转发将数据传递到前台,有几种写法?(必会)
方式一:直接使用 request 域进行数据的传递
request.setAttirbuate("name", value);
方式二:使用 Model 进行传值,底层会将数据放入request 域进行数据的传递 model.addAttribuate("name", value);
方式三:使用 ModelMap进行传值,底层会将数据放入request 域进行数据的传递
modelmap.put("name",value);
方式四:借用 ModelAndView在其中设置数据和视图
mv.addObject("name",value);
mv.setView("success");
return mv;
3.8、在SpringMVC中拦截器的使用步骤是什么样的?(必会)
1.定义拦截器类:
SpringMVC为我们提供了拦截器规范的接口 , 创建一个类实现 HandlerInterceptor,重写接口中的抽象方法;
preHandle 方法:在调用处理器之前调用该方法,如果该方法返回true则请求继续向下进行,否则请求不会继续向下进行,处理器也不会调用;
postHandle 方法:在调用完处理器后调用该方法;
afterCompletion方法:在前端控制器渲染页面完成之后调用此方法。
2.注册拦截器:
在SpringMVC核心配置文件中注册自定义的拦截器

3.9、在 SpringMVC中文件上传的使用步骤是什么样的? 前台三要素是什么?(必会)
文件上传步骤:
1.加入文件上传需要的 commons-fileupload包;
2.配置文件上传解析器,springmvc的配置文件的文件上传解析器的id属性必须为 multipartResolver;
3.后端对应的接收文件的方法参数类型必须为MultipartFile,参数名称必须与前端的name 属性保持一致。
文件上传前端三要素:
1.form表单的提交方式必须为 post;
2.enctype 属性需要修改为:multipart/form-data;
3.必须有一个type属性为file的input标签,其中需要有一个name属性;如果需要上传多个文件需要添加 multiple属性。
3.10、SpringMVC 中如何解决GET|POST请求中文乱码问题?(了解)
(1)解决post 请求乱码问题:在web.xml中配置一个CharacterEncodingFilter 过 滤器,设置成 utf-8;

(2) get 请求中文参数出现乱码解决方法有两个:
①修改 tomcat 配置文件添加编码与工程编码一致,如下:
<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" p rotocol="HTTP/1.1" redirectPort="8443"/>
②另外一种方法对参数进行重新编码:
String userName= new String(request.getParamter("userName").getBytes("ISO885 9-1"),"utf-8")
ISO8859-1 是tomcat 默认编码,需要将 tomcat 编码后的内容按utf-8 编码。




