最近整理的一些常见的面试题,面试大全,黑马程序员面试宝典题库---框架--篇

版权声明:代码共享,欢迎copy https://blog.csdn.net/qq_29073921/article/details/82351320

框架(评论留言获取原件)


一、 SpringMVC


1. SpringMVC 的工作原理


a. 用户向服务器发送请求,请求被 springMVC 前端控制器 DispatchServlet 捕获;
b. DispatcherServle 对请求 URL 进行解析,得到请求资源标识符(URL),然后根据该 URL 调用 HandlerMapping
将请求映射到处理器 HandlerExcutionChain;
c. DispatchServlet 根据获得 Handler 选择一个合适的 HandlerAdapter 适配器处理;
d. Handler 对数据处理完成以后将返回一个 ModelAndView()对象给 DisPatchServlet;
e. Handler 返回的 ModelAndView()只是一个逻辑视图并不是一个正式的视图, DispatcherSevlet 通过ViewResolver 试图解析器将逻辑视图转化为真正的视图 View;
h. DispatcherServle 通过 model 解析出 ModelAndView()中的参数进行解析最终展现出完整的 view 并返回给客户端;


2. SpringMVC 常用注解都有哪些?


@requestMapping 用于请求 url 映射。 

@RequestBody 注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象。
@ResponseBody 注解实现将 controller 方法返回对象转化为 json 响应给客户。


3. 如何开启注解处理器和适配器?


我们在项目中一般会在 springmvc.xml 中通过开启 <mvc:annotation-driven>来实现注解处理器和适配器的开启。


4. 如何解决 get 和 post 乱码问题?


解决 post 请求乱码:我们可以在 web.xml 里边配置一个 CharacterEncodingFilter 过滤器。 设置为 utf-8.
解决 get 请求的乱码:有两种方法。对于 get 请求中文参数出现乱码解决方法有两个:
        1. 修改 tomcat 配置文件添加编码与工程编码一致。
        2. 另 外 一 种 方 法 对 参 数 进 行 重 新 编 码

String userName = New  String(Request.getParameter(“userName”).getBytes(“ISO8859-1”), “utf-8”);


二、 Spring


1. 谈谈你对 Spring 的理解


Spring 是一个开源框架,为简化企业级应用开发而生。 Spring 可以是使简单的 JavaBean 实现以前只有 EJB 才能实现的功能。 Spring 是一个 IOC 和 AOP 容器框架。
Spring 容器的主要核心是:
控制反转(IOC),传统的 java 开发模式中,当需要一个对象时,我们会自己使用 new 或者 getInstance 等直接或者间接调用构造方法创建一个对象。而在 spring 开发模式中, spring 容器使用了工厂模式为我们创建了所需要的对象,不需要我们自己创建了,直接调用 spring 提供的对象就可以了,这是控制反转的思想。
依赖注入(DI), spring 使用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想。
面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。 AOP 底层是动态代理,如果是接口采用 JDK 动态代理,如果是类采用CGLIB 方式实现动态代理。


2. Spring 中的设计模式


a. 单例模式——spring 中两种代理方式,若目标对象实现了若干接口,spring 使用 jdk 的 java.lang.reflect.Proxy感恩于心,回报于行。 面试宝典系列-Java类代理。若目标兑现没有实现任何接口, spring 使用 CGLIB 库生成目标类的子类。
单例模式——在 spring 的配置文件中设置 bean 默认为单例模式。
b. 模板方式模式——用来解决代码重复的问题。
比如: RestTemplate、 JmsTemplate、 JpaTemplate
d. 前端控制器模式——spring 提供了前端控制器 DispatherServlet 来对请求进行分发。
e. 试图帮助(view helper) ——spring 提供了一系列的 JSP 标签,高效宏来帮助将分散的代码整合在试图中。
f. 依赖注入——贯穿于 BeanFactory/ApplacationContext 接口的核心理念。
g. 工厂模式——在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用同一个接口来指向新创建的对象。 Spring 中使用 beanFactory 来创建对象的实例。


3. Spring 的常用注解


Spring 在 2.5 版本以后开始支持注解的方式来配置依赖注入。可以用注解的方式来代替 xml 中 bean 的描述。注解注入将会被容器在 XML 注入之前被处理,所以后者会覆盖掉前者对于同一个属性的处理结果。
注解装配在 spring 中默认是关闭的。所以需要在 spring 的核心配置文件中配置一下才能使用基于注解的装配模式。配置方式如下:
<context:annotation-config />
常用的注解:
@Required:该注解应用于设值方法
@Autowired:该注解应用于有值设值方法、非设值方法、构造方法和变量。
@Qualifier:该注解和@Autowired 搭配使用,用于消除特定 bean 自动装配的歧义。


4. 简单介绍一下 Spring bean 的生命周期

bean 定义:在配置文件里面用<bean></bean>来进行定义。
bean 初始化:有两种方式初始化:
1.在配置文件中通过指定 init-method 属性来完成
2.实现 org.springframwork.beans.factory.InitializingBean 接口
       bean 调用:有三种方式可以得到 bean 实例,并进行调用
       bean 销毁:销毁有两种方式
1.使用配置文件指定的 destroy-method 属性
2.实现 org.springframwork.bean.factory.DisposeableBean 接口
参考资料: https://www.cnblogs.com/zrtqsk/p/3735273.html


5. Spring 结构图


