jsp网站建设项目实战总结,网站友情链接怎么弄,宣传推广网络推广,领导高度重视网站建设一、常见的 ORM 框架有哪些#xff1f;
1.Mybatis Mybatis 是一种典型的半自动的 ORM 框架#xff0c;所谓的半自动#xff0c;是因为还需要手动的写 SQL 语句#xff0c;再由框架根据 SQL 及 传入数据来组装为要执行的 SQL 。其优点为#xff1a; 1. 因为由程序员…一、常见的 ORM 框架有哪些
1.Mybatis Mybatis 是一种典型的半自动的 ORM 框架所谓的半自动是因为还需要手动的写 SQL 语句再由框架根据 SQL 及 传入数据来组装为要执行的 SQL 。其优点为 1. 因为由程序员自己写 SQL 相对来说学习门槛更低更容易入门。 2. 更方便做 SQL 的性能优化及维护。 3. 对关系型数据库的模型要求不高这样在做数据库模型调整时影响不会太大。适合软件需求变更比较频繁的系统因此国内系统大部分都是使用如 Mybatis 这样的半自动 ORM 框架。 其缺陷为 不能跨数据库因为写的 SQL 可能存在某数据库特有的语法或关键词 2.Hibernate Hibernate 是一种典型的全自动 ORM 框架所谓的全自动是 SQL 语句都不用在编写基于框架的 API可以将对象自动的组装为要执行的 SQL 语句。其优点为 1. 全自动 ORM 框架自动的组装为 SQL 语句。 2. 可以跨数据库框架提供了多套主流数据库的 SQL 生成规则。 其缺点为 学习门槛更高要学习框架 API 与 SQL 之间的转换关系 对数据库模型依赖非常大在软件需求变更频繁的系统中会导致非常难以调整及维护。可能数据库中随便改一个表或字段的定义Java 代码中要修改几十处。 很难定位问题也很难进行性能优化需要精通框架对数据库模型设计也非常熟悉。 二、Bean容器/Ioc容器的理解 Spring 容器主要是对 IoC 设计模式的实现主要是使用容器来统一管理 Bean 对象及管理对象之间的依赖关系。 创建容器的 API 主要是 BeanFactory 和 ApplicationContext 两种 1. BeanFactory 是最底层的容器接口只提供了最基础的容器功能 Bean 的实例化和依赖注入并且使用懒加载的方式这意味着 beans 只有在我们通过 getBean() 方法直接调用它们时才进行实例化。 2. ApplicationContext 应用上下文是 BeanFactory 的子接口与 BeanFactory 懒加载的方式不同它是预加载所以每一个 bean 都在 ApplicationContext 启动之后实例化。 3. 除了基础功能还添加了很多增强 整合了Bean的生命周期管理 i18n国际化功能MessageSource 载入多个有继承关系上下文 使得每一个上下文都专注于一个特定的层次比如应用的 web层 事件发布响应机制ApplicationEventPublisher AOP 三、IoC/DI的理解 概念 IoC (Inversion of Control) 即控制反转是面向对象编程中的一种设计原则。主要是通过第三方 IoC 容器对Bean 对象进行统一管理及组织对象之间的依赖关系。获得依赖对象的过程由原本程序自己控制变为了IoC 容器来主动注入控制权发生了反转所以叫做 IoC 控制反转。 IoC 又叫做 DI 由于控制反转概念比较含糊可能只是理解为容器控制对象这一个层面很难让人想到谁来维护对象关系相对 IoC 而言依赖注入实际上给出了实现 IoC 的方法注入。所谓依赖注入就是由 IoC 容器在运行期间动态地将某种依赖关系注入到对象之中。 依赖注入 (DI) 和控制反转 (IoC) 是从不同的角度的描述的同一件事情就是指通过引入 IoC 容器利用依赖关系注入的方式实现对象之间的解耦。 实现方式 DI 是 IoC 的实现方式之一。而 DI 的实现方式主要有两种构造方法注入和属性 Setter 注入。 实现原理 主要依赖反射及 ASM 字节码框架实现字节码框架操作字节码更为高效功能更强大。 四、Spring中的单例bean的线程安全问题 大部分时候我们并没有在系统中使用多线程所以很少有人会关注这个问题。单例 bean 存在线程问题主要是因为当多个线程操作同一个对象的时候对这个对象的非静态成员变量的写操作会存在线程安全问题。 有两种常见的解决方案 1. 在 bean 对象中尽量避免定义可变的成员变量不太现实。 2. 在类中定义一个 ThreadLocal 成员变量将需要的可变成员变量保存在 ThreadLocal 中推荐的一种方式。 五、Spring中的bean的作用域有哪些 1.singleton 唯一 bean 实例 Spring 中的 bean 默认都是单例的。 2.prototype 每次请求都会创建一个新的 bean 实例。 3.request 每一次 HTTP 请求都会产生一个新的 bean 该 bean 仅在当前 HTTP request 内有效。 4.session 每一次 HTTP 请求都会产生一个新的 bean 该 bean 仅在当前 HTTP session 内有效。 5.application 在一个应用的 Servlet 上下文生命周期中产生一个新的 bean 6.websocket 在一个 WebSocket 生命周期中产生一个新的 Bean 六、FactoryBean和BeanFactory BeanFactory 是 Spring 容器的顶级接口所有 Bean 对象都是通过 BeanFactory 也就是 Bean 容器来进行管理 FactoryBean是实例化一个 Bean 对象的工厂类实现了 FactoryBeanT 接口的 Bean 根据该 Bean 的 ID从 BeanFactory 中获取的实际上是 FactoryBean 中 getObject() 方法返回的对象而不是 FactoryBean 本身如果要获取 FactoryBean 对象请在 id 前面加一个 符号来获取。 七、Bean的生命周期 1. 实例化 Bean 通过反射调用构造方法实例化对象。 2. 依赖注入装配 Bean 的属性 3. 实现了 Aware 接口的 Bean 执行接口方法如顺序执行 BeanNameAware 、 BeanFactoryAware 、 ApplicationContextAware的接口方法。 4. Bean 对象初始化前循环调用实现了 BeanPostProcessor 接口的预初始化方法 postProcessBeforeInitialization 5. 执行 Bean 对象初始化方法 6. Bean 对象初始化后循环调用实现了 BeanPostProcessor 接口的后初始化方法 postProcessAfterInitialization 7. 容器关闭时执行 Bean 对象的销毁方法 八、Spring三级缓存的理解 这个问题或者换个问法 Spring 是如何解决循环依赖的答案即是 Spring 的三级缓存 什么是循环依赖 简单说就是 A 对象依赖 B 对象 B 对象又依赖 A 对象类似的代码如下 Component
public class A{
Autowired
private B b;
}
Component
public class B{
Autowired
private A a;
} 其他还有很多种方式如 A 依赖 B B 依赖 C C 依赖 A 或是 A 依赖 A 自己只要产生了依赖关系的闭环 即造成了循环依赖。 那么循环依赖会引发什么问题呢理解这个问题先得理解 Bean 的生命周期以下先回顾下 Bean的生命周期回顾 1. 启动容器加载 Bean 2. 实例化 Bean 对象 3. 依赖注入装配 Bean 的属性 4. 初始化 Bean 执行 aware 接口方法、预初始化方法、初始化方法、后初始化方法 5. 关闭容器销毁 Bean 在以上第四个步骤执行完毕才算一个初始化完成的 Bean 也即 Spring 容器中完整的 Bean 对象。 循环依赖的问题 Spring 容器保存 Bean 的方式是采取缓存的方式使用 MapString, Object 的结构 key 为 Bean 的名称 value 为 Bean 对象。需要使用时直接从缓存获取。 假如 A 、 B 互相依赖循环依赖 1. 容器中没有 A 对象实例化 A 对象 2. 装配 A 中的 B 对象发现 B 在容器中没有需要先实例化 B 3. 实例化 B 对象 4. 装配 B 中的 A 对象发现 A 在容器中没有需要先实例化 A 5. 重复第一个步骤 这就套娃了 , 你猜是先 StackOverflow 还是 OutOfMemory Spring 怕你不好猜就先抛出了 BeanCurrentlyInCreationException [PS] Bean会依赖某些注入的Bean来完成初始化工作 由于Spring支持构造方法注入属性/Setter注入的方式所以不能简单的先把所有对象全部实例化放到缓存中再全部执行初始化。原因很简单此时所有对象的引用都可以获取到但属性都是null执行初始化甚至构造方法都可能出现空指针异常。 那么我们说 Spring 能解决循环依赖也不是所有的情况都可以解决只有以下情况才支持。 Spring支持的循环依赖 在 Spring 容器中注册循环依赖的 Bean 必须是单例模式且依赖注入的方式为属性注入。 原型模式及构造方法注入的方式不支持循环依赖。以下为说明 原型模式prototype的Bean原因很好理解创建新的A时发现要注入原型字段B又创建新的B发现要注入原型字段A... 还是典型的套娃行为... 基于构造器的循环依赖就更不用说了官方文档都摊牌了你想让构造器注入支持循环依赖是不存在的不如把代码改了。 那么默认单例的属性注入场景 Spring 是如何支持循环依赖的 Spring解决循环依赖 Spring 是使用三级缓存的机制来解决循环依赖问题以下为三级缓存的定义 三级缓存的源码见 DefaultSingletonBeanRegistry public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
SingletonBeanRegistry {
/** Cache of singleton objects: bean name to bean instance. */
private final MapString, Object singletonObjects new ConcurrentHashMap
(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final MapString, ObjectFactory? singletonFactories new
HashMap(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final MapString, Object earlySingletonObjects new
ConcurrentHashMap(16);
} 以下是部分说明 三级缓存singletonFactories中保存的是ObjectFactory对象Bean工厂其中包含了 BeanNameBean对象RootBeanDefinition该工厂可以生成Bean对象。 由于Bean可能被代理此时注入到其他Bean属性中的也应该是代理Bean。 单例模式的 A 、 B 循环依赖执行流程如下 为什么要使用三级缓存 依照以上三级缓存的流程其实使用二级缓存也能满足循环依赖的注入 普通的IoC容器使用一级缓存即可但无法解决循环依赖问题。 解决循环依赖问题使用二级缓存即可。一级缓存保存完整Bean二级缓存保存提前曝光的不完 整的Bean。 需要AOP代理Bean时有两种实现思路 1再加一级缓存 2只使用二级缓存其中二级缓存保存Bean的代理对象代理对象中引用不完整的原始对象即可。 Spring使用三级缓存保存ObjectFactory即Bean工厂在代码的层次设计及扩展性上都会更好。 psObjectFactory内部可以根据 SmartInstantiationAwareBeanPostProcessor 这样的后置处 理器获取提前曝光的对象。 九、AOP的理解 AOP Aspect-Oriented Programming 面向切面编程。对多个业务代码横切来实现统一的业务管理而不用侵入业务代码本身。这样面向切面的编程思想就是AOP 。 使用场景日志记录事务管理性能统计安全控制异常处理等 优点代码解耦统一业务功能对具体业务无侵入性这样可扩展性更好灵活性更高 SpringAOP 是采取动态代理的方式具体是基于 JDK 和 CGLIB 两种 JDK动态代理需要被代理类实现接口使用 InvocationHandler 和 Proxy 动态的生成代理类 CGLIB动态代理需要被代理类能被继承不能被final修饰。使用 MethodInterceptor 来对方法拦截。CGLIB底层是基于ASM字节码框架在运行时动态生成代理类 SpringAOP 如何使用 Aspect 定义切面并注册到容器中使用 Pointcut 定义好切点方法后可以对目标方法进行拦截 前置通知 使用Before通知方法会在目标方法调用之前执行。 后置通知 使用After通知方法会在目标方法返回或者抛出异常后调用。 返回之后通知 使用AfterReturning通知方法会在目标方法返回后调用。 抛异常后通知 使用AfterThrowing通知方法会在目标方法抛出异常后调用。 环绕通知 使用Around通知包裹了被通知的方法在被通知的方法通知之前和调用之后执行自定义的行为。 十、Spring事务中的隔离级别有哪几种 在 TransactionDefinition 接口中定义了五个表示隔离级别的常量 ISOLATION_DEFAULT使用后端数据库默认的隔离级别Mysql默认采用的REPEATABLE_READ 隔离级别Oracle默认采用的READ_COMMITTED隔离级别。 ISOLATION_READ_UNCOMMITTED最低的隔离级别允许读取尚未提交的数据变更可能会导致脏读、幻读或不可重复读。 ISOLATION_READ_COMMITTED允许读取并发事务已经提交的数据可以阻止脏读但是幻读或不可重复读仍有可能发生 ISOLATION_REPEATABLE_READ对同一字段的多次读取结果都是一致的除非数据是被本身事务自己所修改可以阻止脏读和不可重复读但幻读仍有可能发生。 ISOLATION_SERIALIZABLE最高的隔离级别完全服从ACID的隔离级别。所有的事务依次逐个执行这样事务之间就完全不可能产生干扰也就是说该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 十一、Spring事务中有哪几种事务传播行为 在 TransactionDefinition 接口中定义了七个表示事务传播行为的常量。 支持当前事务的情况 PROPAGATION_REQUIRED如果当前存在事务则加入该事务如果当前没有事务则创建一个新的事务。 PROPAGATION_SUPPORTS 如果当前存在事务则加入该事务如果当前没有事务则以非事务的方式继续运行。 PROPAGATION_MANDATORY 如果当前存在事务则加入该事务如果当前没有事务则抛出异常。mandatory强制性。 不支持当前事务的情况 PROPAGATION_REQUIRES_NEW 创建一个新的事务如果当前存在事务则把当前事务挂起。 PROPAGATION_NOT_SUPPORTED 以非事务方式运行如果当前存在事务则把当前事务挂起。 PROPAGATION_NEVER 以非事务方式运行如果当前存在事务则抛出异常。 其他情况 PROPAGATION_NESTED 如果当前存在事务则创建一个事务作为当前事务的嵌套事务来运行如果当前没有事务则该取值等价于PROPAGATION_REQUIRED。 12.SpringMVC的流程 SpringMVC 的请求响应步骤如下 具体步骤 第一步发起发起请求到前端控制器(DispatcherServlet) 第二步查找前端控制器请求HandlerMapping查找 Handler可以根据xml配置、注解进行查找 第三步返回处理器映射器HandlerMapping向前端控制器返回HandlerHandlerMapping 会把请求映射为HandlerExecutionChain对象包含一个Handler处理器页面控制器对象多个HandlerInterceptor拦截器对象通过这种策略模式很容易添加新的映射策略 第四步调用前端控制器调用处理器适配器去执行Handler 第五步执行处理器适配器HandlerAdapter将会根据适配的结果去执行Handler 第六步返回Handler执行完成给适配器返回ModelAndView 第七步接收处理器适配器向前端控制器返回ModelAndView ModelAndView是 SpringMVC框架的一个底层对象包括 Model和view 第八步解析前端控制器请求视图解析器去进行视图解析 根据逻辑视图名解析成真正的视图 (jsp)通过这种策略很容易更换其他视图技术只需要更改视图解析器即可 第九步返回视图解析器向前端控制器返回View 第十步渲染前端控制器进行视图渲染 视图渲染将模型数据(在ModelAndView对象中)填充到request域 第十一步响应前端控制器向用户响应结果 以下是对出现的一些组件的介绍 (1) 前端控制器 DispatcherServlet 不需要程序员开发。 作用接收请求响应结果相当于转发器中央处理器。有了 DispatcherServlet 减少了其它组件之间 的耦合度。 (2) 处理器映射器 HandlerMapping 不需要程序员开发。 作用根据请求的 url 查找 Handler 。 (3) 处理器适配器 HandlerAdapter 不需要程序员开发。 作用按照特定规则 HandlerAdapter 要求的规则去执行 Handler 。 (4) 处理器 Handler 需要程序员开发。 注意编写 Handler 时按照 HandlerAdapter 的要求去做这样适配器才可以去正确执行 Handler (5) 视图解析器 ViewResolver 不需要程序员开发。 作用进行视图解析根据逻辑视图名解析成真正的视图 view (6) 视图 View 需要程序员开发 jsp 。 注意 View 是一个接口实现类支持不同的 View 类型 jsp 、 freemarker 、 pdf… ps: 不需要程序员开发的需要程序员自己做一下配置即可。 十三、Mybatis中#{}和${}的区别 #{变量名} 是预处理替换的方式本质是 jdbc 中占位符的替换。如传入字符串会替换为带单引号的值。可以安全性更好 ${变量名} 是字符串的替换只是对 sql 字符串进行拼接。如传入字符串会直接替换为字符串的值不加单引号。 # 的方式可以很大程度的防止 sql 注入相对来说更安全。而 $ 的方式不能。 十四、Mybatis中如何一对一、一对多关联 十五、SpringBoot 自动配置原理