目录
1.请简述你对Spring的理解?
2.简述一下Spring支持的事物管理有哪些?
3.简述一下DAO模式?
4.有哪些不同类型的IOC(依赖注入)方式?
5.Spring实现事物的方式有哪些?
6.SpringMVC的执行流程(工作原理)?
7.Mybatis中#{}和${}的区别是什么?
8.事物的四大特性有哪些(ACID)?
9.JVM有哪些垃圾回收算法?
10.Spring的事物管理机制实现原理?
11.何为Spring Bean容器?Spring Bean容器与Spring IOC 容器有什么不同吗?
12.Spring IOC 如何理解?
13.Spring DI 如何理解?
14.Spring 中基于注解如何配置对象作用域?以及如何配置延迟加载机制?
15.Spring 工厂底层构建Bean对象借助什么机制?当对象不使用了要释放资源,目的是什么?何为内存泄漏?
16.MyBatis应用动态SQL解决了什么问题?
17.Shiro框架权限管理时的认证和授权流程描述?
18.BeanFactory和ApplicationContext有什么区别?
19.请解释Spring Bean的生命周期?
20. Spring Bean的作用域之间有什么区别?
21.怎么保证缓存和数据库的一致性?
22.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)?
23.在Spring AOP 中,关注点和横切关注的区别是什么?
24.Spring 中@Autowired 和@Resource 的区别
25.springboot 如果要直接获取 form 数据的话要怎么做?
26.Spring 是如何管理事务的?
27.SpringMVC 的 controller 里可不可以写成员变量?
30.使用Spring框架的好处是什么?
31. Spring 中用到了那些设计模式?
32.Spring 如何保证 Controller 并发的安全?
33.在 Spring中如何注入一个java集合?
34.Mybatis框架简介?
35.Mybatis和Hibernate的区别?
36.Mybatis缓存?
37.Mybatis 里多对多如何处理? 举个多对多的例子?
38.SpringMVC 常用注解都有哪些?
39.如何开启注解处理器和适配器?
40.如何解决get和post乱码问题?
41.Spring 常用的注解?
42.SpringMvc怎么和AJAX相互调用的?
43.Mybatis 中#和$的区别?
44.mybatis的基本工作流程?
45.什么是MyBatis的接口绑定,有什么好处?
46. MyBatis的编程步骤
47.MyBatis的优缺点?
48.使用MyBatis的mapper接口调用时有哪些要求?
49.Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
50. Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别?
51.Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
52.Mybatis都有哪些Executor执行器?它们之间的区别是什么?
53.为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
54.怎么样把数据放入Session里面?
55.什么是bean的自动装配?
56.什么是基于Java的Spring注解配置? 给一些注解的例子?
57.你给我说一下SpringBoot吧?
58.MySql数据库查询优化方式?
59.Oracel和Mysql的区别?
60.Spring如何解决循环依赖问题(重)?
61.说一下SQL优化问题?
62.数据库的聚合函数有哪些,连接查询有几种?
63.数据库创建索引时候会考虑哪些因素 ?
64.什么时候会添加索引,如何查看索引是否生效?
65.数据库的搜索引擎有几种?
66.什么是事务,Mysql中的事务隔离级别有几种,事务的特性是什么?
67.什么是存储过程?用什么来调用?
68.简述web.xml的作用?
69.表中添加索引的准则有哪些?
70.Spring如何处理线程并发问题?
71.说下注解注入的方式?
72.Filter的作用是什么?
73.Filter的生命周期?
Spring是一个开源框架,为简化企业级应用开发而生。Spring可以是使简单的JavaBean实现以前只有EJB才能实现的功能。Spring是一个IOC和AOP容器框架。
一.优点:
1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦
2.可以使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring属于低侵入式设计,代码的污染极低
8.独立于各种应用服务器
9.spring的DI机制降低了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部
二.DI机制:
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者,因此也称为依赖注入。spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入
设置注入的优点:
直观,自然
构造注入的优点:
可以在构造器中决定依赖关系的顺序。
三.AOP
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面
面向切面编程(aop)是对面向对象编程(oop)的补充, 面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。 AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象, 是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。
aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
四.IOC
IOC 控制反转,像我们之前开发,如果想创建一个对象,就 new 一个,如果想这个对象 中定义其他的变量或者对象,就在对象内部创建一个成员变量。但是现在的话,如果想用这 个类的对象,咱们可以在 spring 的配置文件中配置一个 bean,指定对应的全路径名称。 spring 通过配置文件用反射的方式,就可以直接帮我们获取到这个类的对象。还有 AOP,就 是面向切面编程,它的原理的话,我看过它的底层代码,它实际上就是实现了 JDK 的动态代理,以前的话用这个做过事务的控制,现在的话我们都用注解来控制事务.
1.声明式事务管理:设置配置文件与先前比照简化了许多。我们把这类设置配置文件格式称为 Spring 经典的声明式事务治理。
2.编程式事务管理:为了不损坏代码原有的条理性,避免出现每一个方法中都包括相同的启动事物、提交、回滚事物样板代码的现象,spring 提供了 transactionTemplate 模板来实现编程式事务管理。这种方式意味着你可以将事务管理和业务代码分离。你只需要通过注解或者XML配置管理事务。
3.区别
(1)编程式事务是自己写事务处理的类,然后调用。
(2)声明式事务是在配置文件中配置,一般搭配在框架里面使用。
1.DAO(Data Access Object)顾名思义是一个为数据库或其他持久化机制提供了抽象接口的对象,在不暴露底层持久化方案实现细节的前提下提供了各种数据访问操作。
2.在实际的开发中,应该将所有对数据源的访问操作进行抽象化后封装在一个公共API中。
3.用程序设计语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口,在逻辑上该类对应一个特定的数据存储。
4.DAO模式实际上包含了两个模式,一是Data Accessor(数据访问器),二是Data Object(数据对象),前者要解决如何访问数据的问题,而后者要解决的是如何用对象封装数据。
Spring提供了多种依赖注入的方式。
set注入
2.构造器注入
3.静态工厂的方法注入
4.实例工厂的方法注入
1.aspectJ AOP实现事务:
2.事务代理工厂Bean实现事务:
3.注解方式实现事务:在需要进行事务的方法上增加一个注解“@Transactional(rollbackFor = MyExepction.class )”
(1)一个请求匹配前端控制器 DispatcherServlet 的请求映射路径(在 web.xml中指定), WEB 容器将该请求转交给 DispatcherServlet 处理
(2)DispatcherServlet 接收到请求后, 将根据 请求信息 交给 处理器映射器 (HandlerMapping)
(3)HandlerMapping 根据用户的url请求 查找匹配该url的 Handler,并返回一个执行链
(4)DispatcherServlet 再请求 处理器适配器(HandlerAdapter) 调用相应的 Handler 进行处理并返回 ModelAndView 给 DispatcherServlet
(5)DispatcherServlet 将 ModelAndView 请求 ViewReslover(视图解析器)解析,返回具体 View
(6)DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)
(7)DispatcherServlet 将页面响应给用户
#相当于对数据加上双引号,$相当于直接显示数据
1.#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by#user_id#,如果传入的值是111,那么解析成sql时的值为order by"111",如果传入的值是id,则解析成的sql为order by "id".
2.$将传入的数据直接显示生成在sql中。如:order by$user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id,如果传入的值是id,则解析成的sql为order by id.
3.#方式能够很大程度防止sql注入,$方式无法防止Sql注入。
4.$方式一般用于传入数据库对象,例如传入表名.
1.原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
2.一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
3.隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
4.持久性:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
1.标记-清除算法
从算法的名称上可以看出,这个算法分为两部分,标记和清除。首先标记出所有需要被回收的对象,然后在标记完成后统一回收掉所有被标记的对象。
这个算法简单,但是有两个缺点:一是标记和清除的效率不是很高;二是标记和清除后会产生很多的内存碎片,导致可用的内存空间不连续,当分配大对象的时候,没有足够的空间时不得不提前触发一次垃圾回收。
2.复制算法
这个算法将可用的内存空间分为大小相等的两块,每次只是用其中的一块,当这一块被用完的时候,就将还存活的对象复制到另一块中,然后把原已使用过的那一块内存空间一次回收掉。这个算法常用于新生代的垃圾回收。
复制算法解决了标记-清除算法的效率问题,以空间换时间,但是当存活对象非常多的时候,复制操作效率将会变低,而且每次只能使用一半的内存空间,利用率不高。
3.标记-整理算法
这个算法分为三部分:一是标记出所有需要被回收的对象;二是把所有存活的对象都向一端移动;三是把所有存活对象边界以外的内存空间都回收掉。
标记-整理算法解决了复制算法多复制效率低、空间利用率低的问题,同时也解决了内存碎片的问题。
4.分代收集算法
根据对象生存周期的不同将内存空间划分为不同的块,然后对不同的块使用不同的回收算法。一般把Java堆分为新生代和老年代,新生代中对象的存活周期短,只有少量存活的对象,所以可以使用复制算法,而老年代中对象存活时间长,而且对象比较多,所以可以采用标记-清除和标记-整理算法。
Spring的事务管理机制实现的原理,就是通过这样一个动态代理对所有需要事务管理的Bean进行加载,并根据配置在invoke方法中对当前调用的 方法名进行判定,并在method.invoke方法前后为其加上合适的事务管理代码,这样就实现了Spring式的事务管理。Spring中的AOP实 现更为复杂和灵活,不过基本原理是一致的。
(1)用于创建bean对象,管理bean对象的那个容器。
(2)Spring IOC 容器本质上指的的就是Spring Bean容器,Spring Bean容器中最核心一个机制是IOC机制(控制反转),所以有时候又将springbean容器称之为Spring IOC 容器.
IOC 是Spring中提供一种控制反转机制,目的是将我们项目中对象的依赖管理交给Spring实现,
这样可以更好实现对象关系的解耦,提高程序的可扩展性.
DI 是Spring中的依赖注入机制,IOC的实现需要借助这种机制.我们通常会这样理解。
Spring Bean容器中的IOC思想一种目标,DI是实现这种思想的目标的手段.
@Scope(“singleton”)
@Scope(“prototype”)
@Lazy(value=true)(延迟加载)
借助反射机制,防止内存泄漏,对象已经不使用了但占用着内存,这种现 象称之为内存泄漏,内存泄漏不是内存溢出,但是它是内存溢出的一个导火索. 内存溢出直接就导致系统崩溃了.
有时候,固定的sql语句不能够满足我们的应用需求。这个时候需要在 标准的基础上建立动态的查询语句。
Mybatis提供了多种注解,可以提供动态查询语言。
比如说在开发的时候,遇到这样的场景,界面提供了多种查询,但是都是非 必填写,在选择查询条件时可以选中任意几种组合作为查询条件,如果在使 用jdbc的时候,需要判断参数为空,自己组装sql,但是mybatis提供动态sql机制,依靠标签。
Shiro权限控制流程的原理:
应用代码 —- 调用Subject (shiro的Subject 就代表当前登陆用户) 控制权限 —- Subject 在shiro框架内部 调用 Shiro SecurityManager 安全管理器 —– 安全管理器调用 Realm (程序和安全数据连接器 )。
Subject要进行任何操作,都必须要调用安全管理器(对我们来说是自动的)。 而安全管理器会调用指定的Realms对象,来连接安全数据。
Realms用来编写安全代码逻辑和访问安全数据,是连接程序和安全数据的桥梁。
BeanFactory 可以理解为含有bean集合的工厂类。BeanFactory 包含了种bean的定义,以便在接收到客户端请求时将对应的bean实例化。
BeanFactory还能在实例化对象时生成协作类之间的关系。此举将bean自身与bean客户端的配置中解放出来。BeanFactory还包含了bean生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。
从表面上看,application context如同bean factory一样具有bean定义、bean关联关系的设置,根据请求分发bean的功能。但application context在此基础上还提供了其他的功能。
1.Spring Bean的生命周期简单易懂。在一个bean实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样,当一个bean不在被调用时需要进行相关的析构操作,并从bean容器中移除。
2.Spring bean factory 负责管理在spring容器中被创建的bean的生命周期。Bean的生命周期由两组回调(call back)方法组成。
初始化之后调用的回调方法。
销毁之前调用的回调方法。
Spring框架提供了以下四种方式来管理bean的生命周期事件:
(1)InitializingBean和DisposableBean回调接口
(2)针对特殊行为的其他Aware接口
(3)Bean配置文件中的Custom init()方法和destroy()方法
(4)@PostConstruct和@PreDestroy注解方式
Spring容器中的bean可以分为5个范围。所有范围的名称都是自说明的,但是为了避免混淆,还是让我们来解释一下:
(1)singleton:这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由bean factory自身来维护。
(2)prototype:原形范围与单例范围相反,为每一个bean请求提供一个实例。
(3)request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)Session:与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
(5)global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。
1.淘汰缓存还是更新缓存?
选择淘汰缓存
原因:
数据可能为简单数据,也可能为较复杂的数据,复杂数据进行缓存的更新操作,成本较高,因此一般推荐淘汰缓存
2.先淘汰缓存还是先更新数据库?
选择先淘汰缓存,再更新数据库
原因:
假如先更新数据库,再淘汰缓存,假如缓存淘汰失败,那么后面的请求都会得到脏数据,直至缓存过期。假如先淘汰缓存再更新数据库,如果数据库更新失败,只会产生一次缓存miss,相比较而言,后者对业务影响更小一点。
方案一:
通过key的过期时间,mysql更新时,redis不更新。 这种方式实现简单,但不一致的时间会很长。如果读请求非常频繁,且过期时间比较长,则会产生很多长期的脏数据。
1.优点:
开发成本低,易于实现;
管理成本低,出问题的概率会比较小。
2.不足:
完全依赖过期时间,时间太短容易缓存频繁失效,太长容易有长时间更新延迟(不一致)
方案二
在方案一的基础上扩展,通过key的过期时间兜底,并且,在更新mysql时,同时更新redis。
1.优点:
相对方案一,更新延迟更小。
2.不足:
1.如果更新mysql成功,更新redis却失败,就退化到了方案一;
2.在高并发场景,业务server需要和mysql,redis同时进行连接。这样是损
3.耗双倍的连接资源,容易造成连接数过多的问题。
方案三
针对方案二的同步写redis进行优化,增加消息队列,将redis更新操作交给kafka,由消息队列保证可靠性,再搭建一个消费服务,来异步更新redis。
优点:
1.消息队列可以用一个句柄,很多消息队列客户端还支持本地缓存发送,有效解决了方案二连接数过多的问题;
2.使用消息队列,实现了逻辑上的解耦;
3.消息队列本身具有可靠性,通过手动提交等手段,可以至少一次消费到redis。
不足:
1.依旧解决不了时序性问题,如果多台业务服务器分别处理针对同一行数据的两条请求,举个栗子,a = 1; a = 5;,如果mysql中是第一条先执行,而进入kafka的顺序是第二条先执行,那么数据就会产生不一致。
2.引入了消息队列,同时要增加服务消费消息,成本较高。
方案四
通过订阅binlog来更新redis,把我们搭建的消费服务,作为mysql的一个slave,订阅binlog,解析出更新内容,再更新到redis。
优点:
1.在mysql压力不大情况下,延迟较低;
2.和业务完全解耦;
3.解决了时序性问题。
缺点:
1.要单独搭建一个同步服务,并且引入binlog同步机制,成本较大。
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起。它们通过配置文件中的
many-to-one (多对一)
one-to-many(一对多)
many-to-many(多对多)
关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。
横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。
1.@Autowired 默认的是按照类型进行注入, 如果没有类型会按照名称(红色字体)进行注入. 如果想直接按照名称注入需要加入@Qualifier("gatheringDao") @Autowired @Qualifier("gatheringDao") private GatheringDao gatheringDao;
2.@Resource 默认的会按照名称注入,名称找不着会按照类型来找,如果这里写了名称,就直接 按照名称找了不会按类型找@Resource(name = "aaa") @Resource private GatheringDao gatheringDao;
也是通过形参里添加参数就行啊,和 form 表单里的 name 值对应上就行了啊,在 form 表单的 action 中配置上请求改方法的路径不就行了
我们用 spring 管理事务的时候用的是注解式的方式管理的,他底层实现也是 AOP 的方式来管 理的事务
可以写啊,注入的 service 不就是成员变量么,你是不想问 struts2 里的获取参数的方式啊? Struts2 早就不用了,他那种用成员变量获取参数的方式,在高并发下会造成线程不安全, springmvc 是使用的形参接收前台数据的,线程比较安全。
1.轻量:Spring 是轻量的,基本的版本大约2MB。
2.控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
3.面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
4.容器:Spring 包含并管理应用中对象的生命周期和配置。
5.MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
6.事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
7.异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。
Spring框架中使用到了大量的设计模式,下面列举了比较有代表性的:
1.代理模式—在AOP和remoting中被用的比较多。
2.单例模式—在spring配置文件中定义的bean默认为单例模式。
3.模板方法—用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
4.工厂模式—BeanFactory用来创建对象的实例。
适配器–spring aop
装饰器–spring data hashmapper
观察者– spring 时间驱动模型
回调–Spring ResourceLoaderAware回调接口
Spring 多线程请求过来调用的Controller对象都是一个,而不是一个请求过来就创建一个Controller对象。
并发的安全? 原因就在于Controller对象是单例的,那么如果不小心在类中定义了类变量,那么这个类变量是被所有请求共享的,这可能会造成多个请求修改该变量的值,出现与预期结果不符合的异常
那有没有办法让Controller不以单例而以每次请求都重新创建的形式存在呢?
答案是当然可以,只需要在类上添加注解@Scope(“prototype”)即可,这样每次请求调用的类都是重新生成的(每次生成会影响效率)
虽然这样可以解决问题,但增加了时间成本,总让人不爽,还有其他方法么?答案是肯定的!
使用ThreadLocal来保存类变量,将类变量保存在线程的变量域中,让不同的请求隔离开来。
Spring提供以下几种集合的配置元素:
类型用于注入一列值,允许有相同的值。
Mybatis 框架也是一个持久层框架,我们目前做的这个项目就是用的这个框架,我觉他相 对于以前的hibernate来说比较简单,把sql语句写在配置文件里,解除了代码和sql语句的 耦合度,写一些复杂的查询比较灵活.
Hibernate 一个是全封装,mybatis 是半封装,使用 hibernate 做单表查询操作的时候比 较简单(因为 hibernate 是针对对象进行操作的),但是多表查询起来就比较繁琐了,比如说 5 张表 10 张表做关联查询,就算是有 SQLquery 那后续的维护工作也比较麻烦,还有就是 Hibernate 在 Sql 优化上执行效率上会远低于 MyBatis(因为 hibernate 会把表中所有的字 段查询出来,比较消耗性能)我们以前在做传统项目方面用过 hibernate,但是现在基本上都 在用 mybatis.
1.mybatis 一级缓存是 SqlSession 级别的缓存,默认支持一级缓存,不需要在配置文件去配 置。
2.mybaits 的二级缓存是 mapper 范围级别,除了在 SqlMapConfig.xml 设置二级缓存的总开关
比如说学生表和课程表,一个学生可以选择多门课程, 一门课程都能被多个学生选择,这 样两张表的关系就是多对多的关系, 怎么处理多对多的情况? 遇到这种情况我们得创建一 张中间的桥表,关联后就是 课程表对桥表就是一对多,学生表对桥表也是一对多,就可以了
@RequestMapping 用于请求 url 映射。
@RequestBody 注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对 象。
@ResponseBody 注解实现将 controller 方法返回对象转化为 json 响应给客户
我们在项目中一般会在 springmvc.xml 中通过开启 mvc:annotation-driven 来实现注解处理器和适配器的开启.
解决 post 请求乱码:我们可以在 web.xml 里边配置一个 CharacterEncodingFilter 过滤 器。设置为 utf-8. 解决 get 请求的乱码:有两种方法。对于 get 请求中文参数出现乱码解决方法有两个: 1. 修改 tomcat 配置文件添加编码与工程编码一致。 2.另外一种方法对参数进行重新编码 String userName=NewString(Request.getParameter(“userName”).getBytes(“ISO8859-1”),“utf-8”);
我们开发的时候常用的注解也就@service 业务逻辑,@Transactionnal 事务的注解,有时候 需 要 注 入 DAO 的 话 还 会 用 到 @Repository 还 有 就 是 springMVC 里 的 注 解 啦 , 比 如 说 @Controller 对应表现层的注解在 spring 未来的版本中,@RestController 这个控制器返回 的都是 json 格式,还有@RequestMapping 进入的 URL,@responsebody 也是定义该方法返回 JSON 格式,还有就是@RequestParam 获取参数,@RequestBody 获取前台的数据是 JSON 格式的 数据,@PathVariable 从 URL 请求路径中获取数据,大概常用的也就这些.
通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下
(1)加入Jackson.jar
(2)在配置文件中配置json的映射
(3)在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上
#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值,相当于字符串拼接
使用#{}可以有效的防止SQL注入,提高系统安全性。
1.读取配置文件,配置文件包含数据库连接信息和Mapper映射文件或者Mapper包路径。
2.有了这些信息就能创建SqlSessionFactory,SqlSessionFactory的生命周期是程序级,程序运行的时候建立起来,程序结束的时候消亡
3.SqlSessionFactory建立SqlSession,目的执行sql语句,SqlSession是过程级,一个方法中建立,方法结束应该关闭
4.当用户使用mapper.xml文件中配置的的方法时,mybatis首先会解析sql动态标签为对应数据库sql语句的形式,并将其封装进MapperStatement对象,然后通过executor将sql注入数据库执行,并返回结果。
5.将返回的结果通过映射,包装成java对象。
接口映射就是在IBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们通过直接调用接口方法
例如:UserMapper userMapper=sqlSession.getMapper (UserMapper.class) 就可以,这样比起原来了SqlSession提供的方法,
例如List
注意:
(1)Mapper .xml文件的namespace属性必须配置为接口的全限定名称,接口方法名与Mapper.xml中的
(2)select查询通过在Mapper.xml中配置ResultMap标签,将查询结果的列名与字段名对应。 insert语句通过#{属性名}从接口参数获取值放到sql语句中。
(3)Mapper.xml接口绑定本质是动态代理。
(1)创建SqlSessionFactory
(2)通过SqlSessionFactory创建SqlSession
(3)通过SqlSession执行数据库操作
(4)调用session.commit()提交事务
(5)调用session.close()关闭事务
优点
(1)易于上手和掌握
(2)Sql写在xml里面,便于统一管理和优化
(3)减少Sql与程序代码的耦合
(4)提供xml标签,支持动态Sql编写
缺点
(1)Sql工作量大,尤其是字段多,关联表多时,更是如此
(2)Sql依赖于数据库,导致数据库移植性差
(3)由于xml里面标签id必须唯一,导致DAO中方法不支持方法重载。所以dao层必须是接口
Mapper接口方法名和mapper.xml中定义的每个sql的id相同
Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
Mapper.xml文件中的namespace即是mapper接口的类路径
(1)Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
(2)它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
能,Mybatis不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询,多对一查询,其实就是一对一查询,只需要把selectOne()修改为selectList()即可;多对多查询,其实就是一对多查询,只需要把selectOne()修改为selectList()即可。
关联对象查询,有两种实现方式,一种是单独发送一个sql去查询关联对象,赋给主对象,然后返回主对象。另一种是使用嵌套查询,嵌套查询的含义为使用join查询,一部分列是A对象的属性值,另外一部分列是关联对象B的属性值,好处是只发一个sql查询,就可以把主对象和其关联对象查出来。
第一种是使用
第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。
Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
1.SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
2.ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map
3.BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
可以声明一个request,或者session先拿到session,然后就可以放入数据,或者可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key
Spring 容器能够自动装配相互合作的bean,这意味着容器不需要
基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。
以@Configuration 注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。另一个例子是@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。
SpringBoot是我们最近的项目开始用的。我个人觉得SpringBoot比以前的SpringMVC更好用,因为他的配置文件少了。原来SpringMVC的SSM整合的配置文件特别多,用了SpringBoot之后 配置文件特别少了。就需要一个yml文件几乎全部搞定,我们用SpringBoot时结合的MyBatis 去做得,SpringBoot基本上是一些YML文件,properties文件,MyBatis全程用的注解方式开 发。SpringBoot和SpringMVC用法上大同小异,无非就是少了一些配置文件。启动SpringBoot 服务器的时候是他自带的Tomca和Jetty服务器,可以通过main方法启动。启动的注解是 @SpringBootApplication,我们也用过Spring的全家桶SpringBoot+JPA+SpringCloud组件,
1、选取最适用的字段属性
MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快。因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。另外一个提高效率的方法是在可能的情况下,应该尽量把字段设置为NOTNULL,这样在将来执行查询的时候,数据库不用去比较NULL值。
2、使用连接(JOIN)来代替子查询(Sub-Queries)
MySQL从4.1开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。
3、使用联合(UNION)来代替手动创建的临时表
MySQL从4.0的版本开始支持union查询,它可以把需要使用临时表的两条或更多的select查询合并的一个查询中。在客户端的查询会话结束的时候,临时表会被自动删除,从而保证数据库整齐、高效。
4、事务
尽管我们可以使用子查询(Sub-Queries)、连接(JOIN)和联合(UNION)来创建各种各样的查询,但不是所有的数据库操作都可以只用一条或少数几条SQL语句就可以完成的。事务的另一个重要作用是当多个用户同时使用相同的数据源时,它可以利用锁定数据库的方法来为用户提供一种安全的访问方式,这样可以保证用户的操作不被其它的用户所干扰。
5、锁定表
尽管事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是在很大的应用系统中。
6、使用外键
锁定表的方法可以维护数据的完整性,但是它却不能保证数据的关联性。这个时候我们就可以使用外键。
7、使用索引
索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(),MIN()和ORDERBY这些命令的时候,性能提高更为明显。
8、优化的查询语句
绝大多数情况下,使用索引可以提高查询的速度,但如果SQL语句使用不恰当的话,索引将无法发挥它应有的作用。
本质区别:
1.Oracle数据库是一个对象关系数据库管理系统(ORDBMS)。它通常被称为Oracle RDBMS或简称为Oracle,是一个收费的数据库。
2.MySQL是一个开源的关系数据库管理系统(RDBMS)。它是世界上使用最多的RDBMS,作为服务器运行,提供对多个数据库的多用户访问。它是一个开源、免费的数据库。
spring提供的两种注入方式,构造注入和setter,那其实构造注入时如果发现循环依赖会直接初始化容器失败,setter注入是采用三级缓存,发现循环依赖会有一个半初始化状态进行流转。
1.架构问题,优先架构重构
2.@lazy懒加载
3.不用构造器注入改用set,Spring已经帮忙解决
(1)Where 子句中:where 表之间的连接必须写在其他 Where 条件之前,那些可 以过滤掉最大数量记录的条件必须写在 Where 子句的末尾.HAVING 最后。
(2)用 EXISTS 替代 IN、用 NOT EXISTS 替代 NOT IN。
(3) 避免在索引列上使用计算
(4)避免在索引列上使用 IS NULL 和 IS NOT NULL
(5)对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 及的列上建立索引。
(6)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使 用索引而进行全表扫描。
(7)应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索 引而进行全表扫描。
(8)模糊查询like:关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%。
(9)理论上,尽量使用多表连接(join)查询(避免子查询)
sum 、avg 、max、min、count 等等。 连接查询有:内连接和外连接,外连接又分为左连接和右链接。左连接是指满足查询条 件的左表数据全部展示,右表不展示。内连接是指两张表的条件都必须满足。
我们一般对于查询概率比较高、字段值不固定的,经常作为 where 条件的字段设置索 引。
一般在开发的时候,如果某个查询操作特别慢的时候就会考虑添加索引。还有就是线上 数据库会统计慢 sql,这个时候也会根据情况进行索引的添加。 通过 explain 查看执行计划可以检查 sql 是否通过索引进行查询。
MyISAM:
不支持事务,但是每次查询都是原子的; 支持表级锁,即每次操作是对整个表加锁;
InnoDb:
支持 ACID 的事务,支持事务的四种隔离级别; 支持行级锁及外键约束:因此可以支持写并发; 不存储总行数;
事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些 操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务是数据库维护数 据一致性的单位,在每个事务结束时,都能保持数据一致性。
Mysql 中 InnoDB 支持的四种事务隔离级别: (由高到低)
1.串行化(serializable):一个事务一个事务的执行
2.可重复读(Repeatable-Read) 可重复读,无论其他事务是否修改并提交了数据, 在这个事务中看到的数据值始终不受其他事务影响 (mysql 数据库所默认的级别)
3.读已提交(Read Committed) 读取已提交,其他事务提交了对数据的修改后,本 事务就能读取到修改后的数据值(大多数数据库默认的隔离级别)
4.读未提交:(Read Uncommitted) 读取未提交,其他事务只要修改了数据,即使未 提交,本事务也能看到修改后的数据值
存储过程是一个预编译的 SQL 语句,优点是允许模块化的设计,就是说只需创建一次, 以后在该程序中就可以调用多次。如果某次操作需要执行多次 SQL,使用存储过程比 单纯 SQL 语句执行要快。可以用一个命令对象来调用存储过程
个web中可以没有web.xml文件,也就是说,web.xml文件并不是web工程必须的。
web.xml文件是用来初始化配置信息:比如Welcome页面、servlet、servlet-mapping、filter、listener、启动加载级别等。
当你的web工程没用到这些时,你可以不用web.xml文件来配置你的Application。
1,单表数据太少,索引反而会影响速度;更新非常频繁的数据不适宜建索引
2,where后的条件,order by ,group by 等这样过滤时,后面的字段最好加上索引。根据实际情况,选择PRIMARY KEY、UNIQUE、INDEX等索引,但是不是越多越好,要适度
3,联合查询,子查询等多表操作时关连字段要加索引据量特别大的时候,最好不要用联合查询,即使你做了索引
在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。
ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。
ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
1.@Autowried
(1)默认基于类型查找容器的的Bean进行注入(注入的Bean的实现类是唯一的)。
(2)当实现类的Bean大于一个的时候,需结合@Qualifier,根据Bean的名称来指定需要注入的实例。或者使用@Primary注解标注具体的Bean来让Spring优先选择该Bean进行注入
(3)@Autowried注解可以标注在构造方法、set方法(属性)、字段
@Qualifier标注在方法参数、set方法、字段上、类型上
@Primary标注在类上以及方法上
2.@Resource(JSR250的标准)
(1)默认是基于Bean的名称进行注入,如果查找的name不存在,则会根据类型进行查找
(2)当指定name属性时,则只按照名称进行查找
(3)当指定type属性时,则只按照类型进行查找
(4)当指定name和type时,则这两个属性必须同时满足才可注入
init为初始化方法,在Filter对象被创建出来时,Servlet容器会调用该方法对filter进行初始化。
destory为销毁的方法,在过滤器对象被销毁之前,服务器会调用这个方法执行善后工作。
doFilter为过滤器中最核心的方法,对访问的请求和响应进行拦截,当过滤器拦截到对资源的访问时,服务器会自动调用该方法执行过滤代码。 我们只需要在这个方法中设计过滤器的逻辑代码即可。
当服务器启动,web应用加载后,立即创建出这个web应用中的所有过滤器对象,创建出来后立即调用过滤器的init方法执行初始化操作.从此这些过滤器对象驻留在内存中为后续的拦截进行服务.每当拦截到资源时,都会导致dofilter方法执行.最终直到服务器关闭或web应用移除出容器时,随着web应用的销毁,过滤器对象销毁,销毁之前调用destory方法执行善后工作。