(1) 核心容器:包括 Core、 Beans、 Context、 EL 模块。
Core 模块:封装了框架依赖的最底层部分,包括资源访问、类型转换及一些常用工具类。
Beans 模块:提供了框架的基础部分,包括反转控制和依赖注入。其中 Bean Factory 是容器核心,本质是“工厂设计模式”的实现,而且无需编程实现“单例设计模式”,单例完全由容器控制,而且提倡面向接口编程,而非面向实现编程;所有应用程序对象及对象间关系由框架管理,从而真正把你从程序逻辑中把维护对象之间的依赖关系提取出来,所有这些依赖关系都由 BeanFactory 来维护。
Context 模块:以 Core 和 Beans 为基础,集成 Beans 模块功能并添加资源绑定、数据验证、国际化、 Java EE 支持、容器生命周期、事件传播等;核心接口是 ApplicationContext。
EL 模块:提供强大的表达式语言支持,支持访问和修改属性值,方法调用,支持访问及修改数组、容器和索引器,命名变量,支持算数和逻辑运算,支持从 Spring 容器获取 Bean,它也支持列表投影、选择和一般的列表聚合等。
(2) AOP、 Aspects 模块:
AOP 模块:Spring AOP 模块提供了符合 AOP Alliance 规范的面向方面的编程(aspect-oriented programming)实现,提供比如日志记录、权限控制、性能统计等通用功能和业务逻辑分离的技术,并且能动态的把这些功能添加到需要的代码中;这样各专其职,降低业务逻辑和通用功能的耦合。
Aspects 模块:提供了对 AspectJ 的集成, AspectJ 提供了比 Spring ASP 更强大的功能。
数据访问/集成模块:该模块包括了 JDBC、 ORM、 OXM、 JMS 和事务管理。
事务模块:该模块用于 Spring 管理事务,只要是 Spring 管理对象都能得到 Spring 管理事务的好处,无需在代码中进行事务控制了,而且支持编程和声明性的事务管理。
JDBC 模块:提供了一个 JBDC 的样例模板, 使用这些模板能消除传统冗长的 JDBC 编码还有必须的事务控制,而且能享受到 Spring 管理事务的好处。
ORM 模块:提供与流行的“对象-关系”映射框架的无缝集成,包括 Hibernate、 JPA、 MyBatis 等。而且可以使用 Spring 事务管理,无需额外控制事务。
OXM 模块:提供了一个对 Object/XML 映射实现,将 java 对象映射成 XML 数据,或者将 XML 数据映射成 java对象, Object/XML 映射实现包括 JAXB、 Castor、 XMLBeans 和 XStream。
JMS 模块:用于 JMS(Java Messaging Service),提供一套 “消息生产者、消息消费者”模板用于更加简单的使用 JMS, JMS 用于用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
Web/Remoting 模块: Web/Remoting 模块包含了 Web、 Web-Servlet、 Web-Struts、 Web-Porlet 模块。
Web 模块:提供了基础的 web 功能。例如多文件上传、集成 IoC 容器、远程过程访问(RMI、 Hessian、 Burlap)以及 Web Service 支持,并提供一个 RestTemplate 类来提供方便的 Restful services 访问。
Web-Servlet 模块:提供了一个 Spring MVC Web 框架实现。 Spring MVC 框架提供了基于注解的请求资源注入、更简单的数据绑定、数据验证等及一套非常易用的 JSP 标签,完全无缝与 Spring 其他技术协作。
Web-Struts 模块:提供了与 Struts 无缝集成, Struts1.x 和 Struts2.x 都支持
Test 模块: Spring 支持 Junit 和 TestNG 测试框架,而且还额外提供了一些基于 Spring 的测试功能,比如在测试 Web 框架时,模拟 Http 请求的功能。


6. Spring 能帮我们做什么?


