DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此。
DAO层的设计首先是设计DAO的接口。
然后在Spring的配置文件中定义此接口的实现类。
然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰。
DAO层的数据源配置,以及有关数据库连接的参数都在Spring的配置文件中进行配置。
Service层:Service层主要负责业务模块的逻辑应用设计。
首先设计接口,再设计其实现的类。
接着再在Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理。
Service层的业务实现,具体要调用到已定义的DAO层的接口。
封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。
Controller层:Controller层负责具体的业务模块流程的控制。
在此层里面要调用Service层的接口来控制业务流程。
控制的配置也同样是在Spring的配置文件里面进行,针对具体的业务流程,会有不同的控制器,我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,这样不仅使程序结构变得清晰,也大大减少了代码量。
View层:View层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示。
1、如何理解Spring?
2、介绍一下Spring的事物管理
3 、SSM优缺点、使用场景?
4、MyBatis 中使用#和$书写占位符有什么区别?
5、解释一下 MyBatis 中命名空间(namespace)的作用。
6、什么是 IoC 和 DI?DI 是如何实现的?
7、解释一下什么叫 AOP(面向切面编程)?
8、你是如何理解"横切关注"这个概念的?
9、你如何理解 AOP 中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?
10、Spring 支持的事务管理类型有哪些?你在项目中使用哪种方式?
11、Spring MVC的工作原理是怎样的?
12、什么是 XSS 攻击?
13、SQL 注入攻击?
14、什么是CSRF攻击?
15、简述Mybatis一级、二级缓存
16、JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的?
具体来说Spring是一个轻量级的容器,用于管理业务相关对象的。核心功能主要为:IOC,AOP,MVC。
IOC:控制反转,将对象的创建过程交给容器,让容器管理对象的生命周期如创建,初始化,销毁等。
AOP:面向切面编程,对关注点进行模块化,通过对某一功能点进行编程,比如记录日志,有很多个类都需要记录日志的方法,则创建记录日志的代理方法,需要调用该功能是只需要调用代理方法,这就是AOP。
MVC:SpringMvc,Spring提供的基于MVC模式设计的Web框架,如今比较流行的框架之一。
事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作。这样可以防止出现脏数据,防止数据库数据出现问题。
开发中为了避免这种情况一般都会进行事务管理。Spring中也有自己的事务管理机制,一般是使用TransactionMananger进行管 理,可以通过Spring的注入来完成此功能。
Spring支持如下两种方式的事务管理:
编程式事务管理:这意味着你可以通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
声明式事务管理:这种方式意味着你可以将事务管理和业务代码分离。你只需要通过注解或者XML配置管理事务。
一般选择声明式事务管理,因为这种方式和应用程序的关联较少。
(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
(2)Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
(3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
(4)总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。
答:#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;$将传入的数据直接显示生成在SQL 中。
注意:使用$占位符可能会导致 SQL 注射攻击,能用#的地方就不要使用$,写 order by 子句的时候应该用$而不是#。
答:在大型项目中,可能存在大量的 SQL 语句,这时候为每个 SQL 语句起一个唯一的标识(ID)就变得并不容易了。为了解决这个问题,在 MyBatis 中,可以为每个映射文件起一个唯一的命名空间,这样定义在这个映射文件中的每个 SQL 语句就成了定义在这个命名空间中的一个 ID。只要我们能够保证每个命名空间中这个 ID 是唯一的,即使在不同映射文件中的语句 ID 相同,也不会再产生冲突了。
答:IoC 叫控制反转,是 Inversion of Control 的缩写,DI(Dependency Injection)叫依赖注入,是对 IoC 更简单的诠释。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的"控制反转"就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。IoC 体现了好莱坞原则 -"Don’tcallme,we willcallyou"。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI 是对 IoC 更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
答:AOP(Aspect-Oriented Programming)指一种程序设计范型,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象、类或方法中的横切关注点(crosscutting concern)。
答:"横切关注"是会影响到整个应用程序的关注功能,它跟正常的业务逻辑是正交的,没有必然的联系,但是几乎所有的业务逻辑都会涉及到这些关注功能。通常,事务、日志、安全性等关注就是应用中的横切关注功能。
答:a. 连接点(Joinpoint):程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。Spring 仅支持方法的连接点。
b. 切点(Pointcut):如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。Spring AOP 的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。
c. 增强(Advice):增强是织入到目标类连接点上的一段程序代码。Spring 提供的增强接口都是带方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice 等。很多资料上将增强译为“通知”,这明显是个词不达意的翻译,让很多程序员困惑了许久。
说明: Advice 在国内的很多书面资料中都被翻译成"通知",但是很显然这个翻译无法表达其本质,有少量的读物上将这个词翻译为"增强",这个翻译是对 Advice 较为准确的诠释,我们通过 AOP 将横切关注功能加到原有的业务逻辑上,这就是对原有业务逻辑的一种增强,这种增强可以是前置增强、后置增 强、返回后增强、抛异常时增强和包围型增强。
d. 引介(Introduction):引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过引介功能,可以动态的未该业务类添加接口的实现逻辑,让业务类成为 这个接口的实现类。
e. 织入(Weaving):织入是将增强添加到目标类具体连接点上的过程,AOP 有三种织入方式:
①编译期织入:需要特殊的 Java 编译期(例如 AspectJ 的 ajc);
②装载期织入:要求使用特殊的类加载器, 在装载类的时候对类进行增强;
③运行时织入:在运行时为目标类生成代理实现增强。Spring 采用了动 态代理的方式实现了运行时织入,而 AspectJ 采用了编译期织入和装载期织入的方式。
f. 切面(Aspect):切面是由切点和增强(引介)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。
答:Spring 支持编程式事务管理和声明式事务管理。许多 Spring 框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,因为编程式事务允许你通过代码控制业务。
答:SpringMVC工作原理图如下:
(1)客户端的所有请求都交给前端控制器 DispatcherServlet 来处理,它会负责调用系统的其他模块来真正处理用户的请求。
(2) DispatcherServlet 收到请求后,将根据请求的信息(包括 URL、HTTP 协议方法、请求头、请求参数、Cookie 等)以及 HandlerMapping 的配置找到处理该请求的 Handler(任何一个对象都可以作为请求的 Handler)。
(3)在这个地方 Spring 会通过 HandlerAdapter 对该处理器进行封装。
(4)HandlerAdapter 是一个适配器,它用统一的接口对各种 Handler 中的方法进行调用。
(5)Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给 DispatcherServlet,
ModelAndView 顾名思义,包含了数据模型以及相应的视图的信息。
(6) ModelAndView 的视图是逻辑视图,DispatcherServlet 还要借助 ViewResolver 完成从逻辑视图到真实视图对象的解析工作。
(7)当得到真正的视图对象后,DispatcherServlet 会利用视图对象对模型数据进行渲染。
(8)客户端得到响应,可能是一个普通的 HTML 页面,也可以是 XML 或 JSON 字符串,还可以是一张图片或者一个 PDF 文件。
答: XSS(Cross Site Script,跨站脚本攻击)是向网页中注入恶意脚本在用户浏览网页时在用户浏览器中执行恶意脚本的攻击方式。跨站脚本攻击分有两种形式:反射型攻击(诱使用户点击一个嵌入恶意 脚本的链接以达到攻击的目标,目前有很多攻击者利用论坛、微博发布含有恶意脚本的 URL 就属于这种方式)和持久型攻击(将恶意脚本提交到被攻击网站的数据库中,用户浏览网页时,恶意脚本从数据 库中被加载到页面执行,QQ 邮箱的早期版本就曾经被利用作为持久型跨站脚本攻击的平台)。XSS 虽然不是什么新鲜玩意,但是攻击的手法却不断翻新,防范 XSS 主要有两方面:消毒(对危险字符进行转义)和HttpOnly (防范 XSS 攻击者窃取 Cookie 数据)。
答: SQL 注入攻击是注入攻击最常见的形式(此外还有 OS 注入攻击(Struts 2 的高危漏洞就是通过OGNL 实施 OS 注入攻击导致的)),当服务器使用请求参数构造 SQL 语句时,恶意的 SQL 被嵌入到SQL 中交给数据库执行。SQL 注入攻击需要攻击者对数据库结构有所了解才能进行,攻击者想要获得表结构有多种方式:
(1)如果使用开源系统搭建网站,数据库结构也是公开的(目前有很多现成的系统可以直接搭建论坛,电商网站,虽然方便快 捷但是风险是必须要认真评估的);
(2)错误回显(如果将服务器的错误信息直接显示在页面上,攻击者可以通过非法参数引发页面错误从而通过错误信息了解数据库结构,Web应用应当设置友好的错误页,一方面符合最小惊讶原则,一方面屏蔽掉可能给系统带来危险的错误回显信息);
(3)盲注。防范 SQL 注入攻击也可以采用消毒的方式,通过正则表达式对请求参数进行验证,此外,参数绑定也是很好的手段,这样恶意的 SQL 会被当做 SQL 的参数而不是命令被执行,JDBC 中的 PreparedStatement 就是支持参数绑定的语句对象,从性能和安全性上都明显优于 Statement。
答: CSRF 攻击(Cross Site Request Forgery,跨站请求伪造)是攻击者通过跨站请求,以合法的用户身份进行非法操作(如转账或发帖等)。CSRF 的原理是利用浏览器的 Cookie 或服务器的Session,盗取用户身份,其原理如下图所示。防范 CSRF 的主要手段是识别请求者的身份,主要有以下几种方式:
(1) 在表单中添加令牌(token);
(2) 验证码;
(3) 检查请求头中的 Referer。
令牌和验证都具有一次消费性的特征,因此在原理上一致的,但是验证码是一种糟糕的用户体验,不是必要的情况下不要轻易使用验证码,目前很多网站的做法是如果在短时间内多次提交一个表单未获得成功后才要求提供验证码,这样会获得较好的用户体验。
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
(1)数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
(2) Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
(3) 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决: Mybatis自动将java对象映射至sql语句。
(4)对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象。
另外的参考回答
频繁的创建数据连接,关闭资源,造成性能的下降,使用数据文库连接池 解决这个问题用数据库连接池.在SqlMapConfig.xml 配置数据库连接池 c3p0 DBCP
Jdbc 编程sql 的可维护性不高. Mybatis采用配置文件的方式解决sql可维护的问题
在mapper.xml中配置 ,是sql与代码分离 可维护行变高
Jdbc 传入参数比较麻烦. 参数有时候多,参数要和占位符一一对应.
Mybatis 使用statement 的 paremterType 定义输入的参数类型
对结果解析比较麻烦. Mybatis 使用resultType 自动映射到pojo中解决了jdbc解析结果的麻烦
欢迎大家关注我的公众号【程序员追风】,2019年多家公司java面试题整理了120多页pdf文档,文章都会在里面更新,整理的资料也会放在里面。
欢迎大家一起交流,喜欢文章记得关注我点个赞哟,感谢支持!