文章目录
- hashCode()
- ==与equals()
- equals() 与hashCode()
- Map
- Java8新特性
- 自动拆装箱
- 值传递和引用传递
- Array与ArrayList的区别
- String与StringBuffer
- &和&&的作用
- 正则表达式
- Synchronized锁
- volatile
- Lock
- final
- ==**wait**==
- String不可变
- 重载和重写
- StingBuffer与StringBuilder
- 类加载机制、双亲委派模型
- 泛型
- extends与super 上界不存下界不取
- 接口与抽象
- 面向对象的基本特征
- finalize
- 静态内部类(static nested class) 和内部类
- throws与throw
- 六原则一法则
- Query接口的list方法和iterate方法区别
- 构造函数
- 集合部分
- java高级知识
- 锁
- JDK
- 反射
- JVM
- JVM 分区
- GC
- IO、NIO、AIO
- JAVAEE
- AOP
- SSH整合开发
- Structs拦截器和SpringAOP的区别
- Spring JPA整合
- Hibernate
- 延迟加载、性能优化
- Hibernate分页查询
- 二级缓存与查询缓存
- Struts
- Mybatis
- MVC
- JAVA领域的WebService框架
- ==EJB几种类型、业务执行顺序==
- JAVAWEB
- Web编程基础
- Web编程进阶
- redis
- MVC与DAO
- JSTL、DisplayTag等标签库的用法
- WEB编程原理
- 请求和相应架构原理
- web容器
- JDBC基础
- 数据库连接池
- 事务管理
- JDBC进阶
- XML编程
- Web Service
- 计算机网络
- 协议
- 操作系统
- 输入输出系统
- 存储器管理
- 处理机调度与死锁
- 算法与数据结构
- 设计模式
hashCode()
hashCode的作用就是获取对象的散列码,对象调用hashcode方法可以返回一个int索引值,指示其在哈希表的散列位置。
Object的hashCode方法为c或c++实现的本地方法,直接返回对象的内存地址
==与equals()
==用来比较两个对象的地址是否相同(基本数据类型直接比较数据,引用类型会比较地址)
equals方法分两种情况来说
- 如果重写了equals方法,常见做法是重写方法比较两个对象之间的内容
- 如果没有重写方法,则是调用Object的equals方法,等于“==”,是为了比较两个对象的地址是否相同;
equals() 与hashCode()
hashMap与HashSet检查两个对象是否相等,首先调用hashcode获取哈希值,如果哈希值相同,再比较equals方法,如果相等则为同一对象,否则不同对象。】
a.equals(b),那么a与b的hashCode一定相等
判断对象相等(相同),必须有相同的hashcode,然后在比较equals
Map
java.util.Map接口有四个实现类,hashMap、hashTable、treeMap、linkedHashMap
- HashMap允许key有且仅有一个为null,值可以多个为null。非线程安全,读取速度取决于HashMap的容量,读取顺序也是随机的。如果想用线程安全,可以使用Collections的synchronizedMap方法,或者使用ConcurrentHashMap
- HashTable不允许键值对为null,线程安全,所以读取速度慢
- TreeMap实现SortMap接口,可以对数据进行自然或自定义排序,
- LinkedHashMap集成自HashMap,按插入顺序排序。
Java8新特性
- lambda表达式(非常容易并行计算、简洁、非并行计算下计算速度没有for循环快,不容易调试,难看懂)
- 方法引用
- 默认方法
- 新工具
- StreamAPI
- DateTimeAPI
- Optional类
- Nashorn、JavaScript引擎
自动拆装箱
是Java编译器将基本数据类型与其对应的对象包装类之间做的一个转化
值传递和引用传递
值传递是对于基本型变量来言,传递该变量的一个副本,改变副本不影响原变量,而引用传递是对于对象类型变量而言,传递该对象地址的副本,因此操作对象会改变原对象。
java是值传递
Array与ArrayList的区别
Array可以处理基本数据类型和对象类型
ArrayList只能处理对象类型,所以设计自动拆装箱,所以处理基本数据类型时会相对较慢
String与StringBuffer
java.lang.String类是final类型,不可继承、修改,
StringBuffer字符内容可变,考虑节省空间,推荐使用
&和&&的作用
&&短路与
正则表达式
正则表达式就是记录文本规则的代码
Synchronized锁
若修饰静态方法、同步代码块,则锁的是类
若修饰成员方法,则锁的是调用该方法的对象实例
volatile
volatile保证有序性和可见性
有序性:对一个变量的写操作先发生于后面的读操作
可见性:一个变量从主内存移到工作内存,再返回到主内存的操作,保证数据可见
Lock
- Synchronized:Java关键字,发生异常时会释放线程占有的锁,避免,死锁,不能使等待锁的线程响应中断,不能知道是否成功获取锁
- Lock:java接口,发生异常时,需要之心unLock方法,可以使等待锁的线程响应中断,能知道是否成功获取锁
final
修饰基本数据类型变量,则代表初始化后不能被修改,若修饰引用类型变量,则初始化后不能在指向另一个对象。
使用final的原因1是讲方法锁定,2是效率,早期java中会将final方法转为内嵌调用,但是如果方法过于庞大,就没太大性能提升。
wait
String不可变
可以节省很多堆空间,变量可以多线程共享、hashmap的key值用String最好,因为字符串在使用的时候hashcode就被缓存了,处理速度快
重载和重写
重载:就是在勒种可以创建多个方法,具有相同的名字但是不同的参数,返回值类型没有要求
重写:对父类的方法进行重新定义,方法参数返回值类型必须相同,子类重写的方法一定覆盖父类原有的方法,如需引用原有犯法,使用super关键字,调用当前类的父类,子类访问权限不能小于父类,
方法重写是基于运行时动态绑定的,static是静态绑定的,static关键字表明一个成员变量或者成员方法可以在没有所属类的实例变量的情况下被访问。
StingBuffer与StringBuilder
StringBuffer 线程安全,多加了Synchronized修饰符
StringBuilder线程不安全
类加载机制、双亲委派模型
双亲委派模型:某个特定的类加载器在接受到加载类的请求时,首先将加载任务委托给父类加载器,一次地柜,如果父类加载器可以完成类加载任务,则成功返回,只有父类无法完成类加载任务使,才自己去加载
这样做使得java类随着他的类加载器具备了一种优先级的层次关系,Object肯定是所有类的最高父类,自定义的Object类也会委派java的Object类进行加载,避免自定义的与java的相混淆(比如加载rt.jar中的java.lang.Object,不管是哪个类加载器加载这个类,最终都会委托给顶层的启动类加载器,就保证了使用不同的类加载器最终得到的都是同样的一个Object)
泛型
即参数化类型,普通的方法直接写形参,然后传入对应的实参
泛型就是将原形参改为一种参数形式,在实际调用时再传入一种具体类型的实参
extends与super 上界不存下界不取
- 上界定义:<? extends Fruit>
表示所有继承Fruit的类, - 下界定义:<? super Apple>
表示Apple的所有父类
接口与抽象
- 抽象类可以有抽象方法和非抽象方法,变量没限制,如果有main党发,可以被调用
- 接口中方法都是抽象的,接口中的变量都是public static final的,方法是public的。instanceof运算符可以用来决定某对象的类是否实现了接口
面向对象的基本特征
- 继承:子类可以从父类中派生,继承其方法、实例变量,也可以增加新的方法
- 封装:把数据和过程包围起来,对外提供一个接口,实现自治
- 多态:允许不同的类对象对同一消息做出响应。允许函数同名。运行时多态、编译时多态
- 抽象:忽略与目标无关的方面,聚焦于有关的方面(接口的区别)
finalize
是Object类的方法,垃圾回收时候会调用被回收对象的finalize方法,也可以重写此方法,回收其他资源,比如关闭文件等。
静态内部类(static nested class) 和内部类
内部类的静态成员只能访问外部类的静态成员,但是其实例方法可以访问外部类的所有成员
静态内部类只能访问static属性
静态嵌套类: Static Nested Class 是被声明为静态(static)的内部类,它可以不依赖外部类实例而被实例化。
**内部类:**需要在外部实例化后而被实例化。
throws与throw
throw语句用来明确地抛出一个异常,throws用于标明一个成员函数可能跑出的各种异常。
六原则一法则
- 单一职责原则:一个类只做它该做的事,高内聚低耦合
- 开闭原则:软件实体应当对扩展开放、对修改关闭。1,抽象2,封装可变性
- 依赖倒转原则:面向接口编程,说的直白和具体就是声明方法得参数类型、方法返回类型、变量引用类型尽可能使用抽象类型而不是具体类型,因为抽象类型可被其任何一个子类所替代。
- 里氏替换原则:任何时候都可以用子类型替换掉父类型
- 接口隔离原则:接口要小而专,不能大而全
- 合成聚合复用原则:优先使用聚合或合成关系复用代码。继承Is-A关联Has-A依赖Use-A,优先使用Has_A,
- 迪米特法则:最少知识原则,一个对象应当对其他对象尽可能少的了解
Query接口的list方法和iterate方法区别
- list方法无法利用一级和二级缓存,对缓存只写不读,不会引起N+1问题
- iterator可以充分利用缓存,会引起N+1wenti,如果对目标只读或读取频繁,可以减少性能开销
构造函数
当新对象被创建时,构造函数会被调用,每一个类都有构造函数,程序员没有提供构造函数情况写,java编译器会为这类创建一个默认的构造器
构造函数可以被重载,但是每个构造器必须有唯一的参数列表
集合部分
ConcurrentHashMap:
ConcurrentHashMap线程安全,采用分段锁机制,减少锁的粒度
- jdk1.7 Segment+HashEntry的方式进行实现,lock加在segment上
- jdk1.8 Node+CAS+Synchronized的方式实现,使用volatile的变量baseCount记录元素的个数
- ConcurrentHashMap由若干个Segment对象组成的数组,每个Segment对象有散列映射表的若干个桶组成,每个桶是由若干个HashEntry对象连接起来的链表,每个HashEntry用来封装散列映射表中的键值对。
static final class HashEntry<K,V>{
final K keyl;
final int hash;
volatile V value;
final HashEntry<K,V> next;
...
}
- 若散列时发生碰撞,采用分离链接法:将碰撞的hashEntry对象连接成一个链表,由于hashEntry的next域是final类型,因此新节点只能在链表的表头处插入,所以链表中节点的顺序与插入顺序相反
HashMap内部实现
- HashMap基于数组实现,通过对key的hashcode&数组的长度得到在数组中的位置。
- 数组长度是2n,故hashcode&2n-1得到散列位置,使得散列均匀
- 用拉链法解决冲突
- 负载因子默认为0.75,2^n是为了让散列更加均匀
- jdk1.8中,引入红黑树,当链表元素个数大于等于8时,链表转为树结构,若桶中的链表元素个数小于等于6时,树结构还原成链表。
- 红黑树平均查找长度是log(n),长度为8时,查找长度为3,如果使用链表,则平均查找长度为8/2=4
- 如果长度小于等于6,链表查找长度为3,但是转换为树需要消耗时间,故不需要转为树,
- 中间有个差值7,可以有效防止链表和树频繁转换
hashmap的key如果是一个自定义类,
则需要重写hashcode()与equals()方法
LinkedList
采用双向链表实现
TreeMap
TreeMap使用红黑树实现,即自平衡排序二叉树,可以保证快速检索指定节点。
红黑树
- 插入、删除、遍历使劲都为O(lg n),性能低于hash表,但红黑树是排序插入的,可按照键值大小有序输出
- 每个节点要么是红色要么是黑色
- 根节点永远是黑色
- 所有叶节点都是空节点,并且是黑的
- 每个红色节点的两个子节点都是黑色(从每个叶子到根上的路径不会有两个连续的红色节点)
- 从任一节点到其字数的每个叶子节点都包含相同数量的黑色节点
ArrayList
基于动态数组的数据结构;
扩容方式
并发情况下会出现数组下标越界异常
Vector比ArrayList多了synchronized方法。,线程安全
Serializable接口的作用
- 作用是把对象存储到字节流,然后可以恢复。
- 实现Serializable序列化的作用:将对象的状态保存在存储媒体,以便在以后重建处完全相同的副本。
- clone和serializale的语义和含义是跟具体的实现相关的,因此应由集合类的具体实现类来决定如何被克隆或者序列化
- 将对象的内容流化,便于读写、网络间传输
迭代器
- Iterator提供了遍历操作集合的统一接口,Collection接口实现Iterator接口,每个集合通过实现Iterator接口中的iterator()方法返回Iterator接口的实例,进行迭代
- 在迭代时,不能通过集合的方法删除元素,会抛出ConcurrentModificationException异常,但是可以通过iterator接口中的remove方法删除
- Iterator只能前向遍历,可以遍历Set、List
- ListIterator能前向也能后向遍历,只能遍历List
fail-fast快速失败 fail-safe安全失败
java.util.所有集合类都是快速失败,会抛出异常ConcurrentModificationException
java.util.concurrent包下面的所有的类都是安全失败
Colllection与Collexctions
Collection是集合的上级接口,继承他的有Set、List
Collections是针对集合类的一个帮助类,提供对各种集合的排序、搜索、线程安全化等操作。
java高级知识
如何实现线程安全的计数器
可以使用加锁,比如synchronized或者lock,也可以使用Concurrent包下的原子类
多线程同步的方法:
可以使用synchronized,lock,volatile和threadlocal来实现同步
生产者与消费者
生产者和消费者在同一时间内共用同一存储空间,生产者想空间里生产数据,而消费者取走数据
支持并发解耦
线程池
线程创建有很大开销,可以使用线程池
- 降低资源消耗 通过重复利用已创建的线程降低线程创建和销毁造成的消耗
- 提高响应速度 任务到达时,任务可以不需要等待线程创建就能执行
- 提高现成的可管理型,可以对资源统一分配、调优和监控
事先创建若干个可执行的线程放入一个池中,需要的时候从池中获取线程不用自行创建,使用完毕后,不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。
AQS
AQS是AbstractQueuedSynchronizer的简称。AQS提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架
创建线程
- 继承Thread类,重写run方法,new ThreadTest().start() ;
- 实现Runnable接口,重写run方法。不需要继承。创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
new Thread(runnableTest,“线程1”).start() ; - 覆写Callable接口实现多线程(JDK1.5):实现Callable接口的实现类,实现call方法,使用FutrueTask类来包装Callable对象,该FutureTask对象作为Thread的target创建并启动线程
- 应用程序可以使用Executor框架来创建线程池
CountDownLatch与CyclicBarrier
都能实现线程之间的等待
- CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务后,才执行,不能够重用
- CyclicBarrier一般用于一组线程互相等待至某个状态,然后这组线程在同时执行,可重用
同步方法和同步代码块
- 同步方法默认使用this或者当前类对象作为锁
- 同步代码快可以选择部分代码进行加锁
sleep和wait
- sleep Thread类的方法,使线程暂停执行指定时间,把执行机会给其他线程,但是监控状态依然保持,到时会自动恢复。调用sleep不会释放对象锁
- wait 是Object类的方法 导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify或者notifyall后本线程才进入对象锁定池,准备获得对象锁进入运行状态
- 同步有几两种实现方法,分别是synchronized,wait与notify
反对使用stop方法和suspend方法
- stop方法,不安全,会解除由线程获取的所有锁定。
- suspend方法,不安全,容易发死锁。调用suspend方法,目标线程会停下来但却持有在这之前获得的锁定。任何其他线程都不能访问锁定的资源,除非被挂起的线程回复运行。
sleep与yield区别
- sleep方法给其他线程运行机会时不考虑线程的优先级,会给低优先级的线程运行机会,yield方法只会给相同或更高优先级的线程运行机会
- sleep后线程进入阻塞状态,yield进入就绪态
- sleep方法抛出InterruptedException
- sleep方法可移植性更高
进入阻塞状态的几个原因:
- 调用wait方法进入等待池
- 执行同步方法或同步代码块进入等锁池
- 调用sleep方法或join方法等待休眠或其他线程结束
- 发生I/O中断
如何保证线程安全
- 合理的时间调度,避开共享资源的存取冲突
- 并行任务规则设计,保证过程与数据由一个工作机完成
锁
非公平锁和公平锁在reetrantlock的实现
- 公平锁,锁的获取顺序按FIFO
- 非公平锁,只要CAS设置同步状态成功,则代表当前线程获取了锁,公平锁需要判断当前线程是都有前驱节点,即代表是否有线程更早请求锁
synchronized的**可重入**怎么实现。
- 每个锁关联一个线程持有者和计数器,计数器为0,即代表该锁没有被任何线程占有;若计数器不为0,则代表有线程占有;线程占有,则锁的计数器加1,持有该锁的线程可再次请求该锁,就可以再次得到锁,并将计数器加1。
- 当线程退出一个synchronized方法/块,计数器减1,计数器为0,则释放该锁。
synchronized(同步)与lock(锁)的区别
可以总结为,lock能完成synchronized的所有功能,并提供更精确的线程语义和更好的性能,然后就是释放方式的不同。
- 用法上
- synchronized可以加在方法或代码块上,托管给JVM执行
- lock必须显示的指定起始和终止位置,通过代码达到锁定效果,具有更精确的线程语义
- 性能上
- lock接口的实现类ReetrantLock具有和synchronized相同的并发性与内存语义,还多了超时得的获取锁、定时锁、等候和中断锁
- 竞争不激烈下,synchronized更优,竞争激烈的情况下,synchronized性能下降很快,ReetrantLock基本不变
- 锁机制不同
- synchronized发生呆快结构中,获取多个锁是,必须以相反的顺序释放
- Lock需要开发人员手动释放,必须在finally中释放,否则会引起死锁
死锁
两个或两个以上的线程都在等待对方执行完毕才能继续往下执行,(都在等待对方的资源)即发生死锁
死锁破坏的四个条件
使用多线程避免死锁的简单方式:指定获取锁的顺序,强制线程按照指定顺序获取锁、释放锁,就不会死锁
- 破坏请求和保持条件
- 破坏不可抢占条件
- 破坏循环等待条件
-破坏互斥条件::不可能被破坏
JDK
Java中的LongAdder与AtomicLong的区别
CAS机制就是在一个死循环内不断创世修改目标值知道修改成功
JDK与JRE
JDK=JRE+编译器+其他工具(javadoc,java调试器)
JRE就是java虚拟机,可以执行java程序
反射
反射就是通过字节码文件找到一个类,类种方法、属性等
- Class,类
- Construstor,构造器
- Field,类中的属性对象
- Method,类中的方法
反射机制可以是程序在运行时获取自身的信息
JVM
JVM垃圾回收算法
- 标记清除:标记阶段、清除阶段,存在大量碎片
- 复制算法:
- 标记整理
- 增量算法
JVM垃圾回收器
- Serial收集器
- ParNew收集器
- Parallel Scavenge 收集器
- CMS收集器
- G1收集器
类加载过程
加载-(验证-准备-解析)连接-初始化
- 加载:在内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类中各种数据的入口。
- 验证:确保Class文件中的字节流包含的信息是否符合当前虚拟机的要求,并不会危害虚拟机的安全。
- 准备: 为类变量分配内存并初始化,初始化,并不是赋值,除了final
- 解析:虚拟机常量池中的符号引用替换为直接引用
- 初始化:执行clinit方法(初始化静态变量、静态代码块)
- 子类引用父类的静态字段,只会触发父类初始化
- 定义对象数组,不会触发该类的初始化
- 常量编译期间会存入调用类的常量池,不会触发类初始化
- 通过类名获取Class对象,不会类初始化
- Class.forName加载指定类,initialize参数为false,即不会对类进行初始化
- ClassLoader的默认loadClass,也不会初始化类
- 类加载器
- 启动类加载器(Bootstrap ClassLoader):加载JAVAHOME\lib
- 扩展类加载器(ExtensionClassLoader),加载JAVAHOME\lib\ext
- 应用程序类加载器(ApplicationClassLoader)加载classpath类的类库
JVM 分区
- 程序计数器 program count register
- 本地方法栈 native stack
- 方法区 method area
- 栈 stack
- 堆 heap
Eden区、survial区
主流虚拟机实现都采用分代收集,新生代与老年代,新生代分为Eden(对象在Eden区出生)、From Survivor(保存当前幸存的对象)、To Survivor(空)三块区域。比例8:1:1
- Eden区活着的对象+From Survivor存储的对象复制到To Survivor
- 清空Eden、From Survivor
- 颠倒From Survivor和To Survivor逻辑关系
GC回收垃圾
真正宣告一个对象至少需要进行两次标记过程:如果在进行可达性分析后发现没有与GC Roots相连接的引用链,将会被第一次标记并进行一此筛选,即此对象是否有必要执行finialize方法,>>当对象没有覆盖finalize或finalize方法已经被虚拟机调用过,即直接回收此对象。
JVM中可作为ROOT的对象
- 虚拟机栈中的引用对象
- 方法区类静态属性引用的对象
- 方法去常用引用对象
- 本地方法栈JNI引用对象
JVM内存模型即JMM
线程之间的共享变量存储在主内存中,每个线程具有一个私有的本地内存,存储了该线程以读写共享变量的副本
本地内存并不真实存在,涵盖缓存、写缓冲区、寄存器、以及其他硬件和编译器优化
线程
线程是CPU调度的基本单位,一个进程可以有多个线程,多个线程共享该进程的资源。
Thread类的关键方法,都声明为native。
用户线程的建立同步销毁和调度完全在用户态中完成
JVM的最大内存限制
- 堆内存分配
- -Xms初始分配内存,默认为物理内存的1/64
- -Xmx最大分配内存,默认为物理内存的1/4
堆空余内存>70%,将会逐步缩小堆内存至-Xms的限制;堆空余内存<40%,将会扩大堆内存至-Xmx的限制。
- 非堆内存分配
- -XX:PermSize 设置非堆内存初始值,默认1/64
- -XX:MaxPermSize 设置最大值,默认1/4
- VM最大内存值,限制于实际的最大物理内存
JVM加载class文件的原理机制
java中的所有类都需要类加载器装在到JVM中才能运行。
类加载器的作用就是将class文件从硬盘加载到内存中。
Java类加载是动态的,并不会一次将所有类全部加载运行,将保障程序运行的基础类加载之后,其他类需要时候才进行加载,节省内存开销
GC
可以自动检测对象是否超过作用域而达到自动回收的目的
java中对象不再有作用域的概念,只有对象的引用才有作用域
内存泄漏
不再被使用的对象的内存不能被回收
- 不再需要的对象引用
- 未释放的系统资源
GC
- GC对象是堆空间和永久区
- GC算法:引用计数法,标记清除、标记压缩、复制算法
程序员从创建对象时,GC就开始监控此对象的地址大小、使用情况,GC采用有向图记录和管理堆中所有对象,确定哪些对象可达、不可达。
可以通过System.gc()通知GC运行,但不一定立即运行
IO、NIO、AIO
tail -f /logs 可以查看更新
异常
当Java程序违反了JAVA的语义规则,JVM将发生的错误表示为一个异常
非运行时异常必须声明抛出
运行时异常时虚拟机运行时候可能遇到的异常,
- runtimeException:ArithmeticException、ArrayStoreException、BufferOverflowException、BufferUnferflowException、IllegalArgumentException…IndexOutofBoundsException
字节流字符流
- InputStream、OutputStream
- InputStreamReader、OutputStreamWriter
JAVAEE
IOC AOP
依赖注入:
- 接口注入
- Construstor注入
- Setter注入
IOC与DI一个概念:
- 脱开、降低类之间的耦合
- 倡导面向接口编程、实施依赖倒转原则
- 提高系统可插入、可测试、可修改特性。
IOC对于Spring框架来说,就是Spring负责控制对象的生命周期和对象间的关系
IOC与DI
DI是对IOC更简单的诠释
IOC即把传统上程序代码直接操控对象的调用全交给容器,通过容器来实现对象组件的装配和管理。
- 控制反转就是把组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。
- 依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象,配置的工作应该交给容器去做,查找资源的逻辑也应该从应用组建的代码中抽取出来,交给容器来完成。
- DI是对IOC的更准确的描述,即组件之间的依赖关系由容器在运行期间决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
实现IOC的步骤:
- 定义用来描述bean的配置的java类
- 解析bean的配置,将bean的配置信息转换为上面的BeanDefinition对象保存在内存中,spring采用hashmap存储,会用到一些xml解析技术
- 遍历存放BeanDefinition的hashmap对象,逐条取出beanDefinition对象,获取bean的配置信息,利用java的反射机制实例化对象,将实例化的对象保存到另外一个map郦
bean的生命周期
Spring里的注解 @Autowired与@Resource的区别
- 共同点:都可以写在字段、setter方法上,如果写在字段上,就不需要在写setter方法了
- 不同点
- @Autowired 为Spring提供的注解包,需要导入包or.springframework.beans.factory.annotation.Autowired, 只按照byType注入
- @Resource 为J2EE提供,javax.annotation.Resource,默认byName,也可以byType
@RestController
相当于@ResponseBody+@Controller合起来一起用
BeanFactory和ApplicaitonContext的区别
ApplicationContext继承自BeanFactory,BeanFactory无法支持Spring插件,如AOP、Web应用等功能
区别是:
- ApplicationContext 配置的bean如果是singleton,不管有没有用,都会被实例化,好处就是可以被预加载,但浪费内存
- BeanFactory实例化对象,配置的bean不会被马上实例化,用的时候才会被实例化,好处是节约内存,坏处是速度较慢。多用于移动设备的开发
- 没有特殊要求的话,用ApplicationContext,因为AppliacationContext的功能更完全
ApplicationContext功能包括:
- MessageSource,提供国际化的 消息访问
- 资源访问(URL、文件)
- 事件传递
- Bean的自动装配
- 各种应用层的Contexet实现
Bean的作用域
- singleton单例
bean以单例的方式存在, - prototype原型
每次从容器调用bean时,都会返回一个新的实例
单例模式和原型模式都是重要的设计模式,一般情况下,无状态或者状态不可变的类适合使用单例模式
传统模式下由于DAO持有connection这个非线程安全对象因而没有使用单例模式,但是Spring环境下,所有DAO都可以采用单例模式,因为Spring利用、
AOP和JAVAAPI中的ThreadLocal对非线程的对象进行了特殊处理。
Spring中自动装配的方式
- no 不进行自动装配
- byName 根据bean的名字进行装配
- byType 根据Bean的类型进行自动装配
- Construstor 类似byType,如果参数类型与构造器相同,就自动装配
- autodetect:默认构造器使用construstor的方式,否则使用byType
AOP
用于面向对象的补充,用于处理系统中分布于各个模块的横切关注点,如事务控制、日志、缓存等。
AOP实现关键在于AOP框架自动创建的AOP代理,包括静态代理(如AspectJ)和动态代理(Spring AOP)
- 静态代理:AOP框架会在编译阶段生成AOP代理类,因此成为编译时增强
- 动态代理SpringAOP主要有两种方式,JDK动态代理和CGLIB动态代理
- JDK动态代理:通过反射来接受代理的类,并且要求被代理的类必须实现一个几口。核心是:InvocationHandler类和Proxy类
- CGLIB动态代理:如果目标没有实现接口,使用CGLIB,在运行时动态生成某个子类的子类,通过继承来做动态代理,如果某个类为final,则无法使用CGLIB做动态代理
AOP中的相关名词
- 连接点 JointPoint
- 切点PointCut
- 增强Advice
- 引介Introduction
- 织入Weaving
- 切面Aspect
Spring支持的事务管理类型
- 编程式事务管理,允许代码控制业务
- 声明式事务管理,轻量级
事务分为全局事务、局部事务、
- 全局事务由应用服务器管理,需要底层服务器JTA支持
- 局部事务和底层代用的持久化方案有关。】
SSH整合开发
Spring有6个模块
- Core Container
- AOP
- Message消息发送支持
- Data Access、Integration
- Web(Spring Web内容,包括MVC)
- Test(Spring测试支持,包括JUni等测试单元)
- Instrumentation(设备支持,tomca的支持)
Structs拦截器和SpringAOP的区别
拦截器是AOP的一种实现
- structs2拦截器采用xwork2的interceptor
- 而Spring的AOP是基于IOC基础,底层采用JDK动态代理与CGLIB代理两种方式结合的实现方式
Spring的优点
Spring是一个轻量级的DI和AOP框架,主要有点是
- 非侵入式框架,目标是应用程序代码对框架的依赖最小化,
- 提供一致的编程模型,是应用可以直接使用POJO(Plain Ordinary Java Object简单的Java对象)开发使运行环境隔离开
- 应用风格由面向对象向面向接口变成,提高代码重用性和可测试性
- 改进了结构体系的选择
- IOC容器帮助应用程序管理对象以及对象之间的依赖关系,只需修改配置文件
- AOP,通过配置将横切关注功能动态加入目标代码上,实现了业务逻辑和系统服务之间的分离。
- 事务管理:接纳多种持久层技术,提供声明式事务管理
- MVC
Spring JPA整合
持久层
系统中专注于将数据持久化的相对独立的层面,
数据持久化将内存中的数据保存到关系数据库、文件系统、消息队列等提供持久化支持的设备中。
Hibernate、 Mybatis、 TopLink、 Guzz、 JOOQ 、Spring Data、 Active JDBC
Hibernate
ORM与持久化映射
hibernate对象有四种状态
- 瞬时态new、transient:new一个实体对象后,就是瞬时态,在内存中,与数据库没关系
- 持久态managed、persistent:持久态对象的实例在数据库中有对应的记录,并有一个持久化标识ID
- 游状态detached或脱管态:从会话中清除掉,对象不再持久化管理之内,但还有持久化标识
- 移除态removed(新加的)
延迟加载、性能优化
SessionFactory
- SessionFactory对应Hibernate的一个数据存储的概念,线程安全的,可以被多个线程并发访问
- SessionFactory一般只会在启动时候构建,最好通过单例模式进行封装以便于访问
- Seesion是由SessionFactory创建的一个与数据库进行交互的工作单元,轻量级、非线程安全,任务完成后会被关闭
- session会延迟获取数据库连接,即在需要的时候才会获取
- 为避免创建太多session,可以使用ThreadLocal将session和当前线程绑定在一起,这样可以让同一个线程获得的总是用一个session。
Hibernate中session的load和get方法区别是什么?
- 如果没有查到符合条件的记录,get返回null,load抛出异常
- get返回实体类对象,load返回实体类对象的代理
- 可以通过二级缓存读数据
Hibernate的延迟加载机制
延迟加载并不是在读取的时候就把数据加载进来,而是用的时候再加载。
Hibernate使用虚拟代理机制实现延迟加载,session的load方法调用的时候返回的的是实体对象的代理
延迟加载与session关闭的矛盾
- 关闭延迟加载特性,通过映射文件或注解进行配置,但每次查询的开销都会很大
- 在session关闭之前先获取需要查询的数据,判断对象是否被加载,吐过没有可以使用Hibernate.initialize方法加载对象
- 使用拦截器或过滤器延长session的生命周期直到视图获得数据。如Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterception
hibernate常见的优化策略
- 制定合理的缓存策略(二级缓存,查询缓存)
- 采用合理的session管理机制
- 尽量使用延迟加载特性
- 设定合理的批处理参数
- 如果可以使用UUID作为主键生成器
- 如果可以,选用基于版本号的乐观锁替代悲观锁
- 开发过程中,开启hibernate.showsql选项查看生成的sql,进而了解底层的状况。开发后关闭此选项
- 考虑数据库本身的优化,合理的索引、恰当的数据分区策略
锁机制,hibernate的悲观锁和乐观锁机制
有些业务逻辑在执行过程中要求对数具进行排他性的访问,于是需要锁机制来保证在此过程中数据被锁住,不会被外界修改
- 悲观锁 认为有人同时处理数据,,Hibernate的session的get、load方法从数据库中取数据,可以通过参数配置指定使用悲观锁
- 乐观锁 认为没人同时处理数据,,使用版本号,进行控制。可以通过给实体类加整形的版本字段,在通过XML或@version注解进行配置,空间换时间,系统并发性更好
Hibernate分页查询
提供一些列参数,hibernate会自动生成
提供查询条件或者HQL语句,
二级缓存与查询缓存
- 提供一级缓存、默认总是有效,应用程序保存、修改持久化实体的时候,不会立即操作数据库,而是缓存在session中,等待session的flush或close方法,才提交到数据库。
- 二级缓存全局的,所有session都可以共享这个二级缓存,默认是关闭的。
一级二级缓存都是对整个实体进行缓存,不会缓存普通属性。
普通属性用查询缓存:查询缓存是将HQL或SQL语句以及他们的查询结果作为键值对进行缓存,对于同样的查询可以直接从缓存中获取数据。默认是关闭的。
Struts
Struts的应用??????
Structs是采用Java Servlet/JavaServer Pages技术,开发web应用程序的开放远大framework
- 包含一个controller servlet 能将用户的请求发送到相应的Action对象,
- JSP自由tag库,并在controller servlet中提供关联支持,可以创建交互式表单应用
- 提供一系列适用对象:XML处理、通过Java reflection APIs自动处理JavaBean属性、国际化的提示和消息
Mybatis
Mybatis的命名空间的作用
在大型项目中,大量的sql语句,如果为每个sql语句起一个唯一的标识ID,非常不容易,为了解决这个问题,Mybatis中可以为每个映射文件起一个唯一的命名空间,里面的每个sql语句就是这个命名空间里的唯一ID。
可以保证每个命名空间的ID唯一,不同命名空间相同ID不会冲突。
Mybatis 的动态SQL是什么意思
对于一些复杂的sql查询,可能有很多查询条件、这些条件可能存在可能不存在,动态sql就可以解决这个问题
- if
- choose/when/otherwise
- trim
- where
- set
- foreach
JPA是什么
Java Persistence API,java持久层API
MVC
Spring MVC 注解的优点
- 可以替换xml
- 简化XML配置,
- 相对XML是类型安全的,XML只能在运行期才能发现问题
SpringMVC和SpringBoot的区别
Spring基础是IOC与AOP,在此基础之上有很多发展品,Boot、JPA、Security等等,所以功能比较复杂,配置起来也比较复杂,各种xml、properties处理起来繁琐。为了简化开发者应用,提出了SpringBoot,遵循约定由于配置,极大地降低了Spring使用门槛。
Spring MVC的运行机制
-
客户端的所有请求都交给前端控制器DispatherServlet来处理,会负责调用系统的其他模块来真正处理用户的请求
- 用户发送请求时会从doService方法中,将ApplicaitonContext、localResolver、themeResolver等对象添加到request中,
- 然后调用doDispatch方法。首先检查请求是否为文件上传请求,若是,将request包装成MultipartHttpServletRequest
- 调用getHandler方法匹配每个HandlerMapping对象,若成功,则会返回此handler的处理链HandlerExecutionChain对象,
- 执行拦截器的preHandler
- 将HandlerExecutionChain对象的getHandler()方法获得一个object,通过HandlerAdapter封装得到HandlerAdapter对象
- 调用HandlerAdapter的handle方法执行controller的方法,返回ModelandView
- 。。。
-
DispatherServlet收到请求后,将会根据请求的信息(URL,http协议方法,请求头,请求参数,cookie等)以及handlerMapping的配置找到处理改请求的handler(任何一个对象都可以作为请求的handler)
-
Spring会通过HandlerAdapter对该处理器进行封装。
-
HandlerAdapter是一个适配器,用统一的接口对各种Handler的方法进行调用
-
Handler完成对用户请求的处理之后,会返回一个ModelAndView对象给DispatcherServlet,ModelAndView顾名思义,就是包含了数据模型以及相应的视图信息。
-
ModelAndView的视图是逻辑视图,DispatcherServlet还要借助ViewResolver完成从逻辑视图到真正视图对象的解析工作。
-
真正得到视图对象后,DispatcherServlet会利用视图对象对模型数据进行渲染。
-
客户端得到相应,得到html或xml或jaon或pic或pdf
Mybatis与Hibernate
- Hibernate是流行的ORM(对象关系映射)框架之一,对JDBC有较为完整的封装。实现了POJO和数据库表之间的映射,以及sql的自动生成和执行。
- Mybatis也是流行的ORM框架,主要着力点在于POJO与Sql的映射关系。通过映射配置文件,将sql所需的参数,以及返回的结果字段映射到POJO。
- 相对于Hibernate的O/R,Mybatis是一种SQL mapping的ORM实现。
不同点:
- hibernate的二级缓存配置在SessionFactory生成的配置文件中hog,然后在具体的表-对象映射中配置是哪种缓存。无须关心sql,二级缓存如果出现脏数据,系统会报错。强大、方便、高效、复杂、简介、全自动化
- Mybatis二级缓存配置食杂每个具体的表-对象映射中详细配置。可以针对不同的表自定义不同的缓存机制。Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。使用二级缓存,特别小心。小方便】】高效、简单、直接、半自动化
JAVA领域的WebService框架
- Axis2
- Jersy
- CXF
- Hessian
- Turmeric
- JBoss SOA
EJB
EJB包括Session Bean、 Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现
- SessionBean永利来完成一些服务器端的业务操作(访问数据库、调用其他EJB组件)。
- Stateful Session Bean。可以记录使用者的状态。一个使用者会有一个相对应的Stateful Session Bean.
- Stateless Session Bean:不记录使用者的状态
- EntityBean代表应用系统中用到的数据
EJB与java bean
- Java Bean 可复用。理论上任何一个类都可以成为javabean,但通常Javabean是由容日所创建(如tomcat),所以应当具有一个无参构造器,还要实现Serializable接口用于实现持久性。不能被跨进程访问
- EJB相当于DCOM,即分布式组件。基于JAVA远程方法调用技术(RMI),可以被远程访问(跨进程、计算机)。但必须被部署到webspere、weblogic这样的容器中。WJB客户通过容器访问真正的EJB组件。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。
EJB生命周期
- SessionBean:
- staless session bean生命周期由容器决定,调用时,不一定创建新的bean对象
- stateful session bean,调用时,会立即创建新的bean实例,,关联到客户机上,
- EntityBean: 能存活相当长时间,状态是连续的。即使EJB容器崩溃,entitybean仍然存活。可以由bean或者EJB容器管理器生命周期。
EJB几种类型、业务执行顺序
JAVAWEB
Web编程基础
tomcat服务器如何实现在启动项目时实现不在链接里输入项目名就能启动
可在tomcat里配置虚拟目录
1分钟只能处理1000个请求
限流的几种做法:
- 计数器
- 滑动窗口
- 漏桶法
- 令牌桶
assertion断言
用于保证程序最基本、关键的正确性
assertion就是程序中的一条语句,对一个Boolean表达式进行检查,正确的程序必定为真,为假则程序必有问题
JAVA应用服务器
- WebLogic Server
- WebSphere Application Server
- 9i Application Server
- JBoss
- Tomcat
JSP内置对象及方法
- request,HttpServletRequest对象,包含有关浏览器请求的信息,提供了用于获取cookie、header、session的方法
- response,HttpServletResponse对象,包含可以设置响应头的方法
- out ,javax.jsp.JspWriter,可以浏览器输出数据
- pageContext:javax.servlet.jsp.PageContext对象,用于方便存取各种范围的名字空间、servlet相关的对象的api,并且包装了通用的servlet相关功能的方法。
- session:表示请求的javax.servlet.http.HttpSession对象。可以存储用户的信息。
- application:javax.servlet.ServletContext对象。有助于查找相关servlet引擎和servlet环境得信息。
- config:javax.servlet.ServletConfig对象。用于存取servlet实例的初始化参数。
- page:表示该页面产生的一个servlet实例。
JSP与Servlet的区别
- JSP是servlet的扩展,本质是S而vlet的简易方式。编译之后是类servlet,侧重于视图
- Servlet的应用逻辑在JAVA中,完全可以从表示层的HTML分离出来。侧重于控制逻辑。JSP是java和html的组合。
四种会话跟踪技术:
- page:代表与一个页面相关的对象和属性,jsp、servlet
- request:与客户机发出的请求的相关的对象和属性,请求可能跨越多个页面,涉及多个web组件
- session:是代表与某个客户机的一个用户体验相关的对象和属性,可以跨多个客户机请求
- application:代表与整个web应用程序相关的对象和属性,跨整个web应用程序,包括多个页面、请求、会话的一个全局作用域
文件目录的组织
JSP动作指令(6种)
- jsp:include:在页面被请求时候引入一个文件
- jsp:useBean:寻找或实例化一个javabean
- jsp:setProperty:设置javabean的属性
- jsp:getProperty:输出某个Javabean的属性
- jsp:forward:请求转到新页面
- jsp:plugin:根据浏览器类型,为java插件生成OBJECT或EMBED标记。
JSP的9个内置对象
-
request:封装客户端的请求,
-
response:封装服务端的相应
-
pageContext:通过该对象可以获取其他对象
-
session:封装用户的会话
-
application:封装服务器运行环境的对象
-
out:输出服务器相应的输出流
-
config:web应用的配置
-
page:jsp页面本身
-
exception:封装页面抛出异常
-
第一次请求一个JSP页面,Servlet/JSP容器首先将JSP页面转换为一个JSP页面的实现类,这是一个实现了JspPage接口或者其子接口HttpJspPage的java类。
-
JspPage接口是servlet的子接口,因此每个jsp页面都是一个servlet。
-
转换成功后,容器编译servlet,加载、实例化java字节码,并执行它通常对servlet所做的生命周期操作。
-
对于同一个jsp的后续请求,如果没被修改,则使用已存在的servlet实例,否则重新编译、执行。
EL表达式语言
JSP静态和动态包含
- 静态包含,include指令,编译时包含,如页面不存在,会报错,页面的ContentType应当保持一致,因为会合二为一,只产生一个class文件。
<%@ include file==" " %>
- 动态包含,jsp:forward,运行时包含,可以传递参数。两个页面独立,会编译出来两个class文件,如不村子不会报错
<jsp:include page="...">
<jsp:param name=".." value="..."/>
</jsp:include>
过滤器 filer
是一个驻留在服务器端的web组件,可以截取客户端与服务器端的请求响应信息,并对这些信息进行过滤。
监听器 listener
javaweb中的监听器就是application、session、request三个对象创建、销毁、修改时自动执行代码的功能组件。
web.xml可以配置web应用哪些内容
web.xml可以配置web应用的相关信息,如监听器(listener)、过滤器(filter)、Servlet相关参数、会话超时时间、安全验证方式、错误页面。
Web编程进阶
forward与redirect
- forward是服务器请求资源,服务器直接访问目标地址url,把url地址相应内容读取过来,然后把这些内容发送给浏览器,浏览器不知道这个内容从哪里来,所以地址还是原来的地址。原页面和转发到的页面可以共享一个request的数据。主要用于用户登录时,根据角色转发到相同模块。效率高
- redirect是服务器根据逻辑,返回一个状态码,浏览器重新请求新地址,地址栏显示的是新地址。不能共享数据。主要用于用户注销登录时,返回主页面和跳转到其他网站。效率低。redirect的状态码是302.
servlet生命周期、单实例
从创建到毁灭的过程:
- init():被服务器实例化之后,会调用init(),仅执行一次。
- service(),请求到达时运行service(),自动运行其中的doPost或者doGet方法。
- destroy():销毁是调用destroy。仅执行一次。
- 最后由JVM的垃圾回收器进行垃圾回收。
servlet是单实例的,减少了servlet的开销。
- servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务多个请求,且实例一般不会销毁
- CGI对每个请求都产生新的进程,服务完成就销毁,效率上低于servlet
servlet的异步处理
可以帮助节省容器的线程,特别适合执行时间长而且用户需要到结果的任务,如果不需要得到结果,直接将Runnable对象交给Executor并立即返回即可。
何时调用Servlet的doGet()还是doPost()
Servlet-》HttpServlet-》GenericServlet
HttpServlet重写的service()方法会首先获取用户请求的方法,然后根据请求调用doGet、doPost、doPut、doDelete等。
HTML的元素有一个method属性,用来指定提交表单的方式,其值可以为get或者post。如果是post请求就调用doPost方法,如果是get请求就调doGet方法。
Servlet获取用户提交的查询参数和表单数据
- 通过请求对象的getParameter()方法,通过参数名获得参数值。
- getParameterValues()方法获取多个值的参数如复选框,
- getParameterMap()获得一个参数名和参数值的映射Map
Servlet获取用户配置的初始化参数以及服务器上下文参数
- 通过重写Servlet接口的init(ServletConfig)方法,并通过ServletCOnfig对象的getInitParameter()获取Servlet的初始化对象。
- ServletConfig.getServletContext获取ServletContext对象。
- 在doXXX方法中通过请求对象的getServletContext方法来获得。
redis
redis的主从复制
- 第一阶段:与master建立连接
- 第二阶段:向master发起同步请求(SYNC)
- 第三阶段:接受master发来的RDB数据
- 第四阶段:载入RDB文件
redis为什么读写速率快性能好
redis是纯内存数据库,hash查找可以达到每秒百万此的数量级
redis多路复用IO
多路:多个网络连接,复用指的是复用同一个线程。
采用多路复用技术可以让单个线程高效处理多个连接请求(尽量减少网络IO的时间消耗)
可以理解为:单线程的原子操作,避免上下文切换的时间和性能消耗–加上对内存中数据的处理速度,很自然的提高了redis的吞吐量。
redis 为什么是单线程
cpu不会是redis的瓶颈,redis的瓶颈最有可能是机器内存或网络带宽
缺点是会导致服务器其他核闲置
缓存的优点
- 加快响应速度
- 减少对数据库的操作,数据库压力降低
AOF和RDB的区别
AOF持久化记录服务器的所有写操作命令,并在服务器启动时,通过重新执行这些命令,来还原数据集
RDB持久化可以在指定的时间间隔内生成数据集的时间点快照(point—in-time snapshot)
Redis的List应用场景
redis的list的数据结构是双向链表,可以应用于消息队列(生产者/消费者模型)
MVC与DAO
MVC
- model:代表应用的业务逻辑,EJB实现,
- view:应用的表现层,用于与用户的交互,JSP实现
- controller:提供应用的处理过程控制,servlet实现
DAO
data access object:为数据库或其他持久化机制提供先后将接口对象,不暴露底层持久化实现细节的前提下提供各种数据库的访问接口
DAO实际上包含了两个模式,Data Accessor(数据访问器)解决如何访问数据的问题,Data Object(数据对象),解决如何用对象封装数据
JAVAWEB中的model1与model2
- model1指的是以页面为核心的javaweb开发,使用jsp和javabean技术将页面显示逻辑和业务逻辑处理分开,
- model2基于MVC架构模式的开发,实现了模型和视图的彻底分离,利于团队开发和代码复用
JSTL、DisplayTag等标签库的用法
JSTL:
核心标签库有<c:if> <c:choose> <c:when> <c:otherwise> <c:forEach> 主要用于构造循环和分支结构以控制显示逻辑
自定义标签
368969126
WEB编程原理
POST与GET
- Get方式通过url传递数据,提交的数据最高只能1024字节,用来获取数据。使用MIME类型application/x-www-form-urlencoded的编码(也叫百分号编码)文本的格式传递参数,保证被传送的参数遵循规范的文本组成,如空格的编码是%20
- Post方式通过HTML的header内或消息体中提交,可以提交无限制大小的数据,用来提交数据
转发和重定向
- forward 服务器请求资源,直接访问目标地址的url,把那个url的响应内容读取出来,在转发给浏览器。地址没有变化,RequesDispatcher.forward() ,可以隐藏实际的链接
- redirect 服务器根据逻辑,发送一个状态码,告诉浏览器去重新请求那个地址,地址会变化。HttpServletResponse.sendRedirect()
请求和相应架构原理
cookie和session的区别
- cookie:数据在客户端浏览器中,在本地所以就不安全,单个cookie的数据保存不能超国标4k,很多浏览器限制一个站点最多保存20个cookie
- session:数据在服务器上,一定时间内保存在服务器上,访问增多,会占用服务器性能
设置请求编码以及相应的内容类型
通过ServletRequest.setCharacterEncoding(String)设置请求编码,最好使用UTF-8
乱码彻底解决,就应该让页面、服务器、请求与响应、java程序视同统一的编码方式,最好是UTF-8
也可以通过设置响应对象ServletResponse.setContentType(String)方法,设置响应内容的类型,也可以通过HttpServlet的setHead(String ,String)来设置,解决乱码问题
Web Service
web service向外界暴露处一个通过web调用的api,基于HTTP协议传输数据。
SOA(Service Oriented Architecture)面向服务的架构。,是一种思想,将应用程序的不同功能单元通过中立的契约联系起来,独立与硬件,操作系统和编程语言,使得各种形式的功能单元能够更好地集成。
web容器
J2EE中的名词
- WEB容器:实现J2EE体系结构中web组件协议的容器。规定了一个web组件运行时的环境,包括安全、一致性、生命周期管理、事务、配置和其他的服务
- EJB容器:Enterprise java bean容器,提供在其运行中的组件EJB各种管理功能
- JNDI:java naming & directory interface,java命名目录服务:提供一个目录系统,使得在其上面运行的应用程序留下自己的索引,从而可以快速查找和定位分布式应用程序
- JMS: java message Service java消息服务。
- JTA: java transaction api java事务服务
- JAF: java action framework java安全认证框架
- RMI/IIOP:remote method invocation/internet 对象请求中介协议,主要用于远程调用服务
JDBC基础
数据库水平切分和垂直切分(水平拆分行,行数据拆分到不同表中,垂直拆分列:表数据拆分到不同表)
- 水平切分:把表按模块划分到不同数据库表中,单表大数据量仍然存在性能瓶颈
- 垂直切分:把一个表按照某种规则把数据划分到不同表或数据库中
数据库索引
- 索引是对数据库表中一列或者多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。
- 底层是用B+树实现的,如果没有遵循最左匹配原则,会失效。
数据库引擎
- InnoDB 聚集索引,支持事务,支持行级锁
- MyISAM 非聚集索引,不支持事务,只支持表级锁
数据库的隔离级别
- 未提交读:允许脏读,,可能会读到其他会话中未提交事务修改的数据
- 提交读:只能读到已经提交的数据,
- 可重复读:在同一个事务内的查询都是事务开始时刻一致的。
- 串行读:每次读都需要获得表级共享锁,读写都会阻塞
数据库乐观锁和悲观锁
- 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作,如java中的synchronized,每次修改数据,必须先获得锁,保证一个时刻只有一个线程 能操作数据。
- 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。每次取数据都认为别人会修改,所以不会上锁。,提交时会判断一下再次期间有没有别人更新信息。适用于读少写多,可以提高吞吐量。一般有两种方式,为数据加一个version;或者为数据加一个时间戳
数据库的三范式
- 第一范式:1NF,强调列的原子性,即列不能在分成其他几列
- 第二范式:2NF,在1NF基础上,任何非主属性不依赖于其他非主属性。一个表必须有一个主键,没有包括在主键中的列必须完全依赖于主键
- 第三范式:3NF:是2NF的子集,非主键列必须直接依赖于主键,不能存在依赖传递
数据库ACID
- 原子性Atomicity指事务是一个不可分割的单位,事务中的操作要么全部发生,要么全都不发生
- 一致性Consistency指事务前后的数据完整性必须保持一致
- 隔离性Isolation指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发事务中要相互隔离
- 持久性Durability指一个事务一旦提交,他对数据库中的数据的改变就是永久性的,即便数据库发生故障也不应该对其有任何影响
MysqL主从复制
- 基础:主服务器对数据库修改记录二进制日志,从服务器通过主服务器的二进制日志自动执行更新
- 同步、异步主从复制
leftjoin 与 rightjoin
- 左联接:返回包括左表中的所有记录和右表中联结字段相等的记录
- 右联接:返回包括右表中的所有记录和左表中联结字段相等的记录
数据库优化方法
- 选取最适用的字段属性
数据库中的表越小,查询也越快,因此,可以将表中的字段宽度设置的尽量小一些;另一方面,尽量把字段设置为NOTNULL,因此执行查询的时候,不用去比较空值;有一些文本,如省份、性别,可以定义为ENUM类型,可以被当做整形数值处理,速度会加快 - 使用连接JOIN代替子查询Sub queries
- 使用联合UNION来代替手动创建的临时表
- 事务:可以保持数据库中的数据的完整性,BEGIN开始、COMMIT结束,如果其中的任意一条sql失败,ROLLBACK都可以将数据库恢复到BEGIN前的状态
继承映射
- 每个继承结构一张表,所有子类共用一张,查询速度快,但表很大
- 每个子类有一张表,公共信息放一张。查询速度慢,需要进行连接查询,不适合多态查询。,下同。
- 每个具体类放一张,有多少子类就放多少个表
数据库连接池
数据库连接池工作机制
J2EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池程序会返回一个未使用的池连接,并标记为忙。如果没有空闲连接,池驱动程序根据配置参数新建一定数量的连接。调用完成之后,将此连接标记为空闲。
事务管理
事务
事务只有这存在并发数据访问时,才需要事务。当多个事务访问同一数据,会出现5类问题(3类数据读取问题,脏读、不可重复读和幻读)和2类数据更新问题(第1类丢失更新和低类丢失问题)
JDBC中的事务处理操作
Connnection提供了事务处理的方法,调用setAutoCommit(false)可以设置手动提交事务。事务完成之后使用commit显示提交事务,如发生异常,通过rollback方法进行事务回滚。
JDBC3.0中引入了Savepoint(保存点)的概念,允许通过代码设置保存点让事务回滚到制定的保存点。
JDBC进阶
JDBC反射
通过反射com.mysql.jdbc.Driver类,实例化该类的时候,会执行该类内部静态代码块,会在Java实现的DriverManager中注册自己,会管理所有已注册的驱动类, 当调用DriverManager.getConnection方法时会遍历这些驱动类,并尝试连接数据库,如果有一个连接成功,则返回Connection对象,否则报异常
JDO
Java data Object :Java对象持久化的新规范,用于存取某种数据仓库中的对象的标准化API
JDBC只是面向关系型数据库,JDO更通用,提供到任何数据底层的存储功能,比如关系数据库,文件,xml,以及对象数据库,移植性更强
Statement与PreparedStatement
- PreparedStatement:代表预编译的语句, 可以减少sql的错误,并增加sql的安全性(减少sql注射攻击的可能),
- PreparedStatement 语句可以携带参数,避免字符串拼接
- 在批量处理和频繁执行相同查询时,性能更好(预编译优化后的sql语句会被缓存,所以下次读就会很快)
CallableStatement可以调用存储过程(Stored Procedure)
- 存储过程就是数据库中的一组为了完成特定功能的sql语句集合,编译后存储在数据库中,用户通过指定存储过程的名字并给出参数,来执行。性能会提升,但是如果底层数据库发生迁移,就会比较麻烦,因为各种数据库的存储过程在书写上有差异
JDBC优化,提升读取数据性能
- 读取数据时,通过结果集对象ResultSet的setFetchSize方法指定每次抓取的记录数,(空间换时间)
- 更新数据时,使用PreparedStatement构建批处理语句,将若干sql置于一个批处理中执行
XML编程
##XML文档的定义形式
- dtd:data type definition ,数据类型定义
- schema:schema本身是xml的,可以被xml解析器解析,基于xml编写,语法和类型上强于dtd,
解析XML文档的方式
- DOM:基于DOM的树结构解析,解析之前需要把整个文档装入内存,适合对xml的随机访问,但处理大文件时,性能会下降
- SAX:事件驱动的xml解析方式,顺序读取xml,不需要一次性全部加载整个文件,遇到文件开始、结束、标签开头、结束会触发事件,用户可以在其回调事件中写出处理逻辑,适合对xml的随机访问
- STAX: streaming API for XMl STAX
Web Service
WSDL与SOAP协议
- Web Service:基于网络的、分布式的模块化组件,它执行特定的任务,遵守具体的技术规范,使得webservice能与其他兼容的组件进行互操作
- JAXP:Java API for XML Parsing:定义了java中使用DOM,SAX,XSLT的通用接口
- JAXM:JAVA API for XML Messaging:为SOAP通信提供访问方法和传输机制的API
- SOAP:Simple Object Access Protocol 用于交换XML编码信息的轻量级协议。,是webservice最关键技术,是数据和方法传输的介质
- UDDI:为电子商务建立标准
- WSDL:将网格服务描述成一组端点,这些端点对包含面向文档信息或面向过程信息的消息进行操作,描述webservice的接口和功能
计算机网络
TCP,IP, HTTP
运输层、网络层、应用层
TCP三次握手,
TCP应用场景
对于通信质量有要求的应用场景,HTTP,HTTPS,FTP,POP,SMTP等
TCP可靠的原因
三次握手、超时重传、滑动窗口、拥塞控制
TCP建立连接的原因
为了保证可靠传输
协议
##浏览器接受url到展示压面过程
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
http与https
- https需要申请证书到CA,需要一定经济成本
- http明文传输,https是加密安全传输
- 连接端口http80,https是443
- http连接简单,没有状态,https是ssl加密传输,身份认证的网络协议,较安全
http1.1和http1.0
ssl四次握手
- 客户端请求:浏览器向服务器发出加密通信请求,ClientHello
- 服务器回应:服务器收到客户端请求,发出回应,ServerHello
- 客户端回应:客户端收到浏览器回应,首先验证服务器证书,如果不合格,发出警告,访问者选择是否继续通信
- 服务器回应:服务器受到客户端发送的第三个随机数pre-masterkey,计算省成本次会话的会话秘钥,向客户端发送
- 编码改变通知:之后信息都用双方商定的加密方法与密钥发送
- 握手结束通知:
304
未修改状态码:表示网页自请求者上次请求后再也没有更改过,进而节省带宽和开销。
ARP协议,ARP攻击
地址解析协议
APR攻击的第一步就是ARP欺骗,即伪造的IP和MAC地址
ICMP
网际控制报文协议,用于IP主机、路由器之间传递控制消息。即网络通不通,主机是否可达,路由是否可用等网络本身的消息
路由器和交换机的区别
- 交换机,用于在同一网络内部的快速传输转发,可以通过查看二层头部,数据帧在二层。直接使用硬件处理
- 路由器,用于不同网络间数据的跨网络传输转发,可以通过查看三层头部,转发需要修改TTL,IP头部校验和需要重新计算,数据帧需要重新封装在三层中进行传播,软件控制
DNS:客户端到DNS是递归查询,DNS之间是交互查询,即迭代查询
- 首先检查域名在本地的hosts文件中是否存在,如果有,则进行地址映射,完成域名解析
- 如果没有,则找本地DNS解析器缓存,如果有则返回
- 如果没有首先会找TCP/IP参数中的设置的首选DNS服务器,即本地DNS服务器,进行查询,有则返回,无则下一步
- 如果本地DNS没有解析,但有缓存,有则返回,无则下一步
- 如果都没有,若本地DNS使用的是转发模式,则将请求转发至上一层DNS,有上一层解析,最后把结果返回本地DNS,返回给本机;如果不是转发模式,则直接把请求发给13台根DNS,根DNS判断请求由谁授权管理,返回给负责处理的顶级DNS的IP,本地DNS收到后,联系该域的顶级DNS解析,如不能,则发送给下一级DN
负载均衡中的反向代理Reverse Proxy
- 以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上的结果返回给Internet请求连接的客户端
- 将把来自Internet的连接请求以反向代理的方式动态转发给内部网络上多台服务器,幸而达到负载均衡
- 可以将优化的负载均衡策略和代理服务器的高速缓存技术结合,提升访问速度和安全性
- 缺点是,运行在第七层,针对不同应用服务需要专门开发代理服务器;每一次代理,代理服务器都需要打开两个连接,一个对内,一个对外,如果请求数量非常大,代理服务器会成为瓶颈
操作系统
Centos与Linux
- linux三大发行版本,Slackware, debian,redhat
- centos是linux的众多发行版本之一,centos来自依照开放源代码规定而公布的源代码编译而成,不包含封闭源代码软件,是开源的
64与32位操作系统的区别
32位操作系统针对32位的CPU设计,64位针对64位CPU设计
进程(杀死用 kill pid)
- 一个程序至少有一个进程,一个进程至少有一个线程
- 线程的划分尺度小于进程,即多线程程序并发性高
- 进程拥有独立的内存单元,多个线程共享进程 内存,
- 每个线程有一个程序运行的入口,顺序执行序列 ,和出口。但是线程不能独立运行,必须依托应用程序
- 多线程的意义在于一个应用程序,有多个执行部分可以同时执行,但OS并没有将其看做多个独立的应用
系统最大线程数
LInux的单个进程最大线程数有最大限制,PTHREAD_THREADS_MAX,在。/usr/include/bits/local_lim_h中查看,受限于系统资源,即线程stack所占用的资源,用ulimit-s可以查看默认线程栈大小,一般是8M=8192KB
LINUX下线程
linux实现的就是基于核心轻量级进程的“一对一”线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库实现。
GDI图像设备编程接口类库
输入输出系统
socket编程,BIO,NIO,epoll
存储器管理
页式存储
主存被等分成为大小相等的片,称为主存块,称为实页。
当一个用户程序装入内存时,以页面为单位进行分配,页面大小通常为1KB,2KB,2^nKB等
操作系统内存碎片
内存碎片分为内部碎片和外部碎片
- 内部碎片,已经被分配出去,但不能被利用的内存空间。内存碎片是处于区域内部或页面内部的存储块,占有该区域或页面的进程并不使用这块存储块时,而进程占有这块存储块石,系统无法利用,直到进程释放,或进程结束。单道连续分配只有内部碎片,多道固定连续分配既有内部也有外部。
- 外部碎片:还没有被分配出去(不属于任何进程),大那是由于太小了无法分配给申请内存空间的新进程的内存空间区域。外部碎片是指空闲存储块,可以满足需要,但是由于地址不连续等其他原因,无法分配。
处理机调度与死锁
死锁
- 互斥条件,一个资源一次只能被一个进程访问。
- 请求与保持条件,一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件,进程已经获得的资源,除非自己释放,不能在未使用完前被强行剥夺
- 循环等待条件,若干资源形成一种头尾相接的循环等待资源关系
- 解决办法,银行家算法
系统提高并发性方法
- 提高cpu并发计算能力
- 多线程、多进程
- 减少进程切换,使用线程,考虑进程绑定CPU
- 减少使用不必要的锁,考虑无锁编程
- 考虑进程优先级
- 关注系统负载
- 改进IO模型
- DMA技术
- 异步IO
- 改进多路IO就绪通知策略,epoll
- sendfile
- 内存映射
- 直接IO
算法与数据结构
HashSet是无序的,TreeSet是有序的
HashMap的key如果是Object,则Object的hashcode不能变
一致性哈希算法
构造一个长度232的整数环,即一致性hash环,根据节点将服务器放置上去。根据数据的key值计算得到hash值,顺时针查找距离这个key值最近的服务器节点,完成映射。
能够解决普通余数hash算法伸缩性差的问题,可以保证在上线、下线服务器的情况下,尽量有多的请求能够命中原来的服务器
hashMap 是两个参数,初始容量和加载因子
容量是hash表中桶的数量,初始容量只是hash表在创建时的容量,加载因子是hash表在其容量自动增加前可以达到的多满的一种尺度。默认为0.75。当hash表中的条目超出加载因子与当前容量的乘机,则需要进行rehash(重建内部数据结构)
JAVA中的HashMap工作原理
HashMap类的有一个内部类Entry,包含了key-value作为实例变量。hashmap每push一个keyvalue,都会实例化一个Entry对象,会存到Entry数组table中,存放位置根据key的hashcode方法计算出来的hash值决定。
hashCode与equals
可以用来发现重复值,小心,不同键还有相同的hash值
B+和B-树
- B+树中间节点不保存数据,所以磁盘页能容纳更多地节点元素,更“矮胖”。查询时,必须找到叶子节点,查找更稳定
- b树只要匹配到,可以不用管元素位置。
- 对于范围查找,B+树需要遍历叶子节点链表,b树需要重复终须遍历
TreeSet、TreeMap、Collections.sort
- TreeSet要求存放的对象所属类必须实现Comparable接口,提供比较元素的compareTo方法。
- TreeMap要求存放的键值对映射的键必须实验Comparable接口从而根据键对元素排序
- Collections.sort 有两种重载类型
-
- 传入的对象必须实现Comparable接口
-
- 传入的对象不需课比较,但需要传第二个参数,是Comparable接口的子类型,需要重写sort方法。
检测链表是否有环
- 定义两个指针,同时从链表的头结点出发,一个一次走一步,一个一次走两步,如果走的快的追上了走的慢的,就有环。否则走的快的走到了空节点,即没有环
- 定义一个map(NODE,count),遍历链表,出现一次,count+1,如果count为1,则代表节点被访问过了,即有环
堆栈
- 堆,运行时数据区,类的对象从中分配内存。可以动态分配内存,垃圾回收器自动回收。但存取速度慢
- 后进先出。读取速度比堆快,仅次于寄存器,栈数据可以共享。但数据大小和声明周期没有堆灵活。
- 栈操作很快,但是内存小,大对象通常存在堆中。
- java中,new关键字和构造器创建的对象在堆中,基本数据类型的变量、对象引用、函数调用的现场都是栈。代码上的字面量,常量都是在静态区中。
Java优先级队列Priority Queue
基于优先级堆的无界队列,按照自然排序。不允许空值,不是线程安全,入队和出队时间复杂度是O(logn)
id全局唯一且自增,可使用snowFlake算法,雪花算法
64位二进制整数,转换为10进制数
- 1位标识符,0位正,1位负,始终为0
- 41位时间戳,当前时间-id生成器开始生成时间,
- 10位机器标识码
- 12位序列
- 简单高效,生成速度快,但是按照时间排序生成,服务器时间如果有改变,会有重复值,况且每个服务器始终不可能完全同步
压缩URL
MD5算法。对原始链接进行加密,加密后字符串长度为32位。再进行处理得到地址。
LRU 最近最少用到算法
- 命中率:存在热点数据时,效率会好,但偶发性、批量性的操作会导致LRU命中率急速下降,缓存污染会严重
- 没有空间浪费,实现简单,代价是,命中时需要遍历链表,找到命中的数据块索引,然后将数据移到头部。
设计模式
java代理模式
静态代理,动态代理,cglib代理
IO流设计模式
装饰模式,适配器模式
单例模式
保证一个类只有一个实例,并提供一个访问他的全局访问点
- 优点:单例类只有一个实例、共享资源,全局使用节省创建时间,提高性能。可以用静态内部类实现,保证是懒加载(使用时才会创建实例对象)