a. Spring 能帮我们根据配置文件创建及组装对象之间的依赖关系。
Spring 根据配置文件来进行创建及组装对象间依赖关系,只需要改配置文件即可
b. Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制。
Spring 面向切面编程能提供一种更好的方式来完成,一般通过配置方式,而且不需要在现有代码中添加任何额外代码,现有代码专注业务逻辑。
c. Spring 能非常简单的帮我们管理数据库事务。
采用 Spring,我们只需获取连接,执行 SQL,其他事物相关的都交给 Spring 来管理了。
d. Spring 还能与第三方数据库访问框架(如 Hibernate、 JPA)无缝集成,而且自己也提供了一套 JDBC访问模板,来方便数据库访问。
e. Spring 还能与第三方 Web(如 Struts、 JSF)框架无缝集成,而且自己也提供了一套 Spring MVC框架,来方便 web 层搭建。
f. Spring 能方便的与 Java EE(如 Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。


7. 请描述一下 Spring 的事务


声明式事务管理的定义:用在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。这样的好处是,事务管理不侵入开发的组件,具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可,这样维护起来极其方便。
基于 TransactionInterceptor 的声明式事务管理:两个次要的属性: transactionManager,用来指定一个事务治理器 ,并 将具体事务相关的操作请托给它 ;其他一个是 Properties 类型的transactionAttributes 属性,该属性的每一个键值对中,键指定的是方法名,方法名可以行使通配符,而值就是表现呼应方法的所运用的事务属性。

编程式事务与声明式事务的区别:
编程式事务是自己写事务处理的类,然后调用
声明式事务是在配置文件中配置,一般搭配在框架里面使用!


8. BeanFactory 常用的实现类有哪些?


Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从正真的应用代码中分离。常用的 BeanFactory 实现有 DefaultListableBeanFactory 、 XmlBeanFactory 、 ApplicationContext 等。
XMLBeanFactory, 最常用的就是 org.springframework.beans.factory.xml.XmlBeanFactory ,它根据 XML 文件中的定义加载 beans。该容器从 XML 文件读取配置元数据并用它去创建一个完全配置的系统或应用。


9. 解释 Spring JDBC、 Spring DAO 和 Spring ORM


Spring-DAO 并非 Spring 的一个模块,它实际上是指示你写 DAO 操作、写好 DAO 操作的一些规范。因此,对于访问你的数据它既没有提供接口也没有提供实现更没有提供模板。在写一个 DAO 的时候,你应该使用 @Repository 对其进行注解,这样底层技术(JDBC, Hibernate, JPA,等等)的相关异常才能一致性地翻译为相应的 DataAccessException 子类。
Spring-JDBC 提供了 Jdbc 模板类,它移除了连接代码以帮你专注于 SQL 查询和相关参数。 Spring-JDBC 还提供了一个 JdbcDaoSupport,这样你可以对你的 DAO 进行扩展开发。它主要定义了两个属性:一个 DataSource和一个 JdbcTemplate,它们都可以用来实现 DAO 方法。 JdbcDaoSupport 还提供了一个将 SQL 异常转换为Spring DataAccessExceptions 的异常翻译器。
Spring-ORM 是一个囊括了很多持久层技术(JPA, JDO, Hibernate, iBatis)的总括模块。对于这些技术中的每一个, Spring 都提供了集成类,这样每一种技术都能够在遵循 Spring 的配置原则下进行使用,并平稳地和 Spring 事务管理进行集成。
对 于 每 一 种 技 术 , 配 置 主 要 在 于 将 一 个 DataSource bean 注 入 到 某 种 SessionFactory 或者 EntityManagerFactory 等 bean 中。纯 JDBC 不需要这样的一个集成类(JdbcTemplate 除外),因为 JDBC 仅依赖于一个 DataSource。
如果你计划使用一种 ORM 技术,比如 JPA 或者 Hibernate,那么你就不需要 Spring-JDBC 模块了,你需要的是这个 Spring-ORM 模块。


10. 简单介绍一下 Spring WEB 模块。


Spring 的 WEB 模块是构建在 application context 模块基础之上,提供一个适合 web 应用的上下文。这个模块也包括支持多种面向 web 的任务,如透明地处理多个文件上传请求和程序级请求参数的绑定到你的业务对象。它也有对 Jakarta Struts 的支持。


11. Spring 配置文件有什么作用?


Spring 配置文件是个 XML 文件,这个文件包含了类信息,描述了如何配置它们,以及如何相互调用。


12. 什么是 Spring IOC 容器?


IOC 控制反转: Spring IOC 负责创建对象,管理对象。通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。


13. IOC 的优点是什么?


IOC 或 依赖注入把应用的代码量降到最低。它使应用容易测试,单元测试不再需要单例和 JNDI 查找机制。最小的代价和最小的侵入性使松散耦合得以实现。 IOC 容器支持加载服务时的饿汉式初始化和懒加载。


14. ApplicationContext 的实现类有哪些?


FileSystemXmlApplicationContext :此容器从一个 XML 文件中加载 beans 的定义, XML Bean 配置文件的全路径名必须提供给它的构造函数。
ClassPathXmlApplicationContext:此容器也从一个 XML 文件中加载 beans 的定义,这里,你需要正确设置classpath 因为这个容器将在 classpath 里找 bean 配置。
WebXmlApplicationContext:此容器加载一个 XML 文件,此文件定义了一个 WEB 应用的所有 bean。


15. BeanFactory 与 AppliacationContext 有什么区别


1. BeanFactory
基础类型的 IOC 容器,提供完成的 IOC 服务支持。如果没有特殊指定,默认采用延迟初始化策略。相对来说,容器启动初期速度较快,所需资源有限。
2.ApplicationContext
ApplicationContext 是在 BeanFactory 的基础上构建,是相对比较高级的容器实现,除了 BeanFactory 的所有支持外, ApplicationContext 还提供了事件发布、国际化支持等功能。 ApplicationContext 管理的对象,在容器启动后默认全部初始化并且绑定完成。


16. 什么是 Spring 的依赖注入? 


平常的 java 开发中,程序员在某个类中需要依赖其它类的方法,则通常是 new 一个依赖类再调用类实例的方法,这种开发存在的问题是 new 的类实例不好统一管理, spring 提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过 spring 容器帮我们 new 指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转” ,通俗的理解是:平常我们 new 一个实例,这个实例的控制权是我们程序员,而控制反转是指 new 实例工作不由我们程序员来做而是交给 spring 容器来做。


17. 有哪些不同类型的 IOC(依赖注入)方式?


Spring 提供了多种依赖注入的方式。
1.Set 注入
2.构造器注入
3.静态工厂的方法注入
4.实例工厂的方法注入
参考资料: https://www.cnblogs.com/java-class/p/4727775.html


18. 什么是 Spring beans?


Spring beans 是那些形成 Spring 应用的主干的 java 对象。它们被 Spring IOC 容器初始化,装配,和管理。这些 beans 通过容器中配置的元数据创建。比如,以 XML 文件中<bean/> 的形式定义。
Spring 框架定义的 beans 都是单例 beans。


19. 一个 Spring Beans 的定义需要包含什么?


一个 Spring Bean 的定义包含容器必知的所有配置元数据,包括如何创建一个 bean,它的生命周期详情及它的依赖。


20. 你怎样定义类的作用域?


当定义一个<bean> 在 Spring 里,我们还能给这个 bean 声明一个作用域。它可以通过 bean 定义中的 scope 属性来定义。如,当 Spring 要在需要的时候每次生产一个新的 bean 实例, bean 的 scope 属性被指定为 prototype。
另一方面,一个 bean 每次使用的时候必须返回同一个实例,这个 bean 的 scope 属性必须设为 singleton。


21. 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 情形下有效。
缺省的 Spring bean 的作用域是 Singleton。


22. Spring 框架中的单例 bean 是线程安全的吗?


Spring 框架中的单例 bean 不是线程安全的。


23. 什么是 Spring 的内部 bean?


当一个 bean 仅被用作另一个 bean 的属性时,它能被声明为一个内部 bean,为了定义 inner bean,在Spring 的 基于 XML 的 配置元数据中,可以在 <property/>或 <constructor-arg/> 元素内使用<bean/> 元素,内部 bean 通常是匿名的,它们的 Scope 一般是 prototype。


24. 在 Spring 中如何注入一个 java 集合?


Spring 提供以下几种集合的配置元素:
<list>类型用于注入一列值,允许有相同的值。
<set> 类型用于注入一组值,不允许有相同的值。
<map> 类型用于注入一组键值对,键和值都可以为任意类型。
<props>类型用于注入一组键值对,键和值都只能为 String 类型。


25. 什么是 bean 的自动装配?


无须在 Spring 配置文件中描述 javaBean 之间的依赖关系(如配置<property>、 <constructor-arg>)。 IOC 容器会自动建立 javabean 之间的关联关系。


26. 解释不同方式的自动装配 。 


有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入。
no:默认的方式是不进行自动装配,通过显式设置 ref 属性来进行装配。
byName:通过参数名自动装配, Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byname,之后容器试图匹配、装配和该 bean 的属性具有相同名字的 bean。
byType::通过参数类型自动装配, Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byType,之后容器试图匹配、装配和该 bean 的属性具有相同类型的 bean。如果有多个 bean 符合条件,则抛出错误。
constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
autodetect:首先尝试使用 constructor 来自动装配,如果无法工作, 则使用 byType 方式。


27. 什么是基于 Java 的 Spring 注解配置? 给一些注解的例子


基于 Java 的配置,允许你在少量的 Java 注解的帮助下,进行你的大部分 Spring 配置而非通过 XML 文件。
以@Configuration 注解为例,它用来标记类可以当做一个 bean 的定义,被 Spring IOC 容器使用。另一个例子是@Bean 注解,它表示此方法将要返回一个对象,作为一个 bean 注册进 Spring 应用上下文。


28. 什么是基于注解的容器配置?


相对于 XML 文件,注解型的配置依赖于通过字节码元数据装配组件,而非尖括号的声明。开发者通过在相应的类,方法或属性上使用注解的方式,直接组件类中进行配置,而不是使用 xml 表述 bean 的装配关系。


29. 怎样开启注解装配?


注 解 装 配 在 默 认 情 况 下 是 不 开 启 的 , 为 了 使 用 注 解 装 配 , 我 们 必 须 在 Spring 配 置 文 件 中 配置 <context:annotation-config/>元素。


30. 在 Spring 框架中如何更有效地使用 JDBC?


使用 SpringJDBC 框架, 资源管理和错误处理的代价都会被减轻。所以开发者只需写 statements 和 queries 从数据存取数据, JDBC 也可以在 Spring 框架提供的模板类的帮助下更有效地被使用,这个模板叫 JdbcTemplate 。
JdbcTemplate 类提供了很多便利的方法解决诸如把数据库数据转变成基本数据类型或对象,执行写好的或可调用的数据库操作语句,提供自定义的数据错误处理。


31. 使用 Spring 通过什么方式访问 Hibernate?


在 Spring 中有两种方式访问 Hibernate:
控制反转 HibernateTemplate 和 Callback。
继承 HibernateDAOSupport 提供一个 AOP 拦截器。


32. Spring 支持的 ORM 框架有哪些?


Spring 支持以下 ORM:
Hibernate、 iBatis、 JPA (Java Persistence API)、 TopLink、 JDO (Java Data Objects)、 OJB

33. 简单解释一下 spring 的 AOP


        AOP(Aspect Oriented Programming),即面向切面编程,可以说是 OOP(Object Oriented Programming,面向对象编程)的补充和完善。 OOP 引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过 OOP 允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在 OOP 设计中,它导致了大量代码的重复,而不利于各个模块的重用。
        AOP 技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术, AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。 AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
        AOP 核心就是切面,它将多个类的通用行为封装成可重用的模块,该模块含有一组 API 提供横切功能。比如,一个日志模块可以被称作日志的 AOP 切面。根据需求的不同,一个应用程序可以有若干切面。在 Spring AOP 中,切面通过带有@Aspect 注解的类实现。


34. 在 Spring AOP 中,关注点和横切关注的区别是什么?


关注点是应用中一个模块的行为,一个关注点可能会被定义成一个我们想实现的一个功能。横切关注点是一个关注点,此关注点是整个应用都会使用的功能,并影响整个应用,比如日志,安全和数据传输,几乎应用的每个模块都需要的功能。因此这些都属于横切关注点。


35. 什么是连接点?


被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。


36. Spring 的通知是什么?有哪几种类型?


通知是个在方法执行前或执行后要做的动作,实际上是程序执行时要通过 SpringAOP 框架触发的代码段。
Spring 切面可以应用五种类型的通知:
before:前置通知,在一个方法执行前被调用。
after: 在方法执行之后调用的通知,无论方法执行是否成功。
after-returning: 仅当方法成功完成后执行的通知。
after-throwing: 在方法抛出异常退出时执行的通知。
around: 在方法执行之前和之后调用的通知。


37. 什么是切点?


切入点是一个或一组连接点,通知将在这些位置执行。可以通过表达式或匹配的方式指明切入点。


38. 什么是目标对象?


被一个或者多个切面所通知的对象。它通常是一个代理对象。也指被通知(advised)对象。


39. 什么是代理?


代理是通知目标对象后创建的对象。从客户端的角度看,代理对象和目标对象是一样的。


40. 什么是织入? 什么是织入应用的不同点?


织入是将切面和到其他应用类型或对象连接或创建一个被通知对象的过程。织入可以在编译时,加载时,或运行时完成。


三、 Shiro


1. 简单介绍一下 Shiro 框架


Apache Shiro 是 Java 的一个安全框架。使用 shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE环境,也可以用在 JavaEE 环境。 Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。
三个核心组件: Subject, SecurityManager Realms.
        Subject:即“当前操作用户” 。但是,在 Shiro 中, Subject 这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西” 。但考虑到大多数目的和用途,你可以把它认为是 Shiro 的“用户” 概念。
       Subject 代表了当前用户的安全操作, SecurityManager 则管理所有用户的安全操作。
       SecurityManager:它是 Shiro 框架的核心,典型的 Facade 模式, Shiro 通过 SecurityManager 来管理内部组件实例,并通过它来提供安全管理的各种服务。
       Realm: Realm 充当了 Shiro 与应用安全数据间的“桥梁” 或者“连接器” 。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时, Shiro 会从应用配置的 Realm 中查找用户及其权限信息。


2. Shiro 主要的四个组件


SecurityManager
典型的 Facade, Shiro 通过它对外提供安全管理的各种服务。
Authenticator
对“Who are you ?”进行核实。通常涉及用户名和密码。 这个组件负责收集 principals 和 credentials,并将它们提交给应用系统。如果提交的 credentials 跟应用系统中提供的 credentials 吻合,就能够继续访问,否则需要重新提交 principals 和 credentials, 或者直接终止访问。
Authorizer
身份份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“who can do which actions”。 Shiro 采用“基于 Realm”的方法,即用户(又称 Subject)、 用户组、角 色和permission 的聚合体。
Session Manager
这个组件保证了异构客户端的访问,配置简单。它是基于 POJO/J2SE 的,不跟任何的客户 端或者协议绑定。


3. Shiro 运行原理


1、 Application Code:应用程序代码,就是我们自己的编码,如果在程序中需要进 行权限控制,需要调用Subject 的 API。
2、 Subject:主体,代表的了当前用户。所有的 Subject 都绑定到 SecurityManager, 与 Subject 的所有交互都会委托给 SecurityManager,可以将 Subject 当成一个 门面,而真正执行者是 SecurityManager 。
3、 SecurityManage:安全管理器,所有与安全有关的操作都会与 SecurityManager 交互,并且它管理所有的 Subject 。
4、 Realm:域 shiro 是从 Realm 来获取安全数据(用户,角色,权限)。就是说 SecurityManager要验证用户身份, 那么它需要从 Realm 获取相应的用户进行比较以确定用户 身份是否合法;也需要从Realm 得到用户相应的角色/权限进行验证用户是否 能进行操作; 可以把 Realm 看成 DataSource,即安全数据源 。


4. Shiro 的四种权限控制方式


url 级别权限控制
方法注解权限控制
代码级别权限控制
页面标签权限控制
详见网址: https://www.cnblogs.com/cocosili/p/7103025.html


5. 授权实现的流程


(1)、什么是粗颗粒和细颗粒权限?
对资源类型的管理称为粗颗粒度权限控制,即只控制到菜单、按钮、方法,粗粒度的例子比如:用户具有用户管理的权限,具有导出订单明细的权限。对资源实例的控制称为细颗粒度权限管理,即控制到数据级别的权限,比如:用户只允许修改本部门的员工信息,用户只允许导出自己创建的订单明细。
总结:
粗颗粒权限:针对 url 链接的控制。
细颗粒权限:针对数据级别的控制。

比如:查询用户权限。
卫生局可以查询所有用户。
卫生室可以查询本单位的用户。
通常在 service 中编程实现。
(2)、粗颗粒和细颗粒如何授权?
对于粗颗粒度的授权可以很容易做系统架构级别的功能,即系统功能操作使用统一的粗颗粒度的权限管理。
对于细颗粒度的授权不建议做成系统架构级别的功能,因为对数据级别的控制是系统的业务需求,随着业务需求的变更业务功能变化的可能性很大,建议对数据级别的权限控制在业务层个性化开发,比如:用户只允许修改自己创建的商品信息可以在 service 接口添加校验实现, service 接口需要传入当前操作人的标识,与商品信息创建人标识对比,不一致则不允许修改商品信息。
粗颗粒权限:可以使用过虑器统一拦截 url。
细颗粒权限:在 service 中控制,在程序级别来控制,个性化 编程。


四、 Mybatis


1. Mybatis 中#和$的区别?


#相当于对数据 加上 双引号, $相当于直接显示数据
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 注入。
4.$方式无法防止 Sql 注入。
5.$方式一般用于传入数据库对象,例如传入表名.
6.一般能用#的就别用$.


2. Mybatis 的编程步骤是什么样的?

1、创建 SqlSessionFactory
2、通过 SqlSessionFactory 创建 SqlSession
3、通过 sqlsession 执行数据库操作
4、调用 session.commit()提交事务
5、调用 session.close()关闭会话


3. JDBC 编程有哪些不足之处, MyBatis 是如何解决这些问题的?

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 对象。


4. 使用 MyBatis 的 mapper 接口调用时有哪些要求?

1. Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同
2. Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同
3. Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同
4. Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。


5. Mybatis 中一级缓存与二级缓存?

1. 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或close 之后,该 Session 中的所有 Cache 就将清空。
2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache, HashMap 存储,不同在于其存储作用域为Mapper(Namespace),并且可自定义存储源,如 Ehcache。作用域为 namespance 是指对该 namespance 对应的配置文件中所有的 select 操作结果都缓存,这样不同线程之间就可以共用二级缓存。
启动二级缓存:在 mapper 配置文件中: <cache />。
二级缓存可以设置返回的缓存对象策略: <cache readOnly="true">。当 readOnly="true"时,表示二级缓存返回给所有调用者同一个缓存对象实例,调用者可以 update 获取的缓存实例,但是这样可能会造成其他调用者出现数据不一致的情况(因为所有调用者调用的是同一个实例)。当 readOnly="false"时,返回给调用者的是二级缓存总缓存对象的拷贝,即不同调用者获取的是缓存对象不同的实例,这样调用者对各自的缓存对象的修改不会影响到其他的调用者,即是安全的,所以默认是 readOnly="false";
3. 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存 Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。


6. MyBatis 在 insert 插入操作时返回主键 ID

数据库为 MySql 时:
1. <insert id="insert" parameterType="com.test.User" keyProperty="userId" useGeneratedKeys="true" >
“keyProperty”表示返回的 id 要保存到对象的那个属性中,“useGeneratedKeys”表示主键 id 为自增长模式。
MySQL 中做以上配置就 OK 了
数据库为 Oracle 时:
1. <insert id="insert" parameterType="com.test.User">
2. <selectKey resultType="INTEGER" order="BEFORE" keyProperty="userId">
3. SELECT SEQ_USER.NEXTVAL as userId from DUAL
4. </selectKey>
5. insert into user (user_id, user_name, modified, state)
6. values (#{userId,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR},
#{modified,jdbcType=TIMESTAMP}, #{state,jdbcType=INTEGER})
7. </insert>
由于 Oracle 没有自增长一说法,只有序列这种模仿自增的形式,所以不能再使用“useGeneratedKeys”属性。而是使用<selectKey>将 ID 获取并赋值到对象的属性中, insert 插入操作时正常插入 id。


五、 Struts2


1. 简单介绍一下 Struts2

       struts2 框架是一个按照 MVC 设计模式设计的 WEB 层框架,是在 struts 1 和 WebWork 的技术基础上进行了合并的全新的框架。其全新的 Struts 2 的体系结构与 Struts 1 的体 系结构差别巨大。 Struts 2 以 WebWork 为核心,采用拦截器的机制来处理用户的请求, 这样的设计也使得业务逻辑控制器能够与 ServletAPI 完全脱离开。 

       我们可以把 struts2 理解为一个大大的 servlet,而这个 servlet 就是 ActionServlet。struts2 在处理客户端请求时,会先读取 web.xml 配置文件,根据前端控制器将符合条件的请求 分给各个不同的 Action 处理。 在此之前,会把ActionServlet 会把数据封装成一个 javaBean。 

       struts2 框架提供了许多的拦截器,在封装数据的过程中,我们可以对数据进行一些操 作,例如:数据校验等等。 
当 Action 执行完后要返回一个结果视图,这个结果视图可以跟据 struts2 的配置文件中 配置,选择转发或者重定向。


2. Struts2 的执行流程了解么?


参考资料: https://blog.csdn.net/wjw0130/article/details/46371847
Struts2 的官方文档附带了 Struts2 的架构图。从这张图可以很好的去理解 Struts2


关于图中的 Key:
        Servlet Filters:过滤器链,客户端的所有请求都要经过 Filter 链的处理。
        Struts Core: Struts2 的核心部分,但是 Struts2 已经帮我们做好了,我们不需要去做这个
        Interceptors, Struts2 的拦截器。 Struts2 提供了很多默认的拦截器,可以完成日常开发的绝大部分工作;而我们自定义的拦截器,用来实现实际的客户业务需要的功能。
        User Created,由开发人员创建的,包括 struts.xml、 Action、 Template,这些是每个使用 Struts2 来进行开发的人员都必须会的。


1.FilterDispatcher 是整个 Struts2 的调度中心,也就是 MVC 中的 C(控制中心),根据 ActionMapper 的结果来决定是否处理请求,如果 ActionMapper 指出该 URL 应该被 Struts2 处理,那么它将会执行 Action 处理,并停止过滤器链上还没有执行的过滤器。
2.ActionMapper 会判断这个请求是否应该被 Struts2 处理,如果需要 Struts2 处理, ActionMapper 会返回一个对象来描述请求对应的 ActionInvocation 的信息。
3.ActionProxy,它会创建一个 ActionInvocation 实例,位于 Action 和 xwork 之间,使得我们在将来有机会引入更多的实现方式,比如通过 WebService 来实现等。
4.ConfigurationManager 是 xwork 配置的管理中心,可以把它看做 struts.xml 这个配置文件在内存中的对应。
5.struts.xml,是开发人员必须光顾的地方。是 Stuts2 的应用配置文件,负责诸如 URL 与 Action 之间映射关系的配置、以及执行后页面跳转的 Result 配置等。
6.ActionInvocation:真正调用并执行 Action,它拥有一个 Action 实例和这个 Action 所依赖的拦截器实例。ActionInvocation 会按照指定的顺序去执行这些拦截器、 Action 以及相应的 Result。
Interceptor(拦截器):是 Struts2 的基石,类似于 JavaWeb 的 Filter, 拦截器是一些无状态的类,拦截器可以自动拦截 Action,它们给开发者提供了在 Action 运行之前或 Result 运行之后来执行一些功能代码的机会。
7.Action:用来处理请求,封装数据。


3. Struts2 中 Action 配置的注意事项有哪些?

1.name 包名称,在 struts2 的配置文件中,包名不能重复, name 并不是真正包名,只是为了管理 Action

2.namespace 和 <action>的 name 属性,决定 Action 的访问路径 (以/开始 )
3.extends 继承哪个包,通常开发中继承 struts-default 包 (struts-default 包 在 struts-default.xml 中定义 【可 )
以使用包中默认的拦截器和结果集】


4. 拦截器和过滤器有哪些区别?

* 拦截器是基于 java 的反射机制的,而过滤器是基于函数回调
* 拦截器不依赖与 servlet 容器,而过滤器依赖与 servlet 容器

* 拦截器只能对 action 请求起作用,而过滤器则可以对几乎所有的请求起作用
* 拦截器可以访问 action 上下文、值栈里的对象,而过滤器不能
* 在 action 的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一 次


5. Struts2 的封装方式有哪些?

一、属性封装
1.在 action 中设置成员变量,变量名与表单中的 name 属性值相同
2.生成变量的 set 方法
实例
获取用户输入的用户名和密码
jsp 页面
java 代码
二、模型驱动(常用)
1.action 实现 ModeDriven 接口
2.在 action 里创建实体类对象
3.实现接口的 getModel 方法并返回所创建的对象
示例
获取用户输入的用户名和密码
jsp 页面
java 代码
需注意的是表单 name 的值应与类的属性名相同。
三、表达式封装
1.在 action 中声明实体类
2.生成实体类的 set 和 get 方法
3.在表单输入项的 name 属性值里面写表达式
jsp 页面
java 代码


6. 简单介绍一下 Struts2 的值栈。


值栈是对应每一个请求对象的数据存储中心。 Struts2 的一个很重要的特点就是引入了值栈。之前我们通过缓存或者模型驱动在 action 和页面之间传递数据,数据混乱,并且难以管理,缓存还有时间和数量限制,使用起来非常的困难。值栈的引入解决了这个问题,它可以统一管理页面和action 之间的数据,供 action、 result、 interceptor 等使用。我们大多数情况下不需要考虑值栈在哪里,里面有什么,只需要去获取自己需要的数据就可以了,大大的降低了开发人员的工作量和逻辑复杂性。
参考资料: https://www.cnblogs.com/hlhdidi/p/6185836.html


7. SpringMVC 和 Struts2 的区别?


1、 Struts2 是类级别的拦截, 一个类对应一个 request 上下文, SpringMVC 是方法级别的拦截,一个方法对应一个request 上下文,而方法同时又跟一个 url 对应,所以说从架构本身上 SpringMVC 就容易实现 restful url,而 struts2 的架构实现起来要费劲,因为 Struts2 中 Action 的一个方法可以对应一个 url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
2、由上边原因, SpringMVC 的方法之间基本上独立的,独享 request response 数据,请求数据通过参数获取,处理结果通过 ModelMap 交回给框架,方法之间不共享变量,而 Struts2 搞的就比较乱,虽然方法之间也是独立的,但其所有 Action 变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个 Action,一个 Action 对象对应一个 request 上下文。
3、由于 Struts2 需要针对每个 request 进行封装,把 request, session 等 servlet 生命周期的变量封装成一个一个Map,供给每个 Action 使用,并保证线程安全,所以在原则上,是比较耗费内存的。
4、 拦截器实现机制上,Struts2 有以自己的 interceptor 机制,SpringMVC 用的是独立的 AOP 方式,这样导致 Struts2的配置文件量还是比 SpringMVC 大。
5、 SpringMVC 的入口是 servlet,而 Struts2 是 filter(这里要指出, filter 和 servlet 是不同的。),这就导致了二者的机制不同,这里就牵涉到 servlet 和 filter 的区别了。
6、 SpringMVC 集成了 Ajax,使用非常方便,只需一个注解@ResponseBody 就可以实现,然后直接返回响应文本即可,而 Struts2 拦截器集成了 Ajax,在 Action 中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
7、 SpringMVC 验证支持 JSR303,处理起来相对更加灵活方便,而 Struts2 验证比较繁琐,感觉太烦乱。
8、 Spring MVC 和 Spring 是无缝的。从这个项目的管理和安全上也比 Struts2 高(当然 Struts2 也可以通过不同的目录结构和相关配置做到 SpringMVC 一样的效果,但是需要 xml 配置的地方不少)。
9、 设计思想上, Struts2 更加符合 OOP 的编程思想, SpringMVC 就比较谨慎,在 servlet 上扩展。
10、 SpringMVC 开发效率和性能高于 Struts2。
11、 SpringMVC 可以认为已经 100%零配置。


8. Struts2 中的 # 和 % 分别是做什么的?

(1)使用#获取 context 里面数据
<s:iterator value = “list” var=” user” >
<s:property value = “#user.username” >
</s:iterator>
(2)向 request 域放值(获取 context 里面数据,写 ognl 时候,首先添加符号#context 的 key 名称.域对象名称)
(3)在页面中使用 ognl 获取
<s:property value = “#request.req” >
(4) %在 struts2 标签中表单标签
在 struts2 标签里面使用 ognl 表达式,如果直接在 struts2 表单标签里面使用 ognl 表达式不识别,只有%之后才会识别。
<s:textfield name=” username” value=” %{#request.req}” >


9. Struts2 中有哪些常用结果类型?


1) dispatcher :默认的请求转发的结果类型, Action 转发给 JSP
2) chain : Action 转发到另一个 Action (同一次请求)
3) redirect : 重定向,重定向到一个路径信息,路径信息没有限制(不在一个请求中) , Action 重定向到 JSP
4) redirectAction : Action 重定向到另一个 Action
5) stream :将原始数据作为流传递回浏览器端,该结果类型对下载的内容和图片非常有用。
6) freemarker :呈现 freemarker 模板。
7) plaintext :返回普通文本内容。


