1 springmvc工作原理 / 执行流程
2 springmvc方法怎么返回一个json
- spring2.x做法:每个json视图controller配置一个Jsoniew。
如:
或者
同样要用jackson的jar包。
-
使用JSON工具将对象序列化成json,常用工具Jackson,fastjson,gson。
- 利用HttpServletResponse,然后获取response.getOutputStream()或response.getWriter()直接输出。
使用Springmvc3.x的注解@ResponseBody
3 SpringMVC的controller是单例还是多例?
- springmvc的controller默认是单例的。
- springmvc是基于方法的,用形参接收值,处理完毕就销毁。
- springmvc的controller中不适合定义属性,会造成线程不安全。
- springmvc设计默认单例,主要是为了提升性能。
- springmvc可以修改为多例模式。
- controller类上加注解@Scope("prototype")
4 springmvc常用哪些注解?
5 Spring MVC的主要组件?
-
前端控制器 DispatcherServlet(不需要程序员开发)
- 接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
-
处理器映射器HandlerMapping(不需要程序员开发)
- 根据请求的URL来查找Handler
-
处理器适配器HandlerAdapter
- 在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
处理器Handler(需要程序员开发)
-
视图解析器 ViewResolver(不需要程序员开发)
- 进行视图的解析,根据视图逻辑名解析成真正的视图(view)
-
视图View(需要程序员开发jsp)
- View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
6 SpringMvc怎么和AJAX相互调用的?
通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 :
- 加入Jackson.jar
- 在配置文件中配置json的映射
- 在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。
7 Springmvc 中拦截器如何使用?
-
定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。
- preHandle :进入 Handler方法之前执行,用于身份认证、身份授权,比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
- postHandle:进入Handler方法之后,返回modelAndView之前执行,应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
- afterCompletion:执行Handler完成执行此方法,应用场景:统一异常处理,统一日志处理
-
拦截器配置:
- 针对HandlerMapping配置(不推荐):springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该 拦截器。(一般不推荐使用)
- 类似全局的拦截器:springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中
8 Springmvc 中对于文件的上传有哪些需要注意?
- 在页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行解析。
- 在springmvc.xml中配置multipart类型解析器。
- 方法中使用:MultipartFile attach (单个文件上传) 或者 MultipartFile[] attachs (多个文件上传)
9 Springmvc 中如何解决 GET | POST请求中文乱码问题?
GET方式
- 每次发生请求之前对URL进行编码:
例如:Location.href="/encodeURI"(“http://localhost/test/s?name=中文&sex=女”);
- 更简便的方法,在服务器端配置URL编码格式:修改tomcat的配置文件server.xml:
只需增加 URIEncoding=“UTF-8” 这一句,然后重启tomcat即可。
POST方式
- 可以每次在request解析数据时设置编码格式:
request.setCharacterEncoding(“utf-8”);
- 也可以使用编码过滤器来解决,最常用的方法是使用Spring提供的编码过滤器,在Web.xml中增加如下配置(要注意的是它的位置一定要是第一个执行的过滤器)
charsetFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
该过滤器要做的其实就是强制为所有请求和响应设置编码格式:
request.setCharacterEncoding(“utf-8”);
response.setCharacterEncoding(“utf-8”);
10 Springmvc 怎么样设定重定向和转发的?
- 在返回值前面加"forward:“就可以让结果转发,譬如"forward:user.do?name=method4”
- 在返回值前面加"redirect:“就可以让返回值重定向,譬如"redirect:http://www.baidu.com”
11 Springmvc 如何做异常处理 ?
可以将异常抛给Spring框架,由Spring框架来处理;自定义实现spring的全局异常解析器HandlerExceptionResolver,在异常处理器中添视图页面即可。
12 Springmvc 中 如果拦截get方式提交的方法,怎么配置?
可以在@RequestMapping注解里面加上method=RequestMethod.GET
13 Springmvc 怎么样把ModelMap里面的数据放入Session里面?
可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。
14 Springmvc 和struts2的区别有哪些?
- springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。
- springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
- Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
15 Springmvc 用什么对象从后台向前台传递数据的?
通过ModelMap对象,可以在这个对象里面用put方法,把对象加到里面,前台就可以通过el表达式拿到。
16 springmvc 中当一个方法向AJAX返回特殊对象,譬如Object,List等,需要做什么处理?
要加上@ResponseBody注解。
17 项目使用mybatis开发流程是什么样的,需要做哪些事情?
- 用java写interface
- 写mapper.xml
18 mybatis没有接口实现类背后的原理是什么?
利用了jdk的动态代理。
protected T newInstance(MapperProxy mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
19 Mybatis缓存
- 一级缓存
- 本地缓存,SqlSession级别,一级缓存默认是开启的,最多缓存1024条SQL
- 同一个SqlSession再次发出相同的SQL,就从缓存中取数据,如果两次中间出现commit操作,本SqlSession中的一级缓存区域就会清空。
- 二级缓存
- 全局缓存,mapper级别,二级缓存是通过CacheExecutor实现的,CacheExecutor是Executor的代理对象。
- 二级缓存默认是关闭的,开启二级缓存需要作如下配置:
- mybatis全局配置中开启二级缓存配置
- 对应的Mapper.xml中配置cache节点
- 对应的select查询节点中添加useCache=true
20 Mybatis 是如何进行分页的?分页插件的原理是什么?
Mybatis 使用 RowBounds 对象进行分页,也可以直接编写 sql 实现分页,也可以使用Mybatis 的分页插件。
分页插件的原理:实现 Mybatis 提供的接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql。
举例:select from student,拦截 sql 后重写为:select t. from (select from student)t limit 0,10
21 简述 Mybatis 的插件运行原理,以及如何编写一个插件?
Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接口的插件,Mybatis 通过动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler 的 invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
22 Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
- Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。
- Mybatis 提供了 9 种动态 sql 标签:
trim|where|set|foreach|if|choose|when|otherwise|bind。 - 其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。
23 #{}和${}的区别是什么?
- '#{}是预编译处理,${}是字符串替换。
- Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
- Mybatis 在处理{}替换成变量的值。
- 使用#{}可以有效的防止 SQL 注入,提高系统安全性。
24 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
- Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
- Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。
25 Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
26 请你说一下使用 MyBatis 的 mapper 接口调用时有哪些要求?
- Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同
- Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同
- Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同
- Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。
27 说说在使用JDBC 编程时,它有哪些不足之处,MyBatis 是如何解决这些问题的?
- 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
- 解决:在 SqlMapConfig.xml 中配置数据连接池,使用连接池管理数据库连接。
- Sql 语句写在代码中造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
- 解决:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
- 向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数一一对应。
- 解决: Mybatis 自动将 java 对象映射至 sql 语句。
- 对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。
- 解决:Mybatis 自动将 sql 执行结果映射至 java 对象。
28 MyBatis 的好处是什么?
- MyBatis 把 sql 语句从 Java 源程序中独立出来,放在单独的 XML 文件中编写,给程序的
维护带来了很大便利。 - MyBatis 封装了底层 JDBC API 的调用细节,并能自动将结果集转换成 Java Bean 对象,
大大简化了 Java 数据库编程的重复工作。 - 因为 MyBatis 需要程序员自己去编写 sql 语句,程序员可以结合数据库自身的特点灵活
控制 sql 语句,因此能够实现比 Hibernate 等全自动 orm 框架更高的查询效率,能够完成复
杂查询。
29 简述 Mybatis 的 Xml 映射文件和 Mybatis 内部数据结构之间的映射关系?
- Mybatis 将所有 Xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。
- 在Xml 映射文件中,
标签会被解析为 ParameterMap 对象,其每个子元素会
被解析为 ParameterMapping 对象。 标签会被解析为 ResultMap 对象,其每个子元素会被解析为 ResultMapping 对象。 - 每一个
30 什么是 MyBatis 的接口绑定,有什么好处?
接口映射就是在 MyBatis 中任意定义接口,然后把接口里面的方法和 SQL 语句绑定,我们
直接调用接口方法就可以,这样比起原来了 SqlSession 提供的方法我们可以有更加灵活的选
择和设置。
31 接口绑定有几种实现方式,分别是怎么实现的?
- 一种是通过注解绑定,就是在接口的方法上面加上@Select@Update 等注解里面包含 Sql 语句来绑定;
- 另外一种就是通过 xml 里面写 SQL 来绑定,在这种情况下,要指定 xml 映射文件里面的 namespace 必须为接口的全路径名。
32 什么情况下用注解绑定,什么情况下用 xml 绑定?
- 当 Sql 语句比较简单时候,用注解绑定;
- 当 SQL 语句比较复杂时候,用 xml 绑定,一般用xml 绑定的比较多
33 MyBatis 实现一对一有几种方式?具体怎么操作的?
有联合查询和嵌套查询。
- 联合查询是几个表联合查询,只查询一次,通过在 resultMap 里面配置 association 节点配置一对一的类就可以完成;
- 嵌套查询是先查一个表,根据这个表里面的结果的外键 id,去再另外一个表里面查询数据,也是通过 association 配置,但另外一个表的查询通过 select 属性配置。
34 一个java bean的有参构造器的参数包含另一个java bean,XML怎么配置?
35 Spring特点
36 Spring常用模块
37 Spring主要包
38 Spring核心组件
39 Spring与第三方框架集成
40 Spring常用注解
41 json解析用什么做?内部怎么实现?Fastjson怎么解析java bean到json的?
42 Spring的bean生命周期,关键类和关键方法
43 Spring IOC原理
44 Spring的AOP原理,为什么要用,具体怎么用?
44.1 AOP的两种代理方式
具体哪种方式AopProxyFactory根据AdvisedSupport对象的配置来决定的。
- JDKProxy
- 只能针对接口创建代理
- 主要涉及java.lang.reflect包的Proxy和InvocationHandler
- JDK动态代理执行速度叫CGLib快,性能比CGLib低
- CGLib
- Code Generation Library,是一个强大的高性能、高质量的代码生成类库,CGLib封装了asm,可以运行期动态生成新的class
- Spring AOP如果目标对象实现了接口,则默认使用JDK动态代理;否则使用CGLib
45 Spring源码
46 JPA原理
47 ApplicationContext通常的实现是什么?
- FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
- ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。
- WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。
48 什么是Spring的依赖注入?
依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。
49 有哪些不同类型的IOC(依赖注入)方式?
- 构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
- Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
50 哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入?
两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。
51 解释Spring支持的几种bean的作用域。
Spring框架支持以下五种bean的作用域:
- singleton : bean在每个Spring ioc 容器中只有一个实例。缺省默认。
- prototype:一个bean的定义可以有多个实例。
- request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
- session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
- global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
52 在 Spring中如何注入一个java集合?
Spring提供以下几种集合的配置元素:
- 类型用于注入一列值,允许有相同的值。
类型用于注入一组值,不允许有相同的值。 类型用于注入一组键值对,键和值都只能为String类型。
53 解释不同方式的自动装配 。
有五种自动装配的方式,可以用来指导Spring容器用自动装配方式来进行依赖注入。
- no:默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。
- byName:通过参数名 自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
- byType::通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
- constructor:这个方式类似于byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
- autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。
54 自动装配有哪些局限性 ?
- 重写: 你仍需用
和 配置来定义依赖,意味着总要重写自动装配。 - 基本数据类型:你不能自动装配简单的属性,如基本数据类型,String字符串,和类。
- 模糊特性:自动装配不如显式装配精确,如果有可能,建议使用显式装配。
55 怎样开启注解装配?
注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在Spring配置文件中配置
56 @Required 注解
这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required注解的bean属性未被设置,容器将抛出BeanInitializationException。
57 @Autowired 注解
@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required一样,修饰setter方法、构造器、属性或者具有任意名称和/或多个参数的PN方法。
58 @Qualifier 注解
当有多个相同类型的bean却只有一个需要自动装配时,将@Qualifier 注解和@Autowire 注解结合使用以消除这种混淆,指定需要装配的确切的bean。
59 通知
通知是个在方法执行前或执行后要做的动作,实际上是程序执行时要通过SpringAOP框架触发的代码段。
Spring切面可以应用五种类型的通知:
- before:前置通知,在一个方法执行前被调用。
- after: 在方法执行之后调用的通知,无论方法执行是否成功。
- after-returning: 仅当方法成功完成后执行的通知。
- after-throwing: 在方法抛出异常退出时执行的通知。
- around: 在方法执行之前和之后调用的通知。
60 Spring支持的ORM
- Hibernate
- iBatis
- JPA (Java Persistence API)
- TopLink
- JDO (Java Data Objects)
- OJB
61 Spring解决循环依赖?
61.1 Spring发生循环依赖的现象是什么?
程序抛出异常BeanCurrentlyInCreationException
61.2 什么是循环依赖?
@Component
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
}
@Component
public class B {
private A a;
public void setA(A a) {
this.a = a;
}
}
61.3 Spring能解决哪些场景的循环依赖?
- 构造器注入
- 均采用构造器注入,Spring不能解决此种循环依赖
- A中注入B用setter方法,B中注入A用构造器,Spring可以解决循环依赖
- B中注入A用setter方法,A中注入B用构造器,Spring不能解决此种循环依赖
- setter方式注入(单例,默认方式):Spring用三级缓存解决循环依赖
- 一级缓存,singletonObjects,单例池
- earlySingletonObjects,早期曝光对象
- singletonFactories,早期曝光对象工厂
- setter方式注入(原型,prototype):Spring解决循环依赖的前提是Bean必须是单例的。
- Spring容器不缓存作用域为prototype的Bean,因此无法提前暴露一个创建中的Bean。
61.4 Spring怎么解决循环依赖的?
三级缓存源码
61.5 用二级缓存能解决Spring循环依赖吗?
- 如果用二级缓存,意味着所有Bean在实例化后就要完成AOP代理,这跟Spring设计原则不符
- Spring设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器在Bean生命周期最后一步完成AOP代理,而不是在实例化后立即进行AOP代理。