1.Java基础
1.1 final,finally,finalize 三者区别
Final是一个修饰符: 当final修饰一个变量的时候,变量变成一个常量,它不能被二次赋值 当final修饰的变量为静态变量(即由static修饰)时,必须在声明这个变 量的时候给它赋值 当final修饰方法时,该方法不能被重写 当final修饰类时,该类不能被继承 Final不能修饰抽象类,因为抽象类中会有需要子类实现的抽 象方法,(抽 象类中可以有抽象方法,也可以有普通方法,当一个抽象类中没有抽象方 法时,这个抽象类也就没有了它存在的必要) Final不能修饰接口,因为接口中有需要其实现类来实现的方法 Finally: Finally只能与try/catch语句结合使用,finally语句块中的语句一定会执行, 并且会在return,continue,break关键字之前执行 finalize: Finalize是一个方法,属于java.lang.Object类,finalize()方法是GC (garbage collector垃圾回收)运行机制的一部分,finalize()方法是在 GC清理它所从 属的对象时被调用的
1.2 "=="和equals方法究竟有什么区别
区别主要存在在引用数据类型上 ==为比较两侧的对象是否同一对象,是用内存地址来比较的 equals是对象的方法,默认是用内存地址比较,重写后,主要是用来比较两侧的对象的值是否相同,和equals方法中的实现有关 ==是运算符,可以两侧都为null,但equals左侧的引用指向的对象不能空,不然有NullPointerException 除非需要比较两个引用指向的对象是同一对象,一般都使用equals方法进行比较。尤其是String之类的值对象,另外,常量尽量放在比较的左侧
1.3 静态变量和实例变量的区别
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。 在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。 总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
1.4 Integer与int的区别
int是java提供的8种原始数据类型之一,占用4个字节,直接存值; Integer是引用数据类型,是int的封装类。 1. 默认值:int的默认值为0,Integer的默认值为null。例如考试成绩为0,表示参加了考试,但成绩为0分,但null意味未参加考试。 2. JSP开发中,Integer的默认值为null, 在EL表达式时,文本框显示的值为空白;如果使用int默认值为0,文本框显示的值是0。int不适合在展示层使用。 3. 在Hibernate中,如果将自增ID字段设置成Integer类型,如果值为null,则表示临时对象,保存时,会自动升成ID值。而使用int类型,则需要在hbm映射文件中,设置unsaved-value属性的值为0。 4. Integer提供了许多跟整数运算相关的操作方法,例如与字符串的转换,还定了一些整数的最大值和最小值的转换。
1.5 Overload和Override的区别
Overload是重载的意思,Override是覆盖的意思,也就是重写。Overload和Override有共同之处,两个方法的方法名都必须相同。 1. Override必须发生在父子类之间,Overload可以不在父子类之间 2. Override的特点: a) 参数列表完全相同:个数相同、类型相同、顺序相同 b) 子类的返回值不能比父类的返回值范围大 c) 子类方法抛出的异常不能比父类方法抛出的异常范围大 d) 修饰符只能为public、protected、friendly,不能为private e) 父子类方法不能使用static修饰 3. 重载发生在同一个类或父子类之间,重载中参数列表至少满足个数不同、类型不同、顺序不同中的一个条件,不包含父子类之间的static方法
1.6 abstract class和interface有什么区别
使用abstract修饰符的class为抽象类,abstract类不能创建的实例对象。 接口(interface)是一种特殊的类,使用interface关键字进行修饰。 下面比较一下两者的语法区别: 1. 抽象类可以有构造方法,接口中不能有构造方法; 2. 抽象类中可以有普通成员属性,接口中没有普通成员属性; 3. 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法; 4. 抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法只能是public类型的 5. 抽象类中可以包含静态方法,接口中不能包含静态方法; 6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型; 7. 一个类可以实现多个接口,但只能继承一个抽象类; 8. 在应用上也有区别,接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约;而抽象类在代码实现方面发挥作用,可以实现代码的重用。
1.7 StringBuffer和StringBuilder的区别
相同之处,这两类都是可变长的字符串存储类,都实现了CharSequence接口 1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用 2. StringBuffer为线程安全类,StringBuilder为线程非安全类 3. StringBuffer性能低,StringBuilder性能高,如果在局部优先使用StringBuilder 4. JDK在1.5之前,字符串相加使用StringBuffer对象,在1.5之后使用StringBuilder对象
1.8 error和exception有什么区别
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出,不可能指望程序能处理这样的情况。exception表示一种设计或实现问题,也就是说,它表示如果程序运行正常,正常情况下从不会发生的情况。
1.9 多线程中的sleep()和 wait()有什么区别
1. sleep是在Thread类定义的,wait是在Object类定义的 2. sleep有两个重载方法,wait有三个重载方法 3. sleep能自动唤醒,wait有参数的方法能自动唤醒,但无参数的重载方法不能自动唤醒,需要使用notify/notifyAll进行手动唤醒 4. sleep挂起时,不释放锁资源,wait挂起时,会释放锁资源 5. sleep调用时,不需要放在synchronized内,wait需要放在synchronized内 6. sleep一般不会产生死锁,但是wait可能会产生死锁
1.10 同步和异步有何异同
同步是指所有操作串行化执行,顺序不能改变,前一操作未完成,后个操作不执行。 异步是指所有操作可以并行执行,顺序无关。 例如寄信 同步:如果没有寄完,不能吃饭,邮递员10天后送到,发送人被饿死 异步:寄出后可以立即吃饭,邮递员送完后,通知发送人送信结果。 如果强调执行顺序的话,用同步。如果顺序无关,则可以用异步。 异步执行效率比同步高。该用同步时,如果用了异步,结果可能会出现不一致。
1.11 ArrayList和Vector的区别
1. 线程同步,Vector线程安全,ArrayList线程不安全 2. 效率问题,Vector效率低,ArrayList效率高 3. 增长数量,Vector以1.5倍增长,ArrayList以2倍增长
1.12 HashMap和Hashtable的区别
1. 线程同步,Hashtable线程安9全,HashMap线程不安全 2. 效率问题,Hashtable效率低,HashMap效率高 3. HashMap可以使用null作为key,Hashtable不可以使用null为key 4. HashMap使用的是新实现,继承AbstractMap,而Hashtable是继承Dictionary类,实现比较老 5. Hash算法不同,HashMap的hash算法比Hashtable的hash算法效率高 6. HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey。因为contains方法容易让人引起误解。 7. 取值不同,HashMap用的是Iterator接口,而Hashtable中还有使用Enumeration接口
1.13 ArrayList,Vector, LinkedList的存储性能和特性
1. ArrayList和Vector使用数组存储元素;LinkedList使用链表存储元素 2. ArrayList和Vector插入删除数据时,需要搬运数据,效率较差;LinkedList使用链表,不需要搬运数据,效率高 3. ArrayList和Vectory查询时,按数组下标查询,不需要遍历,效率高;LinkedList需要遍历,查询效率低
1.14 四种线程池介绍
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
1.15 值传递和引用传递的区别
值传递 实参传递给形参的是值,形参和实参在内存上是两个独立的变量,对形参做任何修改不会影响实参 引用传递 实参传递给形参的是参数对于堆内存上的引用地址,实参和形参在内存上指向了同一块区域,对形参的修改会影响实参
1.6 浅复制和深复制的区别
浅复制: 仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会发生相应的改变 深复制: 在计算机中开辟一个新的内存地址用于存放复制的对象 二者最主要的区别在于是否真正获取一个对象的复制实体,而不是引用。 举例: 假设B复制了A,修改A的时候,如果B跟着变了,属于浅复制;如果B没变,属于深复制
1.7 Thread类中的start和run方法的区别
start方法用来启动新线程,内部调用了run方法。当调用run方法时,只有在原来的线程中调用,没有新的线程启动,start方法才会启动新线程
1.8 类加载过程
java文件编译成class字节码文件->类加载器加载字节码文件到jvm中->验证->准备->解析->初始化->使用->卸载
1.9 面向对象的特征
1:封装:通过定义类并且给类的属性和方法加上访问控制 2:继承:子类继承父类,子类可以拥有父类中已定义的方法,并且子类可以修改父类中的方法使其更适合特殊需求。 3:多态:不同对象对统一消息作出不同响应称之为多态
1.10 sleep()和wait()有什么区别
sleep()是线程类的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但监控状态依然保持,到时候会自动恢复。 wait()是Object类的方法,对此对象调用了wait方法导致本线程放弃对象锁,进入等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。
1.11 单例模式
为什么使用单例模式
1:避免重复创建资源造成资源浪费 2:避免存在多个实例造成逻辑混乱
单例模式实现方法:
饿汉式
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
懒汉式(线程安全)
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
1.12 线程的生命周期及五种基本状态
新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable):当调用线程对象的start()方法,线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说此线程立即就会执行; 运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中; 阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种: 1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态; 2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态; 3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
1.13 导致线程死锁的原因?怎么解除线程死锁
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放,而该资源又被其他线程锁定,从而导致每一个线程都得等其它线程释放其锁定的资源,造成了所有线程都无法正常结束。 死锁产生的四个必要条件: 1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用。 2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。 3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。 4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。 解决方法: 1.加锁顺序(线程按照一定的顺序加锁) 2.加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁) 3.死锁检测
2.JavaWeb
2.1 post和get的区别
(1)get是从服务器上获取数据,post是向服务器传送数据。 (2)get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。 (3)get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
2.2 转发与重定向的区别
(1)请求重定向:客户端行为,response.sendRedirect(),从本质上讲等同于两次请求,前一次的请求对象不会保持,地址栏的URL地址会改变。 (2)请求转发:服务器行为,request.getRequsetDispatcher().forward(requset,response);是一次请求,转发后请求对象会保存,地址栏的URL地址不会改变。(服务器内部转发,所有客户端看不到地址栏的改变)
2.3 Servlet的生命周期
1. 加载Servlet类 2. 实例化 3. 初始化init 4. 处理请求 service->进一步调用doGet/doPost方法 5. 销毁 destory
2.4 JSP四大作用域和九大内置对象
四大作用域: page 在当前页面有效 request 在当前请求中有效 session 在当前会话中有效 application 在当前应用程序中有效 九大内置对象; request:客户端的请求信息被封装在request对象中 response:包含了响应客户请求的有关信息,但在JSP中很少直接被用到 pageContext:提供了对JSP页面内所有的对象及名字空间的访问 session:指的是客户端与服务器的多次请求构造一个会话 application:实现了用户间数据的共享,存放全局变量。始于应用的启动,对于应用的关闭 out:是JspWriter类的实例,是向客户端输出内容常用的对象 config:是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象) page:是指向当前JSP页面本身,有点象类中的this指针 exception:是一个例外对象,当一个页面在运行过程中发生了例外,就产生这个对象
2.5 JSP中动态包含与静态包含的区别
<jsp:include page=included.jsp flush=true />它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数 静态INCLUDE用include伪码实现,不会检查所含文件的变化,适用于包含静态页面 <%@include file=included.htm %> 标签不同 执行的时机不同,动态include是在运行时把两个JSP合并,静态include是在编译期合并动态include在页面发生改变时,能及时更新,而静态页面,不会再次重新编译
2.6 JSP和Servlet的区别和联系
1. JSP编译后就是Servlet,因此本质上讲,JSP就是Servlet 2. JSP常用来做展示层,Servlet常用来做控制层 3. JSP更加侧重页面展示,但Servlet更加侧重业务逻辑处理 4. 代码编写上,JSP采用的是模板技术,是HTML代码上添加了些特有的JSP标签,而Servlet却是完全使用Java语法格式。
2.7 MVC的各个部分都有那些技术来实现?如何实现
MVC全名是Model、View、Controller,是模型(model)、视图(view)、控制器(controller)的缩写,一种设计模式,用于将业务逻辑和数据显示分离的方式组织代码。 常用的模型层技术有:JDBC、Hibernate、MyBatis 常用的视图层技术有:JSP、FreeMarker、Struts标签、Velocity 常用的控制层技术有:Spring MVC、Struts、Servlet
2.8 JDBC开发步骤
// 1.加载JDBC驱动 Class.forName("com.mysql.jdbc.Driver"); // 2.创建与数据库的连接 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/1908a", "root", "123456"); // 3.编写SQL语句 String sql = "SELECT * from student"; // 4.创建sql预编译器 ps = connection.prepareStatement(sql); // 5.加入参数 ps.setString(1, username); // 4.执行SQL语句并返回结果 rs = ps.executeQuery();
2.9 Statement和PreparedStatement之间的区别
PreparedStatement是Statement的子类,它们最大的区别是,PreparedStatement允许使用不完整的SQL语句,具体的实参使用问号(?)占位符代替,直到sql语句执行前的时候设置进去即可。
2.10 过滤器和拦截器的区别
1.拦截器是基于动态代理的,而过滤器是基于函数回调 2.拦截器可以在方法前后、异常前后等调用,而过滤器只能在请求前和请求后各调用一次 3.拦截器可以利用依赖注入,因此在Spring框架中,优先使用拦截器
2.11 session和cookie有什么区别
cookie是Web服务器发送给浏览器的一块信息。浏览器会在本地文件中给每一个Web服务器存储cookie。以后浏览器在给特定的Web服务器发请求的时候,同时会发送所有为该服务器存储的cookie。 session是另一种记录客户状态的机制。不同的是cookie保存在客户端浏览器中,而session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是session。 不同点: session对象是在服务器内存中的,而基于窗口的cookie是在客户端内存中的。 cookie不是很安全,别人可以分析存放在本地的cookie,进行cookie欺骗;session会在一定时间内保存在服务器上,当访问增多,会占用服务器性能 cookie保存数据不能超过4k,很多浏览器都限制一个站点最多存放20个cookie
3.数据库
3.1 数据库三范式
第一范式:数据库表中的所有字段值都是不可分解的原子值。 第二范式:需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言) 第三范式:需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关
3.2 事务概述
在数据库中,所谓事务是指一组逻辑操作单元即一组sql语句。 事务的ACID属性 1. 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生, 要么都不发生。 2. 一致性(Consistency) 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏) 3. 隔离性(Isolation) 事务的隔离性是指一个事务的执行不能被其他事务干扰. 4. 持久性(Durability) 持久性是指一个事务一旦被提交, 它对数据库中数据的改变就是永久性的.即使系统重启也不会丢失.
3.3 左连接、右连接、内连接的区别
LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。 RIGHT JOIN 关键字会从右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行。 INNER JOIN 关键字会从两表返回所有匹配的行,要求在两表中都要匹配。
3.4 数据库优化策略
1.sql语句中不要使用*,要使用要查询的具体字段,如select name,age from student 2.对于查询比较频繁的字段要建立索引,如id,name等 3.修改时,要update需要修改的字段,可以进行非空判断,不要更新全部字段 4.连接查询时,可以采用子查询,如: select ps.id,p.pro_name,ps.sale_count from (select pro_name,id from product) p, (select id,pro_id,sale_count from product_sale) ps where p.id = ps.pro_id 5.如果两张表数据量过大,且是一对多或多对多的关系,关联查询较慢,可以通过建立视图的方式进行优化,视图建立后,可以直接查询视图,而不是多表join查询。
3.5 数据库连接池
使用背景: 1.频繁建立数据库连接,非常消耗资源 2.对于每一次数据库连接,使用完都得断开。否则,如果程序出现异常,未能关闭,将会导致内存泄露 工作原理: 在系统初始化的时候,将数据库连接作为对象储存在内存中,用户访问数据库时,直接从连接池中取出一个已建立的空连接对象,使用完毕后,将连接放回连接池中,以供下一个数据库访问请求使用。
3.6 索引的作用?和它的优点缺点是什么?
索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。
3.7 乐观锁和悲观锁
悲观锁: 在整个的数据处理过程中,将数据处于锁定状态。悲观锁的实现,主要是依靠数据库提供的锁机制 缺点:数据库性能开销大,高并发情况下数据库无法承受 乐观锁: 基于数据版本记录机制实现,表中增加一个“version”字段。读取数据时,将版本号一同读出,之后更新数据时,对此版本号加一。然后提交时与表中的版本号进行比对,如果提交的数据版本号大于数据库表当前的版本号,则提交成功。否则提交失败,需要重新进行读取数据操作。
4.JavaEE框架
4.1 对Spring框架的理解
Spring的核心是IOC和AOP,IOC实现了简单工厂模式,可以很好的解耦合,通过IOC和DI的思想将类与类之间的依赖关系放置在配置文件中。各个类都是相对独立存在的,调用关系由配置文件实现,这样就实现了程序之间的松耦合。AOP是面对切面编程,它将不应该聚合在一起的功能(像日志的记录)从业务操作代码中分离并提取出来,使用DI注入到业务代码中,降低代码的耦合度,提高了代码重用率。 Spring提供一种管理对象的方法,把中间层对象有效的组织起来。低侵入性设计,DI机制降低了业务对象替换的复杂性,应用服务器之间是可移植的。方便集成各种优秀框架,写出易于测试的代码方便程序的测试,支持声明式事务,解耦合,简化开发,扩展性好。
4.2 @Resource与@Autowired注解的区别
1.@Resource默认按照名称方式进行bean匹配,@Autowired默认按照类型方式进行bean匹配 2.@Resource(import javax.annotation.Resource;)是J2EE的注解,@Autowired( import org.springframework.beans.factory.annotation.Autowired;)是Spring的注解
4.3 SpringMVC工作原理
1. 整个过程始于客户端发出的一个HTTP请求,WEB应用服务器接收到这个请求,如果匹配DispatcherServlet的映请求映射路径(web.xml中指定),则Web容器将该请求转交给DispatcherServlet处理。 2. DispatcherServlet查询HandlerMapping,找到对应的Controller并分发请求。 3. Controller调用后台的业务逻辑进行处理后,将返回一个ModelAndView,ModelAndView包含了视图逻辑名和模型数据信息。 4. ModelAndView中包含的是"逻辑视图名"而并非真正的视图对象,DispatcherServlet通过查询ViewResolver,从而找到指定的视图对象View。 5. 当得到真实的视图对象View后,DispatcherServlet就使用这个View对象对ModelAndView中的模型数据进行视图渲染。 6. 最终客户端得到的响应信息可能是一个普通的HTML页面,也可能是一个XML或者JSON串,甚至是一张图片或者一个PDF文档等不同的媒体形式。
4.4 对Mybatis的理解
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。 - 解除sql与程序代码的耦合:通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。 - 提供映射标签,支持对象与数据库的orm字段关系映射 - 提供对象关系映射标签,支持对象关系组建维护 - 提供xml标签,支持编写动态sql
4.5 SpringBoot加载Mybatis的过程
1.web应用启动,将@Mapper注解标记的接口,实例化为Spring的bean,这时的bean还没被彻底实例化,还不能使用 2.根据mapper配置文件路径加载xml文件,进行解析 3.将mybatis的mapper对应的bean绑定到jdk的动态代理上,实现接口和动态代理的类绑定
4.6 Hibernate工作原理
1:读取并解析映射信息,创建SessionFactory 2:打开Session 3:创建事物 4:持久化操作 5:提交事务 6:关闭Session 7:关闭SessionFactory Hibernate持久化:Hibernate根据定义的映射规则将对象持久化保存到数据库,这就实现了对象的持久化。
4.7 Spring Aop的五种通知类型
前置通知[Before advice]:在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。 后置通知[After returning advice]:在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。 异常通知[After throwing advice]:在连接点抛出异常后执行。 最终通知[After (finally) advice]:在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。 环绕通知[Around advice]:环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类型,能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。
4.8 Mybatis 中$与#的区别
在mybatis中的$与#都是在sql中动态的传入参数。 #{}: 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个#{}被解析为一个参数占位符,参数是带引号的。 ${}: 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换,参数是不带引号的。
4.9 动态代理的两种实现方式以及区别
实现方式有两种:jdk动态代理和cglib动态代理 jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。 总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
5.互联网技术
5.1 Redis优势
1. redis提供多种存储数据的结构. 2. redis是单线程的,速度特别快. 3. redis是提供了持久化方案的.
5.2 Redis持久化的两种方式
### RDB RDB(Redis DataBase)是 Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis重启会通过加载dump.rdb文件来恢复数据。 Redis会复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程,来进行持久化。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。 RDB保存的文件是dump.rdb文件 ,位置保存在Redis的启动目录。Redis每次同步数据到磁盘都会生成一个dump.rdb文件,新的dump.rdb会覆盖旧的dump.rdb文件。 ### AOF AOF(Append Only File),Redis 默认不开启。它的出现是为了弥补RDB的不足(数据的不一致性),所以它采用日志的形式来记录每个**写操作**,并**追加**到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。 Redis以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。 RDB保存的文件是appendonly.aof文件 ,位置保存在Redis的启动目录。如果开启了AOF,Redis每次记录写操作都会往appendonly.aof文件追加新的日志内容。
5.3 Redis常用命令
key: keys pattern del key exists key expire key second ttl key string: set key value get key incr key incrby key number decr key decrby key number setnx key value setex key second value
5.4 Dubbo+Zookeeper工作原理
0、服务器负责启动,加载,运行提供者(例如在tomcat容器中,启动dubbo服务端)。 1、提供者在启动时,向注册中心注册自己提供的服务。 2、消费者启动时,向注册中心订阅自己所需的服务。 3、注册中心返回提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 4、消费者,从远程接口列表中,调用远程接口,dubbo会基于负载均衡算法,选一台提供者进行调用,如果调用失败则选择另一台。 5、消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。(可以在dubbo管控中心的可视化界面看到)
5.5 高并发优化策略
1.分库分表 读写分离 2.页面静态化 Freemarker Thymeleaf 3.缓存 Redis 4.全文搜索数据库 Solr ElasticSearch 5.数据库连接池 c3p0 druid 6.消息队列 ActiveMQ
5.6 消息队列应用场景和工作原理
消息队列是在消息的传输过程中保存消息的容器,队列的主要目的是提供路由并保证消息的传递。如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。一般来说,消息队列是一种异步的服务间通信方式,是分布式系统中重要的组件,实现高性能,高可用,可伸缩和最终一致性架构。使用较多的消息队列有ActiveMQ、RocketMQ、RabbitMQ、Kafka等。 应用场景: 1.异步处理 2.应用解耦 3.流量削峰 消息队列有两种类型:点对点(一对一)、发布订阅(一对多) 1.点对点模式包含三个角色: 消息队列(Queue) 发送者(Sender) 接收者(Receiver) 每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,可以放在内存 中也可以持久化,直到他们被消费或超时。 特点: 1.每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中) 2.发送者和接收者之间在时间上没有依赖性 3.接收者在成功接收消息之后需向队列应答成功 4.利用FIFO先进先出的特性,可以保证消息的顺序性。 2.发布订阅模型包含三个角色: 主题(Topic) 发布者(Publisher) 订阅者(Subscriber) 多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。 特点: 1.每个消息可以有多个消费者:和点对点方式不同,发布消息可以被所有订阅者消费 2.发布者和订阅者之间有时间上的依赖性。 3.针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。 4.为了消费消息,订阅者必须保持运行的状态。