六、 Hibernate


1. 简述一下 hibernate 的开发流程

第一步:加载 hibernate 的配置文件,读取配置文件的参数(jdbc 连接参数,数据 库方言, hbm 表与对象关系映射文件) 

第二步:创建 SessionFactory 会话工厂(内部有连接池) 

第三步:打开 session 获取连接,构造 session 对象(一次会话维持一个数据连接, 
也是一级缓存) 

第四步:开启事务 

第五步:进行操作 

第六步:提交事务 

第七步:关闭 session(会话)将连接释放 

第八步:关闭连接池 



2. hibernate 中对象的三种状态

瞬时态:(临时态、自由态):不存在持久化标识 OID,尚未与 Hibernate Session 关联对象, 被认为处于瞬时态,失去引用将被 JVM 回收

持久态:存在持久化标识 OID,与当前 session 有关联,并且相关联的 session 没有关闭 , 并且事务未提交 


脱管态:(离线态、游离态):存在持久化标识 OID,但没有与当前 session 关联,脱管状态 改变 hibernate 不能检测到




3. hibernate 的缓存机制。

Hibernate 缓存分为两层: Hibernate 的一级缓存和 Hibernate 二级缓存。
1.Hibernate 一级缓存(Session 的缓存):
(1) Session 实现了第一级 Cache,属于事务级数据缓冲。一旦事务结束,缓存随之失效。一个 Session 的生命周期对应一个数据库事务或一个程序事务。
(2) Session-Cache 总是被打开并且不能被关闭的。
(3) Session-Cache 保证一个 Session 中两次请求同一个对象时,取得的对象是同一个 Java 实例,有时它可以避免不必要的数据冲突。
a.在对于同一个对象进行循环引用时,不至于产生堆栈溢出。
b.当数据库事务结束时,对于同一数据表行,不会产生数据冲突。因为对于数据库中的一行,最多有一个对象来表示它。
c.一个事务中可能会有很多个处理单元,在每一个处理单元中做的操作都会立即被其他的数据单元得知。
2.Hibernate 二级缓存(SessionFactory 的缓存):
(1)二级缓存是 SessionFactory 范围内的缓存,所有的 Session 共享同一个二级缓存。在二级缓存中保存持久化实
例的散装形式的数据。
(2)持久化不同的数据需要不同的 Cache 策略,比如一些因素将影响 Cache 策略的选择:数据的读/写比例、数据表
是否能被其他的应用程序所访问等。
(3)设置 Hibernate 二级缓存需要分两步:首先,确认使用什么数据并发策略。然后,配置缓存过期时间并设置 Cache
提供器。


