必看blog:http://blog.csdn.net/lifetragedy/article/details/8507252
本文是总纲,重点介绍各知识点之间的关系,以及每个知识点的原理及架构,以及一些特别的注意点,不涉及过多的具体细节;
具体细节在其它的分文章中介绍;
知识体系整理:
1.JAVA基础知识(初始化加载顺序,类加载体系,基本API实现及差别(I/O,MAP,LIST,STRING),内部类,网络,异常分类及机制,泛型实现机制,动态代理实现机制(OSGI和其它),线程,并发和同步,引用,本地线程类,反射,注解,JVM结构,JVM调优,垃圾回收,Socket,NIO/BIO/AIO)
2. 设计模式
3. 字符集(ORACLE,JAVA及JSP)
4. Web知识(session,jsp,servlet,filter,自定义标签,Listener),HTTP协议,JS,DOM,AJAX,Jquery,CSS,JQuery,ExtJS
5. JPA规范,JDBC,IBATIS,MYBATIS,,事务,JNDI,datasource(dbcp,op3),HIBERNATE(事务,一二级缓存,配置,三种状态)
6. SPRING,注释及配置,单例多例,SPRING做Control的作用及使用,spring事务,Spring动态代理实现及AOP和事务实现,log4j/slf4j及扩展,SPRING重要工厂类
7. STRUTS2,STRUTS1的架构及原理,struts2重要配置文件及扩展,国际化实现,拦截器实现原理及与SPRING整合
8. View技术:(JSP,自定义标签,EL,JSTL),freemarker,velocity
9. DB原理,ORACLE,MYSQL,ORACLE字符集注意,基本性能注意,SQL,安装与环境搭建;
10. LDAP原理及整合,TOMCAT,JBOSS,WEBSPHERE原理及整合,调优,APACHE,IHS整合,调优,安装与环境搭建;
11. WEBSERVICE原理及实现分类,与REST比较,JAVA Webservice
12. UML,E-R图(外键),XML解析
13. JBPM原理,工作流原理及实现和注意
14. Portal原理,IBM Portal实施及注意
15. RCP原理及实现和注意
======================================================================================================================================================
一。 JAVA基础知识
1. 类初始化加载顺序
JAVA类与加载相关的主要有如下几种元素:类属性,类静态属性,类静态代码块,类构建方法,父类属性,父类静态属性,父类静态代码块,父类构建方法;
初始化包括使用new()和class.newInstance()方法;
如果是Class.forName(String ClassName)方法,则只执行静态代码;
如果是class.LoadClass(String ClassName)方法,则不会执行任何代码;
类第一次初始化时(即之前从未初始化过该类实例):
1. 父类静态属性和静态代码块,依赖于在类代码中的顺序
2. 类静态属性和静态代码码,依赖于在类代码中的顺序
3. 父类属性
4. 类属性
5. 父类构造方法
6. 类构造方法
类初始化时(即之前类曾经初始化过):
1. 父类属性
2. 类属性
3. 父类构造方法
4. 类构造方法
2. 类加载体系
1.JVM标准类加载体系如下:
Bootstrap ClassLoader-->ExtClass Loader-->AppClass Loader-->CusClass Loader
2.在JVM中,父Load的类对子类可见,而子类Load的类则对父类是不可见的,同级的Load加载的类也互不可见;、
3.JVM内部实际的类全称是:Loader名+类全称;
JVM内部实际的方法名是:返回类型+方法名+参数列表;
4. 从加载方式上来看,其实分为两种:系统提供的类加载器和自己实现的类加载器
系统提供的类加载器采用典型的双亲委托模式,而自己实现的类加载器则不一定;
加载类分为初始加载器和定义加载器;调用load()的为初始加载器,最终加载类的称为定义加载器;
其中当前类加载器使用典型的代理模式,先由父加载器加载,若不成功,再由当前类加载器加载;
而线程上下文类加载器则直接由当前类加载,但为了防止与其父类加载器加载的类冲突,一般会先检测加载的类是否为父类加载器范围的类;
3. 基本API实现及差别(I/O,MAP,LIST,STRING)
(1)I/O字节流重要类:
InputStream,FileInputStream,BufferedInputStream,ZipInputStream,GZIPInputStream;已过时的有DataInputStream,StringBufferInputStream;
OutputStream,FileOutputStream,BufferedOutputStream,ZipOutputStream,GZIPOutputStream;
I/O字符流重要类:
Reader,BufferedReader,InputStreamReader,FileReader
Writer,PrintWriter,BufferedWriter,OutputStreamWriter,FileWriter
I/O随机访问重要类:
RandomAccessFile
其中:InputStreamReader,OutputStreamWriter为字节流转字符流,字符流转字节流的类;
常用的读取组合:
BufferedReader(FileReader(File)),BufferedInputStream(FileInputStream(File)),BufferedReader(InputStreamReader(FileInputStream(File)))
常用的写入组合:
PrintWriter(BufferedWriter(FileWriter)),PrintWriter(File),BufferedOutputStream(FileOutputStream),
PrintWriter(OutputStreamWriter(FileOutputStream))
其中,之所以PrintWriter有时加Buffer不是不加,原因在于PrintWriter的除PrintWriter(Writer)以外的构造方法均自带了BufferedWriter;
Buffer的好处:
对于字节流来讲,一次读入一个缓冲(8K)的字符,避免频繁的读取消耗I/O;
对于字符流来讲,一次写入多个字符,且一次进行多个字符(8K)的字符字节转换;
(2)MAP重要类:
Map,Hashtable,HaspMap,TreeMap,WeakHashMap,LinkedHashMap;
其中Hashtable与HashMAp的重要区别在于:
Hashtable的方法定义都加上了synchronized关键字,即当某个方法执行的,该类所有对象的所有方法都不可执行;
至于NULL,在源码是只是添加一些if判断而增加的兼容性;
HashMap的同步则最好通过在方法中加入synchronized(this)来实现最好;
而HashMAP,TreeMap,LinkedHashMap的区别在于:
TreeMap使用红黑树(一种二叉树结构)来实现MAP,而非HASH算法;其键值对按照KEY值有序排列的;
LinkedHashMap则保证按照初始装入的KEY的顺序来排列键值对;
HashMap则不保证任何顺序;
WeakHashMap与其它Map类的区别在于:
其中的键值对为弱引用,即若该键值不正常使用(即不存在引用),则会垃圾回收该键值对;
HashMap的Hash算法的Hash值由key的hashcode()除以Map所有数组的长度获得,而相同Hash值的存储采用线性键表的形式;
HashMap的Entry类:
Entry类使用线性链表来实现HashMap的Hash冲突解决,故Entry的实现实际上是一个键值对的链表节点;其含有指向下一个节点的引用;
(3)Set重要类:
Set,HashSet,LinkedHashSet,TreeSet
其区别与MAP相同,只不过Map的key在这里是值;
List重要类:
LinkedList,ArrayList,Stack;
Stack即数据结构中的栈,但其本身的实现中用的数组,故从效率上讲也不是太快;
LinkedList与ArrayList的区别在于,
一个用链表实现,一个用数组实现,如果数组不够,则再翻倍加COPY原数组数据;
HashMap与ArrayList数组的默认大小均为16,HashMap默认加载因子为0.75;
(4)String重要类
String,StringBuffer,StringBuilder
String
字符串常量,原因在于其用于存储字符的字符数组value定义为final,即初始化后即不可变,故其字符串无法改变;
StringBuffer 字符串变量(线程安全):
定义的存储字符的字符数组变量value非final,故可改变,但其所有的方法都是synchronized的,故线程安全却因为锁也会影响性能,实际上其与StringBuilder都是继承自AbstractStringBuilder,区别在于其又对所有方法加了synchronized;
StringBuilder 字符串变量(非线程安全)
与StringBuffer出自同一父类,其对所有方法未加synchronized,故效率高;通过synchronized(this)实现同步;
4. 内部类
分为:成员内部类、局部内部类、静态内部类、匿名内部类
其中,局部内部类和匿名内部类对外不可见,可访问方法内的变量,但必须是final的;
所有类都可访问外部类的私有变量,而静态内部类只能访问外部类的静态变量;
成员内部类:
即在类内部定义类,可以访问外部类的私有变量,其它类中初始化时需先new一个外部类,再用该外部类new内部类;
局部内部类:
即定义在方法中的内部类,在内部类中可以直接访问外部类的实例变量的局部变量(即方法内的变量),但是变量必须是final的
在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)
静态内部类:
只能访问外部类的静态变量,可通过外部类名直接实例化;
匿名内部类:
通过new 类名(){}来实现,也是最常用的一种,用来重写接口或父类方法;
5. 异常分类及机制
异常分类:Throwable=Error+Exception,Exception=RuntimeException+其它
unchecked异常=Error+RuntimeExceptjion,Check异常=其它
在JAVA中,只有Check异常是必须处理的;但所有的Throwable都可以被catch;
ERROR默认为系统错误,不可处理;而Exception,则认为是可以处理的;
但在实际运行中,更常用的分类是unchecked和check;
通过catch和finally处理;
6. 泛型实现机制
JAVA泛型使用earse机制,通过编译期检查及编译器来实现的,但通常在使用上来讲和真正的泛型并没有太大的区别;
其最大的作用就是用在架构上,去掉很多代码的实现;
需注意如下几点:
1. JAVA泛型实际上是Object对象,当取出对象时,通过强转Object对象来实现;但在添加对象时,添加其它对象时,编译期的检查并不能通过;所以看起来就像实际上就是本对象的样子;
2. JAVA泛型不可兼容:如List<String>对象并非List<Object>对象的子类;
3. 如果你想从一个数据类型里获取数据,使用 ? extends 通配符
如果你想把对象写入一个数据结构里,使用 ? super 通配符
如果你既想存,又想取,那就别用通配符。
7. 动态代理实现机制
动态代理主要用于给类自动添加AOP方法,从这个角度来看,有JAVA的JDK的基于接口的动态代理、CGLIB的基于接口和类的动态代理、STRUTS2的基于执行栈;
狭义上的动态代理则指的是通过生成JAVA字节码来动态的在方法前后添加执行方法,这时则只有JDK的动态代理和CGLIB的动态代理;
CGLIB的动态代理基于ASM包的操作字节码的技术; JDK动态代理通过Proxy类生成接口的代理对象,而Proxy的new_Instance()方法必须提供InvocationHandler接口的类对象,在其invoke()方法中加入添加的操作;然后在代理对象中通过反射动态的调用该类的方法,并在该类方法前后加入自定义的方法;
从这个角度看,JDK的动态代理可以代理FINAL方法和对象;
而CGLIB的动态代理则是通过继承原对象来实现的动态代理,故不能代理FINAL方法和对象;
8. 多线程
JAVA中实现多线程有两种方法:一种继承Thread类,另一种则是实现Runable接口;
继承Thread:
1.覆盖Thread的run()
2.新建该类的Thread对象
3.对象.start();
实现Runable接口:
1.实现run()
2.使用该对象作为构造参数,新建Thread类
3. Thread对象.start()
实现Runable接口好处:
1. 可以继承其它类了
2. 如果用同一个对象做参数构建不同的Thread对象,则多线程可以实现内部变量的共享;
多线程的sleep,wait,notify方法;
1.wait属于object方法,而sleep属于Thread方法;
2.wait方法释放所执有的同步资源,而sleep方法并不释放资源;
3.wait方法只能在同步控制方法和同步控制块中使用,而sleep则可在任何地方使用;
4.wait无须补获异常,而sleep则需捕获;
5.sleep方法到期后,要根据线程优先级看是否执行,而wait因为在同步块中,调用nofity时,其它同步方法肯定已不再执行;
6.wait是普通方法,可对所在的线程对象使用;而sleep是static方法,只能对当前线程有效,而非调用其的线程对象;
9. 并发和同步
并发指的是当多个线程访问同一个对象时,造成的对象状态不一致的现象;故如果对象没有可改变的变量,则不存在并发问题;
并发包括两种:同步并发和异步并发;
同步并发指的是:多个线程同时执行同一个对象中的方法,而该方法又依赖对象中的可变状态或改变对象中的可变状态,则会造成方法执行结果错误的问题;
异步并发指的是:某个线程改变了对象中的状态,而其后的线程在调用该对象方法时,因为之前保留的状态造成的执行结果错误;
解决同步并发的方法是:每一个并行的线程分配一个单独的对象,或者对于对象方法同步,或者对可能有同步问题的代码块同步对象;
解决异步并发的方法是:每个线程都对获得的对象执行初始化,每个线程持有一个单独的对象;
很多情况下,同步并发和异步并发是同时存在的,故采用通知的解决方法,即每个线程分配一个单独的对象;
同步的方法有三种:一种是方法修饰符加synchronized,一种方法加static synchronized,一种则是在实际使用该对象方法是加syschronized(this)来同步代码块;
区别在于:第一种会锁同一对象的同步方法,第二种则只会锁该方法的同步对象,第一种会锁有该标志的代码块;;
*:无论哪种同步都需消耗很大系统开销,所以尽量避免;
*:同步实际上都是根据syschronized(对象)来定的,即只要锁的不是同一对象,则其它对象的方法即可执行;
static锁的是Class对象,故所有类对象的static同步方法都不可执行;
synchronized方法则锁的是对象实例,故该对象实例的同步方法不可执行;
synchronized(this)锁的是代码块,则只有该对象实例的对象代码块不可执行;
10. JAVA引用reference
Java引用分为强引用,软引用SoftReference,弱引用WeakReference,虚引用PhantomReference
其中强引用为普通的引用;
而其它3个则继承的java.lang.ref.Reference<T>类,该T类对象被回收时,三种引用对象都变为可被回收;
SoftReference对象,只有内存空间不足时,才会进行回收;
WeakReference对象,则只要垃圾回收线程扫描到该对象,就会进行回收;
PhantomReference对象,则相当于没有引用,随时可回收,且必须与 ReferenceQueue一起使用;
对象可及性判断:
对象可及的单条路径判断:以最弱的引用代表路径引用;
对象可及的多条路径判断:是最强的路径引用代表引用;
11. 本地线程类ThreadLocal
ThreadLocal类本质上是一个HashMap类,即ThreadLocalMap类,其内部静态类Entry继承了WeakReference<Thread>对象,故其内部的键值对只要对应的Thread对象不存在了,即可被回收;
其get方法实质上即通过Thread.getCurrentThread ()获取当前线程,再取对应的Map中的值;
正因为如此,其看起来像每个线程的局部变量,即每个线程的变量可以*改变,每个线程取到的都是本线程所存储的变量,线程消失时变量亦回收;
12. 反射
重要类有:Class,Method,Field,Constructor,Memeber,除Class外都位于java.lang.reflect包中且继承java.lang.reflect.AccessibleObject类;
其中
Method代表类的方法信息及注解,
Field代表类的变量信息及注解,
Constructor代表类的构造器信息及注解;
Member则代表Method,Field,Constructor标识信息;
通过这些反射,可改变类方法和域定义的访问控制,可动态对象域的值,动态调用对象的方法;
故反射更多的用在框架搭建中:通过参数动态调用不同类的不同方法,通过域的反射来实现一个通用的equals方法或者填充方法等;
反射的实现在于JVM中存在Class定义对象,故可以通过Class对象得到该Class的各种信息,并通过对象引用来关联类定义与类实例;
13. 注解
J2SE内置的注解有:@Override,@Deprecated,@SuppressWarnings;
另外,还包括4种元注解,即用来定义注解的注解; @Target:表示注解可用于哪种类型:CONTRUCTOR(构造器),FIELD(域声明),LOCAL_VARIBLE(局部变量声明),METHOD(方法声明),PACKAGE(包声明),PARAMETER(参数声明),TYPE(类/接口声明);
@Retension:表示什么级别保存该注解信息:SOURCE(注解将被编译器丢弃),CLASS(在CLASS可用,但会被VM丢弃),RUNTIME(VM运行期也保留该注解)
@Documented:注解保存在JavaDoc中;
@Inherited: 允许子类继承父类注解;
注解创建几步:
1. 使用@interface关键字来定义注解,并在注解体中通过"变量()"来定义变量,可在其后追加default 变量值来定义默认值;
2. 在类中加入该注解,并在注解后加入注解本身的变量值;
3. 定义注解的处理类,即根据该注解做什么操作,通常是通过反射方法获取注解,故同时可取得注解所在的方法或域的定义;
4. 在容器启动时,先行启动注解扫描类及注解处理类,预先对注解进行扫描和执行;
4. 根据注解所在的位置以及获取的注解及变量,调用相应的方法或对类做某些操作或执行公共操作;
14. JVM内存结构
根据JVM规范,JVM内存结构包括5大块:堆区,方法区,JVM栈,本地方法栈,程序计数器;
在实际的JVM中,程序计数器是放在JVM栈中的;
JVM实际上同时会有JVM外的内存,因为JDK1.4后引入的NIO类会导致本机分配BUFFER内存;
其中,方法区同时包括运行时常量池;
当然,真正的JVM还分包含如I/O类的BUFFER,JIT内存,垃圾回收内存等;
15. JVM垃圾回收
判断对象是否已无效的方法有2种:引用记数和根搜索算法;
垃圾回收算法主要有:标记-清扫,标记-整理,停止-复制,火车头算法;
对年轻代实施停止-复制,对年老代实行标记-清扫或标记-整理,对于永久代只有进行FULL GC的时候才会进行清理;
根搜索算法:
由GC-root开始进行搜索,
可做GC-root的有如下几种:
虚拟机栈(栈帧中的本地变量表)中的引用的对象。
方法区中的类静态属性引用的对象。
方法区中的常量引用的对象。
本地方法栈中JNI(即一般说的Native方法)的引用的对象。
16. JVM调优
主要包括如下:对方法区,堆区,栈区的调优,加-server参数,还有就是对各个内存代的大小调整;
17. Java Socket与底层TCP实现
TCP的Socket包含了sendQ(发送缓存),recvQ(接收缓存),Delivered(接收者从缓存读取的数据)
通用的发送过程:
1)TCP/IP连接的建立
TCP/IP连接建立需三次握手:客户端连接请求,服务端确认信息,客户端确认信息
对于Socket来说,当接收到服务端确认信息时(第2步),就认为连接建立,即Socket的状态为Established;
对于ServerSocket来说,当accept()方法接收到连接请求时,即产生Socket实例,认为连接建立,而非等到三次握手完成;
2)TCP/IP数据的发送接收
Socket调用write()方法,将数据写入底层sendQ,则wirte()方法完成;
写入前,如果wirte()的buffer比sendQ大,则会将buffer进行分组,待sendQ发送完一部分后,再写入,直至完全写入;
sendQ将数据发送到recvQ
依赖于底层实现,依靠重传机制来保证数据的正确有序到达recvQ
recvQ将数据传入read()
recvQ依据read()方法buffer的大小,分成合适的包传入read()
故write()结束并不代表数据已到达接收端,仅代表数据已写入sendQ,如传输过程中发生异常,则应用程序发送端不会收到任何通知;
3)TCP/IP连接关闭
Socket调用close()或者shutdownOutput()方法,则代表关闭;
而此时,仍有未发送的数据存在于sendQ中,如有异常,应用程序不会知道;
在TCP/IP协议中,则需要另一方也发送close()才算结束;
18. BIO/NIO/AIO区别
HTTP的请求模型:
HTTP的请求模型分为几步:建立连接->传输数据发送请求->处理->发送响应返回数据->断开连接
BIO即通常的请求模式(ServerSocket,Socket),当建立连接时,服务器分配一个线程处理该连接的请求;
该线程负责(传输数据发送请求->处理->发送响应返回数据)过程;
而NIO则将请求与连接分开,用SocketChannel来处理所有的连接,使用selector来对SocketChannel的请求进行轮询,如果有请求,则分配一个线程进行处理;
该线程仅负责(处理)这一步,(传输数据发送请求->发送响应返回数据)则通过selector轮询SocketChannel来处理;线程与SocketChannel之间需要有关联机制;
AIO则依赖操作系统来处理请求数据和返回数据,以及实现关联机制,实现真正的异步机制;
故可知,
因为BIO每个连接由对应的线程CPU来处理请求及响应,故会在I/O处浪费CPU资源,有可能会造成CPU瓶颈; 而NIO则由一个线程selector来处理所有的请求及响应,而专门的线程来处理每个请求,即所有连接的I/O由一个线程来处理,
节省了CPU,但如果I/O过多,可能会在selector处造成瓶颈;因为要处理线程处理结果与SocketChannel的对应关系,不适合用多个selector且也增加了模型的复杂度;
而AIO则去除了selector,I/O以及线程处理结果与I/O的对应关系由操作系统来完成,故效率最高,但需操作系统支持;
19.HTTP中的keep-alive与JAVA中的Socket
1)为何使用keep-alive
HTTP请求基于TCP/IP,如果多个请求都基于同一TCP/IP的连接,则可以节省每个单独建立TCP/IP连接的开销;
2)如何触发keep-alive
对于HTTP/1.0,需在头信息中加入Connection:keep-alive,而在HTTP/1.1中,则默认keep-alive;
3)服务器及浏览器对keep-alive的处理
一个原理:keep-alive需双方的参与,任何一方关闭都会使keep-alive结束;
HTTP/1.1规定服务器如果关闭keep-alive连接,需发出一个通知;
服务器端的处理通常会设置keep-alive有效时间,以在规定时间结束后可以释放连接占用的内存;如果有效,则会在响应头加入Connection:keep-alive;
而浏览器端则有可能使用keep-alive来利用TCP/IP连接,也可能直接新建TCP/IP连接来请求;
原因在于:随着硬件及操作系统的发展,客户端新建TCP/IP连接的开销实际上并不是很大,
比起等待第一个请求结束再发送第二个请求来说,直接新建多个TCP/IP来同时请求,得到响应的速度更快;
4)keep-alive的实际可发挥的作用
事实上,keep-alive对于浏览器来讲,并不一定会提升性能,因为在客户端看来,瓶颈在服务器端的处理响应速度,而非浏览器多建几个TCP连接的时间和资源开销;
keep-alive对于服务器来讲,可以连接复用,节省资源,但是如果连接上总是没有请求,则该连接在该时间内则占用了服务器的内存,浪费资源
因此,keep-alive对于浏览器是多TCP/IP连接的CPU内存消耗和更快的得到处理结果的权衡;
对于服务器则是TCP/IP连接复用对CPU内存的节省和TCP/IP连接空置对CPU内存的浪费之间的合理权衡;
20. Java TCP与UDP
TCP使用Socket与ServerSocket:即需一方建立侦听端
UDP使用DatagramPacket与DatagramSocket:不需某一方做服务端,DatagramSocket负责发送接收,而DatagramPacket负责存储信息及IP等;
======================================================================================================================================================
二。设计模式
可分成创建型(Creational),结构型(Structural),行为型(Behavioral);
创建型分为:工厂方法,抽象工厂,建造者模式,单态模式,原型模式;
结构型分为:适配器模式,桥接模式,组合模式,装饰模式,外观模式,享元模式,代理模式;
行为型分为:责任链模式,命令模式,解释器模式,迭代者模式,中介者模式,备忘录模式,观察者模式,状态模式,策略模式,模板方法,访问者模式;
创建型:
创建型通常要求原对象的构造方法为private;
1. 简单工厂,工厂方法,抽象工厂方法
核心参与者:Creator接口,Product接口,Creator对象,Product对象
简单工厂: 只有Product接口,Creator对象,Product对象,工厂方法会根据参数的不同生成不同的对象,生成方法中包括生成对象的逻辑;
工厂方法:Creator接口,Product接口,Creator对象,Product对象,每个Product对象对应一个Creator对象;
抽象工厂:先对Product对象进行系统分类,每一系列的Product对象对应一个Creator对象;
2. 建造者模式(Builder)
核心参与者:Builder接口,Builder对象,Director对象,Product对象
Builder对象:实现Builder接口中生成Product对象的方法,并生成一个特定的Product对象;
Director对象:接收Builder对象参数,调用其生成对象的部分或全部方法,生成特定的Product对象;
Product对象:特定的Product对象;
优点: 通常Build接口有多个方法,即可实现对象多个域的初始化,在Director对象中则通过调用部分初始化方法,来实现不同的初始化对象;
3. 单例模式(Singleton)
核心参与者:Singleton对象;
优点:通过Singleton对象的指定方法来构建实例,保证全局仅生成一个实例;
4. 原型对象(Prototype)
核心对象:Prototype接口,Prototype对象;
Prototype对象实现clone接口,通过该方法实现对原型对象的clone来获取新对象;
结构型:
1. 适配器模式(Adapter)
作用:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
核心参与者:Target接口,Adapter接口,Adaptee接口;
Target接口:即需要兼容的接口;
Adaptee接口:需被转换以兼容Target接口的接口或对象;
Adapter接口:实现Target接口,接收Adaptee对象,调用Adaptee对象的方法来实现Target方法,从而实现接口的转换;
2. 桥接模式(Bridge)
作用:将高层的实现与低层的实现解藕,以避免类组合爆炸;低层的实现通过调用引用对象方法来实现;
核心参与者:Abstraction接口,RefinedAbstraction对象,Implementor接口,ConcreteImplementor对象
Abstraction接口:定义高层接口类方法,并执有Implementor对象;
RefinedAbstraction对象:实现Abstraction接口方法,其中会调用到Implementor对象的方法;
Implementor接口:定义低层操作;
ConcreteImplementor对象:实现低层操作;
优点:可通过引用不同的低层对象与高层方法的组合,实现不同的功能,有效减少了类的数量;
3. 装饰模式(Decorator)
作用:动态的给对象添加额外的职责;
核心参与者:Component接口,ConcreteComponent对象,Decorator接口,ConcreteDecorator对象
Component接口:定义原始方法;
ConcreteComponent对象:实现Component接口方法;
Decorator接口:实现Component接口,执有Component接口对象引用,并通常会在对应方法中调用引用对象的方法;
ConcreteDecorator对象:实现Decorator接口,会在对应方法中除调用引用对象方法外,额外的添加其它的操作;
4. 外观模式(Facade)
作用:为子系统提供一个一致的界面,即相当于为众多的子系统提供一个默认的类,该类针对一般的使用者的需求,使其不用再了解和选择接口的不同子类;
核心参与者:Facade对象,Subsystemclasses对象
Facade:将客户请求代理给适当的子系统;
Subsystemclasses:处理由facade分派的任务,无指向Facade的引用;
5. 享元模式(Flyweight)
作用:当应用中某类对象有大量实例时,若分析发现实例间的差别并不大或无差别,则可用享元模式来获取实例,从而达到减少内存占用的目的;
核心参与者:Flyweight接口,ConcreteFlyweight对象,FlyweightFactory对象
Flyweight接口:某个类接口
ConcreteFlyweight对象:接口的实现类
FlyweightFactory对象:存储所有的ConcreteFlyweight对象,一般通过Map形式,其KEY通常为对象进行区别的状态,如果KEY相同,则返回已创建的对象,
若不存在,则新建对象放入MAP;
6. 组合模式(Composite)
作用:可表示对象的部分-整体层次结构,通过在每个对象中置相同类型对象的LIST引用;
核心参与者:Component接口,Leaf对象,Composite对象
Component接口:所有对象的接口类,一般会有一些公共方法及List引用
Leaf对象:实现Component接口方法,其LIST会置为NULL,添加对象方法置空;
Composite对象:实现Component接口方法
7. 代理模式(Proxy)
作用:代理对象方法,实现方式有很多种;
行为型(Behavioral)
1. 责任链模式(Chain of Responsibility)
作用:将对象链成一条链并传递请求,直到有一对象处理该请求;
核心参与者:Handler接口,ConcreteHandler对象,Client对象
Handler接口:定义处理方法
ConcreteHandler对象:实现处理方法,并执有后续对象引用,若非该对象处理,则调用后续对象的对应方法;
Client对象:新建对象链,并调用链首对象的方法;
2. 命令模式(Command)
作用:在高层抽象底层对象的方法,从而在该层次对不同的方法集合施以一些公共的操作;
核心参与者:Command接口,ConcreteCommand对象,Invoker对象,Receiver对象,Client对象;
Command接口:命令对象的接口,同时会执有一个receiver对象;
ConcreteCommand对象:接收receiver对象作为构造器参数,并在实现的命令方法中调用receiver的方法;
Invoker对象:执有Command对象,在其方法中调用Command对象的命令方法,通常会在这一层的对象方法中对Command对象或方法做一些统一的封装;
Receiver对象:Command对象执有的对象,可以是任何方法;
Client对象:组装该对象并测试;
3. 解释器模式(interpreter)
作用:用于语法解析,故实际上基本用不到;
4. 迭代器模式(Iterator)
作用:为不同的实现Iterator的对象提供一个统一的迭代方式和容器;
核心参与者:Iterator接口,ConcreteIterator对象,Aggregate接口,ConcreteAggregate对象
Iterator接口:定义迭代方法,包括next(),hasNext(),first(),last();
ConcreteIterator对象:实现Iterator方法,并执有Aggregate接口容器对象的引用;
Aggregate接口:定义迭代对象的容器需实现的方法,如get(),size(),add()等;
ConcreteAggregate对象:实现Aggregate接口的方法;
5. 中介者模式(Mediator)
作用:定义一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显示地相互引用,从而使其耦合性松散,而且可以独立地改变他们之间的交互。
核心参与者:Mediator接口,ConcreteMediator对象,Colleague接口,ConcreteMediator对象;
Mediator接口:定义对象交互的方法;
ConcreteMediator对象:通过调用对应对象的方法来实现对象交互的方法,因此通常需执有所有需交互对象的引用;
Colleague接口:使用Mediator完成交互的对象,需执有Mediator对象;
ConcreteMediator对象:实现Colleague接口;
6. 备忘录模式(Memento)
作用:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
核心参与者:Memento对象,Originator对象
Memento对象:用来保持Originator对象的各种状态
Originator对象:需要时创建Memento对象来保存各种状态,并返回该对象;
7. 观察者模式(Observer)
作用:定义对象间的一对多联系,在目标对象发生改变时,其它的对象都能得到通知并及时更新状态;
核心参与者:Subject接口,Observer接口,ConcreteSubject对象,ConcreteObserver对象
Subject接口:执有Observer对象列表,定义通知方法以及添加删除Observer对象方法;
Observer接口:执有Subject对象,定义Subject对象通知调用的Observer方法,注册或去除Subject监听对象方法
8. 状态模式(Stage)与策略模式(Strategy)
作用:执有不同接口对象的引用,通过动态改变接口对象,来实现相同的方法实现不同的请求,通过组合来防止类爆炸;
核心参与者:Context对象,State接口,State对象;
9. 模板方法(TemplateMethod)
作用:父类实现算法中不变的部分,而将可变的部分留由子类实现;
核心参与者:Template对象,SubTemplate对象;
Template对象:实现算法中不变的部分,其中会引用由子类实现的抽象方法;
SubTemplate对象:实现父类的抽象方法;
10. 访问者模式(Visitor)
作用:其实质是将所有的对象的不同操作用Vistor接口来实现,从来使得各对象之间都与Visitor交互,因此任何对象层次变化都需更改Visitor代码;
====================================================================================================================================================
三、字符集
1. 字符集发展
最早出现的为ASCII编码方案,即将0-127进行编码,用于打印工作;
而后不同地区表示更多的字母,则对128-255进行了编码,这部分编码称为扩展字符集,即ISO-8859-*编码,其中英语的扩展为ISO-8859-1;
中国地区为表示更多的字符,也对ASCII码进行了扩展,小于127的编码意义相同,当大于127的两个编码连在一起时,则合并起来表示一个中文字符,即为GB2312;
后来不够,又规定只要第一个编码大于127,低字节可以为任何编码值,将这部分编码加进来用来表示更多的字符,即GBK;
后来又加入少数民族字符,此时,部分字符会有4个字节,即124字节编码,即GB18030;
故GB18030兼容GBK兼容GB2312兼容ASCII;
为统一编码,ISO提出了UNICODE字符集,而为了网络传输方便,则对应的UNICODE字符集有了UTF-8和UTF-16两种编码;但因为二者都对应同一个字符集,故可以通过算术进行转换;
2. 编码方案的自动检测
一般来说,不同的编码方案都会留空白的编码段来与特定的编码方案兼容或做特殊用途,用这种办法可以做出一些编码方案的检测;
3. JAVA中的字符集
在JAVA中,只有一种字符集即UTF-16,而在JAVA中具体指的则是在JVM内部,在程序运行的内存中;
故所有的变换都发生在JVM和OS交界处,即输入输出流起作用的地方;
输入输出流即面向字节流和面向字符流;
面向字节流即不进行转换,适合传输音频,视频文件;
面向字符流即输入时默认将字节由系统默认编码转为UTF-16,输出时将字节由UTF-16转为系统默认编码,当然,可以人工指定编码;
4. Web中的字符集
Web包括两条路径:即从服务器到客户端,和客户端到服务器;
对于从服务器到客户端:服务器端对页面内容进行编码,浏览器端显示;
服务器端对页面内容进行编码:
JSP中的<%@ page contentType="text/html;charset=gb2312"%>
和servlet中setContentType (“text/html; charset=gb2312”)用来指定服务器端编码字符集;
浏览器端显示:
而<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> 则指定浏览器端显示HTML用的字符集;
从客户端到服务器端:浏览器对请求进行编码,服务器端对请求进行解码
浏览器对请求进行编码
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> 指定浏览器编码的字符集;
但对于GET请求来说:在中文IE,如果在高级选项中选中总以UTF-8发送(默认方式),则路径部分使用UTF-8编码,而参数部分使用meta中的字符集编码
如果高级选项取消总以UTF-8发送,则路径和参数部分都使用meta中的字符集编码
服务器端对请求进行解码:
根据servlet规范,HttpServletRequest.setCharacterEncoding()仅适用于POST请求提交的request body的编码,对GET请求的参数无效;
对于Tomcat,GET请求默认的编码为ISO-8859-1,故需添加URIEncoding="UTF-8"
5. ORACLE中的字符集
对于ORACLE来说,一般情况下的请求和imp/exp的编码转换方式不太相同;
imp/exp:
数据部分以二进制直接导出和导入,不进行任何编码转换;
而代码部分(建表,注释,视图,函数等)则会导出时根据客户端字符集进行转换,而导入时再由客户端字符集转为数据库字符集;
故,数据部分是否乱码仅和源数据库与目标数据库的编码是否相同有关,相同则正常,不同则乱码;
而代码部分是否乱码则与客户端和目标数据库的编码有关,只有二者的字符集中都包括代码部分的所有字符时,才不会乱码;
注:DMP文件的第二和第三个字符代码客户端的编码类型,在Unix上则是第一位和第四位,因为一个高位在前一个低位在前;
而对于普通的DML操作:
在客户端向服务端提交SQL语句时,客户端会根据NLS_LANG和数据库字符集,进行相应转换,如果相同,则不转换,否则转换为数据库字符集;
而数据库端在插入前,则会将提交SQL语句中的国家字符集字段由数据库字符集转为数据库国家字符集;
而在数据库端返回数据时,数据原样返回,而客户端根据普通字符和国家字符将其转为相应的字符集;
6. 不同数据库间的字符集排序
实际上,数据库除了数据字符集外,还有一个排序字符集,供order by使用;
比如在中文版windows上装的SQLServer默认按中文排序,即abcd与{的顺序就与ORACLE的顺序不同;
当做ETL时,对两个不同的数据库进行order by然后merge时,就会出现问题;
SQLServer的排序字符集有上百种,而ORACLE很少,故统一为ORACLE的即可;
===================================================================================================================================================
四、Web知识
1. POST与GET区别
(1)参数长度:
GET方法的参数在浏览器地址栏中,因此有长度的限制;?将路径和参数分开,&将参数之间分开;
POST方法的参数则放在消息体中,因此无长度限制;
(2)安全
GET方法的参数显示在地址栏中,可见,故不安全;
POST方法的参数放在消息体中,不可见,故较安全;
(3)书签
GET可建立,而POST不可建立;
(4)幂等
理论上讲GET方法应该是幂等的(可重复执行多次无副作用),POST方法是非幂等的,实际应用中不一定;
(5)转码区别
根据Servlet规范,HttpServletRequest.setCharacterEncoding()仅对POST请求有效;
而GET请求的URL参数,则需要在服务器的Connector中进行配置;
2. Web存储的4个级别:
ServletContext,session,request,page;
其中,ServletContext,servlet的两个参数Parameter,Attribute;一个只读,由配置文件获取;一个读写,由程序获取;
同样,ServletContext,servlet也可有两个相同的类,config,Listener;config负责存储配置,Listener负责将字符串的变量组装成所要求的对象;
3. session
session包括session生成,有效期;
session生成:
一般来讲,第一次向session中写入数据时,会生成session;session通过ID来进行识别;
第一次生成时,通过首部的set-cookie和URL后追加sessionID,如果客户端请求时,通过Cookie发送,则确定Cookie未禁用,以后只用第一种方式;
session有效期:
在server.xml中定义context时defaultSessionTimeOut设置
在web.xml中通过<session-config>的<session-timeout>设置
在程序中通过HttpSession的setMaxInactiveInterval设置;
session的缺点:
如果使用session,则服务器有了状态;当服务器使用集群时,session状态的所有变化都需要同步至所有集群的节点,限制了程序的水平可扩展性;
4. servlet
servlet生命周期:
客户端第一次请求该servlet
-->加载该servlet类: 加载该Class,有ServletConfig对象(包含了servlet的配置信息)
-->初始化该servlet: 调用init()方法,产生servlet对象实例,可重载该方法来添加一些初始化操作
-->处理该请求service(): 产生一个独立的线程来处理service()方法,按请求类型,service()方法调用doGet或doPost方法
-->销毁servlet: 容器关闭或内存不足时会销毁servlet
5. context-param,listener,filter,servlet初始化顺序
context-param-->listener-->filter-->servlet
context-param: 键值对,即应用上下文信息
listener: 一般用来将一些键值对组装成一些复杂对象,供其它对象使用
filter: 相当于AOP的作用,处理一些公共操作;
servlet: 处理及生成响应
6. filter,servlet不同之处
执行顺序:
先执行filter,再执行servlet
而多个的filter或servlet之间的执行顺序则依据mapping的书写顺序
可见对象:
filter执行过程中可见request,response,filterChain
servlet执行过程中可见request,response
定位作用:
filter定位于线性执行链的一环,故执行完后可继续向下执行其它filter,用于一些公共功能,但并非绝对,如Struts就用其来处理业务逻辑;
servlet则定位于执行链的末尾,执行并生成响应;
二者皆可生成响应,但一般filter不会生成响应,而是继续filter执行链;
7. DOM(Document Object Model)
即文档对象模型,通过document即根节点来遍历HTML中所有元素的一种模型;
通过getElementById,getElementsByTagName获取节点,节点分成元素结点,文本节点,属性节点;
通过document.write()以及innerHTML属性来直接插入HTML增加节点;
也可通过createElement()或appendChild()来添加节点;
8. Ajax(Asynchronous JavaScript and XML)异步JavaScript和XML
Ajax基于JS和http请求;
1)XMLHttpRequest对象是AJAX的基础,浏览器均内置了XMLHttpRequest对象,而老版本的IE(IE5,IE6)则使用ActiveX对象;
创建XMLHttpRequest对象:variable=new XMLHttpRequest();
IE5,6:variable=new ActiveXObject("Microsoft.XMLHTTP");
检查浏览器是否支持XMLHttpRequest对象:
if(window.XMLHttpRequest){}
2)XMLHttpRequest对象向服务器发送请求:
open(method,url,async):规定请求的类型、URL 以及是否异步处理请求。
method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)
Async=true时,一般需规定处于onreadystatechange事件中就绪状态时执行的函数
3)服务器响应:
XMLHttpRequest对象有responseText和responseXML属性;
一般使用responseText属性,若服务器响应为XML且需作为XML对象进行解析,则使用responseXML属性;
4)onreadystatechange事件:
每当 readyState 改变时,就会触发 onreadystatechange 事件。
onreadystatechange 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。
readyState 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
================================================================================================================================================
五、数据访问
JDBC,JNDI,datasource(dbcp,op3),IBATIS,MYBATIS,事务,JPA规范,HIBERNATE(事务,一二级缓存,配置,三种状态)
1. JDBC
DriverManager:
管理驱动程序,用来得到Connection对象
Connection
即数据库连接,可设置事务隔离级别通过setTransactionIsolation()方法;
通过setSavepoint()方法来建立一个临时回滚点对象 Savepoint;
通过setAutoCommit()方法来设置是否自动提交;
通过setReadOnly()方法设置是否为只读模式,以进行优化;
通过getMetaData()方法得到数据库整体信息的对象DatabaseMetaData;
通过createStatement()方法创建Statement对象;
通过prepareStatement(String SQL)方法创建PreparedStatement对象;
通过prepareCall()方法调用存储过程;
DatabaseMetaData
关于数据库的整体综合信息,即数据库及驱动程序本身的一些信息;
Statement
代表未编译的SQL语句;
通过executeUpdate()来执行DML和DDL语句,对于DML返回受影响的行数,对于DDL返回0;
通过executeQuery()执行查询语句,并返回包含结果的ResultSet对象;
通过addBatch(String SQL)将SQL语句添加到命令列表,通过executeBatch()执行全部的SQL语句;
PreparedStatement
代表预编译过的SQL语句对象,可设置参数来进行语句的一次编译批量执行;
通过getMetaData() 方法获取结果列的类型和属性的对象ResultSetMetaData
也可执行executeUpdate()和executeQuery()方法;
通过set参数以及addBatch()以及executeBatch()来批量执行;
CallableStatement
即用于执行 SQL 存储过程的接口
Savepoint
保存点的表示形式,可将事务回滚到该保存点,而非全部回滚;
ResultSet
查询的结果集,通过next()得到下一行,如果无则返回false,通过getXXX(int)来返回指定位置的对象;
ResultSetMetaData
获取关于 ResultSet 对象中列的类型和属性信息的对象
2. JNDI(Java Naming and Directory Interface)JAVA命名和目录接口
用于集中存储共有信息,故不仅可用于JDBC,LDAP,DNS等;
JDBC获取的方式如下:
Context cntxt = new InitialContext();
DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");
ds.getConnection();
其中,DataSource获得Connection有几种方式:生成一个新连接,从连接池获取连接等;
Spring配置获取JDNI的方式:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jcptDataSourceJNDI</value>
</property>
</bean>
3. DataSource
1)重要开源的DataSource类:DBCP,CP30
2)DataSource作用
并发问题:通过同步来解决同时请求Connection
事务处理: 每个连接一个事务,通常交给其它框架解决
连接池的分配与释放
连接池的配置与维护
4. Ibatis,Mybatis
对JDBC的简易封装的一个ORM框架,主要有几个重要内容:
1)DML操作的封装:
通过配置文件将每个DML操作的SQL语句绑定到一个独有的ID上;
2)数据返回的封装:
通过resultMap配置项来实现查询结果与对象属性的对应关系;
5. 事务
1)事务概述
本质上就是底层的Connection,关闭自动提交则会开户事务;
但在实际应用中,比如在Hibernate中,事务也包含了session的刷新的内容,即在提交前,要先将Session中的改变通过对应的SQL语句同步至数据库;
2)全局事务与本地事务
全局事务:跨数据库,使用JTA;本地事务:一般为一个连接;
3)事务可能出现问题:
更新丢失(lost update )
脏读 (dirty read )
非重复读(nonrepeatable read )
幻读 (phantom read )
4)事务隔离
ISOLATION_READ_UNCOMMITTED 未提交读(可读缓存中的数据) 会造成脏读,非重复读,幻读
ISOLATION_READ_COMMITTED 提交读 (大部分数据库采用的默认方式)会造成非重复读,幻读
ISOLATION_REPEATABLE_READ 可重复读(一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据)会造成幻读
ISOLATION_SERIALIZABLE 序列化 (事务串行执行)
6. JPA(Java Persistense API)
JPA为一组规范,其目标是隐藏对象与数据库字段之间转换过程,从而实现面向对象的开发;
其包括三部分:
1)ORM映射
即表达实体对象与数据库字段以及数据库约束的映射关系;
2)JPA API
提供面向对象的CRUD操作,从而免除JDBC与SQL的繁锁工作量;
3)查询语言
一般JPA会提供三种:纯面向对象的,半面向对象的(如HQL查询),面向SQL的;
目前的实现有Hibernate,openJPA等;
7. Hibernate(事务乐观悲观,一二级缓存,配置,三种状态)
1)Hibernate整体架构
Hibernate主要包括:SessionFactory,Session,Transaction,持久化对象(Persistent Objects),瞬态及胶管对象(Transient,detached)
2)SessionFactory
代表了单个数据库的整个映射关系的集合,线程安全;
是生成session的工厂;
可在进程或集群级别上,提供二级缓存;
SessionFactory的二级缓存的一致性要求Hibernate控制数据库的所有连接;不能有其它的框架或API提供连接;
3)缓存框架
二级缓存的实现可采用Memcached,Cache,Ehcache等;
二级缓存的缓存框架一般解决几个问题:
1. 调度算法
即当缓存不足时,缓存对象的调入及调出;
2. 同步问题
即何时进行缓存的同步,对哪些缓存同步等;一般来说由使用缓存的框架自身来保证;
3. 分布式或集群
好的缓存框架通常会支持分布式缓存,此时分布式缓存的同步问题以及通信问题需解决;
4)Session
Session在Hibernate中发挥着两个作用:数据库连接的执有者以及一级缓存;
作为数据库连接的持有者:其可以做语句及对象的增删改查操作;
作为一级缓存:其要负责缓存内对象的同步,以及哪些对象需要同步;
因此,有了load与get对象的差异;
有了对象的evict,flush等决定对象状态以及与数据库同步的操作;
5)Transaction
在通用的SSH框架中,数据库的事务是交给Spring提供的事务管理器来管理的;
Hibernate的事务管理也可能交给JTA或者JDBC等,也可以手工来控制;
Hibernate同时提供了乐观锁和悲观锁的机制,其中乐观锁可以做到可重复读;而悲观锁则是显示的指定数据库的锁;
6)对象:
Hibernate可有三种对象状态:Transient(临时)、Persistent(持久)、Detached(游离)
Transient(临时):还没有与数据库发生任何的关系,不对应于数据库中的任一笔数据
获得方式:通过new创建的对象,原本在session中但通过session的delete方法删除的对象;
Persistent(持久):当对象与数据库中的数据有对应关系,并且与Session实例有关联;
获得方式:通过调用get,load,createQuery方法得到的对象,对Transient和Detached对象调用DML操作都会使之成为持久态;
Detached(游离):与数据库中的具体数据对应,但脱离Session实例的管理;
获得方式:调用clear,evict以及close方法都会使持久对象变成游离的;
==================================================================================================================================================
六、 Spring
使用注意:注释及配置,单例多例,SPRING做Control的作用及使用,spring事务,Spring动态代理实现及AOP和事务实现,log4j/slf4j及扩展,SPRING重要工厂类
1. SPRING框架的功能和解决的问题:
1. 控制反转I/O,即由SPRING框架来产生Bean,而非由程序来产生Bean:
消除不同功能模块的藕合性,从而实现最大的可扩展性,即使用哪种技术,则加载哪种技术的框架;
降低系统的大小和复杂度,即需要解决哪些问题,则加载哪些组件,而非无论解决多少问题,都加载所有组件;
2. 面向切面AOP,基于I/O,通过在生成Bean时在相关方法中加入公共操作来实现:
进行自定义范围的日志记录
进行自定义范围的事务控制
进行自定义范围的异常处理
进行自定义范围的其它公共操作
3. 广泛使用
因:
SPRING提供多种方式来适用于多种情况, 如适用于WEB的WebApplicationContext以及适用于非WEB的FileSystemXmlApplicationContext的BeanFactory,
适用于XML,注解情况的配置定义方式;
适用于File,InputStream,URL,ClassPath等多种的资源输入方式;
SPRING实现了常用框架的实现类及模板类,故可使用SPRING来进行整合常用大众框架;如Hibernate,JDBC,IBATIS等;
SPRING实现了大多数的常用独立功能,可供SPRING进行直接整合,如邮件发送,LDAP访问等;
果:
大部分程序员都了解该框架,故学习成本低,降低了其自身的复杂性;
大多数的框架都提供了对SPRING框架的支持,即实现了供SPRING框架使用的接口类,故可使用SPRING直接整合该框架;如JBPM,STRUTS等;
从架构的组成元素来讲:即组件,连接器,数据;SPRING属于连接器的元素;
2. Spring的框架结构
Spring可以分为几个层次:数据访问层,Web层,AOP层,核心容器层,以及Test层;
1) 数据访问层
数据访问层从几个方面来实现对不同DAO方问技术的统一抽象及管理:
通过一系列的Utils类来统一各种DAO技术的Connection获取方式(最终都是通过TransactionSynchronizationManager对象取连接);
通过一系列的Template类来简化各种DAO技术在Spring的使用;
通过一系列的Support类来保证可通过简单的配置来使用不同的DAO技术对象;
通过一系列的TranactionManager类来保证不同DAO技术的事务管理可在Spring中通过简单的配置实现;
数据访问层包括JDBC,ORM,OXM,JMS,Transaction等5个模块;
JDBC模块提供了一个抽象的JDBC层,通过JDBCTemplate,DataSourceUtils简化了JDBC的使用以及Connection 的获取方式,并服务其后的事务管理;
ORM模块则集成了Hibernate,iBatis,JPA,JDO等ORM框架的API,并使其符合Spring统一的事务及数据访问的抽象来对其进行统一管理,提供了其相应的模板类和Utils类来简化其使用;
OXM模块则提供了一个对象与XML映射的抽象实现;
JMS则提供了对JMS服务的支持;
Transaction通过提供AOP级的统一管理来实现:事务管理与具体代码的解藕,事务管理与具体的DAO层技术的解藕(部分);
2) Web层
Spring在Web层提供了自身的Web框架,即web-servlet和web-portlet框架;
同时,如Struts框架自身也提供了对Spring的集成;
3) AOP层
Spring的AOP提供了自身的AOP控制功能,也提供了对AspectJ框架的集成;
其AOP的实现原理基于Cglib和JDK的动态代理,其在动态代理中插入了对Spring的Advicor拦截器链的调用,通过此来实现Spring的AOP;
Aop几大重要对象:Advice(执行AOP操作的定义),Pointcut(AOP操作插入点),Advisor(执有上述2对象,实际调用的对象);
4) 核心容器
包括Core Beans和Context;
其中Core Beans主要是对Resource处理产生BeanDefinitions,并将其注入给BeanFactory;
而Context则整合了Resouce及BeanFactory,并具有捕获事件以及标识应用上下文等功能;
5) Test层:
整合Junit及TestNG框架;
3. Spring组件初始化顺序
1. 通过不同的ResourceLoader(由资源路径的前缀及ApplicationContext共同确定类型)来加载资源文件进行得到对应的Resource对象;
2. 通过ResourceLoader的BeanDefinitionReader来解析Resource对象,进行得到Bean定义对象BeanDefinition;
3. 初始化BeanFactory对象,并向其注册BeanDefinition对象;
4. BeanFactory对象产生FactoryBean对象,并根据BeanDefinition的配置指导FactoryBean产生通用的Bean;
5. 如果有AOP定义,则会由PorxyFactoryBean通过JDK或CGLIB来产生AOP的代理对象;
6. 初始化单例的Bean;
===================================================================================================================================
七、Struts
1. Struts2与Struts1的区别:
1)藕合性:Struts1与STRUTS API藕合,而STRUTS2不;
2)Web元素:Struts1在Web.xml中使用Servlet,而Struts2则使用Filter,故Struts2可以其后添加处理链;
3)转向机制:Struts1返回ActionForward而STRUTS2则返回String,更加友好;
4)AOP机制:Struts2有拦截器机制,而STRUTS1无;
5)线程安全:Struts1的表单参数通过ActionForm来封装,由此带来的是Struts1的Action只要不声明状态则线程安全;
而Struts2则直接在Action中封装或通过ModelDriven实现,非线程安全;
2. STRUTS2框架的功能和解决的问题:
STRUTS2本身相当于Control层框架以及半个VIEW层框架,其VIEW层的作用主要是通过标签来实现的;
1. 自动转向功能
通过定义的配置,来实现对URL匹配对应的Action及方法的功能;
2. AOP功能
通过拦截器机制来实现对所有Action的AOP功能;
3. 封装HttpRequest,HttpResponse,session请求参数功能
可通过ApplicationContext来获取对应参数;
4. POJO类,解藕HttpServlet
HttpServlet的参数通过ApplicationContext来获取,或者通过自动填充机制来获取;
5. 后台校验功能
通过书写校验文件来实现后台的校验;
6. 自定义标签
通过一些自定义的STRUTS2标签,提供了比J2EE标签更多的便利和灵活性;
其国际化标签+国际化的程序实现了VIEW层的国际化;
7. 国际化
如上,通过标签+国际化文件的加载解析程序+拦截器,实现了VIEW层数据的国际化;
8. 自动填充及组装机制
将请求的参数自动组装成对应的Model或者填充入对应的Action中;
9. 支持更多View框架
通过使用filter的转向结合View框架的servlet拦截功能实现;
3. Struts2拦截器原理
在Struts2中,执行请求时,面向的是一个ActionProxy对象,该对象会先执行注册的拦截器,最后再执行真正的对象方法;
=====================================================================================================================================
八、View技术(JSP,自定义标签,EL,JSTL),freemarker,velocity
1)Web技术概述
流行的View技术主要有三种:JSP,Velocity,FreeMarker,JSF;
其中,Velocity以及FreeMarker都属于模板技术;
区别在于:JSP与Web绑定,只能在Web上使用,且因为可以书写JAVA代码,导致MVC的分离不彻底;
模板技术则因为不与Web绑定,故可以直接通过模板引擎得到页面,正因为如此,导致可以通过模板引擎与Itext配合直接产生PDF文档;
同时,因为模板内不能写JAVA代码,故也实现了MVC的彻底分离;
FreeMarker与Velocity的区别在于:FreeMarker比Velociry更复杂,功能也更强大,故学习更麻烦一些;
Freemarker也可配置使用JSP标签,但一旦如此,则与WEB绑定,不可能直接产生PDF文档;
2)JSP编译过程:
JSP---servlet.java---servlet.class---init()---service()---destroy;
所有的JSP标签在编译成JAVA文件时都会还原成为函数调用;
3)EL及JSTL
EL标签主要是用来取JSP及WEB内置对象的属性值;
而JSTL标签则主要用来逻辑控制;
4)自定义标签
(1)实现自定义标签类:(无正文的JSP标签)继承TageSupport,覆写doStartTag()方法,JspWriter对象输出响应;
(有正文的JSP标签)继承BodyTagSupport ,覆写对应方法,JspWriter对象输出响应;
(2)定义TLD文件:定义其<uri>的值及<tag-class>的标签类的全限定名
(3)JSP引用:<%@ taglib uri="TLD文件中URI属性值" prefix="标签的别名"%>
================================================================================================================================
九、 LDAP
见ldap附件;
====================================================================================================================
十、 Webservice:
1. 三个组成部分
SOAP:简单对象访问协议.
WSDL:Web服务描述语言.
UDDI:通用描述、发现与集成,它是一种独立于平台的,基于XML语言的用于在互联网上描述商务的协议。
2. 两种框架
AXIS以及CXF
一般用的是CXF,因为Spring与CXF集成,使用起来更简单;
AXIS则有多个版本,除JAVA还有C++;
===========================================================================================================
十一、XML解析
主要有SAX及DOM;
SAX:处理时无须读入整个文档,占用内存小;但因为其并不持有整个XML文档结构,故对XML的结构的修改需要应用程序本身来实现;
DOM:基于DOM树处理模型,处理时读入整个文档并构建成XML结构树,占用内存多,但因为其有整个结构,所以可完成对XML任意结点的增删改查功能;
======================================================================================================
十二、JBPM工作流
1. 工作流业务上常用的功能
提交,查看,审批,任意节点驳回,邮件通知,组审批,会签功能;
历史版本查看,流程发布,流程代理,角色管理,流程升级,进度查看等功能;
2. BPM的一些基本概念
节点,服务,任务,sequence流,条件分支,事件触发,流程变量;
3. 中外BPM的一些差别
中国对BPM关注点在于轨迹,即各个点都必须有记录,侧重于流程的记录功能,故对于历史,进度,每个节点时间,各种驳回较关注;
国外BPM则注重于业务的流转,故对于流程的正常运行较侧重;
=====================================================================================================
十二、Portal
Portal首先是Portal规范,各家厂商均实现了规范,但在实际应用中,因为页面效果,单点认证等原因,总会与各服务器藕合,从而导致不可移值性;
Portal是基于servlet的,对于各个Portlte的权限进行了控制,以及页面聚合还是服务器端聚合;
Portal会有portlet配置文件,需运行在Portal容器中;