4. Hibernate 的查询方式有哪些?


Hibernate 的查询方式常见的主要分为三种: HQL, QBC(命名查询) , 以及使用原生 SQL 查询(SqlQuery)
参考资料: https://blog.csdn.net/u010963948/article/details/16818043


5. Hibernate 和 Mybatis 的区别?

        Hibernate 与 MyBatis 都可以是通过 SessionFactoryBuider 由 XML 配置文件生成 SessionFactory,然后由SessionFactory 生成 Session,最后由 Session 来开启执行事务和 SQL 语句。其中 SessionFactoryBuider,SessionFactory, Session 的生命周期都是差不多的。
Hibernate 和 MyBatis 都支持 JDBC 和 JTA 事务处理。
Mybatis 优势:
MyBatis 可以进行更为细致的 SQL 优化,可以减少查询字段。
MyBatis 容易掌握,而 Hibernate 门槛较高。
Hibernate 优势:
Hibernate 的 DAO 层开发比 MyBatis 简单, Mybatis 需要维护 SQL 和结果映射。
Hibernate 对对象的维护和缓存要比 MyBatis 好,对增删改查的对象的维护要方便。
Hibernate 数据库移植性很好, MyBatis 的数据库移植性不好,不同的数据库需要写不同 SQL。
Hibernate 有更好的二级缓存机制,可以使用第三方缓存。 MyBatis 本身提供的缓存机制不佳。


6. Hibernate 和 JDBC 优缺点对比

相同点:
两者都是 java 数据库操作的中间件、
两者对数据库进行直接操作的对象都是线程不安全的,都需要及时关闭。
两者都可对数据库的更新操作进行显式的事务处理。
不同点:
JDBC 是 SUN 公司提供一套操作数据库的规范,使用 java 代码操作数据库。 Hibernate 是一个基于 jdbc 的主流持久化框架,对 JDBC 访问数据库的代码做了封装。
使用的 SQL 语言不同: JDBC 使用的是基于关系型数据库的标准 SQL 语言, Hibernate 使用的是 HQL(Hibernate query language)语言。
操作的对象不同: JDBC 操作的是数据,将数据通过 SQL 语句直接传送到数据库中执行, Hibernate 操作的是持久化对象,由底层持久化对象的数据更新到数据库中。
数据状态不同: JDBC 操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致,而 Hibernate 操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的。


7. 关于 Hibernate 的 orm 思想你了解多少?


ORM 指的是对象关系型映射(Object RelationShip Mapping ), 指的就是我们通过创建实体类对象和数据库中的表关系进行一一对应,来实现通过操作实体类对象来更改数据库里边的数据信息。这里边起到关键作用的是通过
Hibernate 的映射文件+Hibernate 的核心配置文件。
详细内容请见: https://blog.csdn.net/wanghuan203/article/details/7566518


8. get 和 load 的区别?


(1) get 是立即加载, load 是延时加载。
(2) get 会先查一级缓存,再查二级缓存,然后查数据库;load 会先查一级缓存,如果没有找到,就创建代理对象,等需要的时候去查询二级缓存和数据库。 (这里就体现 load 的延迟加载的特性。 )
(3) get 如果没有找到会返回 null, load 如果没有找到会抛出异常。
(4)当我们使用 session.load()方法来加载一个对象时,此时并不会发出 sql 语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的 id 值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出 sql 语句,从数据库中去查询我们的对象;相对于 load 的延迟加载方式, get 就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出 sql 语句去从数据库中查询出来。


9. 如何进行 Hibernate 的优化?


(1) 数据库设计调整。
(2) HQL 优化。
(3) API 的正确使用(如根据不同的业务类型选用不同的集合及查询 API)。
(4) 主配置参数(日志,查询缓存, fetch_size, batch_size 等)。
(5) 映射文件优化(ID 生成策略,二级缓存,延迟加载,关联优化)。
(6) 一级缓存的管理。
(7) 针对二级缓存,还有许多特有的策略。
(8) 事务控制策略。
详情解释请见:https://www.cnblogs.com/xhj123/p/6106088.html


10. 什么是 Hibernate 延迟加载?

延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。在 Hibernate 中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在 Hibernate3 中还提供了对属性的延迟加载。
延迟加载的过程:通过代理(Proxy)机制来实现延迟加载。 Hibernate 从数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据(除标识符外),Hibernate 并不从数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都为默认值;只有在真正需要使用该对象的数据时才创建这个真正的对象,真正从数据库中加载它的数据。


11. No Session 问题原理及解决方法?

Nosession 问题报错如下:
根据字面上的意思,是指代理不能被初始化, session 已经关闭。
Nosession 问题产生的原因:
当执行 Session 的 load()方法时, Hibernate 不会立即执行查询所查询对象关联的对象(在此我们统称被关联的对象类为 A 类),仅仅返回 A 类的代理类的实例,这个代理类具由以下特征:
(1)由 Hibernate 在运行时动态生成,它扩展了 A 类,因此它继承了 A 类的所有属性和方法,但它的实现对于应用程序是透明的。
(2)当 Hibernate 创建 A 类代理类实例时,仅仅初始化了它的 OID 属性,其他属性都为 null,因此这个代理类实例占用的内存很少。
(3)当应用程序第一次访问 A 代理类实例时(例如调用 a..getXXX()或 a.setXXX()方法), Hibernate 会初始化代理类实例,在初始化过程中执行 select 语句,真正从数据库中加载 A 对象的所有数据。但有个例外,那就是当应用程序访问 A 代理类实例的 getId()方法时, Hibernate 不会初始化代理类实例,因为在创建代理类实例时 OID 就存在了,不必到数据库中去查询。
提示: Hibernate 采用 CGLIB 工具来生成持久化类的代理类。 CGLIB 是一个功能强大的 Java 字节码生成工具,它能够在程序运行时动态生成扩展 Java 类或者实现 Java 接口的代理类。
因为 Hibernate 中如果采用 load 加载的话(默认的是延迟加载),也就是 lazy=true 操作,因此,当调用完 load后, session 即可关闭。因为我们的 session 只是放置到了 Dao 层,表现层根本获取不到,所以在表现层调用的时候, session 已经关闭,报错。


12. Spring 的两种代理 JDK 和 CGLIB 的区别浅谈


Java 动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokeHandler 来处理。而 cglib 动态代理是利用 asm 开源包,对代理对象类的 class 文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理实现 AOP
2、如果目标对象实现了接口,可以强制使用 CGLIB 实现 AOP
3、如果目标对象没有实现了接口,必须采用 CGLIB 库, spring 会自动在 JDK 动态代理和 CGLIB 之间转换
参考资料: https://blog.csdn.net/tanga842428/article/details/52716875


13.叙述 Session 的缓存的作用

(1)减少访问数据库的频率。应用程序从内存中读取持久化对象的速度显然比到数据库中查询数据的速度快多了,因此 Session 的缓存可以提高数据访问的性能。
(2)保证缓存中的对象与数据库中的相关记录保持同步。当缓存中持久化对象的状态发生了变换, Session 并不会立即执行相关的 SQL 语句,这使得 Session 能够把几条相关的 SQL 语句合并为一条 SQL 语句,以便减少访问数据库的次数,从而提高应用程序的性能。


14.Session 的清理和清空有什么区别?

Session 清理缓存是指按照缓存中对象的状态的变化来同步更新数据库;清空是 Session 的关闭;


15.请简述 Session 的特点有哪些?

(1)不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个 Session 实例。
(2)Session 实例是轻量级的,所谓轻量级是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创建或销毁 Session 对象,例如为每个客户请求分配单独的 Session 实例,或者为每个工作单元分配单独的 Session 实例。
(3)在 Session 中,每个数据库操作都是在一个事务(transaction)中进行的,这样就可以隔离开不同的操作(甚至包括只读操作)。


16.比较 Hibernate 三种检索策略的优缺点

1、立即检索
优点:对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象;
缺点: 1.select 语句太多; 2.可能会加载应用程序不需要访问的对象白白浪费许多内存空间;
2、延迟检索
优点:由应用程序决定需要加载哪些对象,可以避免可执行多余的 select 语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并且能节省内存空间;
缺点:应用程序如果希望访问游离状态代理类实例,必须保证他在持久化状态时已经被初始化;
3、 迫切左外连接检索
优点: 1、对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地冲一个对象导航到与它关联的对象。 2、使用了外连接, select 语句数目少;
缺点: 1、可能会加载应用程序不需要访问的对象,白白浪费许多内存空间; 2、复杂的数据库表连接也会影响检索性能;


七、 Quartz 定时任务


1.什么是 Quartz 框架

Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。


2.配置文件 applicationContext_job.xml 各个属性作用

(1)、 Job:表示一个任务(工作),要执行的具体内容。
(2)、 JobDetail:表示一个具体的可执行的调度程序, Job 是这个可执行程调度程序所要执行的内容,另外JobDetail 还包含了这个任务调度的方案和策略。
(3)、 Trigger:代表一个调度参数的配置,什么时候去调。
(4)、 Scheduler:代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与JobDetail 组合,就可以被 Scheduler 容器调度了。


3.Cron 表达式详解

Cron 表达式是一个字符串,字符串以 5 或 6 个空格隔开,分为 6 或 7 个域,每一个域代表一个含义。
域:
Seconds(秒):可出现", - * /"四个字符,有效范围为 0-59 的整数。
Minutes(分钟):可出现", - * /"四个字符,有效范围为 0-59 的整数 。
Hours(小时) :可出现", - * /"四个字符,有效范围为 0-23 的整数 。
DayofMonth(日 of 月) :可出现", - * / ? L W C"八个字符,有效范围为 0-31 的整数。
Month(月) :可出现", - * /"四个字符,有效范围为 1-12 的整数。
DayofWeek(日 of 星期) :可出现", - * / ? L C #"四个字符,有效范围为 1-7 的整数 1 表示星期天, 2 表示
星期一, 依次类推。
Year(年) :可出现", - * /"四个字符,有效范围为 1970-2099 年。


4.如何监控 Quartz 的 job 执行状态:运行中,暂停中,等待中?

通过往表(新建一个操作日志表)里插入日志的形式:
运行中:通过 JobListener 监听器来实现运行时更改表信息。
暂停中:调用 scheduler.pauseTrigger()方法时,更改表中 job 信息。
等待中:新添加的 job 默认给其等待中的状态,也是更改表中的 job 信息 但是上面这种形式的麻烦之处是
得频繁的往表里插入数据。

猜你喜欢

转载自blog.csdn.net/qq_29073921/article/details/82351320