java笔记整理

2019年11月10日 阅读数:398
这篇文章主要向大家介绍java笔记整理,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

Java 笔记整理javascript

包含内容css

    Unixhtml

Java 基础,前端

数据库(Oracle jdbc Hibernate pl/sql),java

webnode

JSPmysql

Strutslinux

Ajaxc++

Spring程序员

Ejb

java和模式

Linux/Unix笔记

 

inode :存储编号(地址)

ls -k:查看磁盘分区

ls -li:显示当前文件的inode号。

目录的大小跟文件的大小有关,跟目录里的文件(目录)数量无关。

一行多个命令的话,中间用分号分开。如:pwd;cal;date

last | grep pts/13 表示查看pts/13登录服务器的记录。

find . -mtime -10 -print

-10:表示10天之内的,

+10:表示10天之前的,

.:表示当前路径

-mtime:最后一次修改时间。

-print:表示输出到显示器(可有可没有)。

-user 0:表示UID是0。

size+400:表示大于400*0.5K  ,-400表示小于400*0.5K

-atime:表示最后一次访问时间。

grep:在文件里查找符合要求的那一行。一般用在管道(|)后面,表示对 |  前面的输出作查找。

如:cat /etc/passwd | gred liu | sort

sort:表示排序。

进程是做业,做业是进程。

前台就是终端,后台就是服务器。

当杀掉父进程,前台子进程会消失,,后台做业不依赖于任何终端,会继续运行

LINUX经常使用命令(基础)

1. man 对你熟悉或不熟悉的命令提供帮助解释

eg:man ls 就能够查看ls相关的用法

注:按q键或者ctrl+c退出,在linux下能够使用ctrl+c终止当前程序运行。

2. ls 查看目录或者文件的属*,列举出任一目录下面的文件

eg: ls /usr/man        ls -l

a.d表示目录(directory),若是是一个"-"表示是文件,若是是l则表示是一个链接文件(link)

b.表示文件或者目录许可权限.分别用可读(r),可写(w),可运行(x)。

3. cp 拷贝文件

eg: cp filename1 filename2 //把filename1拷贝成filename2

cp 1.c netseek/2.c //将1.c拷到netseek目录下命名为2.c

4. rm 删除文件和目录

eg: rm 1.c //将1.c这个文件删除

5. mv 移走目录或者改文件名

eg: mv filename1 filename2 //将filename1 更名为filename2

mv qib.tgz ../qib.tgz //移到上一级目录

6. cd 改变当前目录 pwd 查看当前所在目录完整路径

eg: pwd //查看当前所在目录路径

cd netseek //进入netseek这个目录

cd //退出当前目录

7. cat,more命令

将某个文件的内容显示出来。两个命令所不一样的是:cat把文件内容一直打印出来,而 more则分屏显示

eg; cat>1.c //就能够把代码粘帖到1.c文件里,按ctrl+d 保存代码。

cat 1.c 或more 1.c //均可以查看里面的内容。

gcc -o 1 1.c //将1.c编译成.exe文件,咱们能够用此命编译出代码。

8.chmod 命令 权限修改 用法:chmod 一位8进制数 filename。

eg: chmod u+x filenmame //只想给本身运行,别人只能读

//u表示文件主人, g 表示文件文件所在组。 o 表示其余人 ;r 表可读,w 表可写,x 表能够运行

chmod g+x filename //同组的人来执行

9. clear,date命令

clear:清屏,至关与DOS下的cls;date:显示当前时间。

10. mount 加载一个硬件设备

用法:mount [参数] 要加载的设备 载入点

eg: mount /dev/cdrom

cd /mnt/cdrom //进入光盘目录

11. su 在不退出登录的状况下,切换到另一我的的身份

用法: su -l 用户名(若是用户名缺省,则切换到root状态)

eg:su -l netseek (切换到netseek这个用户,将提示输入密码)

12.whoami,whereis,which,id

//whoami:确认本身身份

//whereis:查询命令所在目录以及帮助文档所在目录

//which:查询该命令所在目录(相似whereis)

//id:打印出本身的UID以及GID。(UID:用户身份惟一标识。GID:用户组身份惟一标识。每个用户只能有一个惟一的UID和 GID)

eg: whoami //显示你自已登录的用户名

whereis bin 显示bin所在的目录,将显示为:/usr/local/bin

which bin

13. grep,find

grep:文本内容搜索;find:文件或者目录名以及权限属主等匹配搜索

eg: grep success *    /*查找当前目录下面全部文件里面含有success字符的文件

14. kill 能够杀死某个正在进行或者已是dest状态的进程

eg; ps ax

15. passwd 能够设置口令

16. history 用户用过的命令

eg: history //能够显示用户过去使用的命令

17. !! 执行最近一次的命令

18. mkdir命令

eg: mkdir netseek //建立netseek这个目录

19. tar 解压命令

eg: tar -zxvf nmap-3.45.tgz //将这个解压到nmap-3.45这个目录里

20. finger 可让使用者查询一些其余使用者的资料

eg: finger //查看所用用户的使用资料

finger root //查看root的资料

ftp上传下载ftp 192.168.1.100

用户:xiangf  Pwd xiangf

Put   mput上传多个Get   mget下载多个

linuxJdk的安装

1. 先从网上下载jdk(jdk-1_5_0_02-linux-i586.rpm) 

进入安装目录
#cd /home
#cp jdk-1_5_0_02-linux-i586.rpm /usr/local
#cd /usr/local
给全部用户添加可执行的权限
#chmod +x jdk-1_5_0_02-linux-i586.rpm.bin
#./jdk-1_5_0_02-linux-i586.rpm.bin
此时会生成文件jdk-1_5_0_02-linux-i586.rpm,一样给全部用户添加可执行的权限
#chmod +x jdk-1_5_0_02-linux-i586.rpm
安装程序
#rpm -ivh jdk-1_5_0_02-linux-i586.rpm
出现安装协议等,按接受便可

2.设置环境变量。[U1] 
#vi /etc/profile
在最后面加入 
#set java environment
JAVA_HOME=/usr/java/jdk-1_5_0_02
CLASSPATH=.:$JAVA_HOME/lib.tools.jar
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME CLASSPATH PATH
保存退出。

3.检查JDK是否安装成功。
#java -version
若是看到JVM版本及相关信息,即安装成功!

bash-profile是配置文件,配置java-homepathclasspath

。空格。bash-profile  重新启动 

Vim bash-profile编辑

Javac .java编译成。Class     java运行。Class文件

java –d.按包的名字自动生成相对应的


Core Java笔记

人--->源文件--->编译器--->程序--->CPU

编译器:

1,编译执行:源文件--->可执行代码。如:C/C++语言。

         执行效率高。可移植性差。---->开发成本的增长。

2,解释执行:源文件--->体系结构中立的中间代码( .class)--- >解释器 --->机器指令。 如 :java语言

     执行效率低。 可移植性好。---->  对硬件要求高。

JAVA语言:

(源文件)--->(编译器javac.exe)--->中间码--->(虚拟机java.exe)--->机器指令--->CPU

(编译) (解释)

.java ----> .class ---> 可执行文件

PATH:指定可执行程序(命令)在哪一个目录。不一样目录用(:)分开。--->SHELL

JAVA_HOME:指定JDK的安装目录。给其它应用程序看的。

CLASSPATH:指定(jar文件)中间字节码文件在什么地方。由多个目录组成的集合。--->

           让虚拟机能够找到中间字节码文件。就是能够找到.class文件

服务器上csh:.cshrc

bsh:.profile

客户端上。bash:.bash_profile

  1 # .bash_profile

  3 # Get the aliases and functions

  4 if [ -f ~/.bashrc ]; then

  5  . ~/.bashrc

  6 fi  //if的结尾。

  8 # User specific environment and startup programs  //#表明注释。

  9 JAVA_HOME=/opt/jdk1.5.0_15       JDK 安装路径--- JDK = JRE {JVM(硬件)+编译器( 软件)} +编译器工具+类库            

 10 PATH=$JAVA_HOME/bin:$PATH:$HOME/bin         //系统定义的$PATH   启动命令

 11 CLASSPATH=.:java/jar/servlet-api.jar:/java/jar/jsp-api.jar        //类路径

 12

 13 export PATH CLASSPATH JAVA_HOME   //使三个变量变成全局变量。。

Source .bash_profile:只能通过这条命令以后,才会让修改的变量生效。(csh)

. .bash_profile。 只能通过这条命令以后,才会让修改的变量生效。   (bash)

java -version:查看虚拟机的版本号。

 

2.,编写第一个JAVA程序[U2] 

1),以.java结尾的文件。

2),全部内容,都要写在一个类中(类名要和文件名想同,包括大小写在内)

       pbulic class HelloWorld{......}

3),main函数是程序执行的入口,程序从main函数的第一条语句开始执行,执行到main函数结束为止。

           public static void main(String argvs[]){

                   }

4),输出语句:System.out.println(    );

5),每条语句以(;)结尾

   先指定到源程序存放的目录,而后进行如下步骤运行。

   编译:javac命令。如:javac -d . HelloWorld.java -->生成HelloWorld.class类文件

   启动虚拟机(java),运行类文件。如:java com.work.core.HelloWorld   

      后面的.class省略,无需写成java com.work.core.HelloWorld.class

 

包(package):

1,package com.kettas.corejava; //包声明。

2,必须保证类文件必定放在相应的目录结构中,HelloWorld.class放在com/kettas/corejava目录中。

3,运行时,必定在顶层包的同级目录下运行java命令,

      例如:com(shell界面里运行)java com.kettas.corejava.HelloWorld

 (若是顶级包所在的目录已经被配置到CLASSPATH中的话能够在任意目录中启动 java命令)

1,类文件太多,很差管理。

2,解决重名。

javac -d . HelloWorld.java     (不只可以编译类文件,同时还能建立包结构)

运行命令java xxxx 类的名字--- 启动虚拟机

(一)语言:适合于internet

1,跨平台的   (属于解释执行的语言)

2,更容易开发出安全的程序:

       1)垃圾回收器,(帮助程序员管理内存)

       2)取消了指针,对数组越界进行检查

       3)安全检查机制,(对生成的字节码检测,如:包结构检测)

      Hash算法,,只要加密的源是同样的。通过Hash运算以后,Hash值都同样。

       加密的源若是不同了,通过Hash运算以后,值都不同。

 

(二)变量:

如:  学生,姓名,性别,age

            账户,ID,password,balance,username

内存:没记忆,容量小,成本高,存储变量数据,最小逻辑单位:byte(字节)=8bit(位)

外存(硬盘):有记忆,容量大,成本低,存储文件数据

1,变量声明:给变量起名,是给变量选择一种数据类型。如:int age;

 不一样的变量,

             1)参与的运算是不一样的,

             2)存储的值是不一样的,

             3)须要的存储空间的大小也不一样,

 

 java数据类型:

简单数据类型(原始数据类型)

   数字:    整数:byte(1字节)-short(2字节) -int[U3] (在内存中占4个字节)-long(8个字节)

  小数:float(4个字节,单精度浮点型) - double(8个字节,双精度浮点型)

  字符:char(一个字符=2个字节):只能表示一个字。  如:char c='中'; c存的是‘中‘这个字的编码。

 布尔:boolean(true,false),不能用0和非0表示。

String[U4] (字符串)复杂数据类型(类)

String 类提供了数值不可改变的字符串 String s=new String(“abc”);建立了两个对象1,在字符串池中建立一个对象(此对象是不能重复的)2,new出一个对象。Java运行环境有一个字符串池,由String类维护。执行语句String s="abc"时,首先查看字符串池中是否存在字符串"abc",若是存在则直接将"abc"赋给s,若是不存在则先在字符串池中新建一个字符串"abc",而后再将其赋给s。执行语句String s=new String("abc")时,无论字符串池中是否存在字符串"abc",直接新建一个字符串"abc"(注意:新建的字符串"abc"不是在字符串池中),而后将其付给s。

2,初始化 (局部变量而言,必须初始化才能使用)   如:age=10; 

3,经过变量的名字对变量进行操做,如:age=other;

            赋值时,左=右

                  1)数据性质是否同样。

                  2)所占用的内存空间上考虑   (左>右)不用类型转换。(左<右)要类型强制转换,

                    如:int age=1;

                       long l=10;

                       age=(int)l;

 符号位:0表明正数,1表明负数。

BigDecimal比double更精确,通常用于处理高精度运算。

&和&&的区别。

&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)

Java中的标识符的要求:

1,只能是字母,数字,_,$。 2,数字不能做为标识符的开头。

3,大小写敏感。               4,没有长度限制。如:ArrayOutOfBoudleException  

5,标识符不能是关键字。 

 

通常来讲,类的名字以大写字母开头。

方法和变量的名字以小写字母开头。

标识符的名字应当具备含义,如    age  , name

 

表达式:1,由运算符和变量组成。2,都会有返回值。           

简单表达式:a/b;       复合表达式:"a/b="+(a/b);

 

做业,打印润年,

1,能被4整除,但不能被100整除

2,能被400整除。

 

自增(++),自减(--)运算符。

前++:++a;先对a+1,再返回a+1以后的值。

后++:a++;先返回a的值,而后对a进行+1。

前++,后++共同的特色:a自己的值都会+1;

区别在于表达式的返回值是不同;用返回值来参与计算。

 

? :    -->(boolean express)? A : B;如:char ch=(5>2)?'Y':'N';

?前面的布尔表达式若是为真就执行A,不然执行B。

      (‘:‘左右两侧的返回类型要一致,且与ch的返回类型也同样)

 

 

 

 

 

 

 

 

java打包(压缩包    .zip   .rar    .tar   .gz    .jar)。

 

root/

  yesq/

  |-com/

    |-work/

      |-core/

        |-VarTest.class

        |-RunNian.class

          .  .  .  .  .  .

   压缩命令: jar -cvf abc.jar  dir

   解压命令:jar -xvf abc.jar

 abc.jar为生成压缩包的名字

 dir为被打包的文件目录下的东西

 c:是作压缩。v:为压缩过程的信息。f:指定压缩文件的名字。x:是作解压

  打包通常从顶层包开始打。如:[java@localhost yesq]$ jar -cvf first.jar com    

                                             //当前目录(yesq)下的com文件夹开始打

 

1,得到别人提供的jar文件

2,将jar文件的名字以及他的绝对路径配置到CLASSPATH中

3,使用import语句,将其余包的内容导入到本文件中,如:引入包com.kettas.common包中的SystemIn类

                                              import com.kettas.common.SystemIn;

 

 

------   java中的流程控制   -----

1,顺序

2,条件(代码是否执行,依赖于一个特定的条件)

  if(boolean express){

     XXXXXX;   //若是布尔表达式为真就执行XXXXXX。

     XXXXXX;

 }else{

     XXXXXX;   //若是布尔表达式为假就执行XXXXXX。

     XXXXXX;

 }

3,循环(相同的代码,被重复的执行屡次)

      a,初始化循环条件。b,肯定循环条件。c,肯定循环变量在循环体中的变化。

 

(1)       a;    

while(boolean express){

           XXXXXXXXX;   //若是布尔表达式为真就执行XXXXXX

           XXXXXXXXX;

                 c;

      }

(2)  for(a;b;c){

                

}

(3) do{

           XXXXXXXXXX;      //循环体至少执行一次;

           XXXXXXXXXX;

           }while(boolean express);

          

while(XXX){

      XXXXXX;

      XXXXXX;

      bread;           //或者continue;

      XXXXXX;

}

break :用在循环或分支里,用于退出整个循环或分支

 

 

continue :用在循环里,用于结束本次循环。接着开始下一次循环

4,分支

      switch(var[U5] ){

           case 1 : XXXXXX;

                 break;

           case 2 : xxxxxx;

                 break;

           ........

           default : xxxxxxx;    //    default后面能够不用break;

      }

函数(方法):是由一些相关代码组成的集合,目的是为了解决一个特定的问题,或者实现某个特定的功能。

函数(方法)必定有一个本身的名字,经过函数的名字执行函数中的代码。

          2,在java中如何定义函数:

a,声明:public static void printMenu(int a,double b){.....}

b,编写函数体:

 

如: public static void printMenu(int a,double b){

           XXXXXXXXXXX;

           XXXXXXXXXX;

      }

      函数(方法)里面不容许再有其它的函数(方法),函数(方法)的位置必须是并列的。

      3,调用函数:

      经过函数名,如pirntMenu(a,b);

public static void main(String argv[]){

      XXXXXXXXXXXX;

      printMenu(a,b);

      XXXXXXXX;

}

调用者-原数据->函数

return 做用:1,结束本方法。2,返回结果。

一个函数返回的值只能有一个。

 

 

4,值传递。传递的是实参的值

           被调函数使用的数都是实参的拷贝

           是否改变实参,要看被调函数的设计。

 

数组:一维数组-->:三种声明方式

一,(1)首先要声明。如:int[] array;或int array[];

      (2)申请内存空间如:array=new int[2];

   array表明数组array[]的首地址(引用:引用就是C++里的指针。);当参数传递时,只要用数组的首地址就能够。

1,数组中的元素类型要一致。

2,数组长度不能缺省,不能改变,但能够删了重建。

3,内存空间连续,有索引下标值(从0开始,最大length-1)

优缺点:查询快,增删慢(链表,查询慢,增删快)

 

只要有new在,就要为变量分配内存。 array.length   //表示数组array的长度。

array存的是array数组首变量的地址。

二,数组的显示初始化:int[] array={1,2,3,4,5,6};

三,int[] array=new int[]{1,2,3,4,5,6,7};

 

数组的拷贝:

public static int[] expand(int[] a){

      int[] b=new int[a.length*2];

/* for(int i=0;i<a.length;i++){

           b[i]=a[i];

      }

这段代码等于下面那条代码

*/

      // 从a数组下标为0的位置开始拷贝,到b数组下标为0 的位置开始粘贴。

      // a.length为粘贴的个数。(通常为a数组的长度)。

      System.arraycopy(a,0,b,0,a.length);   

      return b;  //返回扩展后的数组b。b是表明数组b的首地址。

}

 

二维数组(数组的数组)-->:三种声明方式

 

二维数组的第二个[]在声明时能够留空,如:int[][] array=new int[4][];

  //留空说明该二维数组的列是以行的数组下标为数组名,再成为新的数组。

 

一,声明:int[][] array=new int[3][4]; //声明一个三行四列的整型二维数组。

二,int[][] array={{1,2,3},{2,3,4},{2,5,7},{2,3,6}};

三,int[][] array=new int[][]{{1,2,3},{2,3,4},{2,5,7},{2,3,6}};

1,找对象(客观存在的事物);

2,利用对象的功能。就是让对象干点什么;

3,对象的属性能够是其余对象。

4,对象还能够经过调用其余对象的函数产生联系。

5,简单的对象构成复杂的系统。

 

有什么:属性-------》 实例变量

作什么:方法-------》函数

  对象的属性能够是其余对象

  对象还能够经过调用其余对象的函数产生联系     

  简单的对象构成复杂的系统

 

思想:解决问题的过程,

 

总纲(优点)

1,符合人的思惟过程。

2,编写出来的代码比较合理。如:可扩展性,可维护性,可读性等等。(存在就是合理),(贴近生活)

3,弱耦合性,

4,可扩展性

5,可复用性。              不要重复制造轮子。

6,更尽所能,更施其职。

 

==========类:==============

面向过程:是代码的容器。

面向对象:对象所共有的功能和属性进行抽像,成为了类。客观事物在人脑中的主观反映。在程序里类是建立对象的模板。  

 

java中的对象[U6] :对现实对象的抽象(得到有用的,舍弃没用的)。

      存储空间中的一块数据区域,用于存数据。如:人(nama sex age)

       属性:实例变量(定义在类之内,方法以外) 

            1.默认的初值

            2.实例变量的使用范围至少是类之内

            3.实例变量调用必须有对象,实例变量和局部变量重名,局部优先。

              

例:

public class Test{

      public static void main(String[] args){

     

      //新建对象stu;stu存的是新建对象stu的地址。stu的专业术语:引用/对象变量/引用变量/实例变量

           Student stu=new Student();       

           stu.name="tom";       //给对象stu的name属性赋值。

      }}

class Student{              //用类声明的数据(str)为引用类型,如:Student str;

 

      //实例变量:定义在方法以外,类之内的,没有static修饰的变量

      //实例变量会有一个默认的初始值。初始值与变量定义时的类型有关。

      //实例变量(成员变量)--->属性。可经过新建对象的引用来访问类的实例变量。如,stu.name;

      String name;    

      int age;

      String sex;

}

实例变量和局部变量的区别

1,位置:局部变量定义在方法里面。实例变量定义在类之内方法以外

2,使用的范围:局部变量只能在定义他的方法里面使用,直接调用变量名就能够了。

      实例变量至少能够在定义他的整个类内使用,使用时必须用对象去调用。只有跟对象一块儿实例变量才有意义。

3,局部变量使用以前必须初始化。实例变量不须要赋初值,系统会给默认的初值。

 

4,局部变量在同一方法里不能重名。局部变量和实例变量能够重名,在方法里采用就近原则。

 

==方法:======================

包括:

      方法:

       作什么:方法的定义 

           修饰符   返回类型   方法名(参数列表) 异常

       怎么作:方法的实现 {******}          

修饰符(如:public)  返回类型(如:int) 方法名/函数名 (参数表--形参)         

如:

      public void eat(String fish){                //eat(),吃的功能。

           //怎么作.

      }

使用实例方法时也须要用对象去调用。如:stu.eat("fish");

方法重载(overloading):编译时多态。[U7] 

在一个类的内部,方法名相同形参数不一样的方法,对返回类型不要求,这种现象称之为重载;

编译器会自动选择使用的方法。体现了一个编译时多态。

好处:对使用者屏蔽由于参数不一样形成方法间的差别。

找方法时若是没有合适的,采起自动向上扩展原则。

调用时形参之间的区别必定要明确。

    1. 形参的个数不一样

    2. 形参的类型不一样

    3. 形参的顺序不一样

    4. 形参的名字相同

 

方法覆盖(override):运行时多态。

1,发生在父类和子类之间

2,方法名相同,参数相同,返回类型相同

3,子类方法的访问权限不能更严格,只能等于或更加宽松。

 

构造方法:

1,没有返回类型,方法名必须和类同名。

2,构造方法不能手动调用,它只用在建立对象在时候,只出如今new以后。

      只要构造方法被调用运行,就必定有对象产生。

3,在一个对象的生命周期里,构造方法只能被调用一次。

4,类写好后必定有构造方法,

      若是程序没有显示的提供构造方法,JVM会提供一个默认的构造方法,public classname(){}

      若是程序显示提供,系统再也不提供默认的

5,同一个类的多个构造方法必定重载。

6,建立对象的同时构造方法的代码块里还能够写须要运行的代码,还能够给属性(实例变量)赋值,

      引用类型的属性赋值就是用new建立对象,而后调用构造方法。如:Student stu=new Student();

用new建立对象时JVM作的三件事:

如:Student stu=new Student();

1,申请空间;(把值放到空间里,再把空间的地址给引用变量。)----建立父类对象

2,初始化实例变量;没显示声明值的话就用默认值。

3,执行构造方法,

由于实例变量在建立对象的过程当中被初始化,因此使用实例变量前必须建立对象(要用对象去调用),不然实例变量根本不存在

 

=====关键字:this=======

1,在普通方法里,指代当前对象引用(哪一个对象调用该方法,this就指向该对象)

2,this不能出如今静态方法里。

3,在构造方法里,this用来指代本类的其余构造方法。在本类构造方法之间互相调用。如:this(形参);

      使用时放在构造方法里的第一行。

4,不能写成死循环(不能递归调用)

=====关键字:super=======

(和this的用法相似)

1,调用父类的构造方法,在子类调用父类的构造方法必须出如今第一句,构造方法第一句可能出现的三种状况(调用父类的构造方法看子类构造方法的第一句)①super();②super(参数)注意传递的参数必定是实体,有值的。③this(),先在本类的构造方法间调用,再看调用那个构造方法的第一句是什么

2,super访问父类的变量和方法,及super表明父类的对象,super.name;super.setName();

======参数传递========

1,参数至关于局部变量

2,参数传递至关于赋值语句

3,基本类型数据传递的是自己的值,引用类型数据传递的是引用xx(Animal animal)(地址,对象变量自己的值)

 

面向对象的三大特性:

 

一,封装(Encapsulation):一个系统以合理的粒度出现。

定义:封装就是将客户端不该看到的信息包裹起来。使内部执行对外部来看不一种不透明的、是一个黑箱,客户端不须要内部资源就能达到他的目的。(封装是把过程和数据包围起来,对数据的访问只能经过已定义的界面。面向对象计算始于这个基本概

念,即现实世界能够被描绘成一系列彻底自治、封装的对象,这些对象经过一个受保护的接口访问其余对象。)
1.事物的内部实现细节隐藏起来
2.对外提供一致的公共的接口――间接访问隐藏数据         3.可维护性  

访问控制修饰符:public(公开的),protected(受保护的,1,本包内可见;2,其余包的子类可见)

                       default(默认,本包内可见),private(私有的,类内部可见)

访问控制修饰符   (能够范围)          (可修饰)下面的类(指外部类)

      private         本类            方法,属性

      default         本包            类,方法,属性

      protected     本包+子类                方法,属性

      public         处处可见          类,方法,属性

 

1,属性:隐藏全部属性,用private。隐藏后属性只能在类之内访问 。程序能够根据须要提供get和set

2,方法(函数):该公开的公开,该私有的就私有。(视状况而定)

3,公开方法的功能,隐藏方法的实现细节。

 

二,继承(inheritance):抽象出不变性。

从通常到特殊的关系,能够设计成继承

   特色:共性写在父类里面,特性写在子类

全部类的总父类是 Object (Object是类的祖先)

父类里写的是共性,子类里写的是特性。

父类中用private修饰的属性和方法不能被子类继承;

可是父类里的属性子类都有,若是子类有特殊属性的话,就要在子类里定义

且在建立该子类对象的时候初始化属性(包括父类全部属性和该子类全部属性);

 

什么样的功能和属性能够继承到子类?

对于父类里的属性和方法,子类有权访问的,咱们称为能够继承;

 

用new建立子类对象,JVM执行的过程:Dog d=new Dog(); 为d申请空间。 class Dog extends Animal{}   

(1)申请空间;(把值放到空间里,再把空间的地址给引用变量。)

(2)看本类构造方法的第一句

(3)默认的建立父类对象:

      执行顺序:子类(2)--->  父类(2-->3-->4-->5)--->   子类(4-->5),

      新建一个对象空间只申请一次(该空间存放全部父类和子类)。)

(4)初始化本类的实例变量(该类的全部属性);

(5)执行本类的构造方法,(构造方法只会在建立一个对象的时候被执行一次)

 

(建立是先执行父类的构造方法,在执行子类的构造方法,访问时先访问子类本身的特殊属性和方法再访问父类的属性和方法)

用super调用父类被子类覆盖的普通方法和遮盖的属性,

指代的是在建立子类对象过程当中,由JVM自动建立的那个父类,如:super.方法名()/属性

用super调用父类的构造方法;必须出如今子类构造方法的第一句。如:super(形参);

1,在子类的构造方法里若是没有指明调用哪个父类的构造方法(就是子类中没有super(形参)语句;),

      JVM会默认调用父类的无参构造方法,跟本类构造方法的形参没有关系。

2,显示的写super,JVM会根据参数调用相应的父类构造方法。

3,有this(形参),在本类的构造方法之间调用,看被调用的那个构造方法的第一行。

 

 

 

 

三,多态[U8] (polymorphism):多态只有方法多态,没有属性多态。

用父类类型屏蔽子类之间的差别

 

全部的子类对象均可以当父类对象来用,一个父类型的引用可能指向的是一个子类对象,

如:把狗(对象)看做动物(类型)。Animal a=new Dog();               编译看前面,运行看后面。

                            (编译时类型)   (运行时类型)

1,运行时对象不会改变(对象是客观存在的),如:狗这个对象的属性和方法是不会改变的。

2,对一个引用,只能调用编译时类型里的已知方法。

      如:编译器知道动物里已有的属性和方法,但不知道狗的属性和方法。

3,运行时会根据运行时类型自动寻找覆盖过的方法运行。

 

引用  instanceof 类名       //结果为boolean值,

引用所指向的对象和类名类型是否一致(对象是否属于类名类型)

类型的转换:转换编译时类型

   Sub  su= (Sub) s;

   子类型的引用向父类型转换时,不须要强转

   父类型的引用向子类型转换时,须要强转                                                    

     Animal a=new Cat();

     Dog d=(Dog)a;      // 类型转换异常

     引用  instanceof  类名 -----> boolean

     引用所指向的对象和类名所表明的类型是否一致  

     a instanceof Animal ----->  true      a instanceof Cat---------->  true    a instanceof Dog----------->false

     Employee e=new Manager();

     e instanceof Employee ------>true

     e instanceof Manager------> true     

    

 属性没有多态,属性只看编译时类型

   

编写程序的顺序:

class 类名{

      private属性(有什么)

      无参的构造方法(public类名(){})

      有参的构造方法(做用:给属性赋值)

      set和get(设置和得到属性)

      业务方法(作什么)

 

一,修饰符:static [U9] 

      static变量:如:static int index=2;

           类的全部对象共同拥有的一个属性;能够用类名直接访问,又称为类变量,

           类的全部对象共同拥有的一个变量;类第一次被加载时会初始化静态变量

(也就是会先执行static修饰的变量);

           跟类建立了多少对象无关;任何对象对静态变量作的修改,其余对象看到的是修改后的值。

            能够用做计数器,记录类建立对象的个数 , static变量在类加载的时候只会被初始化一次

      static方法:如:public static void teach(){}

           能够用类名直接去调用,不须要对象因此不能直接访问(在没有对象的状况下)实例变量,

在静态方法里不能出现this和super,类的全部对象共同拥有的一个方法;跟类建立了多少对象无关。

           在继承里,父类的静态方法只能被子类的静态方法覆盖,且覆盖之后没有多态

(访问的是父类的静态方法);

      static初始化块:如:class Teacher(){

                                  static int index=4;

                                  static{          //static初始化块

                                       .........

                                       }

                                  }

      静态初始华块:用static修饰类里面的一个独立的代码块,类第一次被JVM加载的时候执行,只被执行一次

      类加载:JVM在第一次使用一个类时,会到classpath所指定的路径去找这个类所对应的字节码文件,

           并读进JVM保存起来,这个过程称之为类加载,一个线程一个jvm

     

二,final  (最后的,最终的)final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承

      final类:如:final class Animal{}

           表示该类不能被继承,意味着不能改变里面的代码;

           对虚拟机的正常运行有重要做用的类一般用final修饰,如:String,System,Math ...等类

      final方法:如:public final void sleep(){}       该方法不能被覆盖(修改),但能被子类访问。

                     

     

      final变量:如:final (static) int index=4;

                      该变量是常量能被继承(访问);

                      final修饰的变量就是常量,一般和static一块儿连用,来声明常量;

                      final修饰引用类型数据,指的是引用(地址)不能变,但引用里的数据不受限制。

                      final修饰的变量,只要在初始化的过程当中就能够赋值。

 

                      实例变量:声明的同时或构造方法里赋值;

                      静态变量:声明的同时或在静态代码块里赋值;

 

三,abstract

      abstract类:如:abstract class Animal{}

                      抽象类,不能建立对象(如一些父类),可是能够声明一个抽象类型的引用

                      (能够声明父类类型子类对象,编译时利用多态调用抽象方法)。

                      含有抽象方法的类必定是抽象类,但抽象类并不必定要有抽象方法;

                      抽象类通常是用来被继承的;子类继承自抽象类,就要实现里面的抽象方法,

                      若是不想让子类也是抽象类的话,必须实现父类里面全部的抽象方法。

                      抽象类有构造方法,有父类,也遵循单继承的规律。

     

      abstract方法:如:public abstract void sleep();

           抽象方法,只有方法名的定义,没有实现体(只定义了能作什么,没定义怎么作),不能被调用,

                      用于被子类的方法覆盖或从新实现。只能放在抽象类中。

                      好处:容许方法的定义和实现分开。

                      public  protected  default  private  static final  abstract

                   能够: public static

                           private static

                          public final

                          public static final

                 不能够:abstract final void eat(); 

                 private abstract void eat();

                 static abstract void eat();

            abstract不能和final,private,static连用。

 

四,interface:是抽象类的变体,。在接口中,全部方法都是抽象的。如:interface M{

                                       int num=3;

                                       void eat();

                                  }

      理解为接口是一个特殊的抽象类,因此接口不能建立对象,且接口没有构造方法,

      但能够声明一个接口类型的引用(m是接口类型实现类对象,如:M m=new N();)

      接口存在的意义是被子类实现,若是不想让子类也抽象,

      就要实现接口里面全部的抽象方法,实现过程当中注意访问权限;

 

      用  implements 关键字实现接口,如:class N implements M{

                                                  public void eat(){...}

                                                }

      接口里面的常量默认都是public static final的;

      接口里面的方法默认都是public abstract的。

     

      接口自己支持多继承,继承了父接口里功能的定义,如,interface A extends B,C,D{}        //A,B,C,D都是接口;

      类能够同时继承一个父类和实现接口(或多个接口)。

      如:class AA extends BB implements CC,DD,EE{}//AA,BB      是类,CC,DD,EE是接口;

      做用:1,用接口去实现多继承,接口是对类的共性进行再次抽象,抽象出类的次要类型。

                 如:蜘蛛侠,拥有人和蜘蛛的属性,但主要类型是人,次要类型(接口)是蜘蛛,

                 由于接口是次要类型,因此在类关系里不占一个节点,不会破坏类层次关系的树状结构,

             2,标准(保证弱耦合):一个接口就是一个标准(里面的属性不能改变,只定义了功能,

但没有被实现),  接口将标准的制定者,标准的实现者以及标准的使用者分离开,

                 下降实现者和使用者的耦合。接口是java里一种重要的下降耦合的工具;

接口能够屏蔽不一样实现类的差别,

                 当底层的实现类更换后,不会对上层的使用者产生影响,体如今参数和返回值。  

                

                 写程序时,应该先写实现者再写使用者,如:Bank.java是实现者,View.java是使用者,

                 可是有了接口以后,就能够用接口回调的功能;

                 接口回调:先定义接口,而后写使用者和实现者的顺序随便(通常是先写使用者,

后写实现者);利用参数把实现者传给使用者(即:实现者是使用者的属性),

使用者利用接口调用实现者相应的功能。

       **接口和抽象类的区别 1一个类能够implements多个接口,而只能extends一个抽象类

                       2,一个抽象类能够实现部分的方法,而接口都是抽象的方法和属性

 

Object是Java里全部类的直接或间接父类,Object类里面的全部功能是全部java类共有的

1,JVM调用垃圾回收器回收不用的内存(没有引用指向的对象)前运行finalize(),给JVM用的方法。

      程序显示的通知JVM回收没用的内存(但不必定立刻就回收):System.gc();或    Runtime.getRuntime().gc();

 

2,toString()返回对象的字符串表现形式,打印对象时,虚拟机会自动调用toString获取对象的字符串表现格式,

      如:System.out.println(str.toString());      ==System.out.println(str);

      若是本类不提供(覆盖)toString(),那么使用的是Object类里的相应方法,打印的就是地址。

      如:public String toString(){

                 return ".....";

           }

          

3,基本类型时“==“判断变量自己的值是否相等;引用类型时,判断的是地址是否相等。

      equals判断的是对象内容是否相等。对于本身建立的类,应该覆盖Object类的equals()方法;

      不然使用的是Object类里的equals()方法,比的是地址。

     

      覆盖方法以下:

      /*****************************************************

      public boolean equals(Object o){ 

        if(o==null)  return false;

        if(o==this)  return true;

        if(!(o.getClass()==this.getClass())) return false;

        final Student s=(Student)o;

        return this.name.equals(s.name) && this.age==s.age ;  //比较原则;

      } 

    ******************************************************/

      覆盖euqals()方法时遵循的原则:

      自反性:a.quals(a);         //true

      对称性:a.equals(b);<==> b.equals(a);      //true

      传递性:a.equals(b);//true         b.equals(c); //true

           --->则:a.equals(c);  //为true               

     

封装类(Wrapper class)[U10] 

OverLoading时,基本类型时采用向上匹配原则,

若是没有基本类型的话就向包装类转换,若是尚未就让这个基本类型在包装类里也采用向上匹配原则;

 

基本类型-转换到-->包装类

boolean----->Boolean

int-------->Integer      //Integer是引用类型,

int-------->Ddouble           //合法,         但Integer------>Double    非法

double------>Double

   ......  ------->   ......

任何类型----->Object

基本数据类型int能够向double自动扩展,可是包装类型之间不能自动的相互转换,

基本类型数据--->包装类型

int i=3;

Integer it=new Integer(i);        //手动转换;基本类型向包装类型转换。

int <----> Integer <----> String

转换时String类型必须为全数字字符串。如:"2515"    不能为:"abc265","aec"...等

String str=”123”; int it=Integer,parseInt(str);把字符串转换成数字。String str2=it+“”;把数字转化成字符串

 

=内部类============

定义在其余代码块(类体或者方法体)里的类称为内部类;

编译后每个内部类都会有本身的独立的字节码文件,

文件名:Outer$Inner.class-->内部类也能够有父类和实现接口。也能够有抽象方法

 

根本位置和修饰符的不一样分为四种:

1,member inner class       成员内部类,当实例方法或变量同样理解。

      1)定义的位置:类之内,方法以外,没有静态修饰符(static)。

      2)自己能定义的属性和方法:只能定义非静态的属性和方法。

      3)能直接访问的什么:能访问外部类的全部静态和非静态的属性或方法。

      4)怎么建立对象:在外部类内的方法内:Outer.Inner inner=new Outer().new Inner();

            在外部类外的类的方法内:Outer.Inner inner=new Outer().new Inner();或

在Outer类里提供一个getInner()方法,返回内部类的对象,这样在外部类外的类的方法内也能够用该成员内部类。

     

2,static inner class 静态内部类(嵌套内部类),当静态方法或变量同样理解。

      static只能修饰内部类,不能修饰外部类。

      1)定义的位置:类之内,方法以外,有静态修饰符(static)。通常写在外部类的属性下面。

      2)自己能定义的属性和方法:能够定义静态和非静态的属性或方法。

      3)能直接访问的什么:只能访问外部类的静态属性和方法。

      4)怎么建立对象:在外部类内的方法里: Outer.Inner inner=new Outer.Inner();

                                 在外部类外的类方法里:   Outer.Inner inner=new Outer.Inner();

3,local inner class        局部内部类           当局部变量同样理解。

      1)定义的位置:方法里面的类,前面不能用public或static修饰。

      2)自己能定义的属性和方法:只能定义非静态的属性和方法。

      3)能直接访问的什么:能访问方法内用final修饰的局部变量(不能与该类内的变量名相同)。

                                       能访问外部类的全部静态和非静态的属性或方法。

      4)怎么建立对象:只能在方法内建立对象,如:Inner inner=new Inner(); 对象的做用范围只在方法内。

4,annonymous inner class         匿名内部类                       如:  Teacher tc=new Teacher(){

      1)没有名字的类,没有构造方法。是一个特殊的局部内部类,                 public void teach(){...}

             能够实现一个接口,   或者一个类,                                           }

             生命周期里只能产生一个对象(tc),也就是说只能被一个对象(tc)调用,

      2)除了没有名字外,看匿名内部类所在的位置,他的定义和访问将和成员内部类、静态内部类、局部内部类同样。

                 通常像局部内部类的定义和访问比较多。

      3)当试图建立接口或者抽象类对象的时候,用匿名内部类。

           表示类体的{...}紧跟在抽象实例(接口)以后,表示实现该抽象实例(接口)。

           调用匿名内部类的方法只能用写类时建立的那个对象(tc)。

做用:1,不破坏访问权限的状况下,内部类能够使用外部类的私有成员变量和方法。

           2,将接口公开,将实现类(实现公开的接口)做成内部类隐藏起来,强制要求使用者使用接口,强制下降偶合度。

        3,Java经过接口和内部类两种机制来实现多继承。在类内部能够创建本类的实例,而后调用本类内的其余方法。

Exception(异常):运行时的概念。

1,Throwable:运行时可能碰到的任何问题的总称;

      1)Error:指很是严重的错误,系统不要求程序员处理,也处理不了。如:硬件坏了.....等。

      2)Exception:从代码的角度是程序员能够处理的问题;

      UncheckedException(RuntimeException 的子类) (未检查异常)若是是RuntimeException(或子类)就是为检查异常,其余就是已检查异常

           程序员当心谨慎彻底能够避免的异常,系统不要求程序员处理(能够无论,运行会提示错误),

           如:3/0          数组下标越界。

      CheckedExcepiton   (已检查异常)

           系统要求必须处理异常。

2,异常处理:异常是相对于方法来讲的

      1)声明抛出异常(消极的处理)

           throws(抛弃):写在方法名的定义上,后面跟要抛弃的异常类型。

           如:public void m1() throws Exception{.}

异常产生时,责任可能并不在当前方法,向外抛弃(把异常抛弃,留给调用者处理)可让异常找到一个最佳的位置处理

           抛弃过程当中能够对异常类型进行扩展,可是不能缩小。

           throw(抛出):通常出如今方法实现里,用来抛出异常对象(或者是产生异常),

           如:throw new FileNotFoundException();

           当代码出现异常时,代码不会向下执行,JVM会将异常封装成相应的异常类的对象,

           而后向外抛出。以后这个方法里剩下的代码就不会再执行了。

      对于一个方法的返回值:

           1)正常运行时,要求方法必须返回定义的类型的值。

           2)若是运行不正常(出现异常),方法返回的是异常对象

      方法覆盖:名相同,参数相同,返回类型相同,访问权限不能更小,子类抛弃的异常不能比父类更多。

2)try....catch(积极的处理):

           一个try语句后能够跟多个catch语句;catch时异常子类放上面,异常父类放下面。

           若是没有父子关系,前后无所谓;

      ---方法---( ){

            try{

                 //可能会出现异常的代码

                 xxxxxxxxxx;      (1)

                 xxxxxxxxxx;      (2)

           }catch(Exception1 e1){

                 //当try代码块出现异常时,执行catch代码块。

                 xxxxxxxxx; (3)

           }catch(Exception2 e2){

                 xxxxxxxxx; (4)

           }finally{

                 //无论有没有异常出现都要执行的代码。

                 xxxxxxxxx; (5)

           }

                 xxxxxxxxx; (6)

      }

1)若是(1),(2)没产生异常,(2)执行后直接执行(5),而后执行(6)。

2)若是(1)产生异常,(2)不会被执行,直接跑出try{..},匹配catch,和catch里定义的类型一致,

执行catch完了后,直接跳到(5)执行,最后再执行(6),若是异常类型都不一致,将导至语法问题。

3)自定义异常类型(业务异常):

           如:class MyException extends Exception{

                      public MyException(String str);

                      super(str);

                 }

Exception异常总结:

一、若是程序用了System.exit(0);则不会执行finally里的程序

二、在程序return前执行finally里的程序

三、Java中异常分为两类:

1) checked Exception

处理方式1、继续抛出,消极作法,直到抛出到JVM

处理方式2、用try..catch

2) unchecked Exception (runtime exception)

throws ArithmeticException,IOException应该是出现这两种异常就向上抛吧。
什么状况下一个方法抛出几个异常?通常来讲应该是会抛出几种异常,而后在一级调用这个方法时处理一下。
若是没有特殊须要的话要把可能出现的异常都截获并处理。
try{
  method();
}catch(exception1 e1){
 do something;
}catch(exception2 e2){
 do something;
}……
e1的范围小于e2.

 

课外考题:12、final, finally, finalize 的区别。

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。

finally 是异常处理语句结构的一部分,表示老是执行。

finalize 是Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,能够覆盖

此方法提供垃圾收集时的其余资源回收,例如关闭文件等。

 

Java高级部分=============================================

集合,经常使用的接口,Collection,List Set,SortedSet,Map,SortedMap

用来管理/容纳多个对象的对象(或称为容器);

面向对象可重用性的体现,对数组做了功能封装。

Collection是一个接口:是以对象为单位来管理元素的。

      基本操做:add  remove  size

      遍历:迭代遍历

有两个子接口:List接口和Set接口

1,List接口:元素是有顺序(下标),能够重复。有点像数组。能够用迭代器(Iterator)和数组遍历集合。

      List接口里自己有本身的方法,还有从父接口Collection里继承的方法。

      remove(int)删除某一位置的对象、add(int,Object)往某一位置插入对象 、get(int)查询某一位置上的元素。

      遍历:迭代遍历、for遍历

      Collections.sort(list); 引入list集合而后对list集合里的对象(如:Student类)进行排序时,

      只要在让对象(类)实现Comparable接口,再覆盖接口里面的方法(compareTo()方法),

      在compareTo()方法里写出进行什么样的方式排序,

      Public int compareTo(Object o){

         Work w=(Work)o;

       If(this.salary!=w.salary){return (int)w.salary-(int)this.salary;}

       Else If(this.age!=w.age){return w.age-this.age;}else  retuen this.name.compareTo(w.name);sss

}

      而后在主函数里使用Collections.sort(list);  ,就对list里的对象进行排序了,

      而不用管Collections.sort()方法是怎么实现的,既不用管Collections.sort()方法的实现体。

      排序规则:对象实现Comparable接口,覆盖compareTo()方法,Collections.sort(List);

     

1)ArrayList[U11] 集合类实现List接口,轻量级,底层是以数组实现的,查询快,增删慢,线程不安全,用get(int)方法多时,

 Vector集合也实现List接口,底层也是以数组实现的。但这个类已经放弃了。重量级,查询慢,增删快,线程安全。(Vector和HashTable是线程同步的(synchronized),因此线程安全。性能上,ArrayList和HashMap分别比Vector和Hashtable要好。)

2)LinkedList集合类实现List接口,他底层是以链表实现的,查询慢,增删快,

           用remove(int)、add(int,Object)方法多时,

           本身实现栈(stack),并对栈里进行增删操做。

           class MyStack{

                 private LinkedList list=new LinkedList();

                 public void push(Object o){

                      list.addFirst(o);

                 }

                 public void pop(Object o){

                      list.removeFirst();}}

2,Set接口无顺序,不能够重复(内容不重复,而非地址不重复)。只能用迭代器(Iterator)遍历集合。

      Set接口里自己无方法,方法都是从父接口Collection里继承的,

      遍历:迭代遍历

      实现类:保证元素内容不重复。

1)HashSet集合类实现Set接口,底层是以数组实现的。HashSet集合里不容许有重复对象

      每向HashSet集合类里添加一个对象时,先使用HashSet集合类里add(o)方法,

      再调用对象o的hashCode()方法算出哈稀码,保证相同对象返回相同的哈希码。

      若是哈稀码同样,再调用对象o里的equals()方法对对象的属性进行比较是否相等,

集合也能够构造集合,如:List<Object> list=new ArrayList<Object>(); Set<Object> set=new HashSet<Object>(list);原来在list集合里的对象是能够重复的,但被set集合构造以后,重复的对象将被去掉

按这三种顺序来理解接口:    1)接口特色;2)接口常见操做(方法);3)接口实现类的特色

Map:对应一个键对象和一个值对象,能够根据key找value,

      (Key--value)不可重复且无序--可重复

      排序(SortedMap是Map的子接口):TreeMap类实现SortedMap接口;对集合进行排序。

      基本操做:put()  get()

      遍历:键遍历  ketSet()返回键的集合(Set)(说明map的键是用set实现的,不能重复)

              值遍历 values() 返回值的集合。

      HashMap类实现Map接口:     查询快,线程不安全,容许键和值对象为null

      Hashtable类实现Map接口:查询慢,线程安全

      TreeMap类实现Map接口:SortedMap的实现类,自动对键进行排序。

 

 

Iterator 实例

Static void printValue(Map map){

  Collection col=map.values();

Iterator it=col.iterator();

  While(it.hasNext()){

Object obj=it.next();…;

}}

 

 

 

Jdk1.5新特性加了forEach循环方便数组和集合的遍历(是在泛型的基础上提出的)

Static void printValue(Map<Integer Product> map){

  Set<Integer> s=map.ketSet();

For(Integer i:s){xxxx}

}

注意:若是须要定位,就得用“普通”的 for,在列表遍历期间没法删除集合对象。

 

 

课外考题、Collection 和 Collections 的区别。

Collection 是集合类的上级接口,继承与他的接口主要有Set 和List.

Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各类集合的搜索、排序、线

程安全化等操做

 

 

=======图形界面(GUI)==================================================

1,选择容器:图形界面容器,容器也是一个对象(至关一个图形界面),用来装组件的。

JFrame:窗口,至关于一个容器;如一些按钮,最大化,最小化等一些。默认的布局管理器是BorderLayout

      JPanel:面版,透明的。默认布局是FlowLayout, 通常放在窗口里

      javax.swing.*;存在于该包中。

2,设置布局管理器

      FlowLayout(): 流式布局。组件会随着容器的大小而改变位置,

      BorderLayout():东西南北中分布组件

      GridLayout():网格布局。一个格只能放一个组件,

      CardLayout():卡片布局。如按上一步和下一步。界面是一个卡片式的布局。

      GridBagLayout():复杂的网格布局,一个格能够放多个组件。

      java.awt.*;存在于该包中。

      setLayout():用于设置什么样的布局。

3,添加组件:一个组件就是一个对象,

      JTextField :单行文本框

      JTextArea :多行文本区

      JComboBox:下拉列表

      JScrollPane:左右拉或上下拉按钮

4,设置事件监听

AWT事件模型,事件三要素:事件对象,事件源,事件监听器

1,事件对象:事件也是一个对象。事件对象继承:java.util.EventObjct类

2,事件源:发生事件的对象,也是报告事件的对象。(点击b1按钮,那么b1按钮就是事件源)

3,事件监听器:处理事件的对象。 监听器接口必须继承java.util.EventListener接口。

      事件源预先就某种事件注册监听器,当事件发生时,事件源就给全部注册的监听器发送一个事件对象,

      全部监听器存在一个数组集合里(如ArrayList集合),由监听器作出相应处理。

      事件源能够同时是多种事件的事件源,就某种事件单独注册监听器。

      事件源就同一种事件,能够注册多个监听器。

      一个监听器能够同时注册在多个事件源当中。

      事件对象中会封装事件源对象。

      事件监听接口中的每个方法,都应以对应的事件对象做为参数类型。

      所谓的事件源给监听器发送事件对象,其实就是事件源以事件对象为参数,调用监听器的方法。

      getSource()方法:是事件对象(EventObject)里的一个方法,用事件对象e调用(如:e.getSource(); )

           getSource()方法返回的是事件对象里的事件源

 

 

=======多线程=======================================================

线程:进程中并发的一个顺序执行流程。

并发原理:CPU分配时间片,多线程交替运行。宏观并行,微观串行。

Tread t=new Thread();表示新建一个线程对象,并不表示线程。

      当调用t.start();才起动线程,当获得CPU时,就会执行线程t的方法体。

线程三要素:CPU、Date、Code

多线程间堆空间共享,栈空间独立。堆存的是地址,栈存的是变量(如:局部变量)

建立线程两种方式:继承Thread类或实现Runnable接口。

Thread对象表明一个线程。

多线程共同访问的同一个对象(临界资源),若是破坏了不可分割的操做(原子操做),就会形成数据不一致的状况。

在java中,任何对象都有一个互斥锁标记,用来分配给线程。

synchronized(o){..同步代码块. .}

对o(o是临界资源)加锁的同步代码块,只有拿到o的锁标记的线程,

           才能进入对o加锁的同步代码块,退出同步代码块时,会自动释放o的锁标记。

synchronized的同步方法,如:public synchronized void fn(){} 对访问该方法的当前对象(this)加锁;哪一个线程能拿到该对象(临界资源)的锁,哪一个线程就能调用该对象(临界资源)的同步方法。

一个线程,能够同时拥有多个对象的锁标记

在java中,任何对象都有一个锁池,用来存放等待该对象锁标记的线程,

           线程阻塞在对象锁池中时,不会释放其所拥有的其它对象的锁标记。

在java中,任何对象都有一个等待队列,用来存放线程,

线程t1对(让)o调用wait方法,必须放在对o加锁的同步代码块中!

      1.t1会释放其所拥有的全部锁标记;

      2.t1会进入o的等待队列

t2对(让)o调用notify/notifyAll方法,也必须放在对o加锁的同步代码块中!

      会从o的等待队列中释放一个/所有线程,对t2毫无影响,t2继续执行。

当一个现成对象调用yield()方法时会立刻交出执行权,回到可运行状态,等待OS 的再次调用

线程的生命周期

下面为线程中的7中很是重要的状态:(有的书上也只有认为前五种状态:而将“锁池”和“等待池”都当作

是“阻塞”状态的特殊状况:这种认识也是正确的,可是将“锁池”和“等待池”单独分离出来有利于对程序的理解)

1,初始状态,线程建立,线程对象调用start()方法。

2,可运行状态,也就是等待Cpu资源,等待运行的状态。

3,运行状态,得到了cpu资源,正在运行状态。

4,阻塞状态,也就是让出cpu资源,进入一种等待状态,并且不是可运行状态,有三种状况会进入阻塞状态。

1)如等待输入(输入设备进行处理,而CPU不处理),则放入阻塞,直到输入完毕,阻塞结束后会进入可运行状态。

2)线程休眠,线程对象调用sleep()方法,阻塞结束后会进入可运行状态。

3)线程对象2调用线程对象1的join()方法,那么线程对象2进入阻塞状态,直到线程对象1停止。

5,停止状态,也就是执行结束。

6,锁池状态

7,等待队列

 

课外问题:7一、简述synchronized 和java.util.concurrent.locks.Lock 的异同 ?

主要相同点:Lock 能完成synchronized 所实现的全部功能

主要不一样点:Lock 有比synchronized 更精确的线程语义和更好的性能。synchronized 会自动释放锁,

而Lock 必定要求程序员手工释放,而且必须在finally 从句中释放。

=======I/O==========================================================================

File:表明了磁盘上的文件或者目录

I/O:jvm和外部数据源的数据交换。File,db—in-àjvm---out-àfile,db

流一共有三种分类:

方向分:输入流和输出流;

单位分:字节流和字符流;

      字节流:

           InputStream/OutputStream 字节流的父接口

(1)FileInputStream/FileOutputStream  文件字节流     ((能够向下转换))

           DataInputStream/DataOutputStream  读写8种基本类型和以UTF-8读写String

           BufferedInputStream/BufferedOutputStream  带缓冲的输入/出流

           PrintStream 融合Data和Buffered,  System.out所属的类

           Piped 管道 用于线程间交换数据

           RandomAccessFile 随机访问文件

      字符流:处理字符编码问题

           Reader/Writer 字符流的父接口

           FileReader/FileWriter 文件字符流,和FileInputStream/FileOutputStream  文件流,

((能够向下转换)) 与上面的(1)是相等,

           只不过一个是字节流,下面是字符流,因此两个没法相传

InputStreamReader/OutputStreamWriter 桥转换 将字节流转成字符流 在桥转换的过程当中,能够制定编解码方式

           BufferedReader/PrintWriter  有缓冲

      字符流转换为字节流时,指定编解码方式是在桥转换时指定的。

功能分:节点流和过滤流;

      节点流:用于传输数据。

      过滤流:帮助节点流更好的传输数据。

      piped(管道节点流):用于两个线程间传输数据。一个线程的输出,是另外一个线程的输入。

对象序列化:

      把对象放在流上传输ObjectInputStream/ObjectOutputStream

      只有实现了Serializable接口的对象才能序列化

用transient修饰的属性,为临时属性,不参与序列化,只能修饰对象的属性。

     

===================网络=====================================================

1 网络通讯的本质是进程间通讯。   

2 Tcp协议和UDP协议
TCP:开销大,用于可靠性要求高的场合。
TCP的过程至关于打电话的过程
UDP:用在对实时性要求比较高的场合。
UDP的过程至关于写信的过程。

注意:socket是套接字,ip和port(端口号 0~65535个端口,一个端口只能有一个进程)

3,  TCP通讯机制,tcp是面向链接的,实现多线程的方法有三个

① 为每一个客户分配一个工做线程。

②  建立一个线程池,由其中的工做线程来为客户服务。

③  利用JDK的Java类库中现成的线程池,由它的工做线程来为客户服务。

下面觉得每一个客户分配一个工做线程来实现多线程

 

在服务端

import java.net.*;

import java.io.*;

public class TCPServer2 {

   public static void main(String[] args) throws Exception{

      ServerSocket ss=new ServerSocket(9000);//端口号

      while(true){

           Socket s=ss.accept();//链接监听客户端

           System.out.println(s.getInetAddress());

           Thread t=new ServerThread(s);//实现多线程链接

           t.start();

      }

   }

}

class ServerThread extends Thread{//分配线程

   Socket s;

   public ServerThread(Socket s){

      this.s=s;

   }

public void run(){

   try {

      OutputStream os=s.getOutputStream();//在网络中获取输出流

      PrintWriter out=new PrintWriter(os);

      for(int i=1;i<=30;i++){

      out.println("Hello "+i);//经过网络发消息给客户端

      out.flush();

      Thread.sleep(1000);

           }

      } catch (Exception e) {

           e.printStackTrace();

      }

      finally{

           try {

                 s.close();//注意关闭线程而不关闭流

           } catch (IOException e) {

                 e.printStackTrace();

           }

      }

   }

}

在客户端

import java.net.*;

import java.io.*;

public class TCPClient {

   public static void main(String[] args) throws Exception{

Socket s=new Socket("192.168.0.10",9000);//链接服务端的ip和端口

      InputStream is=s.getInputStream();//得到输入流,读取服务端发来的信息

      InputStreamReader ir=new InputStreamReader(is);

      BufferedReader in=new BufferedReader(ir);

      for(int i=1;i<=30;i++){

           System.out.println(in.readLine());

      }

      s.close();

   }

}

 

 

4,  Udp 面向无链接,不可靠,效率高,资源占用少 ,先从客户端发起通讯,让服务端知道其地址等信息,不一样的协议其端口号的含义也不同

 

例子:

在客户端

import java.net.*;

public class UDPClient {

public static void main(String[] args) throws Exception{

DatagramSocket ds=new DatagramSocket();注册邮箱

String text1="I am here!";

byte[] bs1=text1.getBytes();//转换成字节用来传输

DatagramPacket letter1=new DatagramPacket(

bs1,0,bs1.length,InetAddress.getLocalHost(),9000);

//写好信(地址和内容)

      ds.send(letter1);//发信    

DatagramPacket letter2=new DatagramPacket(

                      new byte[100],0,100);

//准备空信用来接受服务端的信

      ds.receive(letter2);//收信

      byte[] data=letter2.getData();//获得信的内容

      int offset=letter2.getOffset();

      int length=letter2.getLength();

   String str=new String(data,offset,length);//转换成字符串读取   

      System.out.println(str);

      ds.close();

      }

}

 

 

 

 

 

 

在服务端

import java.net.*;

public class UDPServer {

public static void main(String[] args) throws Exception{

DatagramSocket ds=new DatagramSocket(9000);//服务端口

      while (true) {

      byte[] bs1 = new byte[100];

      DatagramPacket letter1 = new DatagramPacket(bs1, 0, bs1.length);//制做空信封用来收信

      ds.receive(letter1);

      InetAddress address = letter1.getAddress();

      int port = letter1.getPort();

      String str = "北京2008年举行奥运会";

      byte[] bs2 = str.getBytes();

DatagramPacket letter2 = new DatagramPacket(bs2, 0, bs2.length,address, port);//得到客户端的ip和port而后将信息发给客户端

      ds.send(letter2);

           }         

          

      }

 

 

DatagramSocket至关是邮箱有send(发消息)receive(收消息)

DatagramPacket,至关是信,里面有ip端口,信息内容

============jdk1.5新特性===============

1,  可变参数 至关一个数组 m(String …s)一个方法只能有一个可变参数,且只是最后一个参数

2,  Foreach循环(for(object o:list))方便遍历数组和集合

3,  枚举

enum Course{

      UNIX ("Luxw") {

           public void study(){}

      },

      COREJAVA ("Huxz"){

           public void study(){}

      };

  Public void study();

}

使用:

class test { Course [] cs=Course.values(); for(Course c:cs ){System.out.println(s.ordinal+s+s.getName())}}

注意的问题:1枚举值之间用逗号隔开,最后一个用分号2枚举中能够有抽象,但必须在枚举值中实现;

4,  泛型 泛型解决集合中不安全性,泛型强制集合中都是一个类型

List<Integer>  l=new ArrayList<Integer>();Map<Integer,String> m=new HashMap<Integer,String>();

泛型方法:public static <T> void copy(List<T> l,T[] os){ for(T o:os){l.add(o);}}

                          <T extends Integer> <? Extends Integer>

5,反射  类对象,类加载时把类的信息保存在jvm中就会产生一个相应的对象(记录类信息的对象),只要类对象存在则类信息就在

  得到类对象应用的三种方式:

           ①Class c1=ArrayList.class; ②Object l=new ArrayList();Class c2=l.getClass();

           ③String className="java.util.ArrayList"; Class c3=Class.forName(className);

           Class[] cs=c1.getInterfaces();//得到接口

           Class c=Animal.class;

           Field[] fs=c.getDeclaredFields();//得到属性的数组

           Method[] ms=c.getDeclaredMethods();//得到本类全部公私有的方法,getMethods()得到父类全部公开的方法

           Constructor[] cons=c.getDeclaredConstructors();//得到构造方法的数组

           Object o2=c.newInstance();//建立类的对象

           Method m1=c.getDeclaredMethod("study");//找到方法名是study的方法

           m1.setAccessible(true);//设置为能够调用

           m1.invoke(o2);//调用m1方法

           Method m2=c.getDeclaredMethod("study", String.class);

           m2.setAccessible(true);

           m2.invoke(o2,"CoreJava");//调用m2的方法,方法的参数是CoreJava

 

 

6,注释,===注释是一种类型(总共有四种类型:类,接口,枚举,注释)

 

 

定义注释

如:@Override;

标记:@注释名

单值:@注释名(属性名=属性值)

多值:@注释名(属性1=值1,属性2=值2,......)

 

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target()

public @interface MyType {
 String authorName();
 String lastModified();
 String bugFixes() default "ok";
 }

在类中应用注释:

import java.lang.annotation.*;
@MyType(authorName="hadeslee",lastModified="20061207")
  public class Test1 {
  /** Creates a new instance of Test1 */
  public Test1() {
  }
  @Deprecated
  @MyType(authorName="hadeslee",lastModified="20061207",bugFixes="what")
  public void doSth(){
  }

 

 

这里我定义了一个我本身的注释类,声明方式和声明接口差很少,只不过在interface前面多了一个@符号.
注释类也能够用注释类注释,如此下去.
@Retention(RetentionPolicy.RUNTIME) 这句表示它的保存范围是到RUNTIME,也就是运行时,这样在类运行的时候,咱们也能够取到有关它的信息.

@Target() 这句表示它的适用对象,它能够用在哪里地方,我这里定义的是它能够用在类的定义和方法的定义上
而后咱们看咱们是怎么为咱们写的类加上注释的

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

OOAD思想

 

1继承关系:指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并能够增长它本身的新功能的能力,继承是类与类或者接口与接口之间最多见的关系

 

2关联关系

①   关联关系是对于两个相对独立的对象,当一个对象的实例与另外一个对象的一些特定实例存在固定的对应关系时,这两个对象之间为关联,关系是使用实例变量实现的,好比公司和职员

②   聚合关系是关联关系的一种,他体现的是总体与部分、拥有的关系,此时总体与部分之间是可分离的,他们能够具备各自的生命周期,部分能够属于多个总体对象,也能够为多个总体对象共享;好比计算机与CPU、公司与员工的关系等;表如今代码层面,和关联关系是一致的,只能从语义级别来区分,它也是经过实例变量实现的,在java语法上是看不出来的,只能考察类之间的逻辑关系

③   组合也是关联关系的一种特例,他体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合;他一样体现总体与部分间的关系,但此时总体与部分是不可分的,总体的生命周期结束也就意味着部分的生命周期结束;好比你和你的大脑;表如今代码层面,和关联关系是一致的,只能从语义级别来区分

④   依赖关系是类与类之间的链接,依赖老是单项的(人和车,人和房子),依赖关系在java中体如今局部变量,方法的参数,以及静态方法的使用。在A类中的方法中使用B类的引用

 

 

 

代码表示

 class A{

   B b;//聚合

C c=new C();//组合

Public A(B b){this.b=b;}

Public void ect(D d){ d.m(); //依赖}

}

class D{void m(){}}

 

 

 

在UML图形表示[U12] 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ORACLE


第一天:====================

1,     关系数据库的三要素: 1实体----》表(存放数据)

                          2属性---》列

                          3关系---》外键

2,    sqlplus经常使用命令

   help index
能够看到全部的命令,
不会的命令用:
help <命令>;例如:help list

exit       退出SQL*PLUS

desc 表名    显示表的结构

show user    显示当前链接用户

show error    显示错误

show all     显示全部68个系统变量值

edit       打开默认编辑器,Windows系统中默认是notepad.exe,把缓冲区中最后一条SQL语句调入afiedt.buf文件中进行编辑

edit 文件名   把当前目录中指定的.sql文件调入编辑器进行编辑

clear screen   清空当前屏幕显示

 

SQLPLUS到ORACLE的运行图(见笔记本)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  select  columnname(列名)

  1)  select *

  2)  select id,last_name,dept_id

  3)  select id,last_name "Name",salary*12 anual

  4)  select last_name||' '||first_name

       //若是comm为null时,nvl(comm,0)等于0;不然等于comm;

  5)  select  last_name,salary*(1+nvl(comm,0)/100) 

  6)  select distinct last_name,first_name 

 

  from  tablename 

  预约义:  做用的时间长   全部的叫这个列名的列都生效

  sql:   当次生效    当前sql的当前表      

 

  order by:

  select id,last_name,dept_id

  from s_emp

  1)order by dept_id;

    order by title;

  2)order by last_name,dept_id;  

    先按名字升序排,名字相同再按dept_id升序排  ,中间用“ ,  ”隔开;

  3)order by last_name desc;

    order by dept_id,last_name desc;

    dept_id升序,last_name降序

  4)null

    在oracle里是最大,也就是升序的时候放在最后面;

  5)order by 2;  <=======> order by last_name

    select * 里面的第二列

  6)select id,last_name name

    from s_emp

    order by NAME;    

==============================================  select           from         where         order by

 

  select id,last_name,dept_id,start_date

  from s_emp

1)where  dept_id=41;

    where last_name='Smith';   ---->字符串区分大小写,SQL命令不区分大小写;

    where start_date='08-mar-90';       

  2)where salary>1000;

  3)where dept_id between 41 and 45;

    包括边界值

    where dept_id between 45 and 41;  //小的在前,若是反了,查不出记录  

    //dept_id的值只能是41,43,45三个数中的一个,且三个数都会被计算一次。

  4)where dept_id in(41,43,45);

  5)where commission_pct=null;    查不出记录

    where commission_pct is null;    

  6)where last_name like 'S%';

      unix:   *    ?

      oracle: %    _ (下划线)

    查出last_name是以'S_'

    where last_name like 'S_%';  ----> error

    where last_name like 'S\_%' escape '\';       //escape '\'表示“\”为换码字符;

  7) 非

    !=  <>

    not between  and

    not in

    not like

    is not null

  8)and > or

    where dept_id=41 and id>5;   

    where dept_id=41 or id>5; 

    ----->where salary>1000 

              and dept_id=41

              or dept_id=42;

    ----->where salary>1000 

              and (dept_id=41

              or dept_id=42 ); 

    ----->where dept_id=41

             or dept_id=42

             and salary>1000;

select s_customer.name,s_emp.last_name

from

s_customer,s_emp

where s_emp.id(+)=s_customer.sales_rep_id;              

//(+)让员工表补个空值。为的是让全部的客户都有对应的员工

//,由于有些客户没有对应的销售表明,因此设为空

 

        

 

 

 

 

=================================================================================================


次日:

Single Row Function:

 varchar2:

   1)  nvl('hello','world')-----> 'hello'

       nvl(null,'world')--------> 'world'

   2)  select id,last_name,dept_id

       from s_emp

       where lower(last_name)='smith';

   3)  select id,concat(last_name,first_name),dept_id

       from s_emp;

       concat(last_name,first_name)--->result1;

       concat(result1,title);

       --> concat(concat(last_name,first_name),title);

       System.out.println(stu.toString());

           select substr('String',-4,3)

       from dual;

       dual: dummy table ,为了维护select的完整性 

            select id,last_name,dept_id

       from s_emp

       where last_name like 'S%';

       where substr(last_name,1,1)='S';

number: round  trunc

  date:日期类型

    1) select sysdate from dual; 

标准的日期格式:

  年:  yy        08

       yyyy      2008

       rr        08

       rrrr      2008

       year      two thousand and eight

  月:  mm        06

       mon       JUN

       month     june

  日:  dd        19

       ddth      19th

       ddsp      ninteen

       ddspth    ninteenth

 星期: d         4

       dy        thu

       day       thursday

 小时: hh24    22

       hh      10

       am  pm       

 分钟: mi         秒: ss   

  select id,last_name,dept_id,

    to_char(start_date,'yyyy-month-dd,hh24:mi:ss') "sdate"

 from s_emp

 where dept_id=41;

 

 update s_emp

 set start_date=to_date('19-jun-08,11:24:56','dd-mon-yy,hh24:mi:ss')

 where id=100;              

 

 update s_emp

 set start_date=to_date('19-jun-90','dd-mon-yy')

 where last_name='S_abc'; 

 

 select id,last_name,to_char(salary,'$99,999.00')

 from s_emp;     

 

 select id,last_name,

   to_char(start_date,'fmdd-mm-yyyy,fmhh:mi:ss') "sdate"

 from s_emp;      

 

 fm:在不引发歧义的状况下去掉前置的零和空格

    相似于开关变量,第一次写打开功能,再写关闭

 

 Join:数据来源于多张表,叫多表联合查询,多个表之间要作链接

   1.等值链接(内链接)  条件:  fk-----pk

     select s_emp.last_name,s_emp.dept_id,

            s_dept.id,s_dept.name

     from s_emp,s_dept

     where s_emp.dept_id=s_dept.id; 

     

 

     oracle:select e.last_name,e.dept_id,d.id,d.name

            from s_emp e,s_dept d

            where e.dept_id=d.id;   

           

    标准sql:select e.last_name,e.dept_id,d.id,d.name

            from s_emp e inner join s_dept d  

            on e.dept_id=d.id

            where e.last_name='Smith';  

           

            select e.last_name,e.dept_id,d.id,d.name

            from s_emp e join s_dept d  

            on e.dept_id=d.id

            where e.last_name='Smith';       

    

     打印出员工的名字,所在部门的名字,以及所在地区的名字

     select e.last_name,d.name,r.name

     from s_emp e,s_dept d,s_region r

     where e.dept_id=d.id

       and d.region_id=r.id; 

      

     select e.last_name,d.name,r.name

     from s_emp e join s_dept d

       on e.dept_id=d.id

       join s_region r

       on d.region_id=r.id;

 

  2.外链接(左外,右外,全外)

 

    打印全部的客户名字,以及所对应的销售表明的名字 

   

    1)左外:若是左边对应的右边的值为空时,右边补null

    oracle:select  c.name,c.sales_rep_id,e.id,e.last_name

                          from s_customer c,s_emp e

                          where c.sales_rep_id=e.id(+);  

   标准sql:select c.name,c.sales_rep_id,e.id,e.last_name

           from s_customer c left outer join s_emp e

           on c.sales_rep_id=e.id;

   

    2)右外  :若是右边对应的左边的值为空时,左边补null

    select  c.name,c.sales_rep_id,e.id,e.last_name

    from s_customer c,s_emp e

    where  e.id(+)=c.sales_rep_id;    

   

 select c.name,c.sales_rep_id,e.id,e.last_name

    from s_emp e right join s_customer c

    on c.sales_rep_id=e.id;

   

    3)全外 :都不补空值(null)

     select c.name,c.sales_rep_id,e.id,e.last_name

     from s_customer c full outer join s_emp e

     on c.sales_rep_id=e.id;  

    

 3.自链接: 本表的fk指向本表的pk

   能够给表起不一样的别名,再作链接。

   打印出员工的姓名和他的经理的名字

   select e.last_name,m.last_name

   from s_emp e,s_emp m

   where e.manager_id=m.id;

 

   打印出全部员工的姓名和他的经理的名字

select e.last_name,m.last_name

from s_emp e,s_emp m

where e.manager_id=m.id(+); 

  

 4.非等值链接(t1和t2没有pk和fk,还想链接t1,t2)

     table1: id    value

              1      A

              2      B

              3      C

              4      D

     table2: id    value

              1      A

              2      B

              3      C

              4      D

     请写出一句sql语句,打印输出

     AB AC AD BC BD CD 

    

     select  t1.value,t2.value

     from  table1 t1,table2 t2

     where t1.id<t2.id;

    

     请写出一段sql语句,打印输出

     AB AC AD BA BC BD CA CB CD DA DB DC

     select  t1.value,t2.value

     from  table1 t1,table2 t2

     where t1.id!=t2.id;

    

   5.笛卡儿链接(不给链接条件)

    

     请写出一段sql语句,打印输出

     AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD

    

     select t1.value,t2.value

     from table1 t1,table2 t2;  

    

 SubQuery:

1.请打印出和Smith在同一部门的员工的姓名,

start_date,dept_id

     1) select dept_id

        from s_emp

        where last_name='Smith'; -----> result1

        select last_name,dept_id,start_date

        from s_emp

        where dept_id=result1;   

       

     2) select last_name,dept_id,start_date

        from s_emp

        where dept_id=(

             select dept_id

             from s_emp

             where last_name='Smith');  

                                                  

   2.主查询和子查询靠值联系

     1) 值的类型要相同

        select last_name,dept_id,start_date

        from s_emp

        where dept_id=(

             select last_name

             from s_emp

             where last_name='Smith');  

 

     select last_name,dept_id,start_date

        from s_emp

        where dept_id=(

             select salary

             from s_emp

             where last_name='Smith');

 

 select last_name,dept_id,start_date

        from s_emp

        where dept_id=(

             select id

             from s_region

             where id=1);    

 2)值的个数要一致

       select last_name,dept_id,start_date

        from s_emp

        where dept_id=(

                       select dept_id,last_name

                                from s_emp

                       where last_name='Smith');

 

     select last_name,dept_id,start_date

        from s_emp

        where dept_id=(

             select dept_id

             from s_emp

             where last_name='Smith'

            or id=3);  ---->error

        --->改进

        select last_name,dept_id,start_date

        from s_emp

        where dept_id in (select dept_id

                                         from s_emp

                                         where last_name='Smith'

                     or id=3);

                    

     sql----->dbsv

     1)编译

        a.权限检测

        b.语法检测

        c.sql翻译成内部指令

     2)运行内部指令

    

  3)哪些地方能够用子查询

   须要值的地方就能够用子查询

   1)select         不能够

     from           能够(须要表的时候在这里写子查询)

     where          能够(须要值的时候在这里写子查询)

     order by        能够(按select里列的下标值排序 ,如:order by 2)

     group by                 不能够

     having                     能够(跟where用法同样)

     select *

     from (select e.last_name,e.dept_id,d.id,d.name

           from s_emp e,s_dept d

           where e.dept_id=d.id) e;

          

          

 jobs:

  1.SQL-1.pdf  (4)

 

      2.请打印出公司入职最先的五个员工的姓名(last_name),dept_id,start_date

select *

from (

         select last_name,dept_id,start_date

         from s_emp

         order by start_date

) e  

where rownum  between 1 and 5;

       

 

 

      伪列:rownum(表明显示在界面上的行号,数据库自己不提供,查询时会默认的提供,只有在select中显示的写rownum,才会显示行号;)

      rowid(数据库里自己就有的,表明在数据库里存的物理地址)

      select * from s_dept;

      desc s_dept;

 

      分页:子查询和rownum

        打印表里面第五到第十条记录:

select last_name dept_id,start_date

from(

select e.last_name,e.dept_id,e.start_date,rownum rownumid

         from(

                   select last_name,dept_id,start_date

                   from s_emp

                   order by start_date

         ) e

         where rownum between 1 and 10

) a

where a.rownumid between 6 and 10;

 

 

 

 


第三天:===================================

 Group function(组函数):

  1) select avg(salary),max(salary)

     from s_emp;

     select count(*) from s_emp;

     select count(id) from s_emp;

     select count(commission_pct) from s_emp;

     统计commission_pct列不为空的值的个数;

     number: max  min  sum  avg  count

     date:   max  min  count

     char:   max  min  count    

  2) select dept_id,avg(salary),count(*)

    from s_emp

    group by dept_id;

    select   from    where   group by   order by

    select dept_id,avg(salary)

    from s_emp

    where dept_id in (41,50)

    group by dept_id;

   

 3) 当select里面出现组函数和单独的列并存时,要求必须

    写group by子句,而且单独的列必须出如今group by里面

    select dept_id,avg(salary)

    from s_emp

    group by dept_id;      

    select salary,avg(salary)

    from s_emp  

    group by salary;

   

    若是group by里出现多列,那么按照列的联合分组,

    只有多列的值彻底相同才会分到一组

    select last_name,first_name,avg(salary)

    from s_emp

    group by last_name,first_name;

请打印出工资低于公司平均工资的人的姓名,

dept_id,start_date

    select last_name,dept_id,start_date

    from s_emp

    where salary<(select avg(salary) from s_emp ); 

4) 只要写group by,那么select里单独列必须出如今

    group by里

    select dept_id,last_name,start_date

    from s_emp

    group by dept_id,last_name,start_date;

5)where执行时数据处于独立个体状态,里面不能对组函数

   进行判断,只能对单独记录判断

   having必定出现group by后面,此时数据处于组的状态

   因此having只能对组函数或者组的共性进行条件判断,

 

   请打印出部门平均工资大于1500的这些部门的id以及平均工资

   select  dept_id,avg(salary)

   from s_emp

   where avg(salary)>1500

   group by dept_id;     ------>error  

  ====================================

   select  dept_id,avg(salary)

   from s_emp

   group by dept_id       

   having avg(salary)>1500;   

  

   select  dept_id,avg(salary)

   from s_emp

   group by dept_id  -------> group      

   having salary>1000;   ----->整个组  error   

  

   select  dept_id,avg(salary)

   from s_emp 

   group by dept_id

   having dept_id>40;

  

   select  dept_id,avg(salary)

   from s_emp   

   where dept_id>40

   group by dept_id ; 

  

 6) order by 列名,2,别名;

    原来对order by里的列没有任何限制,只要表里有就能够

    select  from   where   group by  having  order by

    在order by以前若是出现了group by,那么order by里面

    就只能按照组函数或者是组的共性排序

     eg: select dept_id,avg(salary)

        from s_emp

        where dept_id > 40

        group by dept_id

        having avg(salary)>1000

        order by last_name; ------>error

        order by max(last_name); ---->correct

        order by dept_id;    -------->dept_id    

  做业: 请打印出工资低于本部门平均工资的员工的姓名,

         dept_id,start_date 

       select dept_id,avg(salary) asalary

        from s_emp

        group by dept_id;   ---->a1

      select e.last_name,e.dept_id,e.start_date

        from s_emp e,a1

        where e.dept_id=a1.dept_id

          and e.salary<a1.asalay;

    --->select e.last_name,e.dept_id,e.start_date

        from s_emp e,(

             select dept_id,avg(salary) asalary

                                from s_emp

                                group by dept_id

                  ) a1

        where e.dept_id=a1.dept_id

          and e.salary<a1.asalary;       //数据库表和表链接的时候,比较的是同一元组;

  

 

      

 Define  Variable

 1. select last_name,dept_id,start_date

    from s_emp

    where dept_id=&did; 

    where last_name=&name;

    where last_name='&name';     

 2.预约义 

   1) define varname=value

      define did=41

       简单,定义出来的变量都是char类型  

      不能写进sql文件

      查询一个数是否已经预约义用define varname

      取消用undefine varname

   2) accept varname type prompt '   ' hide    //单独一句话,为的是永久性的给varname一个值

  accept did number prompt 'please input dept_id value:' hide

      accept did prompt 'please input dept_id value:'----> char

     

     比define复杂, 能够指定变量的类型,能够写进  .sql 文件,

     在bash下:1)进入csh;

                2)setenv EDITOR VI ;

                3)sqlplus 进入SQL的用户名和密码;

                                    4)写一个要保存进文件的命令;

                5)save sqlfile;

     6)ed   进入vi编辑命令,在最上面加上(accept varname type prompt '   ' hide)语句;

      7)ZZ(保存并退出vi);                 

      8)start sqlfile.sql就能够运行刚才保存的命令了。

                

下面是用于实验预约义的

/*select e.last_name

from s_emp e

where e.dept_id='&deptid';

accept deptid number prompt 'please input dept_id value:' hide

*/      

3) define varname   查看状态

      undefine varname  取消预约义      

3.哪些地方能够用变量定义:

   select            

   from

   where              所有能够

   group by

   having

   order by   

  

   select &col1,&col2,&col3

   from &tab1

   where &con1; 

 

    =======================================================================================


 第四天:

Create table:

 1.db structure

   1)table---> store data             2)view----> select              3)sequence            4)index

 2.create table luxw1

   ( id number(7),

     name varchar2(15),

     registdate date

   );       

   create table luxw2

   (id number(7),

    film blob

   );

    

   1)列一级约束

   create table yesq5

   ( id number(7) constraint yesq5_id_pk primary key,

     name varchar2(15) constraint yesq5_name_nn not null,

     age number(3) constraint yesq5_age_ck_age check(age>18 and age<60),

     sex varchar2(2) default 'M' constraint yesq5_sex_ck_sex check( sex in('F','M') ),

     birthday date default sysdate,

     phone varchar2(15) constraint yesq5_phone_uk unique,

     personid char(18)

       constraint yesq5_personid_nn not null

       constraint yesq5_personid_uk unique,

     class_id number(7) constraint yesq5_class_id_fk references s_dept(id) on delete cascade

   ); 

   2)表一级约束

   create table yesq5

   ( id number(7),   

     name varchar2(15) constraint yesq5_name_nn not null,

     age number(3),

     sex varchar2(2) default 'M',

     birthday date default sysdate,

     phone varchar2(15),

     personid char(18) constraint yesq5_personid_nn not null,

     class_id number(7),

     constraint yesq5_id_pk primary key(id),

     constraint yesq5_age_ck check( age>18 and age<60),

     constraint yesq5_sex_ck check( sex in('M','F') ),

     constraint yesq5_phone_uk unique(phone),

     constraint yesq5_personid_uk unique(personid), 

     constraint yesq5_class_id_pk foreign key(class_id) references s_dept(id) on delete cascade

   );

   五种约束:  无约束的地方不用写constraint。

   1) not null

   2) unique

   3) primary key

   4) foreign key  references (on delete cascade)

   5) check

 两种位置定义约束的      区别:

   1) 约束前面是逗号就是表一级,

      约束前面是空格就是列一级;

 2) not null只能定义在列一级

   3) 联合键只能定义在表一级

      eg:联合惟一: unique(last_name,first_name)

   联合主健: primary key(product_id,order_id)     

  on delete cascade:该句在子表最后声明时,说明他的数据随外键的消失而消失

   删除父表记录

  1)写了on delete cascade

    sql: delete from fathertable where id=1;

  2)没写on delete cascade  

    sql: delete from sontables where fk=1;

         delete from fathertable where id=1;   

         

 3 用子查询建表          

  1) 表的列名,列数,类型靠子查询定

     create table luxw04

     as

       select id,last_name,dept_id,start_date

       from s_emp

       where dept_id in(41,42);

              

     create table asalary

     as 

        select dept_id,avg(salary)

        from s_emp

        group  by dept_id; 

 

 

 

  2) 主sql规定了列名,列的个数,不能定义列的类型

     在建表过程当中只保留了非空(not null)约束,其余约束丢失  

     create table asalary

     (did,avgsal)

     as

       select dept_id,avg(salary)

        from s_emp

        group  by dept_id;   

  3) 能够制定约束

     create table luxw06

     (id primary key,

      last_name,

      dept_id references s_dept(id),

      start_date default sysdate

     )

     as

       select id,last_name,dept_id,start_date

       from s_emp

       where dept_id in(41,42);  

         

  约束和数据的关系:

  谁先进入表,谁说了算    

 

 Data dictionary(表的集合):

  1) 表:存放描述数据库状态的数据 

        db server在建库时创建

        由db server维护,在线动态更新

        user只能查询

  2)user:由用户建立的 ,属于这个用户的。

    all: 用户有权使用

    dictionary: 保存了全部数据字典的名字,和描述信息

   

  3)查出yesq5表personid列上的惟一性约束的名字

    用到下面这两个表:

    user_constraints

    user_cons_columns

   

    select cons.constraint_name,cons.constraint_type,cols.column_name

    from user_constraints cons,user_cons_columns cols

    where cons.constraint_name=cols.constraint_name

      and cons.table_name='YESQ5'

      and cols.column_name='PERSONID'; 

     

DML:

  insert:

  * 1) 全表插入,值的顺序,类型,个数必须和表里的列一致

      insert into luxw8

      values(1,'zhangsan','m','12-sep-98');

      insert into luxw8

      values(2,'lisi','f',null);

      insert into luxw8

      values(3,'wangwu','f', to_date('23-06-08','dd-mm-rr'));        

         

      insert into luxw8

      values(4,'lisi','f',&da); 

     

  * 2)选择插入,列的个数,类型,顺序必须和指定的相等

     选择时非空的列必须出现

insert into luxw8(id,name,sex)

     values(5,'huxz','m');

 

     insert into luxw8(name,id)

     values('wangwu',6);

    

     insert into luxw8(name,sex)

     values('liucy','m');     ----->error 无PK        

   3)insert into luxw8(id,name)

     values('7','liucy')

     values('8','luxw');    ---->error    不能同时添加两个数据

     insert into luxw8(id,name)

     values(&idd,&na);  

    

   子查询提供值,值的类型和个数要匹配

     insert into luxw8(id,name)

     select id,last_name

     from s_emp

     where dept_id=45; 

update:

   1) update  luxw8

      set name='sun'

      where id=1;

   2)update  luxw8

      set name='fengwang',sex='m',registdate=sysdate

      where id=2;

delete:

   delete from luxw8

   where id between 2 and 5;  

  

 Transaction(事务):必须具备原子性

 

 ACID

 A:原子性,加钱和减钱都要成功或都失败,保持原子性;

 C:一致性,数据一致性,如:A向B转账5000块,那B就应该收到5000块,不能多也不能少;

 I:隔离性,两个SQL语句的操做只操做本身的,不能影响到另外一个语句,也就是至关于每一个SQL都要有本身的回滚段;

 D:持久性,数据的改变用commit或用rollback,让数据持久化;

 

  1) 一组不可再分的sql命令组成的集合,   若是分了数据将不统一,如:银行转账

     事务的大小跟业务需求有关

  2) 事务结束时结果

     success:   commit   回滚段内的数据写到FILE,锁释放,其它用户也能够看到结果

     fail:      rollback   清空回滚段内容,没写到FILE,锁释放,其它用户看不到修改的值,

  3)

     insert update  delete update  delete commit;

     create--->auto commit;

     insert

     update

     delete

     create --->auto commit;

     insert

     update

     rollback;   

     insert update delete  exit      

 

        

 

 

 

 

 

 

 

 

============================================================================

 

 

  第五天: 

DDL:

 alter:改表结构

 1)增长一列,添加到表的最后一列

   alter table luxw8

   add(age number(3) default 18 check(age<40)); 

  

 2)删除一列(在oracle8i)

   alter table luxw8

   drop (age,registdate);

  

   alter table luxw8

   drop column age;

 

 3)更改列名(在oracle9i)

   alter table luxw8

   rename column oldname to newname;   

 4)更改列(类型,size,添加约束,添加默认值)

   alter table luxw8

   modify(name varchar2(20) default user unique);

   若是表里没有数据,随便改

   若是表里有数据,改的时候必须符合表里的数据

   alter table luxw8

   modify(sex not null);  

   非空约束只能用modify子句加

  

 5)添加约束

   联合键约束加的时候只能用add子句

   alter table luxw8

   add unique(personid);

   alter table luxw8

   add constraint luxw8_personid_uk unique(personid);

  

        当A表的PK是B表的FK且B表的PK是A表的FK时,

        只能先让一个表(A表)的FK为空,再用add以表结构向该表(A表)添加FK,以下:

   create table product

   ( id number(7) primary key,

     name varchar2(15) not null,

     price number,

     b_id number(7)

   );

   create table bid

   ( id number(7) primary key,

     userid number(7) references users(id),

     bprice number,

     product_id number(7) references product(id)

   ); 

   alter table product

   add foreign key(b_id) references bid(id);

  

 6)删除约束

   alter table luxw8

   drop constraint luxw8_personid_nn ;

   alter table luxw8

   drop primary key cascade;

        

  7)失效约束

   alter table luxw8

   disable constraint luxw8_personid_uk;

  

   alter table luxw8

   disable constraint luxw8_id_pk cascade;

级联失效

 

 

8)生效约束

   alter table luxw8

   enable constraint luxw8_personid_uk;

   alter table luxw8

   enable constraint luxw8_id_pk;

   生效时没法级联,只能手动一个一个作   

rename oldtablename to newtablename     改表名

 truncate table tablename;  截取表 

drop table tablename cascade constraint;

 删除父表,而且级联删除子表的外键约束

Sequence:

   数据库提供的产生一系列惟一值的对象,用来生成主键值;

   它是数据库里独立的对象,不依赖任何表

 

 1)create sequence seq1

   increment by 1   //每次递增1

   start with 100              //从100开始计数

   maxvalue 99999          //最大值为99999

   nocycle             //无循环

   nocache;    //没有缓冲

   

   create sequence sql_seq

       increment by 1

       nocycle;

  

2) nextval:

       若是有cache取出cache下一个可用的值

       若是没有cache,取出序列下一个可用的值

                insert into  sql_users(id,name,passwd,phone,email)

                values( sql_seq.nextval,'wangwu','123456abc', 12321,'kdfdfk@gmail.com');

               

                select seq2.nextval

                from dual; 

                 

    currval:当前的链接最后一次使用序列的值

        select seq1.currval

        from dual;

       

   last_number(column):序列下一个可用的值

        select last_number

        from user_sequences

        where sequence_name='SEQ2';  

       

 3)改序列

   alter sequence seq1

   increment by   maxval   minval   cycle    cache

   序列的起始值不可能改变    

  

 4)删除序列

   drop sequence seq1;

  

 5) insert  insert insert rollback; 

    只能朝前走                     

==========================================

 view:

   起了名字的查询语句

   1) create view emp_v1

      as  select id,last_name,dept_id

          from s_emp;

    

     select * from emp_v1;   

    

     简化select语句的复杂度

     限制数据的显示

     节省空间

  

 

 

   2) 复杂视图:里面包含了函数,链接,组函数 

          不能应用DML(增删改),只能查询

      简单视图:      

               

      create view emp_v3  

      (dept_id,asalary)

      as

         select dept_id,avg(salary)

         from s_emp

         group by dept_id;

        

     update emp_v3

     set asalary=1111

     where dept_id=41;   ---->error

  

  3)create view emp_v4

    as

      select id,last_name,dept_id

      from s_emp

      where dept_id=41

with check option constraint emp_v4_ck; //表示该视图(emp_v4)里的数据没法删除或改变,但能够添加数据

  

  

   建立数据库用户:

 create user username identified by password

 default tablespace users

 temprory tablespace temp;

 

 alter user username identified by newpassword;

 

 grant resource,connect to username;

 grant create view to cksd0804;

 

 revoke create view from cksd0804;        

 

 

  至少掌握数据库如下四点:

     1)crud(增删改查)

     2)create table(建表)

     3)transaction(事务)

     4)create sequence   //sequence:序列

 

 JDBC跟下面有很大的联系:

 1  interface

 2  try catch  finally

 3  thread

 4  static{}

 5  socket (url)

 6  encapsulation inheritance poly...   javabean  

 7  collection  map

 

 

 创建表空间  
       create   tablespace   si   datafile   '/u/oradata/en73/si.dat'   size   70M     online  
          default   storage   (   pctincrease   2   );  
  创建用户  
       create   user   zhangwf  identified   by   pwd  default   tablespace   si   temporary   tablespace   si;  
  给用户受权  
       grant   dba,   connect,   resource,   create   table   to   si;  
  创建表在用户SI上  
      create   table   si.tbname(col1   int,col2   varchar2(10));  

修改密码:alter user zhangwf  identified by   newpwd

 

 

 

 

 

 

 

 

考点:行列转换, 重复数据的过滤,索引的创建

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

JDBC笔记


第一天:

  OracleDriver{

     public void connectOracle(){

         ......

     } } 

  DB2Driver{

     public void connectDB2(int i){}

  }                

  telnet 192.168.0.200 

  Unix,Linux: echo $ORACLE_SID      在Unix和Linux下查看链接的哪一个ORACLE

  windows:  net start       在windows下查看链接的哪一个ORACLE

  username

  passwd

  DriverManager.getConnection();

  class OracleDriver implements Driver{ //OracleDriver类的大致实现

     static{  

        OracleDriver d=new OracleDriver();

        DriverManager.addDriver(d);

     }

  }

  class DriverManager{     //DriverManager类的大致实现

     private static List<Driver> dri=new ArrayList<Driver>();

     public static void addDriver(Driver d){

        ......

        dri.add(d);

     }

     public static Connection getConnection(){

        for(Driver d:dri){ 

           if(d!=null)  return d.getconnect();

        }

     } }      

  boolean execute(sql) ---> all  

     boolean 有没有ResultSet返回

     true:有      false:没有

     rs=stm.getResultSet();

  ResultSet executeQuery(sql){}-----> select

  int executeUpdate(sql){} -----> insert update delete

  运行程序可能出现的下面几种异常:

  1 Class not found 

    -------> ojdbc14.jar 

  2 No suitable Driver

    ----->url

  3 Socket Exception 

    ping 200

  4 SQLException ---->  sql

   table: jdbc_users

   sequence:  jdbc_users_seq

   driver=oracle.jdbc.driver.OracleDriver

         url=jdbc:oracle:thin:@192.168.0.200:1521:oradb10g

         username=cksd0804

         password=cksd0804             

         BufferedReader

         1)String str=br.readLine();

         2)String[] s=str.split("=");

         3)if(s[0].equals("driver"){}

         以上三步至关于如下两步:

         Properties info=new Properties();

         info.load(Inputstream);                //表示(1)加载输入流,(2)读取文本内容,(3)解析文本文件,//(4)再存入Properties集合

.properties ------> Map<String,String>

     ------>Properties extends Hashtable<String,String>

JdbcUtil.class.getResourceAsStream("/com/kettas/jdbc/cfg/config.properties");  //为虚拟路径,第一个/表明classpath

/com/kettas/jdbc/cfg/config.properties

  /<====>classpath

 /home/java/jdbc/.....  //全路径

 Student s=new Student();

 第一次加载类时,JVM加载类的顺序:

 1. search file ---->Student.class    经过classpath寻找类文件

    path---->command

    classpath--->.class

 2. read Student.class  读取类文件

 3. Class c----> 得到Student类详细信息(类对象)

Student s2=new Student();  

  .class----> jdbc.jar--->user--->classpath

  1 分散代码集中管理(封装)

  2 变化的内容写进文件(配置文件)             

配置文件通常格试:config.xml和config.properties

  3  .properties  (是一种特殊的文本文件)

  4  Properties   (是Hashtable的子类)

  5  ExceptionInInitializerError

  6  Class.getResourceAsStream( 虚拟路径 )

1. jdbc 六个步骤

     1)注册Driver;

Class.forName("oracle.jdbc.driver.OracleDriver");

     2)得到链接

 String url="jdbc:oracle:thin:@192.168.0.200:1521:oradb10g";

Connection conn=DriverManager.getConnection(url,"用户","密码");

     3)建立Statement,stm=conn.createStatement();

     4)执行sql,      stm.executeUpdate(sql);

     5)select--->处理结果集

ResultSet rs=stm.executeQuery(sql);

while(rs.next()){            System.out.println(rs.getInt(1)+"------"+rs.getString(2));

          }

     6)释放资源(rs,stm,conn)

      if(rs!=null)  try{ rs.close();} catch(Exception ee){}

         if(stm!=null)  try{ stm.close();} catch(Exception ee){}

         if(conn!=null) try{ conn.close();} catch(Exception ee){}

  2. 注册Driver的三种方式   

     1)Class.forName("oracle.jdbc.driver.OracleDriver");

     2)Driver d=new oracle.jdbc.driver.OracleDriver();

       DriverManager.registDriver(d);

     3)程序里没有指定

 java-Djdbc.drivers=oracle.jdbc.driver.OracleDriver classname

  3. ResultSet遍历 

     1) next()---->boolean

     2) get***(int)   get***(columnname) 

        eg: getString("name");

开始时指针指向第一行的上一行,最后指针指向最后一行     的下一行

  4. 三种execute方法的区别

     1)stm.execute(sql)   all   boolean(ResultSet)(返回布尔型,判断是否有结果集)

     2)stm.executeQuery(String selectsql) --->ResultSet(返回结果集,sql是查询语句)

     3)stm.executeUpdate(sql)  --->int(db row)  (返回int,判断改变的行数,通常执行,update,delete,insert)

       ---->delete update  insert 

 

 

Statement和PreparedStatement

  Statement是逐条发送语句(能够执行多条语句),PreparedStatement是先存储sql再一块儿发送(在sql须要设值的时候,效率要高,但只能执行一条语句)例子:

String sql=

"insert into jdbc_users(id,name) values(users_seq.nextval,? )";

pstm=conn.prepareStatement(sql);

pstm.setString(1, names[i]);//1表明是提几个问号,后面是设值

pstm.executeUpdate();一块儿提交

  5.JdbcUtil类

     1)分散代码集中管理(封装)

     2)常常变化的写进文件(配置文件)

       config.xml        config.properties

  3)Properties extends Hashtable<String,String>

       专门处理properties文件,提供load(InputStream is)

     4)在程序加载时读一次文件,因此读文件的代码写在

       静态代码块,里面只能抛一种类型的错误

       ExceptionInInitializerError

     5)利用jvm的类加载器读字节码文件的功能,能够得到

       输入流,

       InputStream is=JdbcUtil.class

             .getResourceAsStream(虚拟路径);

       绝对路径:/是真是的目录里面的根

       虚拟路径:/是classpath

例子:

private static Properties info=new Properties();

         static{          try {

InputStream is=JdbcUtil.class.getResourceAsStream(

"/com/kettas/jdbc/cfg/config.properties");         

info.load(is);

         is.close();

                   } catch (Exception e) {

                            throw  new ExceptionInInitializerError(e);

                   }

         }

 

 

线程ThreadLocal  每个线程对象建立好之后,JVM会为其分配一块内存空间用来存放当前线程对象独占的数据,(一个线程对象和另外一个独占的数据(对象)绑定(如:(tl , conn)表明某一线程的独占数据 ))空间以map形式存放独占数据,至关于Map集合里的健对象和值对象

  每一个线程的独占数据不共享,即:健对象(tl)和值对象(connection)不共享:Map<ThreadLocal,Object>

 

注意:ThreadLocal没法直接获取Map对象,操做Map只能经过ThreadLocalsetget方法

private static final ThreadLocal<Connection> tl

=new ThreadLocal<Connection>();

public static Connection  getConnection() throws Exception{

  Connection conn=tl.get();//用get获取当前线程的链接对象

       if(conn==null){

       Class.forName(info.getProperty("driver"));

         conn=DriverManager.getConnection(info.getProperty("url"),                     info.getProperty("username"),info.getProperty("password"));

       tl.set(conn);//用set把链接对象放在当前线程中

       }       return conn;  }

 

线程ThreadLocal的大体实现过程

     public class ThreadLocal<T>{

         public T get(){

            Map m=Thread.currentThread().getMap(); 

            return m.get(this);

                       }

         public void set(T t){

            Map m=Thread.currentThread().getMap();

            m.put(this,t);

                      }

            }

    

     ThreadLocal<Integer> ta=new ThreadLocal<Integer>()   //例子

     ta.set(new Integer(3)); 

 

 

 

 

  7. Driver方展的四个阶段 

     1)Jdbc-odbc (桥链接)    2)db client(客户端api)

     3)base net pure java (网络服务器)  4)pure java native(纯客户端)

    7. 写程序,向jdbc_users表插入五条记录

   String[] names={"mary","tom","anna","jerry","george"};

 

 

    

 

 次日:=======================================

Statement 和  PreparedStatement

 1)创建

   stm=conn.createStatement();

   pstm=conn.prepareStatement(sql);

 

 2)执行

   stm.execute(sql);   包含数据的完整的sql命令

   pstm.execute();     数据

 

 3)stm 能够执行多条sql

   pstm 只能执行一条sql

 4)使用pstm的环境

   a.执行同构sql,用pstm效率高

             执行异构sql,用stm效率高   

   b.构成sql语句时须要外部的变量值,用pstm

   

 

  dao:

   public void update(Account a){ 

     sql=update account set username=?,passwd=?,

         personid=?,balance=?;

     pstm=conn.....

     pstm.setString(1,a.getName());

   }

=======================================

  

 Transaction: 一组不可再分的sql命令,根具体业务有关

 =============================================

 A:原子性    :事务要么一块儿成功,要么一块儿失败,如:银行转账

  C:一致性  :如:存钱时,存5000,那么在数据库里的钱就要有5000,不能多也不能少

  I:隔离性   :链接db的两个线程操做db时,要操做个自的元组,不能同时操做同一个元组

  D:持久性--->commit,rollback ,就是让更改后的数据要么写加db要么不写进db;

 

  手动划分事务的边界,通常写在业务层(biz)的代码块里。

  划分事物边界的时候通常在要划分的地方加commit和rollback;

   conn.setAutoCommit(false);

     新事物开始

   conn.commit();

     旧事务的结束,新事务的开始

   conn.rollback();

     旧事务的结束,新事务的开始 

   没有手动划分,采用的是默认事务提交策略:

   一条sql一个事务

 

 

----------------------------------------------------

  Connection是线程不安全的,不能在线程间共享链接(connection)用ThreadLocal实现安全的链接

 

  threada   save   withdraw   transfer

  threadb   save   withdraw

    1.common: 5 个 Connection

  2.singleton: 1 个 Connection              

 3.一个线程内部共享链接: 2 个 Connection 

      t1.start();

    t2.start();

  class ThreadA extends Thread{  

     private Connection conn1=null;

     public void run(){

        conn1=JdbcUtil.getConnection();

        save(10000,conn1);

        withdraw();

     }

     public Connection getConn(){return this.conn1;}

  }

class Bank{

  public void save(double balance){   

      conn2=Thread.currentThread().getConn();

      sql="update account set balance=?";

      pstm=conn.prepareStatement(sql);

                        //设置上面问号(?),如pstm.setDouble(int parameterIndex, double x);

      pstm.set***;

      pstm.executeUpdate();

  }

  public void withdraw(double balance){

      conn2=Thread.currentThread().getConn();

      sql="update account set balance=?";

      pstm=conn.prepareStatement(sql);

      pstm.set***;

      pstm.executeUpdate();

  }

}

       

     save  ----> update   insert

     withdraw----> update  insert

     transfer ---> update  insert

                   update  insert

       update()    insert()

       save---->update() insert();           

                                    

  dao: 1)对业务层屏蔽底层数据库设计的细节  ,只有功能被业务层调用

       2)o-r mapping:就是把对像自动的保存到数据库的表中

 

   

 

 第三天:=======================================

1 PreparedStatement

  Statement

  stm=conn.createStatement();

  stm.execute(sql);

  String sql="insert into table value(?,?,?);

  pstm=conn.prepareStatement(sql);   

  pstm.set***(int,value);

  pstm.execute(); 

  pstm同构sql,sql语句须要外界变量值

  stm 异构sql

2 Transaction 

  sqls,跟具体业务有关

  ACID 

  biz:

  try{            

        conn.setAutoCommit(false);

        conn.commit(); 

  }catch(Exception e){

        conn.rollback();   

  }

3 ThreadLocal

  1)将Connection作成Thread的属性

    经过参数的传递,保证一个线程一个链接   

  2)Thread t1-----> map(线程的独占的数据)

    Map: 主键ThreadLocal,没法直接得到Map对象

         操做map只能经过ThreadLocal的set get操做

    eg:让Thread对象独占一个Integer对象

       Integer id=new Integer(3);

       ThreadLocal<Integer> tl=new ThreadLocal<Integer>();

       tl.set(id);

4 Layer 

   1)  app: showinterface 

            业务判断

         =============================

   save

            transfer

            showResultSet    

      ---------------------------------

       view  ---> showinterface

       biz----> 业务处理 

         1)业务判断

         2)业务处理

            =====================

account.balance+=money;

         3) Connection conn

            stm.execute(sql);

            commit();

         4)return result --->view 

        save():       update    insert

        withdraw():   update    insert

        transfer():   update    insert

                    update    insert

                    update 4   insert  4      

        view---->showinterface

        biz----> 业务处理

 1)业务判断   如:查看密码是否正确,或余额是否不足。

 2)业务处理如:密码不正确或正确的处理,余额足时的操做

            account.balance+=money;

          3) 封装对象     如:用户注册

          4)用对象调用dao里的方法存贮数据

         5)提交事物

        dao:---->data access object

          1)完成对某一张的增删改查

             update(): update

             insert(): insert

             delete(): delete

             query():  select

   2)接收从业务层传来的数据(对象),将其存进db

      从db里面查数据(零散),封装对象,返回给业务层

       object----relation  mapping

           save():  update()  insert()

        withdraw: update()  insert()

        transfer:  update()  insert();

        update:1       insert: 1   

       

  1  javabean--->Student

     class Student{    

        private Integer id;

        private String name;

        private String sex;

        private String address;

        private int age;

        private String studentId; 

        public Student(String name,String sex,String address,int age,String studentId){

           ......

        } }

  2  create table jdbc_student

     ( id number(7) primary key,

       name varchar2(15) not null,

       sex varchar2(3) check(sex in('f','m')), 

       age number(3),

       address varchar2(20),    

       studentid varchar2(15) not null unique    

     );

  3 class StudentDao{  

       public void insertStudents(Set<Student> stus) throws Exception{}

       public void insert(Student s) throws Exception{

          Connection conn=null;

          PreparedStatement pstm=null;

          try{

            conn=JdbcUtil.getConnection();

            String sql="insert into jdbc_student"

              +" values(jdbc_student_seq.nextval,?,?,?,?...)";

            pstm=conn.prepareStatement(sql);  

            pstm.set***();

            pstm.execute(); 

            sql="select jdbc_student_seq.currval from dual"; 

            s.setId(?);  

            }finally{ 

             JdbcUtil.release(...);

          } }

       public void update(Student s) throws Exception{

           String sql="update jdbc_student set name=?,age=?,address=?,sex=?,studentId=? where id=?";

       }

       public void delete(Student s) throws Exception{

          delete from jdbc_student where studentId=?

       }

       public Student queryById(Integer id) throws Exception{}

       public Student queryByStudentId(String studentId) throws Exception{}

       public Set<Student> queryByName(String name) throws Exception{

    String sql="select * from jdbc_student where name=?";

                pstm=conn.prepareStatement(sql);

                pstm.setString(1,name);

                rs=pstm.executeQuery();

                Set<Student> stu=new HashSet<Student>();

                while(rs.next()){

                   Student s=new Student();

                   s.setId();

                   s.setName();

                   ......

                   stu.add(s);

                }

                return stu;

       }

    }

  4 class StudentBiz{

       public void registStudent(String name,String sex,int age,String address,String studentId) throws Exception{

          1.  判断     如:判断密码是否正确

          2.  封装对象        如:新建对象

                  3.  dao.insert(s); 

          4.  事务处理           conn.commit 或conn.rollback;

       }

        public void dropStudent(String studentId)...

        public void queryStudent(String studentId)...

        public void updateStudent(String name,String address,String oldstudentId,String newStudentId)....

    }     

    com.kettas.student

      biz

        |--- StudentBiz

             impl

               |---StudentBizImpl

      entity

      dao  

      |--- StudentDao

           impl

               |---StudentDaoImpl

      config

      util

      excp

      view

      test

      sql

 

  Repeatable read 

     select *

     from s_emp for update;

  Serializable  

 

  备份数据库提升效率策略:

   1) 手动控制事务的大小,节约了db服务器的内存

      减小了回滚带来损失

   2) 事务结束时写日志,减小了查找失败事务的时间

   3) 删除备份数据库表里的约束,减小数据进入时验证的时间

      下降数据库服务器维护索引的资源

   4) 下降数据库的隔离级别,设置到read uncommited

   5) 插入时选择PreparedStatement,执行同构sql,减小编译

      sql命令的时间 

   6)插入时使用批处理,减小网络传输时间。


 

 


第四天:===========================

Statement stm=conn.createStatement();

 

stm2=conn.createStatement(int value1,int value2);

  value1:是否可滚动

     ResultSet.TYPE_SCROLL_INSENCITIVE

  value2:是否可更新   

     ResultSet.CONCUR_UPDABLE

 rs=stm2.executeQuery();  

pstm=conn.prepareStatement(sql,int,int);

 数据库表数据的分页

 1.db--sql

   子查询和Rownum

 2.jdbc---->可滚动的结果集 

   String sql="select * from s_emp order by start_date";

   rs=stm.execute(sql);

  ========================================

 int num=1; 

   rs.absolute(5);

   while(rs.next()){ 

      if(num>5) return;

      .........

   }    

       可用addBatch();方法添加批处理

   int[] a=stm.executeBatch(); //执行批处理

       批处理里放的是增删改语句,能够减小网络传输时间;

   stm批处理里缓存的是sql命令,如:stm.addBatch(sql);

   pstm批处理里缓存的是数据,如:pstm.addBatch();

   Object----->db

处理大数据的类型

1,Blob------》二进制的大对象(电影,图片,压缩包)

2,clob-------》字符的大对象(文本小说等)

以Blob为例

第一步:用empty_blob占一个空位置

      String sql="insert into largetable(id,name,largefile)"

                         +" values(3,'file3',empty_blob())";

                stm.executeUpdate(sql);

第二步:查出位置

        sql="select largefile from largetable where id=3";

                rs=stm.executeQuery(sql);

第三步:读文件而后插入数据库

   if(rs.next()){

       Blob blo=rs.getBlob(1);  //得到结果集的列值

//强转成Blob对象这样才有输出流

      oracle.sql.BLOB bo=(oracle.sql.BLOB)blo;

       OutputStream os=bo.getBinaryOutputStream();

    InputStream is=new FileInputStream(filename);//得到文件的输入流

       byte[] b=new byte[1024];  每次读文件的字节数

       int len=0,num=0;

       while(true){

      len=is.read(b);  每次读的本身长度一个数组

        if(len<=0) break;

         os.write(b,0,len); 向数据库写文件

         if(++num%10==0){

          System.out.println("10 k  ok");

        }}

       is.close();

       os.close();

       }       conn.commit();

   

  (类)class(entity)-------table

  (对象)object(persist object)--------row

  (属性)field------column(oid-----pk)

  relation---------> pk  fk

   class Student{

      private Integer oid;

      String name;

      int age;

      String sex;  

      public Student(String name,int age,String sex){

               }

   }

   Student s1=new Student("zhangsan",18,"male");

   Student s2=new Student("lisi",19,"male");

   Student s3=new Student("zhangsan",20,"male");

各类关系表的创建

 one-to-one( Car ---- License ),一对一:互相保留对方的引用,既互相都以对方为属性。

 1.java

   class Car{ 

      //oid

      private Integer cid;    //与数据库对应的cid不用写进构造方法

     

      // 业务属性

      private String manufactory;

      private String productType; 

     

      //关系属性:其它对象作为该对象的属性,关系属性不用写进构造方法里

      private License license;

      // get 和  set

      // 有参和无参的构造方法  

      public Car(String manufactory, String productType, License license) {

                   super();

                   this.manufactory = manufactory;

                   this.productType = productType;

         }

       public void addLicense(License license){

         this.license=license;

         license.addCar(this);

      } 

      public void removeLicense(){  

         this.license.removeCar();

         this.license=null;

      }

   }

   class License{   

      private Integer lid;

      private String serialNum;

      private String LicenseType;

      private Car car;

      // get 和  set

      // 有参和无参的构造方法  

      public void addCar(Car car){

         this.car=car;

      } 

      public void removeCar(){ 

         this.car=null;

      }

   }

   //一对一的数据库创建

 2. db

   create table jdbc_car

   ( cid number(7) primary key,

     manufactory varchar2(15) not null,

     producttype varchar2(15) not null,

   );

   create table jdbc_license

   ( lid number(7) primary key,

     serialnum varchar2(15) not null,

     licensetype varchar2(15) not null,

     car_id number(7) references jdbc_car(cid) unique

   );

3. dao( CarDao--->jdbc_car , LicenseDao--->jdbc_license)

         //当一个程序须要用到两个数据库时,就要创建两个数据访问层(dao)

    class CarDao{

      public void insertCar(Car c) throws Exception{

         1.insert into cartable

         2.c.setCid(?);

         3.insert into license 

         4.l.setLid(?);

      }

      public void deleteCar1(Car c) throws Exception{

         1.delete from license

         2.delete from car

         3.c.setOid(null);

         4.license.setLid(null);

         5.c.removeLicense(l);

      }  

      public void deleteCar(Car c) throws Exception{

         1.update license  set  car_id=null

         2.delete from car

         3.c.setOid(null);

         4.license.setLid(null);

         5.c.removeLicense(l);

      }

      public void updateCar(Car c) throws Exception{

          1. update car table;

          2. update license table set car_id=null;

      }

      public Car queryByCid(Integer cid) throws Exception{

        db-->1.select car table

             2.select license table

        内存--> 3. car.addLicense(license);

        4.return car;

                        } 

    }

      main(){ 

         Car c=queryByCarid(222);

         c.addLicense(license);

         dao.update(c);

                     }    

  1. 维护数据库

  2. 维护内存中的oid (insert delete)

  3. 维护关系(主要对象)

  one-to-one :

    弱耦合:  fk+uk     fk null

    强关联:  pk+fk     fk not null  

one-to-many(Company----Employee)

 1. java

  class Company{ 

     private Integer cid;

     private String cname;

     private String address;

     private Set<Employee> employees=new HashSet<Employee>();

  }

  class Employee{    

     private Integer eid;

     private String ename;

     private Date birthday;   //  java.sql.Date

     private int age;

     private Company company;

  } 

  //一对多的数据库创建

 2. db 

  create table jdbc_company

  ( cid number(7) primary key,

    cname varchar2(15) not null,

    address varchar2(15)

   );

  create table jdbc_employee

  ( eid number(7) primary key,

    ename varchar2(15) not null,

    birthday date ,

    age number(3),

    company_id number(7) references jdbc_company(cid)

  );   

  理性思惟,一步一步的往下作就OK了:

 3 dao

  insert(Object o){ 

    1. insert object

    2. object oid

    3. relation

  }           

  delete(Object o){ 

    1. relation

    2. delete object

    3. object oid

  }             

  update(Object o){

    1. update object field

    2. update relation( option )

  }

  Object query(value){ 

    1. query object

    2. query relation

  }

-----------------------------------------------------

many-to-many       ( Course <----> Student )

 

1. java

   class Student{

      private Integer sid;

      private String sname;

      private int age;

      private Set<Course> courses=new HashSet<Course>();

   }                 

   class Course{

     private Integer cid;

     private String cname;

     private int hours;                                

     private Set<Student> students=new HashSet<Student>();

   }

 2. db                   //多对多的数据库创建

   create table jdbc_student

   ( sid number(7) primary key,

     sname varchar2(15) not null,

     age number(3)

   ); 

   create table relationtable

   ( studentid number(7) references jdbc_student(sid),

     courseid  number(7) references jdbc_course(cid),

     primary key(studentid,courseid)

   );

   create table jdbc_course

   ( cid number(7) primary key,

     cname varchar2(15) not null,

     hours number(5)

   );

 3. dao

    StudentDao    CourseDao

-----------------------------------------------------

 inheritance ---> pojo

 1. java

    class Account{   

       private Integer id;

       private String name;

       private String passwd;

       private String cardId;

       private double balance;

       private String personId;

    }

    class SavingAccount extends Account{

       private String cardType;

       public SavingAccount(String name,String passwd,

            String cardId,double balance,

            String personId,String cardType){ 

          super(name,passwd,cardId,balance,personId);

          this.cardType=cardType;

       }

    }

    class CreditAccount extends Account{ 

       private double overdraft;

    }

2. db ---> one table           //一个超级大表

    create table inheritance_account

    ( id number(7) primary key,

      name varchar2(15) not null,

      passwd varchar2(15) not null,

      cardid varchar2(15) not null unique,

      balance number(10,2),

      personid char(18) not null unique,

      cardtype varchar2(10),

      overdraft number(5),

      atype varchar2(3)

    ); 

3. dao

   class AccountDao{

     public void insert(Account a){

        sql= insert into inheritance_account(.......);

        pstm.setInt(1,....);

        pstm.setString(2,a.getName());

        pstm.setString(3,a.getPasswd());

        pstm.setString(4,a.getCardId());

        pstm.setDouble(5,a.getBalance());

        pstm.setString(6,a.getPersonId());  

        if(a instanceof SavingAccount){ 

           SavingAccount sa=(SavingAccount)a;

           pstm.setString(7,sa.getCardType());

           pstm.setDouble(8,null);

           pstm.setString(9,"SA");

        }else{

          .....

        }

        a.setId(...);

     }

     public void delete(Account a){ 

        sql= delete from table where id=?

        pstm.setInt(1,a.getId());

        pstm.executeUpdate();

     }  

     public void update(Account a){  

        sql= update table set ........ where id=?

        pstm.setString(1,a.getName());

        ................

        pstm.setString(5,a.getPersonId());

        if(a instanceof SavingAccount){

           SavingAccount sa=(SavingAccount)a;

           pstm.setString(6,sa.getCardType());

           pstm.setDouble(7,null);

        }else{       

          ......

        }

        pstm.setInt(8,a.getId());

     }

     public Account queryByCardId(String cardId){

       sql=select id,name,passwd,cardId,balance,personId,cardtype,overdraft,atype

           from table where cardid=?

       pstm.setString(1,cardId);

       rs=pstm.executeQuery();

       if(rs.next()){    

          String type=rs.getString(7);

          if(type.equals("SA"){

            SavingAccount sa=new SavingAccount();

            sa.set****;

          }else{  

            ca.set****

          }

       }

     }

     public Account queryById(Integer id){

     }

   }

------------------------------------------------------

jobs:

  1. license dao    ----> self

  2. employee dao   ----> self -->update(){self relation}

  3. companydao----> queryByCname()

  4. cardao------> delete2(),queryByCid2()

  5. 改写bam

     1) value object

     2) dao ---> delete(Account a)

     3) data---->db

     4) biz,view不改

------------------------------------------------------

1.基本六个步骤

2. Statement 和 PreparedStatement

3. JdbcUtil

    1) ThreadLocal   2) 配置文件

    3) 虚拟路径( Class.getResourcAsStream())

   

    1) 分散代码集中管理

    2) 变化的数据写进文件

4. Transaction

    1)API   2) ACID     3)并发问题   4)隔离级别   

5. Jdbc2.0

    1) Batch

6. ormapping:

   1) dao 步骤

   2) 各类关系表的创建    

7. 1)数据备份时提升效率的方法 

   2)数据分页  

8.Driver的四个发展阶段

 

 

 

 

 

 

 

 

 

 

 

Hibernate


第一&二天:

ORM,即Object-Relationl Mapping,它的做用是在关系型数据库和对象之间做一个映射,这样,咱们在具体的操做数据库的时候,就不须要再去和复杂的SQL语句打交道,只要像平时操做对象同样操做它就能够了(把关系数据库的字段在内存中映射成对象的属性)

1  hibernate---->ormapping

   1) CRUD    2)HQL    3)mapping file    4)性能  

2 基于hibernate的应用步骤:

  1)javabean(pojo)

  2) relation db  -----> create table

  3)mapping file( object----table )

filename.hbm.xml ----> 跟javabean放在一个路径

   <hibernate-mapping package="packagename">  

     <class name="classname" table="tablename">

<id name="oidname" column="pkname" unsaved-value="null">

          <generator class="生成器classname"> 

            <param name="type"> value </param>

          </generator>

        </id>

<propertyname="javaproperty" column="dbcolumnname"></property>

     </class>  

     <class>.....</class>

   </hibernate-mapping>

 4) configure file ----> classpath(src)

    hibernate.cfg.xml

    <hibernate-configuration>

      <session-factory>

        <property>

        <mapping resource="filepath">    

 5) application ( base hibernate )

    a.  start hibernate

       Configuration cfg=new Configuration().configure(...);

    B . create sessionfactory

       SessionFactory sf=cfg.buildSessionFactory();

    c.  open Session

       Session sess=sf.openSession(); 

    d.  begin Transaction

       Transaction ta=sess.beginTransaction();

    e.  persist object  

       sess.save(Object o);    oid=null   ;  insert

       sess.delete(Object o);  oid!=null     delete

       sess.update(Object o);  oid!=null     update

       Object o=sess.get(classname.class,id);

    f.  ta.commit()/ta.rollback()

    g.  release resource

       ( sess , sf )   -----   sess

    sess: 线程不安全

    sf: 线程安全, 重量级的组件      

3 hilo

   1) create table  hilotable

     ( value number(7) );

      insert into hilotable

      values(1);

   2) <generator class="hilo"> 

        <param name="table">hilotable</param>

        <param name="column">value</param>

      </generato>    

     

      name= java name

      class= java type

      type= hibernate type (lower)

      table , column= db name (insensitive)   

---------------------one-to-one---------------

1. javabean  ( 双向(bi),单向 (ui))

2. create table ( fk+uk , pk+fk )

3. mapping file

4. change configure file

5. java app  

    property-ref="car"

  1)双向的一对一

  2) 没有写property-ref, 没有写cascade

      sess.update(car);

      a. update  jdbc_car set ***** where cid=?

      b. update  jdbc_license set car_id=? where lid=?

      

     没有写property-ref, 有写cascade

      sess.update(car)

      a. update jdbc_car set **** where cid=?

      b. update jdbc_license set car_id=?  where lid=?

      c. update jdbc_license set sn=?,lt=?,car_id=? where lid=?

  

 有写property-ref, 有写cascade

      a.update jdbc_car set **** where cid=?

      b.update jdbc_license set **** where lid=?

------------------------------------------------------

   class People{

      Integer id;    

      String name;

      int age;

      Set<Hand> hands=new HashSet<Hand>();

   } 

   class Hand{}    

  1. one-to-one  fk+uk(单向)

  2. one-to-one  pk+fk(单向)

  3. one-to-many (单向)

  4. many-to-many (javabean  table  mappingfile)

 

 

 


第三天:==================================

1. 标签:  类驱动表,真实反应Java里的类,即:以类为主

  hibernate-mapping---->package

  class ----> name  table

  id ----> name column  unsaved-value

  generator----> class

  param ----> name

  property----> name  column  unique  not-null  type

  one-to-one----> name  property-ref  cascade   constraint

  many-to-one---> name  column  unique  cascade

  set----> name  table   cascade  inverse

  key----> column

  one-to-many---> class   

2 id 生成器类的别名:

   sequence ,  hilo  , sequencehilo  ,  foreign

   assigned ,  increment ,  identity(mysql) , native

   3 assosiation:

  ===============================

1) one-to-one

     a. fk+uk 

       <class name="Car"....>   

       <one-to-one name="license" property-ref="car"  cascade="save-update"/>

       </class>

       <class name="License"....>   

          .......

          <many-to-one name="car" column="car_id"  unique="true" cascade="save-update"/>

       </class>

     b. pk+uk

      <class name="Car"....>   

         <id> ....</id>

         .....

         <one-to-one name="license" property-ref="car"

            cascade="all"/>

       </class>

       <class name="License"....>   

          <id name="lid"........>

            <generator class="foreign">

             <param name="property"> car</param>

            </generator>

          </id>

          ...

          <one-to-one name="car" constrained="true"

             cascade="save-update"/>

       </class>  

2) many-to-one

    <class name="Company"....>   

      ......

      <set name="employees" table="jdbc_employee">

        <key colum="company_id"/>

        <one-to-many class="Employee"/>

      </set>

    </class>

    </class name="Employee"...>  

      .....

      <many-to-one name="company" column="company_id"

         cascade="save-update"/>

    </class>    

   

  当写双向级联关系时,肯定只有一方维护关系,(通常多的一方维护关系)

   1 one-to-one  用 property-ref

   2 one-to-many  many-to-many     inverse="ture"

一的一方要 设 <set (inverse="false") casecade="save-update" />,多的一方要设<many-to-one inverse=true (casecade="none") />

两边都用true或都用false都是不对的,关系最好让一方维护

--------------------------------------------------------

 many-to-many

 1.     javabean

    class Student{

                            private Integer sid;

                            private String sname;

                            private int age;

                            private String sex;

                            private Set<Course> courses=new HashSet<Course>();

    }

   class Course{

     private Integer cid;

     private String cname;

                    private int hours;

     private Set<Student> students=new HashSet<Student>();

   } 

 2  db table

   create table hibernate_student

   ();

   create table hibernate_relation

   ();

   create table hibernate_course

   ();    

 3 mapping file

         <class name=”Student” table=”hibernate_student”>

        <id name=”sid” column=”sid”  unsaved-value=”null”>

        </id>

        <property name=”…”/>

        <set name=”courses” table=”hibernate_relation”

                                     cascade=”save-update” inverse=”true”>

     <key column=”student_id”/>

       <many-to-many class=”Course” column=”course_id”>

        </set>

         </class>

         <class name=”Course” table=”hibernate_course”>

        <id name=”cid” column=”cid”  unsaved-value=”null”>

        </id>

        <property name=”…”/>

        <set name=”students” table=”hibernate_relation”

                                               cascade=”save-update”>

       <key column=”course_id”/>

       <many-to-many class=”Student” column=”student_id” />

         </class>

 

1.student and course 没有inverse=true 就会多一次维护关系

         student and course  都有cascade   

         update(student)

                   1)update student table

                   2)update relation table

                   3)update course table

                   4)update relation table   就会多一次维护关系

  

2.student and course 有inverse=true 就不会维护关系

         student and course  都有cascade   

         insert(student)

                   1)insert student table

                   2)insert course table  

                  

3.student有inverse=true  一方维护关系才正确

         course 没有 inverse=true

         student and course  都有cascade         

  update(student)

         1)update student table

        2)update course table

        3)update relation table

----------------------------------------------------

sess.beginTransaction();

sess.save(Object);

   1. insert student table

   2. stm.addBatch(sql1);

   3. insert course table

   4. stm.addBatch(sql2);

   5. insert relation table

   6. stm.addBatch(sql3);

   7. stm.executeBatch();

 ta.commit;

 catch(Exception e){ta.rollbacka();}       

 ===========================================

 得到线程安全的session

 1. 修改配置文件

   <property name="current_session_context_class">thread</property>

 2.在java程序里获取session时

   Session sess=sf.getCurrentSession();

 session特色:

 1) 线程安全     

 2) sess在事务结束时会自动关闭,一个事务用一个sess,当数据量过多时,

         能够用sess.flush(); 将缓存的sql命令发往数据库执行,执行结果保存在回滚段.

 

 

 

 

 

 

 

 

--------------------------------------------------------

persist:

  Session:一级Cache (缓存session操做过的全部对象 )

  SessionFactory: 二级Cache ,用安全的session时,尽可能使sf关闭时,线程也要关闭;

   (缓存生成的sql,以及hibernate管理过的部分对象

 

Hibernate的对象状态,即生命周期

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.Transient(临时,暂时)

  Student s1=new Student("zhangsan",18);

 1)在数据库里没有对应的记录

  2)通常状况下,没有数据库惟一标识符

      特殊状况 1)assingned 临时对象,即新建(new)对象

              2)sess.delete(o)   对象已被删除

              3)不在Session里面

     

2.persist(持久化状态)

  sess.save(s1);  saveOrUpdate()

  Student s2=sess.get(Student.class,123); 

  1)在数据库里有对应的记录

  2)有数据库惟一标识符  

  3)在Session里面 

 

3.detached(游离,脱管状态)  

  sess.close(); sess.clear();sess.evict()

  1)在数据库里有对应的记录 

  2)有数据库惟一标识符  

  3)不在Session里面 

 

Session保留备份(两个集合)

 class SessionImpl implements Session{

     private LinkedList  entities=new LinkedList();   //实体集合,用于存放临时对象

     private LinkedList  copy=new LinkedList();  //深度拷贝集合,跟集合的数据同样,能够减小访问DB

     public Serializable save(Object o){  

        1.Serializable pk=.......

        2.db insert

        3.entities.add(o);   

        4.copy.add(o.deepcopy);

        5.return pk;

     } 

    

public void delete(Object o){

        1.db delete

        2.entities.remove(o); 

        3.copy.remove(o.deepcopy);

     } 

     public void close(){

        entities.removeAll();

        copy.removeAll();

     }         

     public void evict(Object o){

        entities.remove(o);

        copy.remove(o.deepcopy);

     }

 }

 sess保留备份的做用:

   优点:

   1) 查询同一个对象,不用再访问数据库,

      直接返回sess里的数据

   2) 脏的检测,当检测到实体集合与深度拷贝集合里的数据不一样时,会把改变的对象同步到数据库里。

    Student s=new Student("zhangsan",18);

    sess.save(s);

    s.setName("lisi");

    sess.close(); (sess.update(s))  -----> db s name="lisi",在sess关闭前会自动更新脏的数据到db里。

   

    <class name="Student" table="" dynamic-update="true">

    s.setName("wangwu");

    sess.update(s);    

    1)sess=HibernateUtil.getSession();

      ta=sess.beginTransaction();

      Student s4=new Student("zhangsan",18);

      sess.save(s4);

      s4.setName("lisi");  

      ----> sess没有关闭前,脏的检测起做用

      ta.commit();

      db---------> name="lisi" 

    2)sess=HibernateUtil.getSession();

      ta=sess.beginTransaction();

      Student s4=new Student("zhangsan",18);

      sess.save(s4);

      ta.commit();   ----> sess关闭

      s4.setName("lisi");  ----->s4 此时已处在游离状态

      db---------> name="zhangsan"  

    3)sess=HibernateUtil.getSession();

      ta=sess.beginTransaction();

      Student s4=new Student("zhangsan",18);  --->临时

      sess.save(s4);               -----> 持久

      ta.commit();                ---->s4 游离

      ta2=HibernateUtil.beginTransaction(); --->新的sess

      s4.setName("lisi");    ----->s4 游离

      ta2.commit;           ---> 关闭新的sess

      db----------->name="zhangsan"

    4)sess=HibernateUtil.getSession();

      ta=sess.beginTransaction();

      Student s4=new Student("zhangsan",18); --->transient

      sess.save(s4);                         --->persist

      sess.evict(s4);                        --->detached

      s4.setName("lisi");  

      ta.commit();                           --->sess.close

      db---------> name="zhangsan" 

       缺点:不适合作大量数据的插入或者修改       

     Student s=new Student("zhangsan",18); -->transient

    sess.save(s);                         -->persist

    sess.evict(s);                        -->detached

    sess.delete(s);    

    detached--->persist--->transient  

  jobs:

   1. m2m---> javabean  table  mappingfile  dao  biz  test

   2. 如何得到线程安全的session

   3. 三种状态,以及它们之间的转换

   4. sess脏的检测

   5. 测试get和load

 

 

 

 

 


第四天:=======================================

1 many-to-many

  1) java 

    class Student

      Set<Course> courses

    class Course

      Set<Student> students  

 2)db

   hibernate_student   relationtable  hibernate_course

       sid             studentid cid       cid

 3)

  <class name="Student" table="hibernate_student">

    <id name="sid..>

    <property>  

    <set name="courses" table="relationtable"  inverse="true" cascade="save-update" >

      <key column="studentid" >

      <many-to-many  class="Course"  column="cid"> 

</set>

  </class>

  <class name="Course" table="hibernate_course" >

    <id.....>

    <property> 

    <set name="students" table="relationtable"

cascade="save-update">

       <key column="cid">

       <many-to-many .....>

    </set>

  </class>  

------------------------------------------------------

2. hibernate---->ormapping  (object-->db)

   hibernate--->dao

   connection---> not safe ---> ThreadLocal<Connection>

   Session---->not safe---> ThreadLocal(Session)

     1) ThreadLocal<Session>

     2) current_session_context_class   thread

        Session sess=sf.getCurrentSession();

        线程安全,一个事务一个sess,事务结束会自动关闭sess

        ta=sess.beginTransaction();

        Student stu=new Student();

        sess.save(stu);

        ta.commit(); 

   dao: save()   update()   delete()    get()

        saveOrUpdate()

3.Persist

  1)Transient:

      id=null ( assigned ,  sess.delete() )---->saveOrUpdate()

      not in sess

      not in db----not row

        Persistance 

      in db ---- row

      id!=null

      in sess

    Detached

      in db----row

      id!=null

      not in sess 

  2) 一级cache(Session)----> 集合

     session有两个集合(entities,deepcopy)  

     a.缓存操做过的对象,加快查询速度  

       sess.get(Student.class,14);

       get--->一级cache---->db

     b.脏的检测(关闭时)

       在内存中改变对象属性:

        显示调用update():detached

        隐含调用update():Persistance(已经持久化的对象,若是被修改,就会隐含调用)

 3)状态图

4 Student s=new Student();

   持久化s;

   1) sess.save(s)   sess.saveOrUpdate(s)

   2) 利用持久化对象的扩散

      sess=sf.getCurrentSession();

      Course c=sess.get(Course.class,18);

      c.getStudents().add(s); 

      sess.update(c);

      ta.commit(); 

    A--->B--->C--->D

    save(A);  

    cascade:                     

     a. none(default)

     b. save-update  

     c. all ( save-udpate-delete )  

     d. delete

     e. delete-orphan

        com1-------> delete

        emp1  emp2  emp3 ----> delete-orphan

        delete(com1); ---> emp1 emp2 emp3

        delete(emp1);  --->emp1  

 5 查找Student s

   1) query by id ( get() or  load() )

     Student s=sess.get(Student.class,10);

     Student s=sess.load(Student.class,10);

    

     class SessionImpl implements Session{

        public Student get(Class c,Serializable id){

            1. sql= " select * from student where id=? ";

            2. Student o=data

            3. return o;

                 }

        public Object load(Class c,Serializable id){

             Student s=c.newInstance();

             s.setId(id);

             return s;

                }

          }

     getload

     a. get时先查询Session的Cache,若是cache里面没有,

        再生成sql语句查询数据库,默认查询全部的值 

       

        load先在内存中生成一个只有oid的对象, 且返回

        没有查询db,须要其余属性时再去查db 

       

     b. get回来的对象,全部的属性均有值

        load回来的对象只有oid有值,其余属性为null 

    

     c. get---->Student

        load----> SubStudent(cglib.jar)

  

  2) 曲线查询:

     Student s;

     Course c=sess.get(Course.class,167);

     for(Student s: c.getStudents()){   

        System.out.println(s.getSname());

     }   

 

  3)Query(interface)-----> Hibernate查询语言:hql(Hibernate query language)

    String hql="from Student s where s.sid>150";

    Query q=sess.createQuery(hql);

    List l=q.list();

 

batch insert/update:9999

  1) sess=sf.getCurrentSession();

    ta=sess.beginTransaction();

    String hql="from Student s";

    List stus=sess.createQuery(hql).list();

    sess.setFlushMode(FlushMode.COMMIT);

    for(int i=1;i<=stus.size();i++){

       if(i%50==0){

          sess.flush();   // batch 里缓存多少sql命令

            将缓存的sql命令发往数据库执行,执行结果保存 在回滚段

          sess.clear();

            清空一级cache

       }

       stus.get(i).setName("hello"+i);

       sess.update(stus.get(i));

    }

    ta.commit();      // 回滚段的内容写回数据文件

    

    1)   存放临时对象1000块

 2) Session里面留有1000个备份对象

 3) hibernate自动使用batch,缓存1000条sql

 

    默认状况下一个事务一个batch,flush()之后,把一个事务

    划分红若干个batch    

   

  2) sess=sf.getCurrentSession();

     ta=sess.beginTransaction();

     String hql="update Student s set s.sname=?";

     Query q=sess.createQuery(hql);

     q.setString(1,"haha");

     q.executeUpdate();    

     ta.commit();                  

    

  总结: Session( entities  deepcopy )

  1. 三种状态

  2. 持久化一个对象

      save   saveOrUpdate

      persistance(持久保存) object   ---->脏的检测

  3. 查询对象:

     1) get  load              ----> 加快速度

     2) relation object    //关系对象

     3) hql       

 

  4. batch update/insert

     1) query----> change----> update

        batch_size  flush()   clear()

     2) hql

    

 ----------------------------------------------------

 interfact Transaction{

    public Transaction beginTransaction();

    public void commit();

    public void rollback();

 }  

 class JdbcTansaction implement Transaction{

   public Transaction beginTransaction(){

     .......

     conn.setAutoCommit(false);

   }

    public void commit(){

       conn.commit();

    }

    public void rollback(){

       conn.rollback();

    }

 }     

事务的并发控制

1、多个事务运行时的并发问题

       并发问题概括为如下几类:

1    第一类丢失更新:撤销一个事务时,把其余事务已经提交的更新数据覆盖。

2    赃读:一个事务读到另外一个事务未提交的更新数据。

虚读:一个事务读到另外一个事务提交的新插入的数据。

4    不可重复读:一个事务读到另外一个事务已经提交的更新数据。事务A对统一数据重复读两次却获得不一样的结果,有可能在A读取数据的时候事务B对统一数据作了修改

5     第二类丢失更新:这是不可重复读中的特例,一个事务付给另外一个事务已提交的更新事务。

二数据库系统提供了四种事务隔离级别供用户选择:

A.Serializable(串行化):一个事务在执行过程当中彻底看不到其余事务对数据库所作的更新。

B.Repeatable Read(可重复读):一个事务在执行过程当中能够看到其余事务已经提交的新插入的记录,可是不能看到其余其余事务对已有记录的更新。

C.Read Commited(读已提交数据):一个事务在执行过程当中能够看到其余事务已经提交的新插入的记录,并且能看到其余事务已经提交的对已有记录的更新。

D.Read Uncommitted(读未提交数据):一个事务在执行过程当中能够拷打其余事务没有提交的新插入的记录,并且能看到其余事务没有提交的对已有记录的更新。

隔离级别越高,越能保证数据的完整性和一致性,可是对并发性能的影响也越大。对于多数应用程序,能够有优先考虑把数据库系统的隔离级别设为Read Commited,它可以避免脏读,并且具备较好的并发性能。尽管它会致使不可重复读、虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,能够由应用程序采用悲观锁或乐观锁来控制

在hibernate.cfg.xml中设置隔离级别:

<session-factory>
   <!-- 设置隔离层次,并发,缺省时Read Committed: 2 -->

   <property name="connection.isolation">2</property>

<!-- 配置事务实现类 -->

 <property name="transaction.factory_class">

org.hibernate.transaction.JDBCTransactionFactory </property>
       </session-factory>

 

悲观锁: 在查询时加

 1. Student s=sess.get(Student.class,id,LockMode.UPGRADE);

   五种模式

   LockMode.NONE: 查询时先在cache(缓存)里找,若是没有,再到db里加载  无锁机制。

   LockMode.READ: 无论cache有没有,都查询数据库,Hibernate在读取记录的时候会自动获取。

   LockMode.UPGRADE: 无论cache有没有,都查询数据库,而且 对查询的数据加锁,若是锁被其余事务拿走, 当前事务会一直等到加上锁为止. 利用数据库的for update子句加锁。

   LockMode.UPGRADE_NOWAIT: 无论cache有没有,都查询数据库,而且对查询的数据加锁, 若是锁被其余 事务拿走,当前事务会马上返回.  ,hiberna Oracle的特定实现,利用Oracle的for update nowait子句实现加锁             

   LockMode.WRITE:。在作insert,update,delete会自动使用模式.内部使用

                  

 2 .  如下状况用悲观锁:查询数据时,就给数据加锁

     1)数据资源被多个事务并发访问的机会很大

     2)修改数据所需时间很是短 

乐观锁,大可能是基于数据版本 (Version)记录机制实现

1在javabean中加上version的属性提供set和get方法

2,在数据库表上加上vershion列

3在映射文件的<id></id>后加上<version>

<version name=”version” column=”version”/>

 

实现原理:读取出数据时,将此版本号一同读出,以后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据库表对应记录的当前版本信息进行比对,若是提交的数据 版本号大于数据库表当前版本号,则予以更新,不然认为是过时数据。

 

 

 

 

第五天:=================================================================================

Inheritance:

 1. javabean

    Account  ---> SavingAccount  CreditAccount

 2. db

    1)one table 

    2)one class one table

    3)subclass---->table

 3. mapping file   

1) one table

<class  name="Account" table="inheritance_table"

                 discriminator-value="AC" >

          <id>  

          <discriminator column="atype" type="string" length="3"/> 在数据库加一列atype用来分开各类不一样的父类和子类

          <property>

          <subclass name="SavingAccount" discriminator-value="SA">  

            <property name="">         子类的特别属性discriminator-value="SA"默认值是SA

          </subclass> 

          <subclass name="CreditAccount" discriminator-value="CA">  

            <property name="">

          </subclass>

       </class>

   2) one class one table 每一个类都有一个表 子类的主键同时是父类的外键 即父表的主键也子表主键同样

      <joined-subclass name="SavingAccount" table="hibernate_savingaccount">

                <key column="id"></key>

                <property name="cardType"></property>

       </joined-subclass>

   3) one subclass one table每一个子类一张表

     <class name="Account" abstract="true">    抽象父类不能new对象,父类没有对应的表

           <id name="id" column="id" unsaved-value="null">

         <generator class="sequence">

            <param name="sequence">account_seq</param>

         </generator>

       </id>  

       <property name="name"></property>   父类的属性

      <union-subclass name="SavingAccount" table="hibernate_savingaccount">

        <property name="cardType"></property>

      </union-subclass>

      <union-subclass name="CreditAccount" table="hibernate_creditaccount">

        <property name="overdraft"></property>

      </union-subclass>

      

  </class>

 4. change config file

 5. dao     

    public void insertAccount(Account a){

       sess.save(a);

    }

 6. biz

 7. view

 8. test     

 

-----------------------------------------------------

 class Person{

   private Integer id;   ------> oid

   private String name;  ------>业务属性

   private int age;  

   private Head head;   ---->业务属性 

   private Set<Hand> hands=new HashSet<Hand>();  ---->业务属性

   private Computer computer; ---->关系属性  

   private Set<Book> books=new HashSet<Book>();---->关系属性

 } 

 class Hand{

   private String finger;

 }

 class Book{

   private Integer id;

   private String bname;

 }

 class Head{

    private String eye;

 }  

 class Computer{

   private Integer id;

   private String Screen;  

   private Person person;

 }

------------------------------------------------------

如下标签和属性要结合着映射文件看和理解hibernate

base(基础):

   hibernate-mapping:表示映射文件的根标签 --> package:表示要映射的类所在的包。

  

   class:该标签下包含映射的类和DB里的表--> name:要作映射的类  table:对应DB里的表 ;

                 optimistic-lock:常常与version连用,做用是一个数据被多个事务访问时,

                                   若是其中一个事务修改了DB数据,那么其它事务将不能获得提交数据,只能从新访问DB;

                      1 none 无乐观锁2 version 经过版本机制实现乐观锁

3  dirty 经过检查发生变更过的属性实现乐观锁4 all 经过检查全部属性实现乐

                 dynimic-update:默认值为"false",当值为"true"时表示更新被修改的列,而不全表更新;

                 abstract:表示要映射的类是抽象类,不能new对象,只能用他的实现类,不然hibernate会报错;

                 lazy:表示延时加载,即用到DB里的数据时才去DB里加载,默认为"true"。

  

   id:---> name:表示在类里的对应的属性名;  column:表示在DB表里对应的列名;

                           unsaved-value:未存进DB前或当id为临时对象时,默认为null;

    generator:表示生成器标签 ---> class:是用哪一种生成器,在Oracle里是系列(sequence)。

  

   param:参数标签 ---> name:指代用什么配置或初始化生成器的值。

  

   property:该标签用于属性与表里的映射----> name:对应类里的属性名;

               column:对应DB表里的列名;  unique:表示DB表里的列的值是否惟一;

           length:表示DB里那一列的数据存放长度;  type:DB里那一列的数据存放类型;

           not null:DB里那一列的数据是否能够为空。

   version:该标签常常与乐观锁连用,表示其它事务是否修改DB里的值--->

                 name:在类里对应的属性名; column:DB里对应的列名。

assosiation(关联):在类里是一个类的属性是别一个类的类型,在DB里是多表关联。

   one-to-one--> name:表示在类里对应的属性名;constrained:表示该属性必须有值;

       property-ref:表示只维护该表里的属性列,而不维护以该表的ID为外健的其它表;

 cascade:级联操做,即级联关系属性,当值为"save-update"时表示更新A表时,也更新与之对应的B表,(cascade在A表)。

   many-to-one-->name:表示在类里对应的属性名;  column:表示在DB表里对应的列名; lazy:表示当用到该类的对象(A)的属性(name)时,

会自动去DB里加载这个属性对应的行,并用这行生成对象保存在该类的对象(A)的属性里。

                 cascade  unique

   one-to-many--> class:在类里对应哪一个类;

   set:该标签表示类里的属性是set集合----> name:表示set集合在该类里的名称;

                 table:表示set集合里的数据在DB里对应哪一个表;

                 cascade:表示更新cascade所在的表时,级联更新table对应的表(或name属性所在的表);

                 inverse:表示只维护该表里的属性列,而不维护以该表的ID为外健的其它表;

                

   key:该标签表示外健 ----> column:表示表里的外健名;

  

   many-to-many----> class:在类里对应的类;column:在表里对应的外健。

  

inheritance(继承):

  subclass:用于多个子类作成一张表时 ---> name:表示在类里对应的子类名; 

                           discriminator-value:在DB表里对应的列的值;

  discriminator:该标签用于描述discriminator-value ---> column:表示该值在哪一列 ;

                           type:在DB里是什么样的数据类型; length:在DB里以什么样的长度存储的。

                          

  joined-subclass:一个类一个表--->name:表示在类里对应的子类名;  table:在数据库里对应哪一个表;

  union-subclass:一个子类一个表---->name  table

 

valuetype(值类型):没有oidJava对象(某个对象的业务属性,离开该对象没法存在)

component:该标签表示该类(comA)是另外一个类(A)的某一部分(属性)--->name:表示comA类在A类里的名字;

   parent:该标签表示属于哪一个类---> name:在comA类里的属性名;

 set-->.....

   element:值元素(如在map标签里表示值对象)---> type:在对象在DB里存的数据类型;  column:在DB里对应哪一列;

  

   list ---> name  table

   list-index:表示list集合的下标(在数据库中自动生成)---> column:对应DB里table值的哪一列

   idbag:hibernate里特有的一个集合标签,可重复无序。----> name  table   

   collection-id:表示给一重复数据的区别---> column:对应DB表里的哪一列;

   composit-element:该标签表示里面的数据是某一集合的组成元素---> class:表示该集合里的元素是属于哪个类的; 

map----> name:表示map集合在该类里的名称;  table:表示map集合里存的数据在DB里对应哪一个表;

 map-key:map集合里的健对象---> column:表示健对象对应table表里的一列; type:表示健对象的类型;

query

 

 

 

第六天:==================================

1.optimistic-lock

  1) old: <class  optimistic-lock="all/dirty/version"

                  dynimic-update="true"> 

  2) new: a. javabean ---->version(int)

          b. table----->version(number)

          c. mapping file---> <version> (紧跟在<id>)

2. 1)javabean ---> extends

   2)db ----> a. one table

                ( pk, 父类共性 , 各个子类特性 , 类型 )

              b. one class one table

                父表( pk  共性)

                子表( pk-fk  特性)  

              c. one subclass one table

                 表( pk  共性  特性 )

                 表 ( pk  共性  特性 )

   3) mapping file

      a. one table

       <class>         

         <discriminator column="colname" type="string">

         <subclass name="subname" discrinator-value="SA">

         </subclass>

       </class>      

       b. one class one table

     <joined-subclass name="subname" table="subtablename">

            <key columm="">

            <property>

         </joined-subclass>   

      c. one subclass one table

        1) <class>  <class>

        2) <class name="fatherclassname">

             共性

             <union-subclass name=""  table="">  

                特性

             </union-subclass>

           </class>      

3. valuetype 值对象 (没有oidjava对象)

  1) one value ---> component (两个类一张表)

     db: pk  简单类型   v1property1    v1property2

     mapping:  <component name="javavaluetype name">

                 <parent>

                 <property>

               </component> 

  2) one collection  (两个类两张表)

     set:  java---> Set<String>

           db-----> table( id(fk)  value  pk(id,value))

           mapping--->

            <set name="setname" table="">

              <key column="id">//外键

              <element column="value" type="string">

     list: java---> List<String>

           db-----> table( id(fk) index  value  pk(id,index))

           mapping--->

            <list name="listname" table="">

              <key column="id">

              <list-index column="index"> 自动生成下标

              <element column="value" type="string">

 

 

 

    idbag: java---> List<String>

           db-----> table( id(fk) key(pk)  value )

           mapping--->

            <idbag name="listname" table=""> 

              <collection-id column="key">

                <generator>

              <key column="id">

             <element column="value" type="string">

  3) one map 

    java---> Map<String,String>

    db-----> table( id(fk) key  value  pk(id,key))

    mapping--->

      <map name="setname" table="">

      <key column="id"> 

      <map-key column="key">

      <element column="value" type="string">    

------------------------------------------------------

1.query object(Employee): Company--Employee

  1) Company c=sess.get(Company.class,18);

     Set<Employee> employees=c.getEmployees();  

  2) query oid;

     Employee e=(Employee)sess.get(Employee.class,18);

     Employee e=(Employee)sess.load(Employee.class,18);

  3)hql

    String hql="from Employee e where e.name='zhangsan'";

    Query q=sess.createQuery(hql);

    List<Employee> es=q.list();     

    mapping file:

     <query name="querybyname">

        <![CDATA[ from Employee e where e.name='zhangsan']]>

     </query>

    java: Query q=sess.getNamedQuery("queryname"); 

  4) Criteria

     Criteria ct=sess.createCriteria(Employee.class);

     Criterion ce1=Expression.eq("name","zhangsan");

     Criterion ce2=Expression.like("address","W%");

     ct.add(ce1);

     ct.add(ce2);

     List<Employee> es=ct.list();  

  5) 本地sql

    str="select e.NAME as {emp.name},e.AGE as {emp.age}

                 from EMPLOYEE e where e.NAME='zhangsan'"; 

    SQLQuery sq=sess.createSQLQuery(str);

                   sq.addEntity("emp", Employee.class); 

                   str=" select {e.*} from EMPLOYEE e where e.NAME='zhangsan'"; 

    sq.addEntity("e",Employee.class); 

2. 支持多态查询

   public Account queryById(Integer id){

      String hql="from Account a where a.id=?"

      Account a=query.list().get(0);

   }

3.排序(list()iterate()):

   hql1="from Employee e order by e.eid";   

   Query q1=sess.createQuery(hql1);

   List<Employee> es1=q1.list();  

   hql2="from Employee e where e.age>30"; 

   Query q2=sess.createQuery(hql2);

    List<Employee> es2=q1.list();

        // select * from Employee where e.age>30; --->sql

   Iterator<Employee> et=q.iterate(); --->效率高 

         // select e.eid from employee e where e.age>30--->sql

4. 数据分页:

   1)sql--->rownum

   2)jdbc---> ResultSet

   3)hibernate--->

     hql="from Employee e order by e.start_date";

     Query q=sess.createQuery(hql);

     q.setFirstResult(5);//从结果集q中的第五行开始

     q.setMaxResult(5);  //获得五行

     List<Employee> es=q.list();

     list.size===5; 

     q.setFirstResult(5);

     q.setMaxResult(1);

     Employee e=q.uniqueResult();

根据pk查询

5.根据条件查询(where)

  hql=" from Employee e "+"where..."

  1)where e.name='zhangsan'

    where lower(e.name)='zhangsan'

  2)where e.age<30

  3)where e.age between 30 and 60

  4)where e.age in(30,40,50)

  5)where e.name like 'S%'

  6)where e.salary>1000 and e.dept_id=41

    where e.salary>1000 or e.dept_id=41

  7)where e.address is null

  8)!= , not between and , not in  ,not like ,is not null

6. 参数绑定:

  1) hql=" from Employee e where e.name=?";

     Query q=sess.createQuery(hql);

     q.setString(1,"zhangsan");

  2) hql=" from Employee e where e.name=:name";

     Query q=sess.createQuery(hql);

     q.setString("name","zhangsan");

     Company c=(Company)sess.get(Company.class,18);

     hql="from Employee e where e.company=:com";

     Query q=sess.createQuery(hql);   

     q.setEntity("com",c);

     public List<Student> query(String name,Integer age){

      StringBuffer sb=new StringBuffer("from Student s ");

      if(name!=null) sb.append(" where s.name=:name");

      if(age!=null && name!=null)

         sb.append(" and s.age=:age");

      if(age!=null && name==null)

         sb.append(" where s.age=:age");

      Query q=sess.createQuery(sb.toString()); 

      if(name!=null) q.setString("name",name);

      if(age!=null)  q.setInt("age",age);

      return q.list();

   }

   public List<Student> query2(String name,int age,String address,String sex){

      Student s=new Student();

      s.setName(name);

      s.setAge(age);

      s.setAddress(address);

      s.setSex(sex);

      Criteria c=sess.createCriteria(Student.class);

      Example e=Example.create(s);

      c.add(e);

      return c.list();

   }

  7. 链接:

  sql: inner join ;  outer join ;  no equal join ; self join

 

  hql: inner join --- inner join fetch(迫切内链接)

       left outer join -- left outer join fetch(迫切左外链接)

       right outer join

       隐式链接 

      

  1)left outer join:( left join ) 

      hql="from Company c left join c.employees e";

      Query q=sess.createQuery(hql);

      List<Object[]> list=q.list(); 

      /* Company对象关系属性没有被初始化,全部每条记录

             被封装成两个独立的对象

      */

      sql= select c.*,e.* 

           from  jdbc_company c left join jdbc_employee e

           on c.cid=e.company_id; 

      result:

        cid  cname  address  eid  ename  age

         1   kettas   wdk     1    mary   18

         1   kettas   wdk     2    tom    19

         1   kettas   wdk     3    ann    20

         2    IBM      sd      

    -------------------------------------------------

    hql="select c from Company c left join c.employees e";

    Query q=sess.createQuery(hql);

    List<Company> list=q.list();

    sql= select c.*

        from  jdbc_company c left join jdbc_employee e

        on c.cid=e.company_id;  

 2)left join fetch:

   hql="from Company c left join fetch c.employees e";

   Query q=sess.createQuery(hql);

   List<Company> list=q.list();

   Set<Company> set=new HashSet<Company>(list);

  

   /* list里的每个Company对象,全部的属性都有值,

      包括关系属性也被初始化,而且里面存有查回来的

      Employee对象

   */   

   sql= select c.*,e.* 

        from  jdbc_company c left join jdbc_employee e

        on c.cid=e.company_id; 

   result:

     cid  cname  address  eid  ename  age

      1   kettas   wdk     1    mary   18

      1   kettas   wdk     2    tom    19

      1   kettas   wdk     3    ann    20

      2    IBM      sd 

3)隐式链接: 如:写hql语句时,hibernate会自动的使用sql对数据库进行查找。

   hql=" select e from Employee e

         where e.company.cname='kettas'";

   sql= select e.*

        from jdbc_employees e,jdbc_company c

        where e.company_id=c.cid  and c.cname='kettas'

8. 组函数

  sql: avg()  sum()   max()  min()  count()

  hql: avg()  sum()   max()  min()  count() 

                                           

  需求:打印出地区名字,以及该地区公司的个数

  hql=" select c.address,count(*)

        from Company c

        group by c.address

        having count(*)>1 ";

  hql=" select e.dept_id,avg(salary)

        from Employee e

        group by e.dept_id";     

       

9 子查询:

  1)相关: 请查询员工数量大于一的公司

    hql=select c  from Company c

        where 1<( select count(*) from c.employees e );

 

 

 2)无关: 查询工资高于平均工资的员工对象

    hql=select e1 from Employee e1

    where e1.salary>( select avg(e2.salary) from Employee e2);

  3)all(查询出的全部记录)

    some/any/in(任意一条记录) 

   

    打印出公司全部员工年龄大于30的公司

    hql="select c from Company c

         where 30< all(select e.age from c.employees e)";       

    打印出公司有员工年龄大于30的公司

    hql="select c from Company c

         where 30< any(select e.age from c.employees e)";

10.投影查询:

    hql="select c.cname,c.address,e.ename,e.age

        from Company c left join c.employees e"; 

    Query q=sess.createQuery(hql);

    List<Object[]> list=q.list();

    --->Object[] o1={"kettas","wdk","tom",18};

    result:

       cname   address   ename  age

       kettas    wdk      tom    18

       kettas    wdk      mary   19

       IBM       sd

   ------------------------------------------------

   packate hibernate.test;

   class UserData{

     private String cname;

     private String address;

     private String ename;

     private int age;

     public UserData(String cname,String address,String ename,int age){

      this.cname=cname;

      this.address=address;

      this.ename=ename;

      this.age=age;

     }

   }

   hql=select new hibernate.test.UserData(c.cname,c.address

         ,e.ename,e.age)

        from Company c left join c.employees e; 

   Query q=sess.createQuery(hql);

   List<UserData> list=q.list();  

UserData在session中没有数据备份,是把零散的数据从数据库中拿回来本身现封装的对象。

11.集合过滤:

   Company c=sess.get(Company.class,18);

   c.employees没有初始化,默认lazy=true  

   取回c的全部员工

   Set<Employee> es=c.getEmployees();

   sql="select * from jdbc_employee where company_id=c.getId()

   取回的是c的年龄大于30的员工

   1)hql="from Employee e where e.company=:com and e.age>30";

     Query q=sess.createQuery(hql);

     q.setEntity("com",c);

     List<Employee> e=q.list(); 

   2)Query q=sess.createFilter(c.getEmployees(),"where this.age>30");

     List<Employee> es=q.list();    

12. batch update

    1)sess

      a. List<Employee> list=sess.createQuery("from Employee").list();

      b. for(int i=0;i<list.size();i++){

            if(i%100==0){

               sess.flush();

               sess.clear();

                                       }

            list.get(i).setName("hello"+i);

                      }

         ta.commit(); 

        

    2) hql="update Employee e set e.ename=:name";

       Query q=sess.createQuery(hql);

       q.setString("name","hello");

       q.executeUpdate();        

      

    3) hql="delete Employee e where e.eid>20";

   

13. SQL语句是对数据库的表操做,HQL语句是对类的操做。

   

如下是要掌握的内容:

  oracle: create table  ,  create sequence

          select  update  delete  insert  

  jdbc:  基本步骤

         jdbcUtil

         dao 的概念

         Transaction

         association(one-to-one) 

        

  hibernate: mapping file

             Session

   1)标签  2)三种状态    3)Session(集合)

   4)association     5)Inheriatance(one table)

   6)hql

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC

         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

 

<!--====>     配置文件   <==== -->

         <session-factory>

                   <!--<<  配置事务实现类 ,下面能够不写, 默认状况下为JDBC>> -->

                   <property name="transaction.factory_class">

                                     org.hibernate.transaction.JDBCTransactionFactory

                   </property>

 

                   <!--<<   配置JDBC里Batch的大小  >> -->

                   <property name="jdbc.batch_size">50</property>

                   <property name="cache.use_second_level_cache">false</property>

                  

                   <!--<<   得到线程安全的Session  >> -->

                   <property name="current_session_context_class">thread</property>

                  

                   <!--<<   运行时,是否显示SQL语句   >> -->

                   <property name="show_sql">true</property>

                   <property name="format_sql">true</property>

 

                   <!--<<   配置数据库方言   >> -->

                   <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>

 

                   <!--<<   配置数据库链接   >> -->

                   <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>

                   <property name="connection.username">cksd0804</property>

                   <property name="connection.password">cksd0804</property>

                   <property name="connection.url">jdbc:oracle:thin:@192.168.0.200:1521:ORADB10G</property>

                  

                   <!--<<   c3po  配置链接池   >> -->

                   <property name="c3p0.max_size">2</property>

                   <property name="c3p0.min_size">2</property>

                   <property name="c3p0.timeout">5000</property>

                   <property name="c3p0.max_statements">100</property>

                   <property name="c3p0.idle_test_period">3000</property>

                   <property name="c3p0.acquire_increment">2</property>

                   <property name="c3p0.validate">false</property>

 

                   <!-- <<   指定(hibernate管理的)映射文件   >> -->

                   <!--<mapping resource="day1/Users.hbm.xml"></mapping>--> 

<!-- <<   当用tomcat服务器配置的链接池时用下面代替上面的链接   >>-->

<!--<property name="hibernate.connection.datasource">java:comp/env/oracle/ds</property> -->

 

<!--该路径是相对于hibernate.cfg.xml的路径 (相对路径)-->

                   <!--<mapping resource="orm/o2o/fkuk/bi/Car.hbm.xml"></mapping> -->

                   <!--<mapping resource="orm/o2o/fkuk/bi/License.hbm.xml"></mapping> -->

                   <!--<mapping resource="orm/o2o/fkuk/ui/CarLicense.hbm.xml"></mapping>-->

                   <!--<mapping resource="orm/o2m/bi/CompanyEmployee.hbm.xml"></mapping>-->

                   <mapping resource="orm/m2m/bi/StudentCourse.hbm.xml"></mapping>

         </session-factory>

</hibernate-configuration>

 

Hibernate 的工做原理-------------------------à

 

 

 

 

 

 

 

 

 

 

 

 

HTML&JavaScript


 

Html==================================================================================


Head相关

Meta 描述属性

Style 样式

Script 脚本

字体相关

h1 ... h6 字体的大小  一次变小

p  段落标签 换行且有段间距

pre  预备役标签,保留你的输出

font --> size | color  字体变化,设置大小和颜色

b | strong  加粗

center 居中

em 斜体,着重显示,不一样的显示器,着重显示不同

br  换行符

hr  分割线

图片/超连接

图片 img src(名字) | width height(宽高) | alt (图片找不到的时候显示的东西) | align(控制写在图片以后文字的位置 bootom 下方middle中间) | border (控制图片边框)

超级链接a href链接目标的url) | name(锚点名) | target (4个备选 _new第一次链接开一个新窗口,第2,3次在同一个窗口里刷新  _self本身窗口里打开  _blank链接打开一个新窗口,点几回开几个窗口  _top(我在最顶端,把frameset框架替换了,要代替真个框架显示出来))href=“#”表示本页面

表格

table (tbody) border | bordercolor | bgcolor | cellsapcing | width height | align

         |- tr

      |- td colspan | rowspan  和并列| 合并行

表单

form --> method | action

         |- input --> type : text | password | checkbox | radio | button | submit | reset | hidden    

         |- select

                                     |- option

         |- textarea --> cols rows

name=value

框架

frameset ---> 不容许出现body  ---> rows cols

         |- frame ---> name | src

C/S           B/S

web 1.0 --->  发布式体系

web 2.0 --->  强调用户参与 ---> blog

==================================

internet    ---> 铺路

web         ---> 车

http  --- 底层传输层协议 来自于ARPA 

   --->  无状态协议

   --->  一次性链接  

   --->  80端口

HTML  ---> 标识性语言 --- 被浏览器解释    

                      Active X    

W3C制定的  

<body xxx="xxx">

       xxxx

</body>     

---------------------

<html>

         <head>  ----> 

         </head>

         <body>

         </body>      

</html>

字体相关标签

<h1 --- h6>

<p>             <pre>

<font size color>

<center>

<br><hr>

<b><strong>

 

图片\超连接

<img>

 |- src

 |- width height

 |- alt

 |- align

 

<a>

 |- target --->  _new _self _blank _top 若是不加_表示一个frameset的name

 |- href

 |- name

 

表格

<table> --> border | bordercolor | width / heigth | align | cellspacing

 |- <tr>

                   |- <td>   --->  colspan | rowspan

表单

<form>      

         |- method

                   |- get

                            参数以URL方式进行提交  

         参数用来提交给服务器看,须要服务器端主动拿取

                            缺点: 不安全

                                      URL长度有限制

                                       编码问题

                            |- post       

                                     参数包含在请求体中提交    

                                     服务器端直接从请求中得到数据

                                    

         |- action

                            file:///C:/Documents%20and%20Settings/user/桌面/html/form.html

                            ? --> 链接符 表示后面提交参数

                            userName=kettas

                            & --> 参数链接符用于多个参数分隔

                            password=123456

                            &radio1=hibernate

                            &heshang=JinChuangGuang

                            &heshang=SunShuai&sel=tianjin

         <input>

</form>

 

框架<frameset>

<html>

<frameset rows="15%, 70%, 15%"> 

         <frame name="title" src="title.html">

         <frameset cols="15%,*">

                   <frame name="leftBar" src="leftBar.html">

                   <frame name="main" src="main.html">

         </frameset>

         <frame name="footer" src="footer.html">

</frameset>

</html>

 

Inputàtype:text文本|password|checkbox多选框||radio单选框|botton|submit|reset

Select下拉列表 option标签

Textarea

 

 

==================================================================================================


1) Css Cascading Style Sheets)什么用   

优势: 1 避免传统html标签过于繁琐的步骤

                                     2 比传统html标签更灵活

                                     3 可重用性

<head>

 <style type="text/css">

         h1.rb, h2.rb{

                            color : red;   

                            background-color : black ;

                            }  

                                    

         h1.gy{

                    color :green ;

                  background-color : yellow;

         } 

                                    

         #p1{

                    color : red;

         }

     .mylayout{ //通常用点号“。”后面是css的名字

        color:red;

}

                    </style>

         </head>

         <body>         

                   <h1 class="rb">Hello Css World!</h1>

                   <h1 class="gy">Have a nice day!</h1>

                   <h1 class="rb">Good luck & Have fun!</h1>                      

                   <h2 class="rb">this is h2 line</h2>               

                   <h3 class="rb">this is h3 line</h3>     

                   <p id="p1">this is p line</p>

                   <textarea class=”mylayout”/> class调用css

2) selector{

                   property : value;

          }

 

 

3) 外部引入css  使用的时候和内部同样

     1) <style type="text/css"></style>

     2) <link rel="stylesheet" type="text/css" href="…/home.css"/>

     3) nested

内部标签使用 <h1 style="color:blue">this is 3 line</h1>

4,经常使用的css相关标签

文本相关

   text-align : left | center | right

   text-indent : 10px ;

   color : 制定文字颜色

字体相关

     font-family : 字体:

       “times new Roman" , times , serif ....

     font-weight : normal , bold , lighter , bolder

     font-size : xxxx

               % , smaller , larger .font-size:10pt}

.s1 {font-size:16px}

.s2 {font-size:16pt}

.s3 {font-size:80%}

.s4 {font-size:larger}

.s5 {font-size:xx-large}

 letter-spacing : 字符间隔

 word-spacing : 单词间隔

  .p1 {text-indent: 8mm}

  .d1 {width:300px}

 .p2 {text-indent:50%}

 

颜色背景

    background-color :

    background-image:url( images/xxxx.jpg )---背景图片

    background-repeat :  决定显示方式。

         repeat : 重复显示

        repeat-x : 左上方开始横向重复显示。

         repeat-y : 纵向重复显示

         *no-repeat : 只显示一次 。 

        

关于div span

 

边框相关

  border : style width color

         style : 边框的种类.

              none , hidden , dotted , dashed, solid , double, groove , ridge, inset , outset

                border-style :

                   border-top-style :

                   border-left-style :

                   border-right-style:

                   border-bottom-style :

 

         border-width:

                   border-top-width:

                   border-left-width:

                   border-right-width:

                   border-bottom-width:

         border-color :

                   border-top-color:

                   border-left-color:

                   border-right-color:

                   border-bottom-color:

 

高度,宽度 :

   width : height :

 

补白:变相的缩进

 

         padding:

            padding-top

            padding-right

            padding-left

     padding-bottom

  margin:

             margin-top

             margin-right

             ....................


 

 

 

 

JavaScript_1:============

动态网页技术

                   ---> 服务端技术

                   ---> 客户端技术

javascript 基于解释性的语言

  动态网页:

    服务器端动态

 客户端动态

减小服务器压力

                            功能受浏览器控制 须要看浏览器支持什么

========= 词法特性 =================

采用unicode字符集,可是仅限于注释和字符串变量值, 变量和函数的标识符不能使用

Unicode字符集。

基本特征 :

    变量没有数据类型 。

    JAVA:

       int a = 123;

       String b = "123";

    Javascript :

       var a = 123;

       var b = "123";

    基本程序控制和java同样。

==============================================

数据类型和值 :

         弱数据类型 设计的比较简单 随着功能越发强大 已经成为了一个缺陷

      在程序中,变量的值能够是 :

      三种基本数据类型 :

      数字: 123, 123.22

      文本字符串: "zhongguo" ,"中国", '123' 

      boolean类型: true | false  

                        非0 和  0    非null| null

     

      除基本数据类型之外, javascript 还支持复合类型 :

      Object( 对象 ) , Array( 数组 )

     boolean :

    boolean 的其余表示方法 :

                1 , 0 和 非0 值 。

                2, 空 和非空 。

      特殊数据类型:null 和 undefine (未定义的).

javascript 是 弱数据类型的语言,其变量没有数据类型。

全部变量声明时都使用 var 类型 。 并且统一变量可分别

存储不一样类型的值

 

var a = 123;

a = "123";   

var a = 1;

var b = "2";

var c = a + b ;    "12"

 

 

javascript代码引入到Html

1,代码直接嵌入

<script language="javascript">

    ......

    ......

</script>

 

2, 引入外部文件

<script type="text/javascript" src="js/functions.js"></script>

<link rel="stylesheet" type="text/css" href="*.css">

 

javascript简单交互手段

alert( "" );

document.write( "" ) ;

只有function里才算局部变量

If、for里都不算

    建立并使用对象 。

    1,

    var obj = new Object();

   obj.name = "zhangsan" ;

   obj.age =123 ;

   obj.email = "liucy@cernet.com" ;

 

属性的两种访问方式:

   alert( obj.name ) ;

   alert( obj["name"] ) ;

         本质:多个属性的集合

         缺点:不严谨

    var  obj = { name : "zhangsan" , age : 24 , email : "liucy@cernet.com" } ;

   alert( obj.gender ) ;

 

for循环

   第一种

for (i = 0; i <= 5; i++)

{

document.write(i)

document.write("<br>")

}

  第二种使用 for...in 循环语句

for...in 循环中的循环计数器是一个字符串,而不是数字。它包含了当前属性的名称或者表示当前数组元素的下标。

<script type="text/javascript">

// 建立一个对象 myObject 以及三个属性 sitename, siteurl, sitecontent。

var myObject = new Object();

myObject.sitename = "布啦布啦";

myObject.siteurl = "blabla.cn";

myObject.sitecontent = "网页教程代码图库的中文站点";

//遍历对象的全部属性

for (prop in myObject)    prop是数组元素的下标和java

{                      foreach有不一样的含义

document.write("属性 '" + prop + "' 为 " + myObject[prop]);

document.write("<br>");

}

 

 

 

建立并使用数组

     1,

     var arr = new Array();

     var[0] = 1 ;

     var[1] = 3 ;

     2,

     var arr = [ 1,2,3,4,5,6 ] ;

     3,

     var arr = [ 1,,,,6] ;

     4,

     var arr = [ 1, 4.4, "sd" , true]  相似一个集合

不须要指定数组长度

使用变量 :

    变量须要先声明,后使用 。

    未付值的变量初始值是undefine .

   重复声明 :

      使用 var 重复声明是合法的. 若是重复声明中有初始值的话, 则至关于付值

      语句 , 没有初始值的话,变量保留之前的值 .

  遗漏声明 :

     若是使用了一个未声明的变量 , javascript会对这个变量做隐式声明。

      可是全部隐式声明的变量,都会成为全局变量,即便声明是发生在函数体

       以内的 。

函数声明和使用 :

    function name( a , b , c ) {}

   支持内联函数 :

  function a(){

         function b();

         b();

  }

  内联函数只能在做用域内使用

  变量做用域 :

      javascript中不存在块做用域, 声明在块中的变量,在块的外面同样能够使用

   if(){

           var a = 10 ;

       }

   alert( a ) ; //合法 。

   做为数据的函数 :

         function a( x, y ){  .... }

         var b = a ;//用变量存函数;

         b( 1 , 2 ) ;//至关于a(1,2);

思考:

         var student = new Object();

         student.name = "zhangsan";

 

   经过构造函数建立函数

   var a = new Function( "a" , "b" , "return a + b " );

  a , b , 新建对象的参数名称 , 若是有多个能够依次填入 :

   new Function( "a" , "b" , "c" , ... " return a + b + ... + n ; " ) ;

      调用 : a( 10 , 20 ) ;

   经过函数直接量:

       var a = function ( x , y ){ return x + y ; }

    参数数量验证:arguments.length

    变量做用域:

         不存在块做用域注意这里所说的块并非函数块

window.parent

JavaScript_2:==================

javascript中的常见事件

    通常性事件

          onclick            单击事件

          ondblclick      双击事件

          onmouseomove    鼠标移动

          onmouseover     鼠标移入

          onmouseout      鼠标移出

          onmousedown   鼠标键按下

          onmouseup       鼠标键松开

         适用 几乎所有的可显示元素(标签) 。

   页面相关事件

         onload   :   页面加载时触发。即把页面全部的东西都下载完时触发              <body>

         onscroll :   页面滚动时触发。                        <body>

         onstop   :   按下stop按钮时触发。               <body>

         onresize :   调整大小时触发 。                       <body>

         onmove   :   窗口移动时触发。                     <body>

   表单相关事件

        onblur   : 当前元素失去焦点时触发。 <input>

        onchange : 当前元素失去焦点,而且值发生变化时触发。<input>

        onfocus  : 当前元素得到焦点时触发,指光标移到当前处,即得到焦点 。  <input>

        onsubmit : 表单被提交时触发  <form onsubmit=”return tes()”>

==============================================

DOM : W3C提供的一组规范 能够在独立于平台的前提下修改文档的内容和结构。

DOM  将文档的内容封装到对象及对象的属性和关系中 。

经过操做DOM对象及对象的属性,达到修改文档内容及结构的目的 。

DOM里有各类方法,用于修改文档内容和结构;

能够将DOM理解为文档内容的树状表示法 。

<table>

   <tbody>

       <tr><td>zhangsan</td><td>20</td></tr>

       <tr><td>lisi</td><td>21</td></tr>

   </tbody>

</table>         

用于遍历XML文档的DOM方法:

    document.getElementById( "" )       XMLElement

    document.getElementsByTagName( "name" )    array

用于处理XML文档的DOM属性 :

     childNodes      Array     //返回的是一个数组

     firstChild       XMLElement     //第一个子标签

     lastChild           XMLElement                 //最后一个子标签

     nextSibling       XMLElement  //同级的下一个标签

     previousSibling   XMLElement //同级的上一个标签

     parentNode      XMLElement    //直接父标签

经过 "." 访问element属性 。

    document对象为DOM的内置对象,表明XML文档的根

    在HTML文件中能够理解为body标签 。

    document.createElement( "div" ) ;

    document.createTextNode( "text" ) ; 建立文本

var txtA = document.createTextNode("hello");    //建立文本内容

var colA = document.createElement("td");  //建立标记

colA.appendChild(txtA);    //添加子标记

     element.getAttribute( Name ) ;

     element.setAttribute( "name" , value ) ;

     element.appendChild() 

     element.insertBefore( newNode , targetNode ) ;

     element.removeAttribute( node )

     element.removeChild( node ) ;

     element.replaceChild( newNode , oldNode ) ;      //用newNode替换oldNode

     element.hasChildnodes()

浏览器差别。

    1) table 和 tbody

2) 设置属性   ff     element.setAttribute( "name" , "value" ) ; 

                            ie     element.name = value

3

设置css   ff   element.setAttribute("style","color:blue" ) ;

              ie            element.style.cssText = "color:blue" ;

              ff            element.setAttribute("class","xxx" ) ;

              ie            element.className ;

 

1 变量没有数据类型 ---> 值有

                   基本数据类型 :

                            数字 | 字符串 | boolean

                                                                           |-  0,非0 | null 和非null

                   复合类型:

                   数组(没有固定长度,能够装任何类型的值)

                   对象(只有属性没有方法) 

2 变量能够重复声明

3 变量若是没有通过声明,系统会自动对其作隐式声明(做为全局变量)

4 function 函数名(a, b){}

5 经过构造方法建立函数: var fun = new Function("");

         经过函数直接量建立函数: var fun = function(){}

6 做为变量函数

         var fun;

         function testFun(a, b){

                    return a+b;

         }                                 

         fun = testFun; 

         fun(1,2);  

7 事件句柄:onclick……

8 DOM ---> getElementById

              getElementsByTagName

 


 

9各类表单验证=====================

1) 两次输入密码是否相同

<FORM METHOD=POST ACTION="">

<input type="password" id="input1">

<input type="password" id="input2">

<input type="button" value="test" onclick="check()">

</FORM>

<script>

 

function check(){

with(document.all){

if(input1.value!=input2.value) {

alert("false")

input1.value = "";

input2.value = "";

}

else document.forms[0].submit();

}}

</script>

 

2)6. 验证油箱格式

<SCRIPT LANGUAGE=javascript RUNAT=Server>

function isEmail(strEmail) {

if(strEmail.search(/^w+((-w+)|(.w+))*@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+)*.[A-Za-z0-9]+$/) != -1)

return true;

else alert("oh");

}

</SCRIPT>

<input type=text onblur=isEmail(this.value)>

 

3)表单项不能为空

<script language="javascript">

function CheckForm(){

if (document.form.name.value.length == 0) {

alert("请输入您姓名!");

document.form.name.focus();

return false;

}

return true;

}

</script>

 

4) 比较两个表单项的值是否相同(密码比较)

<script language="javascript">

function CheckForm()

if (document.form.PWD.value != document.form.PWD_Again.value) {

alert("您两次输入的密码不同!请从新输入.");

document.ADDUser.PWD.focus();

return false;

}

return true;

}

</script>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

servlet


Servlet是位于Web 服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不一样,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机

* 它们不是独立的应用程序,没有main()方法。* 它们不是由用户或程序员调用,而是由另一个应用程序(容器)调用。

* 它们都有一个生存周期,包含init()和destroy()方法。

 

要使用Servlet,必须导入包servlet-api.jar。这里使用的服务器是Tomcat,其主目录结构为 :

                |- bin : 用于存放可执行命令( catalina.sh )

           |- conf : 用于存放tomcat须要的配置文件.

           |- lib : 存放tomcat在运行时要用到的类文件(jsp-api.jar、servlet-api.jar、...).

           |- webapps : 最重要的一个目录,其下放置各类Servlet文件、网页文件(JSP HTML ...)、

                                                 配置文件以及资源文件.此目录的结构 :

                              |- 应用目录(好比是一个学生管理网站,就在webapps文件夹下建一个StudentManage目录)

                                       |- WEB-INF目录

                                                 |- classes目录, 放置全部的Servlet文件或其余类文件

                                                 |- lib目录, 放置本应用所要用到的类文件(jar包)

                                                 |- web.xml 配置文件

                                       |- 资源文件(好比图片), 网页文件(JSP HTML ...)

                                                                            

           |- logs : 日志文件 .

           |- work : 内部临时文件.

           |- temp : 临时文件.

安装tomcat  环境变量的配置,和配jdk差很少servlet-api.jar;jsp-api.jar

1  Servlet接口、GenericServlet类、HttpServlet :

         Servlet是最顶层的接口,其提供的方法有 :

                   init(ServletConfig config) : void   // 初始化  

                   getServletConfig() : ServletConfig  // 取得该Servlet配置信息

                   getServletInfo() : String                        // 取得相关信息

                   service(ServletRequest req, ServletResponse res) : void   //核心方法

                   destroy() : void   // Servlet生命周期结束时候执行的方法

                   显然咱们最关心的是service方法,其余的几个方法在实现的时候是千篇一概、无关痛痒的。故提

         供了GenericServlet类,此类实现了Servlet接口,咱们在使用Servlet的时候,只需继承这个类而后

         覆盖其中的service方法(抛出ServletException、IOException异常)便可。

                   因为Servlet基本上是在http协议下使用的,故提供了HttpServlet这个类,此类继承自

         GenericServlet类,咱们在使用Servlet时,只需继承HttpServlet类而后覆盖如下方法 :

                   service( HttpServletRequest request ,

                                      HttpServletResponse response )

                                      throws ServletException , IOException : void

                   注意:HttpServletRequest和HttpServletResponse分别是从ServletRequest和ServletResponse继承

                   此外,HttpServlet还提供了doPostdoGet方法,参数和返回值与service方法同样。只是service

         方法能够针对客户端的任何请求类型(GET和POST),而doPost和doGet方法分别只能对应客户端的POST方式

         请求和GET方式的请求。

HttpServlet-----àextends   GenericServlet ----à implements Servlet

使用GenericServlet实例 :

         package com.kettas.servlet;

         import javax.servlet.* ;

         import java.io.* ;

         public class GenDateServlet extends GenericServlet{

                   @Override

                   public void service( ServletRequest request , ServletResponse response )

                            throws ServletException ,IOException

                   {                response.setContentType( "text/html" ) ; // 设置响应内容类型

                                      PrintWriter out = response.getWriter();// 得到文本写入流

                                      // 给客户端回应的html文本

                                      out.println( "<html>" ) ;

                                      out.println( "<body>" ) ;

                                      out.println( "<h1>Hello Servlet !</h1>" );

                                      out.println( "</body>" ) ;

                                      out.println( "</html>" ) ;

                                      out.flush();// 刷新写入

                   }}

         配置文件web.xml以下 :

                   <?xml version="1.0" encoding="UTF-8"?>

                   <web-app xmlns="http://java.sun.com/xml/ns/javaee"

                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

                      version="2.5">          

                            // Servlet文件路径

                            <servlet>

                                     <servlet-name>query</servlet-name>

                                     <servlet-class>com.kettas.servlet.GenDateServlet</servlet-class>

                            </servlet>      

                            // 指定映射,说明在浏览器中输入".../query"则对应当前Servlet                              

                            <servlet-mapping>

                                     <servlet-name>query</servlet-name>

                                     <url-pattern>/query</url-pattern>

                            </servlet-mapping>

                   </web-app>

使用HttpServlet简单实例 :

         package com.kettas.servlet ;

         import javax.servlet.* ;

         import javax.servlet.http.* ;

         import java.io.* ;

         public class LoginServlet extends HttpServlet{

                   @Override

                   public void service( HttpServletRequest request , HttpServletResponse response )

                            throws ServletException , IOException

                   {   response.setContentType("text/html; charset=GB2312"); // 注意设置编码的方式

                            request.setCharacterEncoding("GB2312");

                            PrintWriter out = response.getWriter();

                            // 取得客户端提交的数据

                            String name = request.getParameter( "userName" ) ;

                            String pwd = request.getParameter( "password" ) ;

                            out.println("<html>");

                            out.println("<body>");

                            out.println("<h1>");

                            out.println("Name : " + name + "   " + "Password : " + pwd);

                            out.println("</h1>");

                            out.println("</body>");

                            out.println("</html>");

                            out.flush();

                   }}

配置文件web.xml片断 :

                            <servlet>

                                     <servlet-name>login</servlet-name>

                                     <servlet-class>com.kettas.servlet.LoginServlet</servlet-class>

                            </servlet>                                     

                            <servlet-mapping>      

                                     <servlet-name>login</servlet-name>

                                     <url-pattern>/login</url-pattern>

                            </servlet-mapping>

请求转发 :

         实现不一样servlet之间的数据传递,这样即可实现业务逻辑和显示逻辑的分离

         实例 :

                   (1) 第一个servlet,负责业务

                            package com.kettas.servlet ;

                            import javax.servlet.* ;

                            import javax.servlet.http.*;

                            import java.io.*;

                            import java.util.* ;

                            public class ForwardA extends HttpServlet{

                                     @Override

                                     public void service( HttpServletRequest request , HttpServletResponse response )

                                               throws ServletException , IOException

                                     {           System.out.println( "=== This is forward A ===" ) ;

                                                  // 将业务部分的数据存储在request对象中,传递给下一个servlet使用

                                                  Date d = new Date();

                                                  request.setAttribute( "date" , d ) ;

                                                  /* 注意转发的过程

                                                      * 首先得到一个知道下一棒地址的"接力棒"对象,而后将这个"接力棒"传给下一个

                                                      * servlet,这样便将请求转发了。

                                                      */

                                                  RequestDispatcher disp = request.getRequestDispatcher( "/forwardB" ) ;

                                                  disp.forward( request , response ) ;

                                     }

                            }

                            注意 : 1 这种请求转发的方式是共用一个链接的,无论你中途通过了多少个servlet,正因如此,

                                                这些servlet才能共享request中存储的数据。

                                        2 只有最后一个servlet,才能在客户端浏览器中显示。

                   (2) 第二个servlet,负责显示

                            package com.kettas.servlet ;

                            import javax.servlet.* ;

                            import javax.servlet.http.*;

                            import java.io.*;

                            import java.util.* ;

                            public class ForwardB extends HttpServlet{

                                     @Override

                                     public void service( HttpServletRequest request , HttpServletResponse response )

                                               throws ServletException , IOException

                                     {       response.setContentType( "text/html" );

                                                  PrintWriter out = response.getWriter();

                                                  out.println( "<h2>This is forwared B</h2>" ) ;

                                                  // 经过getAttribute方法,从request中取得数据

                                                  // 因为此方法返回的是Object对象,故要强转

                                                  Date d = (Date)request.getAttribute( "date" ) ;

                                                  out.println( "<h2>" + d + "</h2>" ) ;

                                                  System.out.println( "=== This is forward B ===" ) ;

                                                  out.flush();

                                     }

                            }

                   (3) web.xml片断 :

                                     <servlet>

                                               <servlet-name>a</servlet-name>

                                               <servlet-class>com.kettas.servlet.ForwardA</servlet-class>

                                     </servlet>                                 

                                     <servlet-mapping>

                                               <servlet-name>a</servlet-name>  

                                               <url-pattern>/forwardA</url-pattern>

                                     </servlet-mapping>

                                     <servlet>

                                               <servlet-name>b</servlet-name>

                                               <servlet-class>com.kettas.servlet.ForwardB</servlet-class>

                                     </servlet>                                 

                                     <servlet-mapping>

                                               <servlet-name>b</servlet-name> 

                                               <url-pattern>/forwardB</url-pattern>

                                     </servlet-mapping>

    页面跳转的两种方式 1)request.getRequestDispatcher(“/forwardA”).forward(request , response); 这种跳转是在服务器内部是servlet之间跳转,显示的老是最后一个servlet  A-àB--à----àD

                        2)response.sendRedirect(“mayservlet/query”) 它实际上是在客户端的url发生改变,至关一次新的请求,故不能传递数据,但能在不一样的应用中跳转

关于Cookie, 在客户端浏览器保存用户状态的一种机制

         servlet中的Cookie含有三个属性: name, value, maxAge

         maxAge = 60 表示:此cookie在客户端存在1分钟

         两个特殊值:

         maxAge = -1 表示 : 此Cookie生命周期由保存它的浏览器决定 ,(浏览器开则生,关则死),默认的

         maxAge = 0  表示 : 删去之前的相应cookie存储

         Cookie应用实例 :

                   package com.kettas.servlet ;

                   import javax.servlet.*;

                   import javax.servlet.http.*;

                   import java.io.*;

                   public class CookieServlet extends HttpServlet{

                            @Override

                            public void service( HttpServletRequest request , HttpServletResponse response )

                                     throws ServletException , IOException

                            {// 建立一个新的Cookie对象, 构造参数分别为Cookie的name和value属性

                                     Cookie c = new Cookie( "test" , "1234567890" );

                                     // 将Cookie对象加入response中,这样才能被带入客户端

                                     response.addCookie( c ) ; 

                                     // 从请求中获取客户端Cookie数组

                                     Cookie[] cookies = request.getCookies();

                                     response.setContentType( "text/html" );

                                     PrintWriter out = response.getWriter();

                                     out.println("<html>");

                                     out.println( "<body>" ) ;

                                     out.println( "<h1>Cookie List</h1><hr/><p></p>" ) ;

                                     if( cookies != null ){

                                               for( Cookie cookie : cookies ) {

                                                        out.println( "<h2>" + cookie.getName() + "=" + cookie.getValue() + "</h2>" ) ;

                                               }

                                     }else{

                                                 out.println( "<h2>No cookie</h2>" ) ;

                                     }

                                     out.println( "</body>" ) ;

                                     out.println("</html>");

                                     out.flush();

                            }

                   }          

6  关于HttpSession, 在服务器端保存用户状态的一种机制

         (1) 获取HttpSession对象的方法 :

              // 参数为true,表示若存在对应的HttpSession对象,则返回。若不存在,则建立一个新的。

              // 若参数为false,表示若存在对应的HttpSession对象,则返回。若不存在,则返回null。

                    HttpSession session = request.getSession(true);

         (2) 对HttpSession对象, 进行存取数据的操做

         // 两个参数,分别为命名属性和对应的数据

         session.setAttribute("name", data);

         // 一个参数,命名属性,注意返回的为Object对象,要强转

         session.getAttribute("name");

    (3) 比较Session和request :

        request :

            建立 : 当用户请求到达服务器的时候

            销毁 : 当本次请求的应答回到客户端的时候.

                   客户端的一次请求应答之间

        session :

            建立 : 当用户第一次调用request.getSession( true )

            销毁 : 超时 ( 两级超时限制 )

                          1) 内存 ---> 文件 .

                             2) 从文件系统销毁 .      

        session的原理 :

             给每一个浏览器一个cookie,这个cookie的name属性为"jsessionid",value属性为这个session

             对应的ID值。

    (4) 当浏览器拒绝cookie时能够用URL把session的id提交给服务器

       如 : http://localhost:8989/servletapp/forwardB;jsessionid=37D50D093CCD4A37CC1118785E38F438

                 "url;jessionid="+ session.getId()

       response.encodeURL("url") :对url进行编码

7  ServletConfig对象和ServletContext对象

       (1)ServletConfig : 用来保存一个Servlet的配置信息的(好比 : name, class, url ... )

                这些配置信息没什么大用处,咱们还能够在ServletConfig中保存本身在web.xml文件中定义的数据

                此时的web.xml文件片断以下 :

                        <servlet>

                                       <!-- 本身定义的,要保存在ServletConfig对象中的数据 -->

                                   <init-param>

                                            <param-name>jdbc.driver</param-name>

                                            <param-value>oracle.jdbc.driver.OracleDriver</param-value>

                                   </init-param> 

                                   <init-param>

                                            <param-name>jdbc.user</param-name>

                                            <param-value>yinkui</param-value>

                                   </init-param>

                                   ...

                                   <servlet-name>query</servlet-name>

                                   <servlet-class>com.kettas.servlet.Query</servlet-class>

                              </servlet> 

                     在Servlet中取得这些数据 :

                                    // getServletConfig方法继承自父类GenericServlet

                                     ServletConfig sc = this.getServletConfig();

                                     // 显然,getInitParameter方法返回的只能是字符串类型数据

                                     String driver = sc.getInitParameter("jdbc.driver");

                                     String user = sc.getInitParameter("jdbc.user");

            注意: 1 ServletConfig对象只能从web.xml文件中获取自定义数据(字符串数据),不存在setAttribute

                             方法去存入自定义数据。

                           2 在Servlet中,若要覆盖父类的init(ServletConfig config)方法,必须这么作 :

                               public void init( ServletConfig config ){

                                             // 覆盖以前调用父类的这个方法, 不然ServletConfig对象会丢失

                                             // 此时this.getServletConfig()返回的是null, 那样咱们就不能使用它了

                                             super.init( config ) ;

                                   ...   }                              

       (2)ServletContext : 用来保存数据的全局惟一对象,一个应用中只有一个ServletContext对象

                       1 : 经过web.xml文件,在ServletContext对象中存入数据

                                 此时的web.xml文件片断以下所示 :

                                          <!-- 在此处写入咱们要存入ServletContext对象中的数据 -->

                                          <context-param>

                                                       <param-name>jdbc.driver</param-name>

                                                       <param-value>oracle.jdbc.driver.OracleDriver</param-value>

                                               </context-param>

                                               <context-param>

                                                        <param-name>jdbc.url</param-name>

                                                        <param-value>jdbc:oracle:thin:@192.168.0.201:1521:kettas</param-value>

                                               </context-param> 

                                               ...

                                               <servlet>

                                                        <servlet-name>...</servlet-name>

                                                        <servlet-class>...</servlet-class>

                                               </servlet>    

                                     取得其中的数据 :           String driver = servletContext.getInitParameter("jdbc.driver");

                       2 : 经过setAttribute方法,在ServletContext对象中存入数据

                               servletContext.setAttribute("name", data); // 两个参数分别为命名属性以及对应的数据

                               // 取得ServletContext对象中的数据, 参数为命名属性

                               // 返回的是Object对象, 故要强转

                               servletContext.getAttribute("name");

                       3 : 取得ServletContext对象的三种方法(this指代当前Servlet)

                                 (1) ServletContext sc = this.getServletContext();

                                 (2) ServletContext sc = this.getServletConfig().getServletContext();

                                 (3) ServletContext sc = request.getSession(true).getServletContext();

                                 ServletContext对象的一个重要方法 :                                                 

                                   InputStream is = sc.getResourceAsStream( "fileName" ) ;

                                           fileName : 使用的是虚拟目录, 不依赖于实际路径/books/ajax.pdf

                                         最左边一个"/" : web 应用的根目录 

                                    // 得到实际路径        String path = ctx.getRealPath( "/books/ajax.pdf" )

监听事件和过滤器

         监听包括三种状况,分别是HttpRequestSessionServletContext监听。

经常使用的是implements  servletContextListener(全局变量)两个方法 public void contextInitialized(ServletContextEvent arg0)

                                                             arg0.getServletContext()

Session监听事件所示 :

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpSessionEvent;

import javax.servlet.http.HttpSessionListener;

import com.kettas.upp02.util.Constant;

public class SessionListener implements HttpSessionListener {

         public void sessionCreated(HttpSessionEvent ent) {

                   HttpSession session = ent.getSession();

                   synchronized (this) {

                            ServletContext ctx = session.getServletContext();

                            Integer counter = (Integer) ctx.getAttribute("sessionCount");

                            ctx.setAttribute("sessionCount", counter.intValue() + 1);

                            System.out.println(Constant.LOGO + "SessionCount:"

                                               + (counter.intValue() + 1));

                   }}

         public void sessionDestroyed(HttpSessionEvent ent) {

                   HttpSession session = ent.getSession();

                   synchronized (this) {

                            ServletContext ctx = session.getServletContext();

                            Integer counter = (Integer) ctx.getAttribute("sessionCount");

                            ctx.setAttribute("sessionCount", counter.intValue() - 1);

                            System.out.println(Constant.LOGO + "SessionCount:"

                                               + (counter.intValue() - 1));

                   }

         }}

         在web.xml文件中配置以下 :

                   <listener>

                            <listener-class>shop. SessionListener </listener-class>

                   </listener>

                  

         其余两个监听事件的实现同上并没有二致。                                    

过滤器       // 实现Filter接口

import java.io.IOException;

                                     import javax.servlet.*;

                                     public class EncodingFilter implements Filter{

                                     //销毁时执行,不必覆盖

                                               public void destroy() {}

                                               //发送请求时执行

                                               public void doFilter(ServletRequest request, ServletResponse response,

                                                                 FilterChain chain) throws IOException, ServletException {

                                                        //设置发送请求和接收请求时的编码方式,统一才能达到过滤做用

                                                        request.setCharacterEncoding("UTF-8");

                                                        response.setCharacterEncoding("UTF-8");

                                                        try {

                                                                 chain.doFilter(request, response); 请求转发

                                                        } catch (RuntimeException e) {

                                                                 e.printStackTrace();

                                                        }}

                                               //加载时执行,也不必执行

                                               public void init(FilterConfig arg0) throws ServletException {}

                                     }

                   web.xml文件中:

                     //配置当发生什么要的请求时,让那个过滤流执行操做

                        <filter>

                                     <filter-name>encodingFilter</filter-name>

                                     <filter-class>filter.EncodingFilter</filter-class>

                            </filter>

                            <filter-mapping>

                                     <filter-name>encodingFilter</filter-name>

                                     <url-pattern>/*</url-pattern>

                            </filter-mapping>

9,解决乱码问题  1)response.setContentType(“text/html;charset=gbk2312”)

                 2)requset.setCharacterEnconding(“gbk”)  ------是post的时候

                 3)在server.xml中加URLEncoding=“gbk”------是get发送数据的时候

10,servlet的生命周期

        1Servlet在容器中运行,其实例的建立及销毁等都不是由程序员决定的,而是由容器进行控制的。

建立Servlet实例有两个时机:1客户端第一次请求某个Servlet时,系统建立该Servlet的实例:大部分的Servlet都是这种Servlet。

2,Web应用启动时当即建立Servlet实例,即load-on-startup     <load-on-startup>1</load-on-startup>

Servlet的生命周期经过javax.servlet.Servlet接口中的init()service()destroy()方法来表示。

每一个Servlet的运行都遵循以下生命周期。

1)加载和实例化:找到servlet类的位置经过类加载器加载Servlet类,成功加载后,容器经过Java的反射API来建立Servlet实例,调用的是Servlet的默认构造方法(即不带参数的构造方法),

2)初始化:容器将调用Servlet的init()方法初始化这个对象。初始化的目的是为了让Servlet对象在处理客户端请求前完成一些初始化的工做,如创建数据库的链接,获取配置信息等。对于每个Servlet实例,init()方法只被调用一次

3)请求处理:Servlet容器调用Servlet的service()方法对请求进行处理。要注意的是,在service()方法调用以前,init()方法必须成功执行

4)服务终止:容器就会调用实例的destroy()方法,以便让该实例能够释放它所使用的资源

考点 2)从始至终只有一个对象,多线程经过线程池访问同一个servlet

Servlet采用多线程来处理多个请求同时访问,Servelet容器维护了一个线程池来服务请求。

线程池其实是等待执行代码的一组线程叫作工做者线程(WorkerThread),Servlet容器使用一个调度线程来管理工做者线程(DispatcherThread)。

当容器收到一个访问Servlet的请求,调度者线程从线程池中选出一个工做者线程,将请求传递给该线程,而后由该线程来执行Servlet的service方法。

当这个线程正在执行的时候,容器收到另一个请求,调度者线程将从池中选出另一个工做者线程来服务新的请求,容器并不关系这个请求是否访问的是同一个Servlet仍是另一个Servlet。

当容器同时收到对同一Servlet的多个请求,那这个Servlet的service方法将在多线程中并发的执行。

3)、如何现实servlet 的单线程模式

<%@ page isThreadSafe=”false”%>

 

 

 

 

 

 

 

 

 

 

JSP

1  JSP 语法:

   jsp中嵌入java代码的方式 :

        1) 表达式标签 <%=  1 + 1 %>

            a) 计算表达式的返回值 .

            b) 能将返回值在网页上显示出来 .

               不能出现 ";"

               <%= 1+1%>则在网页上显示2

        2) 声明标签 : <%!    %>

            用来声明变量和函数, 在声明标签中声明的变量和函数, 能够在本页面的其余的java代码中使用.

            声明的位置是首是尾皆无妨. 建议尽可能少声明变量, 由于jsp最终要被解释为servlet, 声明的变

            量在servlet中就体现为实例变量, 在多个线程访问这个servlet的时候, 因为实例变量被多个线

            程共享使用(实例变量线程不安全, 局部变量线程安全), 有可能出现问题, 而且很差解决.

        3) 普通脚本 :  <%   %>   普通脚本是不能嵌套的

            <%

              for( int i = 0 ; i < 10 ; i++ ){

                      <%= 1+ 1 %>

              }

            %>

指令元素 : 用来讲明一个jsp文件自身的一些特色.

              以便服务器(tomcat)做出正确的处理 .

    页面指令 :

    <%@page contentType="text/html;charset=utf-8" %>

    <%@page import="java.util.*" %>

    标签库指令

<%@taglib %> 

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

    包含指令 :静态包含

      用来包含其余jsp的源代码 (静态包含).

      所谓静态包含, 就是先将引入的jsp页包含入本页面中, 而后解释为同一个servlet

      <%@include file="xxx"%>  静态包含包含的是源代码,考虑变量冲突,而且xxx后面不能传参数   

动做元素                

    <jsp:include page="/a.jsp" />   

    动态包含: 包含的是对方的输出结果, 分别解释为不一样的servlet.

    动态包含实例 :

      

 

(1) header.jsp :

                <%

                   String text = request.getParameter( "text" ) ;

            %>

                   <center>

                   <h1>       

                   <font color="blue">

                   <%

                      if( text != null ){

                     %>                  

                            <h1><%=text%></h1>

                      <%

                     }else{

                       %>

                            <h1>Welcome to kettas</h1>

                        <%

                   }

                             %>

                   </font>

                   </h1>  

         </center>  

 

 

 

 

 

 

 

      

       (2) body.jsp :

                <%@page contentType="text/html" %>

                            <html>

                            <body>

<!-- 至关于<jsp:include page="/header.jsp?name=This is param"/> -->                   

         <jsp:include page="/header.jsp">

                   <jsp:param name="text" value="This is param"/>

                            </jsp:include> 

                   <h1>This is body</h1>

                            <%

                                     for(int i = 0 ; i< 3 ; i++ ){

                            %>

                            <h1><%= new java.util.Date() %></h2>

                            <%

                                     }

                            %>                                         

                            <%

                                     for( int i =0 ; i < 3 ; i++ ){                 out.println( "<h2>" + new java.util.Date() + "</h2>" ) ;

                            }

                       %>

                            </body>

                   </html>

    <jsp:forward page="/b.jsp" />

       页面转向 : 至关于servlet中的"接力棒"转向, 是在同一个链接中的页面转向.

    <% response.sendRedirect("/a.jsp"); %>

页面转向 : 链接已经换了一个.

 

        

 

 

 

4  jsp 中的隐含9对象 . (能够直接拿来使用)

    request ----> HttpServletRequest .

    response ---> HttpServletResponse .

    session ----> HttpSession .

    application -> ServletContext .

                   |-> web.xml

                   |-> setAttribute, getAttribute.

                   |-> 全局惟一 . 

    如下四个用的不多, 知道有这个东西便可  

    out  ---------> response.getWriter();<% out.println()%>

    config -------> ServletConfig <在xml中也能够配置servlet,能够配置初始化参数>

    exception  ---> Exception

    page    ------> Object

    至关重要的隐含对象, 重点说明之

    pageContext --> javax.serlvet.jsp.PageContext

    关于pageContext :

               1, 自己也是一个能存储命名属性的做用域 .

                     setAttribute("name", data)

                     getAttribute("name")

                     pageContext 做用域和声明周期 .

                     声明周期只局限在本页面 .

                     在同一页面的不一样标签之间传递数据 .(本页面共享数据)

                     同时保证数据不流传到其余页面上 .             

               2, 能够管理其余做用域中的命名属性 .

                    pageContext.getAttribute("name");

                    pageContext.getAttribute("name",int scope);

                            scope 值为:

                       PAGE_SCOPE

                       REQUEST_SCOPE

                       SESSION_SCOPE

                       APPLICATION_SCOPE

                       为了选择做用域

                    pageContext.setAttribute( "name" , value );

                    pageContext.setAttribute( "name" , value , int scope );  

                    pageContext.findAttribute( "name" ) ;

                    按照从小到大的顺序依次查找做用域中的命名属性 .

                    pageCOntext --> request ---> session  --> application

                            pageCOntext.findAttribute( "a" ) ;

               3, 得到其余全部的隐含对象 .

                   pageContext.getRequest() ---> request

                   pageCOntext.getSession()

                   pageCOntext.getConfig()

                   pageCOntext.getOut()

               注意 :  隐含对象在表达式标签和普通脚本中均可以使用

                                           <%= request.getParameter("name") %>

                                       <%  sesison.getAttribute() %>

                            可是在声明脚本中不能用, 好比 :

                                       <%!

                                            void fn(){

                                                     session.getAtrreibute();

                                            }

                                       %>

5  JSP的几个页面指令 :

         页面指令  : 向服务器说明页面自身的特征,以便服务器

           1 <%@page contentType="text/xml;charset=utf-8" %> 客户端--->>服务端的编码

           2 <%@page import="" %> 引入名字空间      

           3 <%@page pageEncoding="GBK/GB2312/utf-8"%>(网页的静态内容乱码想到pageEncoding,

                jsp文件文本编辑器所采用的编码)--->服务器内部使用的用来指定jsp 源文件所采用的编码方式.           

           4 <%@page isELIgnored="false" %> EL一种表达式语言,默认值不一样的服务器不同,最好明确写出            

                 ${ 1+1 } (false:显示结果。true:显示 ${ 1+1 }源代码)           

           5 <%@page errorPage="/error.jsp"%>

                 指定错误页面 .

                 jsp ---> 业务代码 .

           6 <%@page isErrorPage="true|false"%>当是TRUE时就会有exception的隐含对象

             <%@page isErrorPage="true" errorPage="/other.jsp"%>  不能这样转

             A(源页面) -------------------------> B(错误页面)

             errorPage="B"           isErrorPage="true"          

           7 <%@page session="true"%>--默认值, 表示本页面是否须要session对象.

             在servlet中只有直接调用才能获得,而jsp中默认是有的

             <%@page language="java"%>默认的语言

             <%@page extends="XXX" %>服务器本身决定

             <%@page buffer=""%>   服务器本身决定调节

6  JSP(Servlet)中从链接池获取链接

       1) 创建链接 .

       2) 执行SQL   .

       3) 处理结果  .

       4) 释放资源 .   

     Connection pool  链接池

     DataSource 

     LDAP ( Light directory access protocal )轻量级目录访问协议

     JNDI ( java naming director interface ) Java 命名目录接口

  使用链接池 :

    1) 配置链接池

        改配置文件 conf/context.xml  

                    <Resource driverClassName="oracle.jdbc.driver.OracleDriver" 

                     注:jar包应该放在外边的lib包中,由于它是给tomcat用的

                                            url="jdbc:oracle:thin:@127.0.0.1:1521:XE"

                                            username="kettas"

                                            password="kettas"

                                            maxActive="2"  最大链接数

                                            type="javax.sql.DataSource" 链接类型

                                            auth="Container"  通常不改

                                            name="oracle/ds" 

                                            />

    2) 使用DataSource   

       用法:%@page import="javax.naming.*"%>

                <%

                     Context ctx = new InitialContext();

                     DataSource ds = (DataSource)ctx.lookup("java:comp/env/oracle/ds");tomcat特色:必须加java:comp/env/*

                     Connection conn = ds.getConnection();

                     out.println( "<h1>get connection!</h1>" );

                     conn.close();

                   %>

处理javabeanJSP标签

         (1) 关于javabean要求:

                        1 具备无参的构造函数 .

                        2 针对每个成员变量,因改提供相应get/set

                        3 implments Serializable(实现才能对象序列化)

         (2) <jsp:useBean />

                      使用一个保存在某个做用域(pagecontext , request ,session, application)中的javabean .

                      <jsp:useBean id="user" class="beijing.User" scope="session"/>

                         实际上执行的代码为 : User u = session.getAttribute("user");

                         id的含义 : 1, 为要使用的javabean取个名字.  

                                            2, javabean在session做用域中的命名属性.

                         class : java bean 的类型.

                         scope : 指定一个做用域(page,request,session,application), 若不指定, 则由小到大.

         (3) <jsp:setProperty /> 五种设置属性的方法

                   <jsp:setProperty name="" property="" value=""/>

                            name: 被操做的javabean 的名字. 即useBean中的id

                            property: 属性名称 id , name , phone

                            value: 值 

                   <jsp:setProperty name="" property="" param=""/>

                       param:表示该属性的值来自于客户端提交的参数. param用来指定这个参数的名字.   

                   <jsp:setProperty name="" property=""/>

                       客户端提交的参数名称和成员变量的名称正好一致. 省略param

                   <jsp:setProperty name="" property="*"/>

                       用一个标签为全部的属性赋值, 属性的值来自于客户端提交的参数,

                       参数名字和属性名字 一一对应.

         (4) <jsp:getProperty />

                   使用javabean中的属性, 可用于页面显示 .

                 <jsp:getProperty name="" property=""/> 

                            name: 被操做的javabean 的名字. 即useBean中的id

                            property: 属性名称 id , name , phone

                   使用片断以下 :    

                            <html>

                                     <body>           

                                               <h2><jsp:getProperty name="user" property="name" /></h2>

                                               <h2><jsp:getProperty name="user" property="id"/></h2>

                                               <h2><jsp:getProperty name="user" property="phone"/></h2>

                                               <h2><jsp:getProperty name="user" property="password"/></h2>

                                     </body>

                            </html>

使用自定义的标签

         (1) 构思, 好比写一个对指定名字说hello的标签, 应该是<前缀:hello user="zhagnsna"/>

         (2) 写类

                   要实现的基础接口 :  javax.serlvet.jsp.tagext.SimpleTag

                            其中含有五个方法 :

                             doTag         ---> 实现标签的功能 .

                               setJspContext ---> pageContext .

                               setParent     ---> 父标签的实现类                         

                              setJspBody    ---> JspFragement

                               getParent  

                 要实现五个方法, 显得很繁琐, javax.servlet.jsp.tagext.SimpleTagSupport类实现了这个

                 基础接口, 咱们在写类时只须要继承这个类, 而后覆盖doTag方法便可.

             类以下 :

                package com.kettas.tag ;

                            import javax.servlet.http.*;

                            import javax.servlet.jsp.tagext.* ;

                            import javax.servlet.jsp.* ;

                            import java.io.* ;

                            public class HelloHandler extends SimpleTagSupport{

                                               private String user ;

                                               public void setUser( String user ){

                                                        this.user = user ;

                                               }                  

                                               public String getUser(){

                                                        return user ;

                                               }             

                                               @Override

                                               public void doTag() throws JspException , IOException{

                                                        PageContext ctx = (PageContext)this.getJspContext();

                                                        ctx.getOut().println( "hello " + user  );

                                                        ctx.getOut().flush();

                                               }

                            }

         (3) 写tld配置文件(位置为 : /WEB-INF/***.tld)

                   <?xml version="1.0" encoding="UTF-8"?>

                   <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

                            "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

                   <taglib>

                            <tlibversion>1.0</tlibversion>

                            <jspversion>2.0</jspversion>

                            <shortname>mytag</shortname>

                            <!-- 指定命名空间 引入标签时使用 -->

                            <uri>liucy@cernet.com</uri>

                            <tag>

                                     <!-- 标签名 -->

                                     <name>hello</name>

                                     <!-- 标签对应的类 -->

                                     <tag-class>com.kettas.tag.HelloHandler</tag-class>   

                                     <!-- 标签体之中是否含有内容 -->

                                     <body-content>empty</body-content>

                                     <!-- 标签属性 -->

                                     <attribute>

                                               <name>user</name>

                                               <type>java.lang.String</type>

                                               <required>true</required>

                                               <rtexprvalue>true</rtexprvalue>

                                     </attribute>

                            </tag>

                   </taglib>

         (4) 在jsp文件中使用

                   <%@page contentType="text/html"%>

                   <%-- 注意引入自定义标签的方式, prefix属性指定标签前缀, 前缀解决不一样标签库标签重名 --%>

                   <%@taglib uri="liucy@cernet.com" prefix="liucy"%>

                   <html>                                       

                            <body>

                                     <h2>

                                               <liucy:hello user='<%= request.getParameter( "name" )%>'/>

                                     </h2>

                            </body>

                   </html>

                   自定义一个循环标签 :

                            : =================================================================

                                    

 

package com.kettas.tag ;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

import javax.servlet.jsp.tagext.*;

import java.io.*;

public class LoopHandler extends SimpleTagSupport{

private int begin ;

private int end ;

public void setBegin( int begin ){

         this.begin = begin ;

         }                    

         public int getBegin( ){

                  return begin ;

                   }              

         public void setEnd(int end ){

                   this.end = end ;

         }                

         public int getEnd( ){

         return end ;

                   }

         @Override

         public void doTag()throws JspException ,IOException{

           // JspFragment对象能够获取标签体内部的内容

           JspFragment f = this.getJspBody();

           PageContext ctx = (PageContext)this.getJspContext();

  for( int i = begin ; i < end ; i++){

                   f.invoke( ctx.getOut() );

                              }

                   }

         }

 

                  

         配置文件以下 :=================================================================

                  

 

<?xml version="1.0" encoding="UTF-8"?>

         <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"

                            "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

                   <taglib>

                            <tlibversion>1.0</tlibversion>

                            <jspversion>2.0</jspversion>

                            <shortname>mytag</shortname>

                            <uri>liucy@cernet.com</uri>

                            <tag>

                            <name>hello</name>

                            <tag-class>com.kettas.tag.HelloHandler</tag-class>   

                            <body-content>empty</body-content>

                            <attribute>

                            <name>user</name>

                            <type>java.lang.String</type>

                            <required>true</required>

                            <rtexprvalue>true</rtexprvalue>

                            </attribute>

                            </tag>

                            <tag>

                            <name>loop</name>

                            <tag-class>com.kettas.tag.LoopHandler</tag-class>

                            <!-- 标签体内含有内容, 而且是非脚本的内容 -->

                                     <body-content>scriptless</body-content>

                            <attribute>

                            <name>begin</name>

                            <type>int</type>

                   <required>true</required>                                                 <rtexprvalue>true</rtexprvalue>

                            </attribute>

                            <attribute>

                            <name>end</name>

                  <type>int</type>

                  <required>true</required>

                   <rtexprvalue>true</rtexprvalue>

                  </attribute>

                   </tag>

         </taglib>

 

                            使用以下 :======================================================================

                                     <%@taglib uri="liucy@cernet.com" prefix="liucy"%>

                                     <liucy:loop begin="0" end="3">

                                               <h2>Hello !</h2>

                                     </liucy:loop>

                                     如此即可连续在网页上输出三个"Hello !"

 

 

9  EL表达式( ${ } )

           (1) 完成一些简单运算.

                 数学运算

                          + - * % /      ${ a + b }

                 布尔运算

                 >       gt  ( great than )

                 <       lt  ( less than )

                 >=      ge  ( great equal )

                 <=      le  ( less equal )

                  !=      ne  ( not equal )

                 ==      eq  ( equal )

                 ${ a > b }   ${ a gt b }

            逻辑运算

                     && || !

                     and or not 

            非空运算 :

                   a == null

                   ${ not empty a }

                      |-> a 不存在返回true

                      |-> a 存在 返回false 

           (2) 经过EL表达式,快捷的访问做用域中的命名属性

               <%= session.getAttribute( "name" )%>

               用EL表达式 : ${ name }

           (3) 快速访问javabean的属性.

               <jsp:getProperty name="user" property="name"/>

               用EL表达式 : ${ user.name }

           (4) 经常使用隐含对象 .

               ${ param } 

               ${ param.age }

               ${ param.name }

               至关于 : <%= request.getParameter( "name" ) %>

               用来访问客户端提交的参数.

               ${ cookie.age }

               实际要执行的代码 :

                         Cookie[] c = request.getCookies();

                         for( Cookie a : c ){

                                    if(a.getName() == "age"){

                                            a.getValue();

                                            ...

                                    }

                         }

10 JSP写的一套核心标签, 有了这套标签, 根本不须要自定义标签了

         (1) 准备

                   须要standard.jar, jstl.jar两个jar包, 放入Tomcat 6.0/lib目录中(或者是/WEB-INF/lib)

(2)core<%@tagliburi="http://java.sun.com/jsp/jstl/core"

prefix="c"%>

         forEach循环

     ①通常用法 至关普通的for循环

<c:forEach begin =”1” end=”10” varstatas="st">

                ${ st.count }</c:forEach>

 

               

 

② 迭代循环 集合

<c:forEach var="u" items="${ users }">

                                  ${ u .name}

                 </c:forEach>

如果map集合${ user.key}获得值的集合

             set 

                        (1)<c:set var="a" value="1234"/>  

                        (2)<c:set var="a">

                        xxxxx

                        </c:set>  把标签体内全部的输出都看成var的值,不直接显示在网页上

                             使用须要调用${a}

                   remove    

                        <c:remove var="a"/>

                                    ${a}

                   url

                        <c:url var="date" value="/jspapp/date.jsp">

                        <c:param name="age" value="23"/>

                        <c:param name="name" value="lisi"/>

                        <c:param name="passwd" value="ffff"/>

                        </c:url>

 

                        <a href="${date}">test</a>

                        /jspapp/xxx.jsp?age=23  

<a href="/jspapp/xxx.jsp?age=23&name=lsis&passwd=123">

                          test

                        </a>

                      if swith

               <c:if test=”s{4>2}”>xxxxx</c:if>

 

                      <c:choose>

                          <c:when test="a">

                                    cccccccc

                          </c:when>

                          <c:when test="b"></c:when>

                          ....

                      </c:choose>

                      <c:choose>

                          <c:when test="">

                                    cddddddd

                          </c:when>

                          <c:when test="">

                           sssss

                          </c:when>

                          <c"when test="">

                           xxxxxx

                          </c:when>

                          <c:otherwise>

                         

                          </c:otherwise>

                      </c:choose> 


 


 

第五天:===========================

MVC :

   M : model ( 业务逻辑与业务数据 ): javabean

   V : view ( 显示逻辑 )

        将数据按照用户的    要求显示出来 .

        对同一份数据而言,能够 以 多种形式

        体现 ( 类表, 屏图,柱图 等等 )

           用JSP实现。

   C : controller ( 控制器 , 负责程序的流程控制 )

       接收用户请求 , 根据业务逻辑的执行状况 返回

       相应的结果 .

                 用Servlet来实现。

===================================================

好处 :

   1) 各司其职, 解耦合 .

      代码可重用。

================================================

前端控制器(Servlet)的工做指责 :

  1) 可以接受全部的用户请求 .

      <url-pattern>*</url-pattern>

  2) 能跟据请求的不一样 调用 不一样的处理(javabean) .

      a, 请求的不一样 ---> url ---> servletpath

         http://loxxx:8080/app/login

         http://loxxx:8080/app/query

         request.getServletPath() --> path

          

          login=A f1 f2 f3

         

=================================

query=B

          delete=C

         

      b, 经过一个配置文件,向servlet说明 被调用

         组件 和 serlvetpath 之间的对应关系 .

      C, 要求全部的被调用的组件 必须按照某个接口

         的规发来进行开发 .这样才能由servlet正确的

         调用 . 

        

Action的主要做用是得到参数,让业务(Biz)处理,而后把处理的结果返回给Action再返回给Servlet。

         public interface Action{

          public String  execute( request , response )

         }

         LoginAction

            execute( Request , response ){

            String name = request.getParameter( .. ) ;

            String pwd = request.getParameter( "" );

                 UserBiz biz = new UserBiz();

                 biz.login( name , pwd );

                 return "ok.jsp|error.jsp" ;

          }

         UserBiz

            login( userName , password )

 

        Servlet ---> Action ---> Biz 

       1) biz 实现业务逻辑

       2) 写Action

           a, 准备参数

           b, 调用biz

           c, 根据biz的运行结果,返回对应URL

       3)在配置文件中, 指定servletpath 与 Action之间的对应关系 .

       4) 编写下一个JSP

   ============================================

   ProductBiz

      |-> Collection<Product> getAllProducts();

      return Collection;

     

      QuerProductAction

      |-> execute()

            |-> biz.getAllProducts(); --> disp.jsp

                 return disp.jsp;

 

MVC的大至执行顺序:

1,用户发送请求>2获取用户的servletpath>3根据servletpath在配置文件中查找javabean的名字,>4返回名字>5,execute>6,复杂业务计算>7,返回下一个页面的URL>8根据URL转向下一个页面>9把页面返回给用户。

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Struts 1.2

第一天:

MVC : M : 业务逻辑,业务数据 ( 能够重复利用 ) java Bean ( VO BO) EJB    其实struts1没有实现业务层,也没法实现

V : 显示逻辑 ,同一份数据 ,对应多种显示方法. JSP代码实现。

C:流程控制器 , Servlet代码实现。javabean Servlet javabean 其实他有两个部分组成:

       1,系统核心控制器 由Struts 1 框架提供,就是 ActionServlet

2,业务逻辑控制器 由Struts 1框架提供就是用户本身写的Action 实例

 在struts-config.xml配置文件中的一些属性: >

Struts : 基于mvc的软件框架 . Struts :

1使用struts须要完成的准备工做 :

1) 前置控制器 (ActionServlet) .

 2) 定义了配置文件的格式 . /WEB-INF/struts-config.xml

 3) 提供了一个父类, Action , 要求全部的javabean 都来继承这个父类 , 覆盖其中的方法 .  使用struts1须要完成的准备工做 : version 2.0  version 1.2.x  下面是1.2的版本

1) 获取struts的jar包 --> 拷贝到WEB-INF/lib

2) 对struts提供的前端控制器( ActionServlet ) 在 本身的web.xml中 进行配置

3) 确保struts用到的配置文件被放置到指定的位置 . struts1.2.7/webapps/struts-blank.war 解

         压以后,从中拷贝struts-config.xml到咱们 本身的应用里 .

4) 将struts提供的jar包配置到classpath中. struts.jar : 编译时依赖

 

2经常使用的业务流程

0) 写jsp , 这个jSP中有用户须要的链接或表单,

1) javabean , 经过它里面的方法,完成业务逻辑 .

2) 写Action , 调用javabean ,并根据javabean的结果,返回不一样的页面 .

3) 在配置文件中对Action进行配置 .

4) 写jsp login.do http://localhost:8989/strutsapp/ok.jsp Resource file

1) 编写资源文件. a, properties

2) 在struts-config.xml中对资源文件进行配置 . 通知struts, 要使用的资源文件的名称 .

3) 在jsp中使用资源文件的内容 . 编程时使用key 显示时看到的是value

errors.header //errors会在全部错误的开头自动加上该key所表明的值(value), errors.footer //errors会在全部错误的结尾自动加上该key所表明的值(value), ActionForm : 用来保存客户端提交的数据 .

name password ----> Object |->name |->password

1) 写一个类( ActionForm ) , 用于保存客户端提交的参数.

2) 编辑配置文件, 告知struts,什么样的请求 使用哪一个ActionForm 对象 .

3) Actionexecute方法中, ActionForm对象中获取数据 .经过ActionForm作验证 .

1) 在配置文件中说明,哪些请求是须要作验证的 .

2) 在ActionForm里编写验证代码 . @Override validate() ActionMessage ---> Resource

3) 在错误页面上显示错误信息 .

0) 编写biz对象的方法,用于处理用户请求 . |-> 测试功能

1) 编写用户发送请、求的页面

                           2) 根据表单的参数 编写 ActionForm

3) 编写Action对象.execute方法 |-> 调用biz对象的方法. |->

根据biz方法的返回结果,返回不一样的ActionForward

4) 对ActionForm , Action 进行配置 .

5) 编写与 ActionForward 对应的jsp页面 .

 

次日:具体实现

  <form-beans>

        <form-bean name="" type=""/>

  </form-beans>

  <action-mappings>

        <action path="" type="" name="" validate="true" input="">

                 <forward name="" path="" redirect="true"/>

        </action>

  </action-mappings>

<html:errors />

3,经常使用配置文件  最原始的Action接口,验证登录的实例

         (1) web.xml文件 :

                   <?xml version="1.0" encoding="utf-8"?>                 

                   <web-app xmlns="http://java.sun.com/xml/ns/javaee"

                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

                      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">   

                     

                       <!—在web.Xml配置前端控制器 -->

                            <servlet>           

                                     <init-param>

                                               <param-name>config</param-name>

                                               <param-value>/WEB-INF/struts-config.xml</param-value>

                                     </init-param>

                                     <init-param>

                                               <param-name>debug</param-name>

                                               <param-value>2</param-value>

                                     </init-param>  

                                     <init-param>

                                               <param-name>detail</param-name>

                                               <param-value>2</param-value>

                                     </init-param>

                                     <servlet-name>actionServlet</servlet-name>

                                     <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

                                     <load-on-startup>3</load-on-startup>

                            </servlet>

                           

                            <!-- 对任意请求,都采用Struts提供的那个ActionServlet进行转发 -->

                            <servlet-mapping>

                                     <servlet-name>actionServlet</servlet-name>

                                     <url-pattern>*.do</url-pattern>

                            </servlet-mapping>

                           

                   </web-app>

                  

         (2) struts-config.xml文件 :

                   ActionServlet<?xml version="1.0" encoding="utf-8" ?>

                   <!DOCTYPE struts-config PUBLIC

                             "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"

                             "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">

                   <struts-config>

                   <form-beans>

<!-- 将表单提交的数据封装为一个对象 name属性对应Action中的name  本身手动写的actionform-->

                                     <form-bean name="loginForm" type="com.kettas.struts.LoginForm"/>

                      <!—动态actionForm

<form-bean name="regForm" type="org.apache.struts.action.DynaActionForm">

                            <form-property name="userName" type="String"/>

                            <form-property name="age" type="java.lang.Integer"/>

                         </form-bean>

                            </form-beans>

                           

                            <!-- 指定映射 指定请求路径对应指定Action

                                      name属性指定与此Action对应的表单对象

                                      validate指定是否采用表单验证 input指定如果表单验证出错 要去的页面 -->

                            <action-mappings>

                                     <action path="/login" type="com.kettas.struts.LoginAction" name="loginForm"

                                               validate="true" input="/login.jsp">

                                               <forward name="ok" path="/ok.jsp" redirect="true"/>

                                               <forward name="error" path="/error.jsp"/>

                                     </action>

                            </action-mappings>

                           

                            <!-- 指定资源文件 注意 : 以WEB-INF/classes为根目录 -->

                            <message-resources parameter="res.AppResources"/>

                   </struts-config>

                  

         (3) 表单对象  本身手动写actionForm

                   package com.kettas.struts ;

                   import org.apache.struts.action.* ;

                   import javax.servlet.http.* ;

                   // 要继承ActionForm类

                   public class LoginForm extends ActionForm{

                            // 成员变量的名字要和客户端参数一一对应.

                            private String userName ;

                            private String password ;

                            // 添加get、set方法

                            。。。。。。。。

                             

                            /***********************************************

                             * 用于对表单的数据进行验证, 该方法在调用execute以前

                             * 被前端控制器调用,根据他的返回结果,来判断验证是否

                             * 成功

                             ************************************************/

                            @Override

                            public ActionErrors validate( ActionMapping mapping ,

                                                                  HttpServletRequest request )

                            {// errors用于存放错误的集合

                                      ActionErrors errors = new ActionErrors();

                                      if( userName == null || userName.trim().length() == 0 ){

                                              // ActionMessage对象用来装载错误信息 初始化参数为资源文件中的键

                                              ActionMessage m = new ActionMessage( "errors.username.required" );

                                              errors.add( "error" , m );    

                                      } 

                                      if( password == null || password.trim().length()<3 ){

                                               ActionMessage m = new ActionMessage( "errors.password.required" ) ;

                                               errors.add( "error" , m ) ;

                                      }           

                                      // 若返回的对象size为0 则说明验证经过 不然进入Action中input属性指定的页面中        

                                      return errors ;

                            }

                   }

                  

                   // 在input指定的页面中要显示ActionErrors中的错误信息 则要用到标签 : <html:errors/>

                      errors.header : 错误信息的头    

                      errors.footer : 错误信息的主体

                      引入标签库 : <%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>

                  

                   // <bean:message key="login.password"/> : 用于显示资源文件中指定键值对应的内容

                      因为规范的jsp页面中除了标签是不能含有静态文本内容的,故这个标签会被大量使用

                      引入标签库 : <%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

(4) Action : 的实现

                   package com.kettas.struts ;

                   import org.apache.struts.action.* ;

                   import javax.servlet.http.* ;

                   import com.kettas.biz.*;

                  

                   public class LoginAction extends Action{

                            @Override

                            public ActionForward execute( ActionMapping mapping , ActionForm form ,

                                                                           HttpServletRequest request ,  HttpServletResponse response )                                                                                                                                         

                            {        // 传统的获取表单数据方式

                                      // String name = request.getParameter("userName" ) ;

                                      // String pwd = request.getParameter("password" ) ;                                                         

                                      // 获得表单对象 从中获取表单数据

                                      LoginForm lf = (LoginForm)form ;

                                      // 调用biz对象,返回下一个页面 .

                                      try{

                                              UserService biz = new UserService();     

                                              biz.login( lf.getUserName() , lf.getPassword() ) ;

                                             

                                              ActionForward af = mapping.findForward("ok");

                                              return af ;

                                      }catch( Exception e ){

                                                request.setAttribute( "errorMessage" , e.getMessage() ) ;

                                                return mapping.findForward( "error" );

                                      }

                            }                                                                                                                                                   

                   }

                  

         (5) Biz的实现 :

                   package com.kettas.biz ;

                   public class UserService{

                            public void login( String name , String pwd ){

                                     if( ! name.equals( "liucy" ) ){

                                               throw new RuntimeException( "user " + name + " not found" ) ;    

                                     }

                                     if( ! pwd.equals( "12345" ) ){

                                               throw new RuntimeException( "Invalid password" ) ;

                                     }

                            }

                   }

 

 

 

4,资源文件 .国际化

 1, 默认资源文件 : 当没有专门为每一个用户准备资源文件

                  时 ,使用默认资源文件 .

  <message-resources parameter="res.AppResources"/>

2,其余资源文件在命名上有一个规定 .

     默认资源文件名_国家缩写 .

     AppResources_zh

     AppResources_ja

  内容上是键值对  login.username=USER NAME:  前面是名称后面是显示的值

在jsp上的使用:<bean:define id="add"> <bean:message key=" login.username "/></bean:define>

3, 全部的资源文件要以utf-8的编码来编写 .若是不是的话要进去如下转换。

     a,用中文编写一个临时的资源文件a.properties ( 中国字 GBK )

                       临时文件中的编码   临时文件的名字   新文件的文件名

 b, native2ascii -encoding       GBK         a.properties     AppResources_zh.properties

.        

    

5struts 中的异常处理 :==================

  ---> Action ---> Biz ---> Dao

      Action中对异常进行捕获 .

      try{

              biz.fn();       

              return mapping.findforward( "ok" ) ;

      }catch( Exception e){

              return mapping.findforward( "error" );

      }

          系统级异常:

     * 因为没个具体的技术操做致使的异常 ,

     * 系统级异常一般是定义好的类型( SQLException , IOException )

     * 通常发生在DAO层 .

     * 在处里上要粒度粗一些 RuntimeException

     应用级异常 

     * 因为用户违反了特定的业务逻辑致使的异常

     * 应用级通常是用户自定义的异常 .    

     * 通常发生在 biz 层 . 

     * 粒度细一些 .

    

     最好作一个异常的体系结构

    

     实例 :

     (1) struts-config.xml文件 :

               <?xml version="1.0" encoding="UTF-8" ?>

                            <!DOCTYPE struts-config PUBLIC

                                      "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"

                                      "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">

                            <struts-config>

                                     <form-beans>

                                               <form-bean name="loginForm" type="com.kettas.struts.LoginForm"/>

                            动态actionForm

                           <form-bean name="regForm" type="org.apache.struts.action.DynaActionForm">

                                    <form-property name="userName" type="String"/>

                                    <form-property name="age" type="java.lang.Integer"/>

               </form-bean>

                                     </form-beans>

                                    <!-- 全局变量 可用在一些struts标签中 如<html:link /> -->

                                <global-forwards>

                                        <forward name="login" path="/login.jsp"/>

                                </global-forwards>

                                     <action-mappings>

                                               <action path="/login" type="com.kettas.struts.LoginAction" name="loginForm"

                                                        validate="true" input="/login.jsp">

                                                        <!-- 将Action中抛出的异常捕获 并跳转到对应的错误页面

                                                                  在错误页面中 仍是用标签<html:errors />来显示错误

                                                                  可见 这里key标签中指定的资源文件内容已经被封装到

                                                                  ActionErrors对象中去了 -->

                                                        <exception type="com.kettas.struts.expt.SystemException"

                                                                 path="/error.jsp" key="errors.system"/>

                                                        <exception type="com.kettas.struts.expt.UserNotFoundException"

                                                                 path="/error.jsp" key="errors.user"/>

                                                        <exception type="com.kettas.struts.expt.PasswordException"

                                                                 path="/error.jsp" key="errors.pwd"/>

                                                       

                                                        <!-- redirect="true"表示在一个新的链接中打开指定页面

                                                                  默认在同一个链接中打开指定页面 -->

                                                        <forward name="ok" path="/ok.jsp" redirect="true"/>

                                                        <forward name="error" path="/error.jsp"/>

                                               </action>                                          

                                     </action-mappings>

                                     //引入资源文件

                                     <message-resources parameter="res.AppResources"/>

                            </struts-config>

                           

                   (2) 定义根系统异常 做为其余一切系统异常的父类 这一步是有意义的

                            package com.kettas.struts.expt ;

                            // 继承至RuntimeException类而不是Exception 如此无需trycatch捕获可自动抛出异常

                            public class SystemException extends RuntimeException{

                                     // 注意写这三个构造函数 后面都这么写

                                     public SystemException( ){

                                               super();       

                                     }        

                                     public SystemException( String msg ){

                                               super( msg ) ;

                                      }              

                                     public SystemException( Throwable t ){

                                               super( t );

                                     }}

                            // 定义根业务异常 做为其余一切业务异常的父类

                            package com.kettas.struts.expt ;

                            public class BizException extends RuntimeException{

                                     ..

                            }

                            // 密码错误异常 继承至根业务异常

                            package com.kettas.struts.expt ;

                            public class PasswordException extends BizException{

                                     ...

                            }

                            // 用户未发现异常 继承至根业务异常

                            package com.kettas.struts.expt ;

                            public class UserNotFoundException extends BizException{

                                     ...

                            }

                   (3) dao的实现 :

                            import ...

                            // 因为是采用tomcat的链接池获取链接故这里引入这两个名字空间

                            import javax.sql.* ;

                            import javax.naming.* ;

                           

                            public class UserDao{

                                     public User queryByLoginName( String loginName ){

                                               Connection conn = null ;

                                               PreparedStatement pstm = null ;

                                               ResultSet rs = null ;  

                                               String sql = "select id , loginname , password from liucy_users where loginname=?" ;

                                               User u = null ;

                                               try{

                                                        // 从链接池中获取链接的三个步骤        

                                                        Context ctx = new InitialContext();

                                                        DataSource ds = (DataSource)ctx.lookup( "java:comp/env/oracle/ds" ) ;         

                                                        conn = ds.getConnection();                                                    

                  

                                                        pstm = conn.prepareStatement( sql ) ;

                                                        pstm.setString( 1 , loginName ) ; 

                                                        rs = pstm.executeQuery();

                                                        if( rs.next() ){

                                                                 u = new User();

                                                                 u.setId( rs.getInt( 1 ) ) ;

                                                                 u.setLoginName( rs.getString(2 ) ) ;

                                                                 u.setPassword( rs.getString( 3 ) ) ;

                                                        }                                    

                                                        return u ;

                                               }catch( Exception e){ 

                                                         e.printStackTrace();

                                                         // 抛出前面定义的系统异常 抛给biz 再从biz抛出 抛给Action 而后被系统捕获

                                                         throw new SystemException( e );

                                               }finally{

                                                        if( rs != null ) try{ rs.close(); }catch( Exception e){}

                                                        if( pstm != null ) try{ pstm.close();}catch( Exception e ){}

                                                        // 因为是链接池中的链接 故不会真的关闭 只是被链接池回收

                                                        if( conn != null ) try{ conn.close();}catch( Exception e ){}

                                               }}}

                   (4) biz的实现 :

                            public class UserService{

                                     public void login( String name , String pwd ){

                                               UserDao dao = new UserDao();

                                               User u = dao.queryByLoginName(name);

                                               if( u == null ){

                                                        // 抛出用户不存在业务异常

                                                        throw new UserNotFoundException( "user " + name + " not found" ) ;

                                               }

                                               if( ! u.getPassword().equals( pwd ) ){

                                                        // 抛出密码错误业务异常

                                                        throw new PasswordException( "Invalid password" );

                                               }}}

                   (5) Action的实现 :

                            public class LoginAction extends Action{

                                     @Override

                                     public ActionForward execute( ActionMapping mapping , ActionForm form ,

                                                                           HttpServletRequest request ,  HttpServletResponse response )                                             {    LoginForm lf = (LoginForm)form ;

                                                /*

                                                try{

                                                */             

                                                        // 这里会自动抛出biz和dao中的异常 抛给struts处理

                                                        UserService biz = new UserService();     

                                                        biz.login( lf.getUserName() , lf.getPassword() ) ;

                                                        ActionForward af = mapping.findForward("ok");

                                                        return af ;                                          

                                                /*

                                                // 若本身处理异常 则比较麻烦,能够在struts配置文件配置

                                                }catch( SystemException e ){

                                                         request.setAttribute( "errorMessage" , "System is busy" ) ;

                                                         return mapping.findForward( "error" );

                                                }catch( UserNotFoundException  e){

                                                         request.setAttribute( "errorMessage" , e.getMessage() ) ;

                                                         return mapping.findForward( "error" ) ;

                                                }catch( PasswordException e ){

                                                         request.setAttribute( "errorMessage" , e.getMessage() ) ;

                                                         return mapping.findForward( "error" ) ; 

                                                }catch( Exception e ){

                                                         request.setAttribute( "errorMessage" , "you catch an error" );

                                                         return mapping.findForward( "error" ) ; 

                                                }  

                                                */                                         

                                     }}                                                                                                  

4  ActionMessages对象 :

         public class MessageAction extends Action{     

                   @Override

                   public ActionForward execute( ActionMapping mapping , ActionForm form ,        

                                                        HttpServletRequest request , HttpServletResponse response )                                     

                   {ActionMessages messages = new ActionMessages();

                            // 用资源文件内容初始化

                            ActionMessage m1 = new ActionMessage( "msg1" );

                            ActionMessage m2 = new ActionMessage( "msg2" ) ;

                            messages.add( "message" , m1 ) ;

                            messages.add( "message" , m2 ) ;

                            request.setAttribute( "msgs" , messages );

                            return mapping.findForward( "ok" );                

                   }                                                                                                                                                   

         }

         // 在jsp中显示ActionMessages内容

         <html>

                   <body>

                            This message jsp

                            <!-- name指定命名属性 -->

                            <html:messages id="m" name="msgs">  

                                     <h1>${m}</h1>

                            </html:messages>

                   </body>

         </html>

<bean:message />

<html:errors />

 

html: 处理页面的显示问题

bean: 定义变量和javabean  <c:set />

logic: <c:if > <c:forEach> 

       <forward name="ok" path="/path.jsp"/>

 

html:

  <html:link /> <===> <a href="">

 

  <html:link forward="xxxx" page="xxx">Test</html:link>

      page : 指向一个明确的链接地址 .

      forward : 全局的forward 的 逻辑名字 .

    * 能够自动加应用名称

    * 能够使用逻辑名字 .

    * 在不支持cookie的状况下, 自动增长jsessionid

  <html:link forward="ok"></html:link>

 

 

 <html:form action="/login.do" method="">

    <input type="text" name="age"/>

    <html:text property="age"/>

   

    <input type="password" name=""/>

    <html:password />

   

    <select name="">

       <option>aaa</option>

    </slelect>  

   

    <html:select>

       <html:option></html:option>

    </html:select>              

   

    <input type="hidden" name="" value=""/>

    <html:hidden />

</html:form>  

 

 

<html:messages id="" name="">

</html:messages>           

name : 被迭代的消息结合在做用域中的名字 .

id   : 当前整备迭代的消息对象 .

* 被该标签迭代的集合类型是 ActionMessages类型 .

  集合中的每一个元素都是 一个 ActionMessage , 他

  可以封装资源文件中的数据 .

<html:errors />

 

定义一个变量:id表示变量名,value:表示变量值

<bean:define id="a" value="1234"/>

<bean:define id="">

         XXXXXXXX

</bean:define>

定义命名属性:

<bean:define id="a" name="data"/>

Action ---> a.jsp

request.setAttribute( "a" , "hello")

${ a }

 

 

 

 

 

 

 

第三天标签的使用======================================================================================

5  struts标签 :

 

<html:link forward="login"page="/webdir/login.jsp">

Test</html:link>

      page : 指向一个明确的链接地址 .

      forward : 全局的forward的逻辑名字, 在配置文件中指定的 :

    <global-forwards>

<forward name="login" path="/login.jsp"/>

      </global-forwards>

    * 能够自动加应用名称

    * 能够使用逻辑名字, 在配置文件中说明实际路径

    * 在不支持cookie的状况下, 自动增长jsessionid

   

     在html中表单标签用struts标签代替 :

     <!-- action中无需写应用名 会自动添加上 -->

       <html:form action="/login.do" method="">

         <-- <input type="text" name="age"/> -->

             <html:text property="age" value=""/>  

       <!-- <input type="password" name="pwd"/> -->

              <html:password property="pwd"/>

 <!--<select name="">

<option>aaa</option>

 </slelect> --> 

      <html:select>

         <html:option></html:option>

      </html:select>              

              

   <!-- <input type="hidden" name="" value=""/> -->

               <html:hidden />        

      </html:form>  

            

      html :

           <html:link  forward|page="/" >

           <html:form action="" method="">

            <html:text property="" value=""/>

            <html:password  property=""/>

            <html:select property=""/>

        <html:option/>

        <html:radio  property=""  />

        <html:checkbo property=""/>

      </html:form>

      <html:errors/>             

      <html:messages id="m" name="">

                 ${m}

      </html:messages>

                

     bean :

      <!-- 在当前页面范围内 定义一个变量 -->

       <bean:define id="" value=""/>

        <bean:define id="">

                      ...

        </bean:define> 

       <!-- 将某一个命名属性对应的值赋予变量 -->

       <bean:define id="a" name="student"/>

  <bean:define id="a" name="student" property="name"/> 

 至关于 : String a = student.getName();

 <!-- 将客户端提交的指定表单数据赋予变量 -->      

       <bean:parameter id="a" name="age"/>

       <!-- 将客户端提交的指定cookie的值赋予变量 -->

        <bean:cookie id="c" name="JSESSIONID"/>  

        <!-- 显示资源文件内容 -->

        <bean:message key=""/>

             

      logic :

      <logic:present parameter|cookie|name="age">

                       xxxxxxx ;

                       xxxxxxx ;

                       xxxxxxx ;

                   </logic:present> 

                   <logic:notPresent >

                       Xxxxx

                   </logic:notPresent>

                  

 <logic:greaterThan  parameter="age" value="23">

                      

 </logic:greaterThan>  

 <logic:greateThan cookie="age" value="23"> 

                       cxddddd

 </logic:greateThan >

<logic:greateThan name="student"property="age"value="23">

 </logic:greateThan>

                  

<logic:equal>

  <logic:notEqual>

 <logic:greaterThan>

 <logic:lessThan>

 <logic:greaterEqual>

 <logic:lessEqual>   

 <!-- 循环标签 -->

 <logic:iterate id="" collection="">

 </logic:iterate>

 

 

=================================================

request ----> ActionForm  ---> Action  

简化对ActionForm 的开发 .直接在配置文件配置,不用写单独的类

DynaActionForm ( 动态 ActionForm )

    1) 在配置文件中配 .

      <form-beans>

           <form-bean name="" type=""/>

           <form-bean name="regForm" type="org.apache.struts.action.DynaActionForm">

              <form-property name="userName" type="String"/>

              <form-property name="age" type="java.lang.Integer"/>

           </form-bean>

      </form-beans>

    2) Action中使用. 

         execute( ActionForm form ){

                 DynaActionForm af = ( DynaActionForm )form ;

                     af.get( "age" ) ;

                     af.get( "userName" ) ;

         }  

================================================

login , register , query

      

关于MappingDispatchAction, DispatchAction, LookupDispatchAction

      (1) MappingDispatchAction : 允许一个action中包含多个方法,分别处理与之对应的请求

      实例 :

           配置文件 :

                      <form-bean name="dynaLoginForm" type="org.apache.struts.action.DynaActionForm">

                            <form-property name="userName" type="java.lang.String"/>

                            <form-property name="password" type="java.lang.String"/>

                      </form-bean>

                     

                      <form-bean name="dynaRegForm" type="org.apache.struts.action.DynaActionForm">

                            <form-property name="userName" type="java.lang.String"/>

                            <form-property name="password" type="java.lang.String"/>

                            <form-property name="email" type="java.lang.String" />

                      </form-bean>

                      ...

                      ...

                      <action parameter="login" path="/login" type="com.kettas.struts.

                            UserSelfServiceAction" name="dynaLoginForm">

                            <exception type="com.kettas.struts.expt.SystemException" path="/error.jsp"

                                  key="errors.system"/>

                            <exception type="com.kettas.struts.expt.UserNotFoundException"

                                  path="/error.jsp" key="errors.user"/>

                            <exception type="com.kettas.struts.expt.PasswordException" path="/error.jsp"

                                  key="errors.pwd"/>

                            <forward name="ok" path="/ok.jsp" redirect="true"/>

                      </action>                                 

                     

                      <action parameter="register" path="/reg" type="com.kettas.struts.

                            UserSelfServiceAction" name="dynaRegForm">

                            <forward name="ok" path="/regok.jsp"/>

                      </action>

                      ...

                     

                 Action :

                      public class UserSelfServiceAction extends MappingDispatchAction{

                            // 用于处理用户登录请求 .

                            public ActionForward login( ActionMapping mapping , ActionForm form ,

                                                  HttpServletRequest request , HttpServletResponse response )

                          {

                                  DynaActionForm daf = (DynaActionForm)form ;

                                  String userName = (String)daf.get( "userName" );

                                  String password = (String)daf.get( "password" ) ;

                                 

                                  UserService biz = new UserService();

                                  biz.login( userName , password );

                                  return mapping.findForward( "ok" ) ;

                            }                               

                            // 负责处理用户的注册请求

                            public ActionForward register( ActionMapping mapping , ActionForm form ,

                                                  HttpServletRequest request ,   HttpServletResponse response )

                          {

                                   DynaActionForm daf = ( DynaActionForm ) form ;

                                   System.out.println( daf.get( "userName" ) ) ;

                                   System.out.println( daf.get( "password" ) ) ;

                                   System.out.println( daf.get( "email" ) ) ;

                                   return mapping.findForward( "ok" ) ;

                          } }                 

      (2) DispatchAction :

           1 将相关的操做合并在同一个Action中处理,这些相关的操做,必须使用同一个ActionForm 

           2 客户端提交的参数值决定使用Action中的哪一个方法

           3 不能覆盖execute方法,为每个请求单独写一个方法

           4 采用DispatchAction的方式简化了配置文件

          

           实例 :

                 配置文件 :

                 <!-- parameter指定客户端请求中决定action方法的那个参数 -->

                 <action parameter="method" path="/all" type="com.kettas.struts.

                      DispatchActionSample" name="allForm">

                      <exception type="com.kettas.struts.expt.SystemException" path="/error.jsp"

                            key="errors.system"/>

                      <forward name="ok" path="/ok.jsp" redirect="true"/>

                      <forward name="regOk" path="/regok.jsp"/>

                 </action>

                

                 Action :

                      public class DispatchActionSample extends DispatchAction{    

                            public ActionForward login( ActionMapping mapping , ActionForm form ,

                                                  HttpServletRequest request , HttpServletResponse response )

                            {

                                  DynaActionForm daf = (DynaActionForm)form ;

                                  String userName = (String)daf.get( "userName" ) ;

                                  String password = (String)daf.get( "password" ) ;

                                  UserService service = new UserService();

                                  service.login( userName , password ) ;

                                  return mapping.findForward( "ok" ) ;

                            }

                            public ActionForward register( ActionMapping mapping , ActionForm form ,

                                                   HttpServletRequest request ,   HttpServletResponse response )

                            {

                                   DynaActionForm daf = (DynaActionForm)form ;

                                   System.out.println( daf.get( "userName" ) );

                                   System.out.println( daf.get( "password" ) ) ;

                                   System.out.println( daf.get( "email" ) ) ;

                                   return mapping.findForward( "regOk" ) ;

                            }}

                 客户端 :

                      <a href="/webdir/all.do?method=login">登陆</a>

                      <a href="/webdir/all.do?method=register">注册</a>

                      Method有不一样的参数,对应处理的action方法

      (3) LookupDispatchAction :

            (1) 不能覆盖父类的execute方法,为每个按钮单独写一个方法

            (2) 覆盖父类getKeyMethodMap方法,在这个方法中指明按钮的值与方法名称的对应关系

            (3) 按钮的值,不能直接写死在程序中,要来自于资源文件             

            (4) 在配置文件中对Action进行配置

                <action parameter="指明按钮的名称" path="" type="" name="" ></action>  

            (5) 适合一个表单多种请求方式的时候                    

              

            实例 :

                 配置文件 :

                      <action parameter="btn" path="/math" type="com.kettas.struts.MathAction"

                            name="allForm">

                            <forward name="ok" path="/submit.jsp"/>

                      </action>

                     

                 Action :

                      public class MathAction extends LookupDispatchAction{

                            // 覆盖父类getKeyMethodMap方法,在这个方法中指明按钮的值与方法名称的对应关系

                            @Override

                            public Map getKeyMethodMap(){ 

                                  // 按钮的值应来自于资源文件 在map中保存是资源文件中的key,values是对应的方法

                                  Map m = new HashMap();

                                  m.put( "btn.add" , "addOperate" );

                                  m.put( "btn.subtract" , "subOperate" ); 

                                  return m ;

                            }

                            // 加法运算

                            public ActionForward addOperate( ActionMapping mapping,  ActionForm form ,

                                                  HttpServletRequest request , HttpServletResponse response )

                            {                      

                                   DynaActionForm daf = (DynaActionForm)form ;

                                   Integer a = (Integer)daf.get( "a" ) ;

                                   Integer b = (Integer)daf.get( "b" ) ;

                                   int ret = a.intValue() + b.intValue();

                                   request.setAttribute( "ret" , ret ) ;

                                   return mapping.findForward( "ok" ) ;                             

                            }

                           

                            // 减法运算

                            public ActionForward subOperate( ActionMapping mapping, ActionForm form ,

                                                  HttpServletRequest request , HttpServletResponse response )

                            {

                                   DynaActionForm daf = (DynaActionForm)form ;

                                   Integer a = (Integer)daf.get( "a" ) ;

                                   Integer b = (Integer)daf.get( "b" ) ;

                                   int ret = a.intValue() - b.intValue();

                                   request.setAttribute( "ret" , ret ) ;

                                   return mapping.findForward( "ok" ) ;

                            }

                      }

                     

                 客户端 :

                      <%@page contentType="text/html"%>

                      <%@page isELIgnored="false"%>

                      <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

                      <%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

                      <html>

                            <body> 

                                  <!-- 为变量赋值 得到资源文件的值 -->

                                  <bean:define id="add">

                                       <bean:message key="btn.add"/>

                                  </bean:define>                

                                  <bean:define id="sub">

                                       <bean:message key="btn.subtract"/>

                                  </bean:define>                              

                                 

                                  <form action="/strutsapp/math.do" method="GET">

                                       Number A :<input type="text" name="a"/><br/>

                                       Number B :<input type="text" name="b"/><br/>

                                       <!-- 按钮的name属性与action配置中的parameter属性是对应的 -->

                                       <input type="submit" name="btn" value="${add}"/>

                                       <input type="submit" name="btn" value="${sub}"/>                             

                                  </form>

                                 

                                  <!-- 显示计算结果 -->

                                  <c:if test="${!empty ret}">

                                       <h2>ret = ${ret}</h2>

                                  </c:if>

                            </body>

                      </html>

      ================================== ====================================================

n m ( m-1 ) * n ---> Begin

    (m-1)*n + n ---> end

   select id

     from

           ( select id , rownum rn from product ) 

     rn> ? and rn < ? 

======================================================

   ResultSet

   1) 改bug.

   2) 增长上一页 , 下一页 功能 .

   3) 总页数 经过 ServletContextListener

      保存到ServletContext对象中 .

 

第五天:

Validation --> 表便验证 .

 Overide

 validate()

   1) dynaActionForm

   2)

   3) 

validation  :

         1,varliator.jar | jakarta-ora.jar .

             |-> 在这些类中实现了通用的验证方法.

         2, validator-rules.xml .

             |-> 至关于类的使用说明. 写给struts看的.

               not null --->class ---> function

         3, validation.xml :

              |-> 至关于程序员编写的需求说明书 .

            loginForm

               |--> userName

                       |--> not null .

Validation框架的使用方式 :

  1) 程序员负责编写需求说明书 . 说明

      哪些表单 , 哪些数据,须要作什么验证 .

  2) struts 经过阅读validator-rules.xml,

     调用相应方法,实现验证逻辑 .

===============================================

使用validation框架的准备工做 :

  1) 保证validation.jar , jakarta-ora.jar

      保存在应用的/WEB-INF/lib

  2) 保证两个配置文件 validator-rules.xml

     validation.xml 要保存到/WEB-INF 中 .

  3) 将validation以插件的方式嵌入到struts中.

     修改 struts-config.xml ,插件的配置标签

     能够从validator-rules.xml的注释中拷贝.

  4) 确保须要验证的请求 validate="true"

      <action path="login" type="xxxAction"

                 name="xxxForm" validate="true"

                 input="xxx.jsp"/>

 5) 若是要经过Validation做验证的话 .

       ActionForm   

            - DynaValidatorActionForm  在validation.xml配置文件中的form标签中的属性为path

          - DynaValidatorForm     在validation.xml配置文件中的form标签中的属性为name

       DynaActionForm

          - org.apache.struts.validator.DynaValidatorForm

          - DynaValidatorActionForm 

  6) 将错误提示信息从validator-rules.xml中拷贝到本身的资源文件中 .

编辑需求说明书( validation.xml ) 提出本身的验证需求

 formset

       |-> form

                      |-> field

       |-> form

tiles .  

<script>

      function fn(){

            xxxxxxxxx ;

            xxxxxxxxxx;

            return false ;

      }

</script> 

<form action="" method="" onsubmit="return xxxx();">

</form> 

1) 将validation写的javascript代码嵌入到本身的网页中. 

   <html:javascript formName=""/>

2) 获取javascript验证函数的名字 .

    allForm ---> valdiateAllForm

    abc -------> validateAbc

login.do

regster.do

AllForm

MappingDisaptcherAction

 

<action path="/login" type="" name="all" validate="true" >

<action path="/reg" type="" name="all" validate="true">

 

9  struts中的模板

(1) 在struts-config.xml文件中指定使用模板 : 经过插件件的方式

              <action-mappings>   ... </action-mappings>

              <plug-in className="org.apache.struts.tiles.TilesPlugin" >

                    <!-- 指定模板配置文件的路径 -->

                  <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />

                  <!-- 使模板识别生效 -->

                  <set-property property="moduleAware" value="true" />

              </plug-in>

             

      (2) tiles-defs.xml文件 :

           <?xml version="1.0" encoding="UTF-8" ?>

           <!DOCTYPE tiles-definitions PUBLIC

                  "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"

                  "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">

           <tiles-definitions>

             <!-- template.jsp是个模板页面 里面只有一个页面布局 -->            

             <definition name="base" path="/tiles/template.jsp">

               <!-- 向模板页面的指定位置插入其余页面 -->

                 <put name="header" value="/tiles/header.jsp"/>

                 <put name="menu" value="/tiles/menu.jsp"/>

             </definition>

             <!-- 继承至上面的添加了部份内容的模板 再添加新的内容 -->

             <definition name="register" extends="base">

                      <put name="body" value="/tiles/regBody.jsp"/>

             </definition> 

            

             <!-- 继承至上面的添加了部份内容的模板 再添加新的内容 -->                              

             <definition name="login" extends="base">

                      <put name="body" value="/tiles/loginBody.jsp"/>

             </definition>

           </tiles-definitions>

          

      (3) template.jsp页面 :

           <%@page contentType="text/html;charset=utf-8"%>

           <%@taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>

           <html>

                 <body>

                      <table width="100%" height="100%">

                            <tr height="10%" bgcolor="gray">

                                  <td colspan="2" align="center">

                                 <!-- 指定此地能够插入新的页面 -->

                                 <tiles:insert attribute="header"/>

                            </td>

                            </tr>

                            <tr height="90%">

                                  <td width="15%" bgcolor="blue">

                                        <!-- 指定此地能够插入新的页面 -->

                                        <tiles:insert attribute="menu"/>

                                  </td>

                                  <td width="85%" align="center">

                                        <!-- 指定此地能够插入新的页面 -->

                                        <tiles:insert attribute="body"/>

                                  </td>

                            </tr>

                      </table>

                 </body>

           </html>

          

      (4) 使用的时候 页面格式以下 register.jsp :

           <%@taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>

          

           <!-- definition属性指定tiles-defs.xml文件中装配完成的页面名称 -->

           <tiles:insert definition="register"/>

          

           <!-- 若在tiles-defs.xml文件中没有声明 则要这么写 :

           <tiles:insert page="/tiles/template.jsp">

                 <tiles:put name="header" value="/tiles/header.jsp"/>

                 <tiles:put name="menu" value="/tiles/menu.jsp"/>

                 <tiles:put name="body" value="/tiles/regBody.jsp"/>

           </tiles:insert>

           -->

   一个客户在浏览器的地址栏输入了以下:

URL: http://www.tarena.com/webdev/account/deposit?accno=1212&amt=1000

调用 EG 的方法 F 能够得到初始参数interestRate的值。

在accountServlet中调用HttpServletRequest的getRequestURI返回H    ,

调用getQueryString返回B ,调用getContextPath返回 A   ,

调用getServletPath返回 C ,调用getPathInfo返回 D 。  

A.    /webdev

B.    accno=1212&amt=1000

C.    /account

D.    /deposit

E.    Servletconfig

F.    getInitParameter

G.    HttpServlet

H.    /webdev/account/deposit

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Struts 2

1,  Struts2的体系和struts1的体系差异很大,由于struts2使用WebWork的设计核心,而不是原来struts1的设计核心。Struts2大量使用拦截器来处理用户请求,从而容许用户的业务逻辑控制器与Servlet API分离。

2,  struts2框架的大体处理流程以下:

①浏览器发送请求,例如请求 /mypage.action[U13]     /report/myreport.pdf等

②核心控制器FilterDispatcher根据请求决定调用合适的Action

③WebWork的拦截器链自动对请求应用通用功能,例如 workflow,validation或文件下载和上传

④回调Action的execute方法(其实能够是任意方法),该方法execute方法先得到用户的请求参数,而后执行某种数据操做,调用业务逻辑组组件来处理用户请求。

⑤Action的execute方法处理结果信息将被输出发哦浏览器中,能够是html页面,pdf还有jsp,Velocity,FreeMarker等技术模板。 

 

3,在struts2 中的web.xml配置  加拦截器(拦截器是整个struts的核心技术)

    <?xml version="1.0" encoding="GBK"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 <!-- 定义Struts2的FilterDispathcer的Filter -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>

 <!-- FilterDispatcher用来初始化struts2而且处理全部的WEB请求。 -->
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

3,  struts.xml的配置
<struts>
 <!-- include节点是struts2中组件化的方式 能够将每一个功能模块独立到一个xml配置文件中 而后用include节点引用 -->
    <include file="struts-default.xml"></include>
    <!-- package提供了将多个Action组织为一个模块的方式
        package的名字必须是惟一的 package能够扩展 当一个package扩展自
        另外一个package时该package会在自己配置的基础上加入扩展的package
        的配置 父package必须在子package前配置 
        name:package名称 extends:继承的父package名称
        abstract:设置package的属性为抽象的 抽象的package不能定义action 值true:false
        namespace:定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为                    

http://localhost:8080/struts2/test/XX.action    -->
    <package name="com.kay.struts2" extends="struts-default" namespace="/test">
        <interceptors>
            <!-- 定义拦截器 name:拦截器名称  class:拦截器类路径  -->
            <interceptor name="timer" class="com.kay.timer"></interceptor>
            <interceptor name="logger" class="com.kay.logger"></interceptor>
            <!-- 定义拦截器栈 -->
            <interceptor-stack name="mystack[U14] ">
                <interceptor-ref name="timer"></interceptor-ref>
                <interceptor-ref name="logger"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 定义默认的拦截器 每一个Action都会自动引用 若是Action中引用了其它的拦截器 默认的拦截器将无效 -->
        <default-interceptor-ref name="mystack"></default-interceptor-ref>
        <!-- 全局results配置 -->
        <global-results><result name="input">/error.jsp</result> </global-results>
        <!-- Action配置 一个Action能够被屡次映射(只要action配置中的name不一样)
             name:action名称 class: 对应的类的路径  method: 调用Action中的方法名 -->
        <action name="hello[U15] " class="com.kay.struts2.Action.LoginAction">
            <!-- 引用拦截器 name:拦截器名称或拦截器栈名称  -->
            <interceptor-ref name="timer"></interceptor-ref>
            <!-- 节点配置 name : result名称 和Action中返回的值相同
                type : result类型 不写则选用superpackage的type struts-default.xml中的默认为dispatcher
             -->
         <result name="success" type="dispatcher">/talk.jsp</result>

<result name="error" type="dispatcher">/error.jsp</result>

<result name="input" type="dispatcher">/login.jsp</result>

<!-- 配置Action返回cancel时重定向到Welcome的Action-->

         <result name="cancel" type="redirect-action">Welcome</result>

          <!—异常处理  result表示出现异常时返回的name为success的结果处理—》

<exception-mapping exception=”java.lang.Exception” result=”success”/>
         <!-- 参数设置 name:对应Action中的get/set方法 -->
         <param name="url">http://www.sina.com</param>
        </action>
    </package>

          <!—引用国际化文件的base名-->

<constant name=”struts2.custom.i18n.resources”value=”messageResource”
</struts>

 

4,struts2的action编写

例1 HelloWorld.jsp

<% @ page contentType = " text/html; charset=UTF-8 " %>
<% @ taglib prefix = " s " uri = " /struts-tags " %>
[U16] < html >
< head >
    < title > Hello World! </ title >
</ head >
< body >
    < h2 >< s:property value ="message[U17] " /></ h2 >
</ body >
</ html >

例1 classes/tutorial/HelloWorld.java

 import com.opensymphony.xwork2.ActionSupport;

 public class HelloWorld extends ActionSupport  {
     private String message[U18] ;
     public String getMessage()  {
         return message;
    }
   public void tring setMessage(String message)  {
         this.message=message;
    }
    @Override
     public String execute[U19] ()  {
        message = " Hello World, Now is " + DateFormat.getInstance().format( new Date());
         return success;
    }
}

例1 classes/struts.xml中HelloWorld Action的配置

< package name ="ActionDemo" extends ="struts-default" >
    < action name ="HelloWorld" class ="tutorial.HelloWorld" >
        < result > /HelloWorld.jsp </ result >
    </ action >
</ package >

 

4,  拦截器的编写

  编写权限控制器

public class AuthorityInterceptor extends AbstractIntercepto[U20] r {   

    private static final long serialVersionUID = 1358600090729208361L;   

    //拦截Action处理的拦截方法   

    public String intercept(ActionInvocation invocation) throws Exception {   

        ActionContext ctx=invocation.getInvocationContext();   // 取得请求相关的ActionContext实例

        Map session=ctx.getSession();   

        String user=(String)session.get("user"); //取出名为user的session属性     

        //若是没有登录,或者登录全部的用户名不是aumy,都返回从新登录   

        if(user!=null && user.equals("aumy")){   

            return invocation.invoke();[U21]    

        }   

        //没有登录,将服务器提示设置成一个HttpServletRequest属性   

        ctx.put("tip","您尚未登陆,请登录系统");   

        return Action.LOGIN;           

    }   

}

 

Struts2.xml的配置文件

<struts>    

    <include file="struts-default.xml"/>     

       

    <!--授权限控制的Action请求配置-->   

    <package name="authority" extends="struts-default">   

        <interceptors>   

            <!--定义一个名为authority的拦截器-->   

            <interceptor  class="com.aumy.struts.example.intercepter.AuthorityInterceptor"  name="authority"/>

            <!--定义一个包含权限检查的拦截器栈-->   

            <interceptor-stack name="mydefault">  

                <interceptor-ref name="defaultStack"/>   <!--配置内建默认拦截器--> 

                <interceptor-ref name="authority"/>  <!--配置自定义的拦截器-->   

            </interceptor-stack>   

        </interceptors>   

           

        <default-interceptor-ref name="mydefault" />[U22]    

        <!--定义全局Result-->   

        <global-results>   

            <result name="login">/login.jsp</result>   

        </global-results>   

           

        <action name="show" class="com.aumy.struts.example.LoginAction"  

            method="show">   

            <result name="success">/show.jsp</result>   

        </action>   

        <action name="add" class="com.aumy.struts.example.LoginAction"  method="add">

            <result name="success">/add.jsp</result>   

        </action>   

    </package>   

</struts>  

 

 

 

还要一种方法拦截器,能够对某个action的方法进行拦截 编码相似action拦截器

  public class MyInterceptor3 extends MethodFilterInterceptor {   

    @Override  

    protected String doIntercept(ActionInvocation invocation) throws Exception {   

        System.out.println("use MethodFilterInterceptor");   

        String result = invocation.invoke();   

        return result;   

    }  

}

只是在配置的时候和其余interceptor有些区别:

<interceptor name="myInterceptor3" class="com.langhua.interceptor.MyInterceptor3">  

                <param name="excludeMethods">execute,login</param>  <!-- execute,login两个方法不须要拦截

               <!—addmessage 方法须要拦截 能够指名多个方法,只须要用逗号隔开

 <param name="includeMethods">addmessage</param>     

</interceptor>  

 

 

6,拦截结果的监听器,用来精肯定义在execute方法执行以后,在处理物力资源转向以前的动做,这个监听器是经过手动注册到拦截器内部的

 

public class MyListener implements PreResultListener[U23]  {   

    public void beforeResult(ActionInvocation invocation, String resultCode[U24] ) {   

        System.out.println(“放回的逻辑视图是:”+resultCode);   

    }   

}

而后再在拦截器里面调用  invocation.addPreResultListener(new MyListener());  
监听器是在这个拦截器完成别的拦截器以后调用的

 

 

5,struts2的标签库  相比struts1,struts2提供了大量的标签,且更增强大  ,且主要有,1 UI 用户界面标签(html页面显示)   2 非UI 主要是数据访问,逻辑控制的标签   3 Ajax支持的标签

 

 

6,Struts2 的(客户端和服务端)校验更为方便更容易国际化处理

7,国际化处理:

8,支持文件的上传和下载

Struts1和Struts2的区别和对比:

Action 类:
• Struts1要求Action类继承一个抽象基类。Struts1的一个广泛问题是使用抽象类编程而不是接口。
• Struts 2 Action类能够实现一个Action接口,也可实现其余接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现经常使用的接口。Action接口不是必须的,任何有execute标识的POJO对象均可以用做Struts2的Action对象。

线程模式:
• Struts1 Action是单例模式而且必须是线程安全的,由于仅有Action的一个实例来处理全部的请求。单例策略限制了Struts1 Action能做的事,而且要在开发时特别当心。Action资源必须是线程安全的或同步的。
• Struts2 Action对象为每个请求产生一个实例,所以没有线程安全问题。(实际上,servlet容器给每一个请求产生许多可丢弃的对象,而且不会致使性能和垃圾回收问题)

Servlet 依赖:
• Struts1 Action 依赖于Servlet API ,由于当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
• Struts 2 Action不依赖于容器,容许Action脱离容器单独被测试。若是须要,Struts2 Action仍然能够访问初始的request和response。可是,其余的元素减小或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。

可测性:
• 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
• Struts 2 Action能够经过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。

捕获输入:
• Struts1 使用ActionForm对象捕获输入。全部的ActionForm必须继承一个基类。由于其余JavaBean不能用做ActionForm,开发者经 常建立多余的类捕获输入。动态Bean(DynaBeans)能够做为建立传统ActionForm的选择,可是,开发者多是在从新描述(建立)已经存 在的JavaBean(仍然会致使有冗余的javabean)。
• Struts 2直接使用Action属性做为输入属性,消除了对第二个输入对象的需求。输入属性多是有本身(子)属性的rich对象类型。Action属性可以经过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,可以用做输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。

表达式语言:
• Struts1 整合了JSTL,所以使用JSTL EL。这种EL有基本对象图遍历,可是对集合和索引属性的支持很弱。
• Struts2能够使用JSTL,可是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).

绑定值到页面(view):
• Struts 1使用标准JSP机制把对象绑定到页面中来访问。
• Struts 2 使用 "ValueStack"技术,使taglib可以访问值而不须要把你的页面(view)和对象绑定起来。ValueStack策略容许经过一系列名称相同但类型不一样的属性重用页面(view)。

类型转换:
• Struts 1 ActionForm 属性一般都是String类型。Struts1使用Commons-Beanutils进行类型转换。每一个类一个转换器,对每个实例来讲是不可配置的。
• Struts2 使用OGNL进行类型转换。提供基本和经常使用对象的转换器。

校验:
• Struts 1支持在ActionForm的validate方法中手动校验,或者经过Commons Validator的扩展来校验。同一个类能够有不一样的校验内容,但不能校验子对象。
• Struts2支持经过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性

Action执行的控制:
• Struts1支持每个模块有单独的Request Processors(生命周期),可是模块中的全部Action必须共享相同的生命周期。
• Struts2支持经过拦截器堆栈(Interceptor Stacks)为每个Action建立不一样的生命周期。堆栈可以根据须要和不一样的Action一块儿使用

 

 

 

 

 

Ajax部分

1定义:多种应用异步通讯,可以数据的局部刷新,使用户有不间断的体验

ajax 的四项技术:

javascript, css, dom, XMLHttpRequest

 

2四者之间的关系:

1. javascript 建立XMLHttpRequest 对象并用它与web server 通讯得到数据;

2. javascript 使用dom 的api 将数据更新到页面;

3. javascript 将css 应用到HTML 的元素上

Ajax的传输步骤------------------------------à

 

 

 

 

3 ajax 的编程步骤

1. 建立XMLHttpRequest 对象xhr;

2. 使用xhr 的open 函数打开资源;open("GET or POST" , "传向的页面"+若是是GET要加参数(不用加/));

3. 使用xhr 的onreadystatechange 属性注册处理应答的回调函数的句柄;(为何只传句柄?若是传display()的话至关于传入的是函数值,

而传入display()的话是将整个函数传给它,当有变化时交个这个函数来处理传入display()还会出错?)

4. (在使用POST 方法使用)使用xhr 的setRequestHeader 设置请求头。一般设置content-type

请求头,可能的值是:application/x-www-form-urlencoded 和text/xml;

5. 使用xhr 的send 方法发送请求;

6. 编写回调函数处理应答:在此函数里经过xhr 的readyState 属性判断通讯是否结束(等于4 结束);而后再经过xhr 的status 属性判断web server 是否正确处理应答(等于200 正确),若是正确处理应答,应答的文本存放在xhr 的responseText 属性中,应答是xml 再将生成的xml 文档放在xhr 的responseXML 中 传XML文档只能用POST方法传

 

res.getCharactorEncoding();可得到res的字符编码

res.setCharactorEncoding("UTF-8");

 

用DOM api 解析XML 文档的步骤:

1. 建立DocumentBuilderFactory:

DocumentBu ilderFactory dbf = DocumentBuilderFactory.newInstance();

2. (可选)设置dbf 的属性:

设置合法性检测: dbf.setValidating(true);

设置处理名字空间: dbf.setNamespaceAware(true);

3.建立DocumentBuilder:

DocumentBu ilder db = dbf.newDocumentBuilder();

4a.解析XML 文档:

Document doc = db.parse(xmlResource);

4b.生成XML 文档:

Document doc = db.newDocument();

 

4 XMLHTTPRequest的属性和方法介绍

 方法属性:

open(string method, string url, boolean asynch, string username, string password):post仍是get,url地址,同步仍是异步 后面三个参数是可选的

void send(content):

string getAllResponseHeaders()

void setRequestHeader(string header, string value):这个方法为HTTP请求中一个给定的首部设置值。它有两个参数,第一个串表示要设置的首部,第二个串表示要在首部中放置的值。须要说明,这个方法必须在调用open()以后才能调用。

string getResponseHeader(string header):

onreadystatechange :每一个状态改变时都会触发这个事件处理器,一般会调用一个JavaScript函数、回调函数

readyState:请求的状态。有5个可取值:0 = 未初始化,1 = 正在加载,2 = 已加载,3 = 交互中,4 = 完成

responseText:服务器的响应,表示为一个串

responseXML:服务器的响应,表示为XML。这个对象能够解析为一个DOM对象

statusText:HTTP状态码的相应文本(OK或Not Found(未找到)等等)

 

5 kettasAjax 封装XMLHttpRequest 四个方法说明:

1.kettasAjax.doGetText(url, textHandler, async):

用GET 方法发出请求到url, 返回的文本responseText 做为回调函数textHandler 的参数。

textHandler 的签名相似function(txt).

2.kettasAjax.doGetXml(url, xmlHandler, async):

用GET 方法发出请求到url, 返回的XML Document 也就是responseXML 做为回调函数

xmlHandler 的参数。xmlHandler 的签名相似function(doc).

3.kettasAjax.doPostText(url, textHandler, body, async):

用POST 方法将请求体body 发送到url, 返回的文本responseText 做为回调函数textHandler

的参数。textHandler 的签名相似function(txt).

4.kettasAjax.doPostXml(url, xmlHandler, body, async):

用POST 方法将请求体body 发送到url, 返回的XML Document 也就是responseXML 做为

回调函数xmlHandler 的参数。xmlHandler 的签名相似function(doc).

 

 

6 AJAX全称为"Asynchronous JavaScript and XML"(异步JavaScript和XML),是指一种建立交互式网页应用的

网页开发技术。它允许网页的部分刷新,比起传统的整个页面刷新,传输的数据量大大减小,这样就显著提升了

用户浏览web页面的速度。

1)  获取ajax核心对象XMLHttpRequest的标准JavaScript函数 :

      function createXhr(){

           // 判断是IE浏览器仍是其余浏览器,而后返回对象

           if(window.ActiveXObject){

                 return new ActiveXObject("Microsoft.XMLHTTP");

           }else if(window.XMLHttpRequest){

                 return new XMLHttpRequest();

           }else{ throw new Error("Does not ajax programming");}

      }

                

          

      注 : 下面的笔记中,都用 createXhr()这个函数获取XMLHttpRequest对象

     

2)  实例 : 在网页中验证电子邮箱输入的格式

      (1) 网页文件

           <title>Validate Email Format</title>

           <!-- createXhr()以及其余工具函数都在utils.js中 -->

           <script type="text/javascript" src="js/utils.js"></script>

          

           <script type="text/javascript">             

                 //如下是标准的步骤,要牢记

                 var xhr = null;

                 function validateEmail(){

                      xhr = createXhr();// 获取XMLHttpRequest对象

// 要提交到服务器的请求,escape函数用于除去字符串两端空格,$函数根据id得到对象(此方法在util.js中)  vm是servlet的访问地址

                      var url = "vm?mail=" + escape($("mail").value);

                      /* 指定发送的方式、接受请求的页面(或servlet)、是否采用异步回调

                       * 参数也能够是("GET", url, true)

                       * true是默认的,故可省略不写,表示采用异步回调

                       */

                      xhr.open("GET", url);

                      // 指定异步回调函数

                      xhr.onreadystatechange = displayStatus;

                     

                      // 若采用POST方式提交请求,这里就必须发送请求体,这里是GET方式,故为NULL

                       //请求体的设置xhr.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);

                      xhr.send(null);

                 }

                 //异步回调函数的实现

                 function displayStatus(){

// readyState是服务端状态, 0表明无状态,1表明创建链接,2准备发送数据,3正在发送数据 ,等于4代表对请求响应完毕,该返回客户端的数据都返回了

                      if(xhr.readyState == 4){

                            // status是客户端状态,等于200代表数据已经存在于缓存,能够直接拿来使用了

400 url出错,500内部出错

                            if(xhr.status == 200){

                                  var status = $("mailFormatStatus");

                                  // 得到服务器返回的文本数据

                                  var mailStatus = xhr.responseText;

                                  if(mailStatus == "true"){

                                       status.innerHTML = "valid email format";

                                  }else{ status.innerHTML = "invalid email format"; }

                            }else{// 得到客户端状态值以及对应的描述性文本

                                  errorHandler(xhr.status, xhr.statusText);}

                      }else{ status.innerHTML = "please wait..."; }}

           </script>

           </head>

           <body>

                 <h2>Please enter an email address to validate</h2>

                 <input type="text" id="mail" onblur="validateEmail()"/><br/>

                 <div id="mailFormatStatus"></div>

           </body>

           </html>

          

      (2) Servlet文件ValidateEmailFormatServlet.java片断

                 protected void doGet(HttpServletRequest request, HttpServletResponse response)

                      throws ServletException, IOException {

                      // 注意这里不是"text/html" 由于咱们只须要返回纯文本字符串便可 故用"text/plain"

                      response.setContentType("text/plain;charset=gbk");

                      String mail = request.getParameter("mail");

                      String status = "false";

                      if(mail != null){

                            Pattern p = Pattern.compile("\\S+@\\S+");

                            Matcher m = p.matcher(mail);

                            if(m.matches()) status = "true";

                      }

                      PrintWriter out = response.getWriter();

                      out.print(status);

                      out.flush();

                      //这里关闭与否 应该无关痛痒

                      out.close();

                 }

      (3) web.xml片断

                 <servlet>

                      <description>

                      </description>

                      <display-name>

                      ValidateEmailFormatServlet</display-name>

                      <servlet-name>ValidateEmailFormatServlet</servlet-name>

                      <servlet-class>

                   com.kettas.ajax.xhr.day1.ValidateEmailFormatServlet</servlet-class>

              </servlet>

                 <servlet-mapping>

                      <servlet-name>ValidateEmailFormatServlet</servlet-name>

                      <url-pattern>/vm</url-pattern>

                 </servlet-mapping>

                

3)  向服务器请求得到xml文件(对象)

      本例中,获得从服务器返回的xml对象,而后将数据填充到表格

      <title>Online super store</title>

      <script type="text/javascript" src="js/utils.js"></script>

      <script type="text/javascript">

           var xhr = null;

           function initStore(){

                 xhr = createXhr();

                 xhr.open("GET", "xmlListProduct.jsp");

                 xhr.onreadystatechange = display;

                 xhr.send(null);

           }

          

           function display(){

                 if(xhr.readyState == 4){

                      if(xhr.status == 200){

                            fillStoreTable(xhr.responseXML);

                      }else{

                            errorHandler(xhr.status, xhr.statusText);

                      }}}

           function fillStoreTable(productsRoot){

                 // 将xml数据,填充表格,具体过程略

                 ...

           }

      </script>

      </head>

      <body onload="initStore();">

      <table id="storeTable">

           <tbody id="storeBody">

           </tbody>

      </table>

      </html>

     

      xmlListProduct.jsp文件内容以下 :

           <!-- 注意,客户端须要的是xml文件,故这里是"text/xml" -->

           <%@page language="java" contentType="text/xml; charset=ISO-8859-1"

               pageEncoding="ISO-8859-1"%>

           <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

           <jsp:useBean id="store" class="com.kettas.ajax.xhr.day1.SuperStore" scope="application"/>

           <products>

               <c:forEach var="product" items="${store.products}">

                 <product>

                      <id>${product.id }</id>

                      <name>${product.name }</name>

                      <price>${product.price}</price>

                 </product>

               </c:forEach>

           </products>

                     

7 封装ajax的调用步骤 :

   得到XMLHttpRequest对象,而后向服务器发送请求,最后对服务器返回的数据进行处理。这个过程

   千篇一概,每次按照相同的步骤书写,故将它们封装起来是当务之急。这样的话,调用起来会方便

   得多。

   封装的具体实现以下所示(十分经典的javascript代码,掌握并牢记) :

           function Request(l){

                 var xhr = createXhr();// 私有属性 XMLHttpRequest对象

                 var listener = l; // 私有属性 此对象负责对服务端响应做反应

                 // 保险起见 若初始化时没有赋予对象 则赋予一个新建立的对象

                 if(!listener) listener = new ResponseListener();

                 // 公有属性 请求体内容的类型 默认的表示发送的是表单数据

                 // 若发送的是xml类型数据 则this.contentType = "text/xml";

                 // 实际上 这个是无关痛痒的 都用默认的类型便可

                 this.contentType = "application/x-www-form-urlencoded";

                 // 公有方法 以GET方式发送请求

                 this.doGet = function(url,async){

                      sendRequest("GET", url, null, async);

                 }

                 // 公有方法 以POST方式发送请求

                 this.doPost = function(url, requestBody, async){

                      sendRequest("POST", url, requestBody, async);

                 }

                 // 私有方法 向服务器发送请求

                 function sendRequest(method, url, requestBody, async){

                      if(async == undefined) async = true; // 若是没有说明是否采用异步回调 则采用异步回调

                             // 若是async有值 而且async != ( false || 0 || null ) 则采用异步回调

                           else if(async) async = true;

                            else async = false; // 其余状况( async = false || 0 || null ) 则不采用异步回调

                            // 指定发送的方式、接受请求的页面(或servlet)、是否采用异步回调

                            xhr.open(method, url, async);

                            if(async) xhr.onreadystatechange = callback; // 指定异步回调函数

                           // 设置请求体的内容类contentType =application/x-www-form-urlencoded”

xhr.setRequestHeader("Content-Type", contentType);

                            xhr.send(requestBody); // 发送请求

                            // 若没有采用异步回调 则执行此函数

                            if(!async) listener.complete(

                                  xhr.status, xhr.statusText, xhr.responseText, xhr.responseXML

                            );

                 }

                 // 私有函数 异步回调函数的实现

                 function callback(){

                      switch(xhr.readyState){

                            case 0: listener.uninitialized(); break;

                            case 1: listener.loading(); break;

                            case 2: listener.loaded(); break;

                            case 3: listener.interactive(); break;

                            case 4: listener.complete(

                                  xhr.status, xhr.statusText, xhr.responseText, xhr.responseXML

                            ); break;

                      }}

                 // 私有函数

                 function createXhr(){

                      if(window.ActiveXObject){

                            return new ActiveXObject("Microsoft.XMLHTTP");

                      }else if(window.XMLHttpRequest){

                            return new XMLHttpRequest();

                      }else{

                            throw new Error("Does not ajax programming");

                      }}}

           // 此对象处理服务端响应

           function ResponseListener(){

                 this.uninitialized = function(){}

                 this.loading = function(){}

                 this.loaded = function(){}

                 this.interactive = function(){}

                 // 最后一个响应状态 响应完毕

                 this.complete = function(status, statusText, responseText, responseXML){}

           /* 继承上面的对象

            * 对于其它四个状态 通常是不须要处理响应的 故这里不予理会

            * 只是覆盖响应完毕后的处理方法

            */

           function ResponseAdapter(){

                 this.handleText = function(text){}

                 this.handleXml = function(xml){}

                 this.handleError = function(status, statusText){

                      alert("Error: " + status + " " + statusText);

                 }

                 // 覆盖父类的方法

                 this.complete = function(status, statusText, responseText, responseXML){

                      if(status == 200){

                            this.handleText(responseText);

                            this.handleXml(responseXML);

                      }else{

                            this.handleError(status, statusText);

                      }

                 }

           }

           // 注意 javascript的继承机制

           ResponseAdapter.prototype = new ResponseListener();

           ResponseAdapter.prototype.constructor = ResponseAdapter;

           // 对以上部分实现功能的组织调用类

           if(!kettasAjax) var kettasAjax = {};

           // 采用GET方式发送请求 对返回的文本数据进行处理

           if(!kettasAjax.getText){

                 kettasAjax.getText = function(url, handleText, async){

                      var l = new ResponseAdapter();

                      l.handleText = handleText;

                      var req = new Request(l);

                      req.doGet(url, async);

                 }}

           // 采用GET方式发送请求 对返回的XML数据进行处理

           if(!kettasAjax.getXml){

                 kettasAjax.getXml = function(url, handleXml, async){

                      var l = new ResponseAdapter();

                      l.handleXml = handleXml;

                      var req = new Request(l);

                      req.doGet(url, async);

                 }

           }

           // 采用POST方式发送请求 对返回的文本数据进行处理

           if(!kettasAjax.postText){

                 kettasAjax.postText = function(url, requestBody,handleText, async){

                      var l = new ResponseAdapter();

                      l.handleText = handleText;

                      var req = new Request(l);

                      req.doPost(url,requestBody, async);

                 }

           }

           // 采用POST方式发送请求 对返回的XML数据进行处理

           if(!kettasAjax.postXml){

                 kettasAjax.postXml = function(url, requestBody, handleXml, async){

                      var l = new ResponseAdapter();

                      l.handleText = handleXml;

                      var req = new Request(l);

                      req.doPost(url, requestBody, async);

                 }

           }  

           注 : 之后就使用这个kettasAjax对象,会方便异常

          

采用kettasAjax对象,采用不一样的方式向服务器发送不一样类型的数据

      (1) html文件以下 :

           <title>Send Request Parameters</title>

           <script type="text/javascript" src="js/utils.js"></script>

           <script type="text/javascript" src="js/kettasAjax.js"></script>

           <script type="text/javascript">

                 function handleForm(httpMethod){

                      if(httpMethod == "GET"){

                            // 采用GET方式向服务器发送表单数据

                            kettasAjax.getText("echo.jsp?" + getQueryString(), display);

                      }else{

                            // 采用POST方式向服务器发送表单数据

                            kettasAjax.postText("echo.jsp", getQueryString(), display);

                      }}

                 // 显示服务器返回的数据

                 function display(txt){

                       $("response").innerHTML = txt;

                 }

                 // 得到表单数据的字符串组织形式

                 function getQueryString(){

                      var name = escape(getEavById("name"));

                      var age = escape(getEavById("age"));

                      var password = escape(getEavById("password"));

                      var queryStr = "name=" + name +"&age=" + age + "&password=" + password;

                      return queryStr;

                 }

                 // 采用POST方式向服务器发送xml数据

                 // 因为发送的是xml形式字符串 故服务端不能以getParameter的方式读取 要以readLine方式读取

                 function handleXmlForm(){

                      kettasAjax.postText("handleXml", getXmlFromForm(), display);

                 }

                 // 得到表单数据的xml字符串表现形式

                 function getXmlFromForm(){

                      var name = getEavById("name");

                      var age = getEavById("age");

                      var password = getEavById("password");

                      var xmlStr = "<params>"

                      + "<name>" + name + "</name>"

                      + "<age>" + age + "</age>"

                      + "<password>" + password + "</password>"

                      + "</params>"

                      return xmlStr;

                 }

           </script>

           </head>

           <body>

                 <form action="#">

                  Name: <input type="text" id="name"/><br/>

                  Age: <input type="text" id="age"/><br/>

                  Password: <input type="password" id="password"/><br/>

                 </form>

                 <button onclick="handleForm('GET')">Get</button>

                 <button onclick="handleForm('POST')">Post</button>

                 <button onclick="handleXmlForm()">Send Parameters as XML</button><br/>

                 <div id="response"></div>

           </body>

           </html>

      (2) echo.jsp内容以下 :

           Http method: ${pageContext.request.method}, and parameters

           are name: ${param.name}, age: ${param.age}, password: ${param.password}

      (3) Servlet文件HandleXmlServlet片断以下 :

                 protected void doPost(HttpServletRequest request,

                            HttpServletResponse response) throws ServletException, IOException {

                      response.setContentType("text/plain");

                      StringBuilder sb = new StringBuilder();

                      // 因为客户端发送的是xml形式的字符串 故要得到BufferedReader对象用于读取

                      BufferedReader reader = request.getReader();

                      PrintWriter out = response.getWriter();

                      String line = null;

                      // 可能客户端是采用多行发送的 故不能只读取一行了事

                      while ((line = reader.readLine()) != null)

                            sb.append(line);

                      // 解析xml数据

                      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

                      try {

                            DocumentBuilder db = dbf.newDocumentBuilder();

                            // 因为不存在.xml文件 故只能之内存字节流的方式初始化

                            Document doc = db.parse(

                                  new ByteArrayInputStream(sb.toString().getBytes())

                            );

                            String name = getElementData(doc, "name");

                            String age = getElementData(doc, "age");

                            String password = getElementData(doc, "password");

                            out.print("Parameters are name: " + name

                             + " age: " + age

                             + " password: " + password

                            );

                      } catch (Exception e) {

                            e.printStackTrace();

                            out.print("error");

                      }

                      out.close();

                 }

 

 

页面部分更新,只更新表格部分

      (1) html文件的实现 :

           <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

           <html>

           <head>

           <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

           <title>Online super store</title>

           <script type="text/javascript" src="js/utils.js"></script>

           <script type="text/javascript" src="js/kettasAjax.js"></script>

           <script type="text/javascript">

                 function initStore(){

                      kettasAjax.getText("listProduct.jsp", display);

                 }               

                 function display(txt){

                      $("store").innerHTML = txt;

                 }

           </script>

           </head>

           <body onload="initStore();">

                 <div id="store"></div>     

           </body>

           </html>

      (2) listProduct.jsp内容以下 :

           <%@ page language="java" contentType="text/html; charset=GBK"

                 pageEncoding="GBK"%>

           <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

           <jsp:useBean id="store" class="com.kettas.ajax.xhr.day1.SuperStore" scope="application"/>

           <table border="1">

             <tbody>

               <c:forEach var="product" items="${store.products}">

                 <tr>

                      <td>${product.id }</td>

                      <td>${product.name }</td>

                      <td>${product.price}</td>

                 </tr>

               </c:forEach>

             </tbody>

           </table>

10  于Ajax中的Json

Json 是一种线上协议,轻量级的xml 一种文体格式

      Json的功能,简单的说,就是实现字符串和对象之间的转换。要使用其功能,在客户端,要引入

      json.js文件,在服务器端,则要引入json.jar这个包。

      Json对象和数组  {}大括号表明一个对象,,【】表明数组

      (1) Json在客户端的应用实例 :

           <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

           <html>

           <head>

           <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

           <title>JSON test</title>

           <script type="text/javascript" src="js/json.js"></script>

           <script type="text/javascript" src="js/utils.js"></script>

           <script type="text/javascript">

                 // 建立一个对象,注意格式  {}

                 var product = {

                      id: 1,  name: "core java",  price: 100       };

                 // 建立一个对象字符串,注意格式

                 var s = '{"id": 1, "name": "George", "age":30}';

                 // 实现对象和字符串之间的互换 只须stringify和parse这两个方法便可

                 function display(){

                      // 将对象转换为字符串,发送给服务器处理

                      byId("json").innerHTML = JSON.stringify(product);

                      // 将字符串转换为对象,把服务端的字符串组装成对象

                      var student = JSON.parse(s);

                      alert(student.id + "\t" + student.name + "\t" + student.age); }

           </script>

           </head>

           <body onload="display()"><h2>

                 <div id="json"></div>

                 </h2>

           </body>

           </html>

      (2) Json在客户端和服务器端同时应用 :

           1 客户端html文件 :

                 <html><head>

                 <title>Query Price</title>

                 <script type="text/javascript" src="js/json.js"></script>

                 <script type="text/javascript" src="js/kettasAjax.js"></script>

                 <script type="text/javascript" src="js/utils.js"></script>

                 <script type="text/javascript">

                      function query(){

                            // obj4form是一个工具函数 根据表单id 将用户输入表单的数据封装为一个对象

                            var car = obj4form("carInfo");

                            // 直接向服务器发送对象字符串

                 //"queryPrice"是访问servlet地址,JSON.stringify(car)发送对象字符串,display为服务器返回内容

                            kettasAjax.postText("queryPrice", JSON.stringify(car), display);

                      }

                      function display(txt){

                            // 将从服务器返回的对象字符串转换为对象

                            var ret = JSON.parse(txt);

                            var model = ret.model;

                            var price = ret.price;

                            $("result").innerHTML = model + " " + price

                      }

                 </script>

                 </head>

                 <body>

                      <h2>Please enter car information</h2>

                      <!-- 利用输入的汽车id和生产厂商信息 得以查询汽车的价格 -->

                      <form action=#" id="carInfo">

                            Id: <input type="text" id="id"/><br/>

                            Make: <input type="text" id="make"/><br/>

                      </form>

                      <button onclick="query()">Query Price</button>

                      <div id="result"></div>

                 </body>

                 </html>

           2 Servlet文件QueryPriceServlet的片断 :

                      protected void doPost(HttpServletRequest request, HttpServletResponse response)

                            throws ServletException, IOException {

                            response.setContentType("text/plain");

                            BufferedReader reader = request.getReader();//获得客户端的字符串

                            PrintWriter out = response.getWriter();

                            StringBuilder sb = new StringBuilder();

                            String str = null;

                            while((str = reader.readLine()) != null)

                                  sb.append(str);

                            try { // 将客户端发送的对象字符串转化为JSONObject对象

                                  JSONObject jsonObj = new JSONObject(sb.toString());

                                  // 得到对象中的数据 注意格式

                                  int id = jsonObj.getInt("id");

                            String make = jsonObj.getString("make");

                                  // 不用make.equals("Audi") 避免了make == null的状况下抛异常 小技巧

                                  if(id == 1 && "Audi".equals(make)){

                                       // 给客户端回应一个对象字符串 注意格式// 首先建立一个新的JSONObject对象

                                       jsonObj = new JSONObject();

                                       // 向这个对象中填充数据

                                       jsonObj.put("model", "A8");

                                 jsonObj.put("price", 860000);

                                       // 将对象转化为对象字符串 回发给客户端

                                       // 这个对象字符串的格式为 : '{"model" : "A8" , "price" : 860000}'

                                       out.print(jsonObj.toString());

                                  }

                            } catch (Exception e) {

                                  e.printStackTrace();  throw new ServletException(e);

                            }finally{  out.close();

                            }}  

      (3) 在服务器端将java中的实体bean、collections、array以及map对象转换为对象字符串 :

           要实现这个功能,能够借助内部工具类JsonUtil.java,其中的几个方法是颇有用的,如 :

                 public static JSONObject bean2Json(Object bean),

                 public static JSONObject map2Json(Map map),

                 public static JSONArray array2Jarr(Object value),

                 public static JSONArray collection2Json(Object value)

           测试类片断以下 :                 

                 public class TestJsonUtil {           

                      public static void main(String[] args) {

                            SuperStore ss = new SuperStore();

                            // ss.getProducts()方法返回一个商品对象的集合

                            JSONArray jarr = JsonUtil.collection2Json(ss.getProducts());

                            System.out.println(jarr.toString());

                      }               

                 }    

 

 

11 关于Ajax中的dwr框架 :

      有了dwr框架,操做html页面感受就是在直接操做java代码。实际上,仍是经过服务器端执行的。

      要使用此框架提供的功能,必须引入dwr.jar这个包。

      思想:在web上的servlet动态生成javascript代码

      (1) 最简单的实例

           java类文件 :

                 package com.kettas.ajax.dwr.day4;

                 public class Hello {                  

                      public String sayHello(String user){

                            try{

                                  Thread.sleep(2000);

                            }catch(Exception e){

                            }

                            return "Hello, " + user;

                      }

                 }

           配置文件dwr.xml(与web.xml处于同一个位置) :

                 <dwr>

                      <allow>

                            <!-- javascript="hello"指定客户端对象名称为hello

                                   creator="new"指定java对象的建立方式

                                   scope="application"指定java对象的放置位置 -->

                            <create javascript="hello" creator="new" scope="application">

                                  <param name="class" value="com.kettas.ajax.dwr.day4.Hello"></param>

                            </create>

                      </allow>

                 </dwr>

           客户端html文件的内容 :

                 <!-- 服务器动态生成的js文件 内有hello对象 -->

                 <script type="text/javascript" src="dwr/interface/hello.js"></script>

                 <!-- dwr引擎包 -->

                 <script type="text/javascript" src="dwr/engine.js"></script>

                 <!-- 引入dwr提供的工具包 -->

                 <script type="text/javascript" src="dwr/util.js"></script>

                 <script type="text/javascript">

                      // element.style.visibility = "hidden";

                      // element.style.visibility = "";

                      // CSS内容 对象的隐藏属性  

                      /*

                      // 这样写的话 仅此函数就能够了

                      function sayHello(){

                            // 直接给参数赋内部函数

                            hello.sayHello($("user").value, function(txt){

                                  dwr.util.setValue("helloStr", txt);

                            });

                      }*/

                      /*

                      // 也能够这么写 最简便

                      function sayHello(){

                       // hello是在dwr.xml配置的,hello.sayHello至关调用服务端的方法,($("user").value 参数,display回调方法,返回值就是display(text)中的text值

                      hello.sayHello($("user").value, display);

                      }

                      */

                      // 这么写 是最完整的

                      function sayHello(){                        

                            //dwr.util.useLoadingMessage("Wait a minute...");

                            // 给参数赋一个对象

                            var cb = {

                                  callback: display, // 指定回调函数

                                  timeout: 500, // 指定等待时间 若是超出这个时间 则出错

                                  errorHandler: display, // 指定处理错误的回调函数

                                  // ???

                                  name: "George"

                            };

                            // 在客户端调用方法 始终比服务端对应方法要多一个参数

                            // 这个参数最终的实现是一个回调函数

                       // 这个回调函数的参数就是服务端方法返回的对象(在客户端是javascript对象)

                            hello.sayHello($("user").value, cb);

                      }

                      function display(txt){

                            // 调用工具包中的工具函数 为容器添加文本

                            dwr.util.setValue("helloStr", txt);

                      }

                 </script>

                 </head>

                 <body>

                      <h2 id="h2">Please enter a user who you want to say hello to:</h2>

                      User: <input type="text" id="user"/><button onclick="sayHello()">Say Hello</button><br/>

                      <div id="helloStr"></div>

                 </body>

                 </html>

           在web.xml文件中不妨加上以下内容做为测试用 :

                      <servlet>

                            <servlet-name>dwr</servlet-name>

                            <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>

                            <init-param>

                                  <param-name>debug</param-name>

                                  <param-value>true</param-value>

                            </init-param>

                      </servlet>

                      <servlet-mapping>

                       <servlet-name>dwr</servlet-name>

                       <url-pattern>/dwr/*</url-pattern>

                   </servlet-mapping>

      (2) 实例 : 人员管理

           Person实体类 : Integer id; String name;     String address;  float salary;

           人员管理类PersonMgmt :

                 package com.kettas.ajax.dwr.day5;

                 import java.util.Collection;

                 import java.util.HashMap;

                 import java.util.Map;

                 public class PersonMgmt {

                      private Map<Integer, Person> people = new HashMap<Integer, Person>();

                      private static int count = 10;

                      public PersonMgmt() {

                            Person fred = new Person("Fred", "1 Red Street", 2, 100000.0f);

                            Person jim = new Person("Jim", "42 Brown Lane", 3, 20000.0f);

                            Person shiela = new Person("Shiela", "12 Yellow Road", 4, 3000000.0f);

                            people.put(new Integer(fred.getId()), fred);

                            people.put(new Integer(jim.getId()), jim);

                            people.put(new Integer(shiela.getId()), shiela);

                      }

                      public Collection<Person> getPeople() {

                            return people.values();

                      }

                      public Person getPerson(Integer id) {

                            return people.get(id);

                      }

                      public void add(Person p) {

                      //若是p中没有值时执行

                            if (p.getId() == -1)

                                  p.setId(count++);

                                  people.put(p.getId(), p);

                            }

                      public void remove(Person p) {

                            people.remove(p.getId());

                      }

                 }

           配置文件dwr.xml :

                 <dwr>

                      <allow>

                            <create javascript="personMgmt" creator="new" scope="session">

                                  <param name="class" value="com.kettas.ajax.dwr.day5.PersonMgmt"></param>

                            </create>

                            <!-- 因为客户端传入的是javascript的Person对象

                                   故这里要声明对应的服务器端java的Person对象

                                   不然服务端将没法将对象从客户端类型转换为服务端类型

<convert》转换器,对象到字符串之间的转换 -->

                            <convert match="com.kettas.ajax.dwr.day5.Person" converter="bean"></convert>

                      </allow>

                 </dwr>

           客户端html文件内容 :

                 <title>Person Management</title>

                 <script type="text/javascript" src="dwr/engine.js"></script>

                 <script type="text/javascript" src="dwr/util.js"></script>

                 <script type="text/javascript" src="dwr/interface/personMgmt.js"></script>

                 <script type="text/javascript">

                      // 初始化显示人员信息

                      function init(){

                            personMgmt.getPeople(fillTable);

                      }

                      // 函数数组

                      var peoplebodyCellFuncs = [

                            // 函数参数为人员对象 返回值即咱们要在单元格中显示的内容

                            // 此数组的长度即表主体显示内容的列数

                            function(person) { return person.name;},

                            function(person) { return person.address;},

                            function(person) { return person.salary;},

                            // 在第四列添加两个操做按钮

                            function(person) {

                                 var div = document.createElement("div");

                                  div.appendChild(createBtn("personId", person.id, prepareEdit, "Edit"));

                                  div.appendChild(createBtn("personId", person.id, removePerson, "Remove"));

                                  return div;

                            }

                      ];

                      // 编辑人员信息

                      function prepareEdit(){

                            var personId = this.personId; // 得到此人id 注意这里this的使用

                            personMgmt.getPerson(personId, fillFields) // 调用服务端方法 得到此人对象

                      }

                      // 填充人员信息编辑表

                      function fillFields(person){

                            // person对象以下 : {id : 1, name : "yinkui", address : "xf", salary : 50000}

                            // 至关于执行 : document.getElementById("id").value = 1

                            //              document.getElementById("name").value = "yinkui" ...

                            dwr.util.setValues(person);

                      }

                      // 删除一我的

                      function removePerson(){

                            var personId = this.personId; // 得到此人id 注意这里this的使用

                            // 因为对应服务端java方法中 删除一我的只须要此人id

                            // 故 建立person对象时只须要赋予id

                            // 这样传到服务端 建立的java的Person对象顶可能是其余属性为null

                            var person = {

                                  id: personId

                            };

                            personMgmt.remove(person, init); // 调用服务端方法删除此人 而后刷新人员信息表的显示

                      }

                      // 建立按钮的函数

                      function createBtn(attrName, attrValue, onclick, label){

                            var btn = document.createElement("button");

                            btn[attrName] = attrValue; // 按钮对象中存放对应人员id值

                            btn.onclick = onclick; // 为按钮添加事件

                            btn.appendChild(document.createTextNode(label)); // 为按钮添加显示内容

                            return btn;

                      }

                      // 填充人员信息表

                      // 其中people对象是从服务端返回的人员对象数组

                      // 其格式为[{id : 1, name : "yinkui", address : "xf", salary : 50000}, {...}, ...]

                      function fillTable(people){

                            dwr.util.removeAllRows("peoplebody");// 调用工具函数 清空表主体中的全部行

                            // 调用工具函数 经过人员对象数组 为表主体添加行

                            // 其中peoplebodyCellFuncs是一个函数数组

                            dwr.util.addRows("peoplebody", people, peoplebodyCellFuncs);

                            clearPerson();// 初始化人员信息编辑表的内容

                      }

                      // 添加新人员

                      function writePerson(){

                            var person = {

                                  id: -1,

                                  name: null,

                                  address: null,

                                  salary: null

                            };

                            // 注意此工具函数的使用

                            // 其做用与dwr.util.setValues({...})偏偏相反

                            // 至关于执行 : person.id = document.getElementById("id").value

                            //    person.name = document.getElementById("name").value

                            dwr.util.getValues(person);

                            personMgmt.add(person, init); // 调用服务端方法 而后刷新人员信息表的显示

                      }

                      // 初始化显示人员信息编辑表

                      function clearPerson(){

                            // 注意此工具函数的使用 参数为对象

                            // 至关于执行 : document.getElementById("id").value = -1

                            //              document.getElementById("name").value = null ...

                            dwr.util.setValues(

                                  {     id: -1,         name: null,

                                       salary: null,         address: null

                                  }

                            );

 }

                 </script>

                 </head>

                 <body onload="init()">

                 <h1>Dynamically Editing a Table</h1>

                 <h2>People Management</h2>

                 <!-- 人员信息列表 -->

                 <table border="1">

                      <!-- 表头 -->

                      <thead>

                            <tr> th>Name</th>

                                  <th>Address</th>

                                  <th>Salary</th>

                                  <th colspan="2">Actions</th></tr>

                      </thead>

                      <!-- 表的主体 -->

                      <tbody id="peoplebody"></tbody>

                 </table>

                 <h4>Edit Person</h4>

                 <!-- 对人员信息进行编辑 或是添加新人员 -->

                 <table>

                      <tr><td>ID:</td>

                            <td><span id="id">-1</span></td></tr>

                      <tr><td>Name:</td>

                            <td><input id="name" type="text" /></td></tr>

                      <tr><td>Salary:</td>

                            <td><input id="salary" type="text" /></td></tr>

                      <tr><td>Address:</td>

                            <td><input type="text" id="address" /></td></tr>

                      <tr><td colspan="2" align="right">

                            <input type="button" value="Save" onclick="writePerson()" />

                            <input type="button" value="Clear" onclick="clearPerson()" /></td></tr>

                 </table></body></html>

12,关于DOJO的框架:

    含义:Dojo是一个很是强大的面向对象的JavaScript的工具箱, 建议读者可以去补充一下JavaScript下如何使用OO进行编程的, 这对于你之后阅读Dojo Source有很大的用处

做用:①处理浏览器的不兼容问题,能够方便创建互动的互动用户见面。②更容易统一页面风格。③封装与服务端的通讯,动态从服务器下载javascript

开发流程:①把dojo工具包考到js文件下

②引用 dojo 的启动代码

                   <script type="text/javascript" src="/yourpath/dojo.js" />

③声明你所要用到的包

<script type="text/javascript">
  dojo.require("dojo.math");引入数学方法
  dojo.require("dojo.io.*"); 引入io

dojo.require("dojo.event.*");  引入事件
  dojo.require("dojo.widget.*");引入页面

  function init(){  初始化

       var btn = dojo.widget.byId("helloBtn");

       dojo.event.connect(btn, "onClick", "sayHello");事件源,产生关联,时间方法

  }

  function sayHello(){

       dojo.io.bind(

         { url: "sayHello.jsp",处理事件的url

             handler: callback,  回调函数

             formNode: "myForm" 表单内容

         });}

  function callback(type, data, evt){

       document.getElementById("result").innerHTML

         = data;

  }

 

  dojo.addOnLoad(init);加入事件

</script>

</head>

<body>

  <h2>DOJO Test</h2>

  <form action="#" id="myForm">

       User: <input type="text" name="user" />

  </form>

  <button dojoType="Button" widgetId="helloBtn">DOJO Say Hello</button>

  <div id="result"></div>

</body>

</html>

13,关于Ext框架         

   参考项目文档

 

     

14补充:Dom部分 建立标签 var td=document.createElement(“td”); td.apperdchild(childName)

 

 

javascript的高级部分

            1,javascript的对象和继承  因为javascript是采起prototype机制的伪继承”,prototype必须显示引用“基类”对象,因此注定了javascript只能实现“弱继承”,或者叫作“对象继承”
注意这里的次序关系须要很明确,prototype的赋值必须在对象构造以外。

function classA()
{  classA.prototype.name=”xxx”;属性

 classA.prototype.methodA = function() {...}这是一个对象方法

classA.methodA = function(){...} //这是一个类方法至关于java的static方法

}
 function classB()
{  classB.prototype.methodA = function(){...}
 }

classB.prototype = new classA();
                      
//注意这里声明B继承自A出如今function classB()函数体以外,而且先于
//classB对象的构造被执行。

 

私有成员的设置

 Var name=“zhang”;

 this.getName=function(){return name;}

 this.setName=function(myname){name=myname; }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Spring

一:Ioc

1含义:为解决企业应用开发的复杂性而建立的开源框架,用基本的javaBean来完成EJB的事情 从大小和开销方向spring都是轻量级的

2,用途

①   Ioc容器能够将对象之间的依赖关系交由spring管理,进行控制

②   AOP:方便进行面向切面的编程,是oop的扩展,想加什么功能直接加

③   可以集成各类优秀的框架,struts hibernate等

3,spring 组成内容

 

 

 

 

 

 

 

 

 

 

4准备配置工做

①下载SpringFramework的最新版本,并解压缩到指定目录。

在IDE中新建一个项目,并将Spring.jar将其相关类库加入项目

② 配置文件 bean.xml

③在classpath建立日志输出文件。log4j.properties

④org.springframework.beans及org.springframework.context包是Spring IoC容器的基础

5 Spring 基础语义

     1)IoC (Inversion of Control)=DI (Dependency Injection)控制反转和依赖注入

     它是一种基于接口的编程,bean由容器建立在须要的时候拿来用便可,主要是采用反射来实现,其核心组建就是BeanFactory 但实际开发经常使用XmlBeanFactory

2)依赖注入的几种实现类型

  Type1设值注入:经过类的setter方法完成依赖关系的设置,就是给bean类中属性加set方法

Type3 构造子注入:即经过构造函数完成依赖关系的设

public class DIByConstructor {

private final DataSource dataSource;

private final String message;

public DIByConstructor(DataSource ds, String msg) {

this.dataSource = ds;

this.message = msg;

}}

   

3)几种依赖注入模式的对比总结


Type2 设值注入的优点

1. 对于习惯了传统JavaBean开发的程序员而言,经过setter方法设定依赖关系显得更加直

观,更加天然。

2. 若是依赖关系(或继承关系)较为复杂,那么Type3模式的构造函数也会至关庞大(咱们需

要在构造函数中设定全部依赖关系),此时Type2模式每每更为简洁。

3. 对于某些第三方类库而言,可能要求咱们的组件必须提供一个默认的构造函数(如Struts

中的Action),此时Type3类型的依赖注入机制就体现出其局限性,难以完成咱们指望的功

能。

 

Type3 构造子注入的优点:

1. “在构造期即建立一个完整、合法的对象”,对于这条Java设计原则,Type3无疑是最好的

响应者。

2. 避免了繁琐的setter方法的编写,全部依赖关系均在构造函数中设定,依赖关系集中呈现,

更加易读。

3. 因为没有setter方法,依赖关系在构造时由容器一次性设定,所以组件在被建立以后即处于

相对“不变”的稳定状态,无需担忧上层代码在调用过程当中执行setter方法对组件依赖关系

产生破坏,特别是对于Singleton模式的组件而言,这可能对整个系统产生重大的影响。

4. 一样,因为关联关系仅在构造函数中表达,只有组件建立者须要关心组件内部的依赖关系。

对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽没必要要的信息,也为系统的

层次清晰性提供了保证。

5. 经过构造子注入,意味着咱们能够在构造函数中决定依赖关系的注入顺序,对于一个大量

依赖外部服务的组件而言,依赖关系的得到顺序可能很是重要,好比某个依赖关系注入的

先决条件是组件的DataSource及相关资源已经被设定。

 

 

 

理论上,以Type3类型为主,辅之以Type2

类型机制做为补充,能够达到最好的依赖注入效果,不过对于基于Spring Framework开发的应用而言,

Type2使用更加普遍。

 

 

 

5)bean.xml配置文件

Bean Factory,顾名思义,负责建立并维护Bean实例。

Bean Factory负责根据配置文件建立Bean实例,能够配置的项目有:

1. Bean属性值及依赖关系(对其余Bean的引用)

2. Bean建立模式(是否Singleton模式,便是否只针对指定类维持全局惟一的实例)

3. Bean初始化和销毁方法

4. Bean的依赖关系

6)XmlBeanFactory两中注入方式的配置

①property-------àset方法的注入配置

<p:bean id=”hello” class=”com.kettas.HelloIFImp”>

   <p:property name=”user” value=”xxx”></p:property>
</p:bean>

②constructor---------à构造方法的注入配置

<p:bean id="hello2" class="com.kettas.spring.ioc.day1.HelloIFImpl">

   <p:constructor-arg index=”0” value="world"></p:constructor-arg>

   <p:constructor-arg type="java.lang.String"”ref="calendar"></p:constructor-arg>

</p:bean>

说明: index=”0”构造方法第一个参数,用index能够稍微减小冗余,可是它更容易出错且不如type属性可读性高。你应该仅在构造函数中有参数冲突时使用index。

7) 依赖的目标类型分红三种形式           

 

1) 基本类型+String 
   <value>data</value>类型自动转化
 2) 对其余bean 的引用 
       <ref bean="target"/>

 3) 集合类型       list props set map
   list set properties配置相似

  <p:property name="intList">

      <p:list>

                    <p:value>1</p:value>

                    <p:value>2</p:value>

       </p:list>

</p:property>

   <p:property name="objMap">

        <p:map>

     <p:entry>

        <p:key>

              <p:value>1</p:value>

</p:key>

    <p:ref local="hello2"/>

     </p:entry>

   </p:map>

</p:property>

<p:property name="pros">

        <p:props>

              <p:prop key="1">red</p:prop>

              <p:prop key="2">green</p:prop>

        </p:props>

</p:property>

 


               

 Xml配置文件属性的说明

<bean id="TheAction" ⑴ class="net.xiaxin.spring.qs.UpperAction" ⑵ singleton="true" ⑶

init-method="init" ⑷destroy-method="cleanup" ⑸depends-on="ActionManager" ⑹ >

<property…>

</bean>

⑴ id

Java Bean在BeanFactory中的惟一标识,代码中经过BeanFactory获取

JavaBean实例时需以此做为索引名称。

⑵ class Java Bean 类名 即真正接口的实现类

⑶ singleton bean的做用域(建立模式(prototype仍是singleton))

单例(Singleton)模式,若是设为“true”,只维护此Java Bean的一个实例,反之,若是设为“false”, BeanFactory每次都将建立一个新的实例返回。默认为true

实现方式是第一次getBean时放入Map中保存,第二次再用时直接在Map中拿,类名为key,实例为value。Bean的其余做用域还有prototype:原型模式:在获取prototype定义的bean时都产生新的实例,其生命周期由客户端维护。Session对每次HTTPsession中都回产生一个新的实例。Global session 仅在使用portletcontext的时候才有效,经常使用的是singleton和prototype

⑷ init-method

初始化方法,此方法将在BeanFactory建立JavaBean实例以后,在向应用层返回引

用以前执行。通常用于一些资源的初始化工做。在javaBean中建立init方法,再添加属性init-method=“init”就行

⑸ destroy-method

销毁方法。此方法将在BeanFactory销毁的时候执行,通常用于资源释放。与init用法相似

⑹ depends-on

Bean依赖关系。通常状况下无需设定。Spring会根据状况组织各个依赖关系的构建工做(这里

示例中的depends-on属性非必须)。

只有某些特殊状况下,如JavaBean中的某些静态变量须要进行初始化(这是一种Bad

Smell,应该在设计上应该避免)。经过depends-on指定其依赖关系可保证在此Bean加

载以前,首先对depends-on所指定的资源进行加载。

⑺ <value>

经过<value/>节点可指定属性值。BeanFactory将自动根据Java Bean对应的属性

类型加以匹配。

下面的”desc”属性提供了一个null值的设定示例。注意<value></value>表明一

个空字符串,若是须要将属性值设定为null,必须使用<null/>节点。

⑻ <ref>指定了属性对BeanFactory中其余Bean的引用关系。

 

8)使用抽象bean  定义抽象类Abstract=“true”抽象bean不能实例化,一个类能够建立多个bean

                抽象bean的配置和通常bean的配置基本同样只是在增长了Abstract=“true”抽象bean是一个bean的模板,容器会忽略抽象bean的定义,不会实例化抽象bean,故不能经过getBean()显示的得到抽象bean的实例也不能将抽象bean注入其余bean的依赖属性。

抽象bean的配置和继承

   经过Abstract属性配置抽象bean

   <bean id=”fatherTemple” class=”abstractClass” abstract=”true”>

<!—注入属性à

<property name=”name” ref=”xxx”/>

</bean>

<!—经过parent属性定义子beanà

<bean id=”childTemple” parent=”fatherTemple”>

 <property name=”name2” ref=”yyyy”/>  -定义本身的属性

</bean>

说明:子bean配置能够增长新的配置信息,并能够定义新的配置覆盖父类的定义

       子类和父类中至少有一个class属性不然不知道实现类,父类的class能够不写

 

9)bean在容器上的生命周期

初始化两种方法 1使用init-method属性指定那个方法在bean依赖关系设置好后自动执行

          2实现initializingBean接口 实现该接口必须实现void afterPropertiesSet()throws Exception那么就不用设置init-method方法了,注意:最好使用init-method方法,减小代码的侵入性,若是两种方法都实现则先实现接口再init方法(通常写入日志文件)

 销毁两种方法和初始化同样也有两种方法:1,destroy-method和1实现DisposableBean接口

 

 

 

 

 

 

 

 

 

6,Spring容器,最基本的接口就是BeanFactory 负责建立,配置,管理bean 它有一个子接口ApplicationContext并将功能扩展。

理论上bean装配能够从任何资源得到,包括属性文件,关系数据库等,但xml是最经常使用的XmlBeanFactory , ClassPathXmlApplicationContext , FileSystemXmlApplicationContext ,

XmlWebApplicationContext应用系统配置源。Spring中的几种容器都支持使用xml装配bean,包括:

XmlBeanFactory , ClassPathXmlApplicationContext ,FileSystemXmlApplicationContext ,
XmlWebApplicationContext

 

BeanFactory接口包含以下的基本方法:
Boolean containsBean(String name): 判断Spring容器是否包含id为name的bean定义。
Object getBean(String name): 返回容器id为name的bean.
Object getBean(String name, Class requiredType): 返回容器中id为name,而且类型为requiredType的bean.
Class getType(String name): 返回容器中id为name的bean的类型.

ApplicationContext有三个实现类实现资源访问

FileSystemXmlApplicationContext:基于文件系统的xml配置文件建立ApplicationContext,

ClassPathXmlApplicationContext :以类加载路径下的xml的配置文件建立ApplicationContext(更为经常使用)

XmlWebApplicationContext:对使用servletContextResource进行资源访问

得到容器的应用的方式

①InputStream is = new FileInputStream("bean.xml");

XmlBeanFactory factory = new XmlBeanFactory(is);

或者BeanFactory factory = new XmlBeanFactory(

new ClassPathResource("classpath:bean.xml"))

Action action = (Action) factory.getBean("TheAction");

ApplicationContext bf=new ClassPathXmlApplicationContext("classpath:bean.xml")

Action action = (Action) factory.getBean("TheAction");

ApplicationContext bf=new FileSystemXmlApplicationContext(“classpath:bean.xml”)

第一种BeanFactory启动快(启动是不建立实体,到用时才建立实体),

第二种ApplicationContext运行快(在加载时就建立好实体)更为经常使用,继承BeanFactory

 

        5)工厂bean和bean工厂

FactoryBean(工厂bean)是bean的加工工厂,是对已知Bean的加工,是一个接口,要实现三个方法:

①   Object getObject()能够对bean进行加工添加功能

②Class getObjectType()③Boolean isSingleton()

              Bf.getBean(“ab”)只是获得MyFactory.getObject()的object对象 因此最后要强转。

 

Beanfactory bean工厂 就是生产bean的工厂,注入:

因为Spring IoC容器以框架的方式提供了工厂方法的功能,并以透明的方式给开发者,不过在一些遗留系统或第三方类库中,咱们还会碰到工厂方法,这时用户能够使用Sping使用工厂方法注入的方式进行配置。

 

静态工厂方法:
不少工厂类方法都是静态的,这意味着用户在无须建立工厂类实例的状况就能够调用工厂类方法。所以静态工厂方法比非静态工厂方法的调用

更加方便。咱们将carFactory类的getCar()方法调整为静态的而后再Spring配置以下:
<bean id=”car” class =”carFactory” factory-method=”getCar”/>
用户直接经过class属性指定工厂类, 而后在经过factory-method指定对应的静态工厂方法建立bean。

若是静态工厂方法须要参数则用<p:constructor-arg index=”1”value="calendar"></p:constructor-arg>传入

 

实例工厂方法
有些工厂是非静态的,即必须是实例化工厂类才能调用工厂方法。
下面咱们实例化一个工厂类CarFactory类来为Car类提供实例。
package com.car;
public class CarFactory
{ public Car getCar(){return new Car();}}
工厂类负责建立一个或多个目标类实例,工厂类方法通常以接口或抽象类变量的形式返回目标类。工厂类对外屏蔽了目标类的实例化步骤。调

用甚至不知道如何具体的目标类是什么。
下面咱们在Spring 配置文件中进行配置
<!--工厂Bean生成目标Bean-->
<bean id=”carFactory” class=”com.CarFactory”/>
<!--工厂Bean目标Bean-->
<bean id=”car” factory-bean=”carFactory” factory-method=”getCar”/>
factory-bean=”carFactory”指定了工厂类Bean,factory-method=”getCar”指定了工厂类Bean建立该Bean的工厂方法。

和静态工厂相似若是工厂方法须要参数则用

<p:constructor-arg index=”0”value="calendar"></p:constructor-arg>传入

 

7,使用ApplicationContext  ApplicationContext覆盖了BeanFactory的全部功能,并提供了更多的特,容器建立时就建立了singleton Bean

相对BeanFactory而言,ApplicationContext提供了如下扩展功能:

1. 国际化支持:继承MessageSource接口,提供国际化支持

2. 资源访问:支持对文件和URL的访问。

3. 事件传播:事件传播特性为系统中状态改变时的检测提供了良好支持。

4. 多实例加载:能够在同一个应用中加载多个Context实例,即加多个配置文件

 1,国际化处理的步骤

1)  写相应的国家资源文件如:ApplicationResources_zh.properties  

注意字符的转化相似struts的国际化

2)  bean.xml 的配置

<p:bean id="messageSource[U25] " class="org.springframework.context.support.ResourceBundleMessageSource">

  <p:property name="basename" value="com.kettas.spring.ioc.day3.ApplicationResource" />

  </p:bean>

  <p:bean id="msc" class="com.kettas.spring.ioc.day3.MessageSourceConsumer" />

  </p:beans>

 

3)实现类MessageSourceConsumer

具体的实现类implements MessageSourceAware。注入messageSource ms

获得字符:String name = ms.getMessage("name", null, Locale.CHINA);name是资源文件的key值

 Locale.CHINA是中文,Locale.ENGLISH英文

 

2. 资源访问:即外部资源文件的获取;资源文件

两种引入外部资源的方式

①<!-- <p:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

           <p:property name="location" value="com/kettas/spring/ioc/day3/jdbc.properties"></p:property>

     </p:bean> -->

 

②,引入解析:xmlns:context="http://www.springframework.org/schema/context"

<context:property-placeholder location="com/kettas/spring/ioc/day3/jdbc.properties"/>

使用<p:property name="driverClassName" value="${jdbc.driver}"></p:property>

jdbc.driver是资源的key值

其它:ApplicationContext.getResource方法提供了对资源文件访问支持,如:

Resource rs = ctx.getResource("classpath:config.properties");

File file = rs.getFile();

3. 事件传播:事件机制是观察者模式的实现

    事件框架两个重要的成员:

1)  ApplicationEvent:容器事件,必须由ApplicationContext发布

2)  ApplicationListener:监听器:可有其余任何监听器bean担任

3)  ApplicationContext是事件源必须由java程序显示的触发

1)事件流程:

 

 

 

 

 

 

 

 

 

 

 

 

 

2)代码实例


1,  事件源.

public class LogEventSource implements ApplicationEventPublisherAware

{

  private ApplicationEventPublisher publisher;   public void setApplicationEventPublisher(

ApplicationEventPublisher publisher){ 

this.publisher = publisher;

  }

 public void fireEvent(){

     LogEvent evt = new LogEvent(this, "Test message");

     publisher.publishEvent(evt);

}

}

 

 

2,  事件监听

public class Logger implements ApplicationListener {

private Log logger = LogFactory.getLog(Logger.class);

 public void onApplicationEvent(

ApplicationEvent evt) {

         logger.info("Event type: " + evt.getClass().getName());

 if(evt instanceof LogEvent){                logger.info(((LogEvent)evt).getMessage());

   }}

}


3)配置文件

<p:bean id="les"  class="com.kettas.spring.ioc.day3.LogEventSource">   有相应的事件方法

</p:bean>

<p:bean class="com.kettas.spring.ioc.day3.Logger"></p:bean> 处理事件的后台

</p:beans>

说明:LogEventSourc有相应的事件方法publisher.publishEvent(evt)主动触发容器事件; Logge处理事件的后台

 

4. 多实例加载

 BeanPostProcessor bean后处理器 实现BeanPostProcessor接口 对bean实例进一步增长功能,实现两个方法processBeforeInitialization(Object bean,String name)方法(该方法的第一个参数是将进行后处理的实例bean,name是该bean的名字)和ProcessaAfterInitialization(Object bean,String name).在init()或destory以前作一些处理.Spring的工具类就是经过bean的后处理器完成的。

BeanFactoryPostProcessor 容器后处理器:实现接口BeanFactoryPostProcessor只负责处理容器自己 ,实现的方法是 postProcessBeanFactory(ConfigurableListableBeanFactory  beanFactory)参加资源的引入和获取,能够修改bean工厂bean的定义至关一个再配置的过程。相似BeanPostProcessor,ApplicationContext能够自动检测到容器中的容器后处理器,可是BeanFacory必须手动调用。
         

5,web中如何使用spring

1),加入相应的jar包

2)Web.xml的配置

<listener>

<listener-class> org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

或者

(  <servlet><servlet-name>context</servlet-name>

<servlet-class> org.springframework.web.context.ContextLoaderServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>   )

经过以上配置,Web容器会默认自动加载/WEB-INF/applicationContext.xml初始化

ApplicationContext实例,若是须要指定配置文件位置,可经过context-param加以指定

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/myApplicationContext.xml</param-value>

</context-param>

3) Servlet中应用

WebApplicationContext wac= WebApplicationUtils.getRequiredWebApplication(Context(getServletContext()));

HelloIf h=( HelloIf)wac.getBean(“hello”);

 

 

6,BeanFactoryLocator工厂的工厂,主要的两个实现类ContextSingletonBeanFactoryLocator和SingletonBeanFactoryLocator

BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();

BeanFactoryReference bfr = facLoc.useBeanFactory("il8b");

// BeanFactory fac = bfr.getFactory();

MessageSourceConsumer msc=(MessageSourceConsumer)bfr.getFactory().getBean(“xxxx”);

配置文件只能是beanRefFactory.xml且放在根目录下

<p:bean id=”il8n” class=”org.springframework.context.support.ClassPathXmlApplicationContext”>

 <p:constructor-arg><p:value>spring/il8n.xml</p:value></p:constuctor-arg>

</p:bean> 应用另一个配置文件即另一个beanFactory

7, .spring完成自动装配Autowiring 解决<ref>标签为javaBean注入时难以维护而实现的

下面是几种autowire type的说明:

  ● byname : 试图在容器中寻找和须要自动装配的属性名相同的bean或id,若是没有找到相应的bean,则这个属性未被装配上。配置文件中的id/name中查找

  ● byType : 试图在容器中寻找一个与须要自动装配的属性类型相同的bean或id,若是没有找到,则该属性未被装配上。

                 至关set方法注入

  ● constructor : 试图在容器中寻找与须要自动装配的bean的构造函数参数一致的一个或多个bean,若是没找到则抛出异常。构造方法注入

  ● autodetect : 首先尝试使用constructor来自动装配,而后再使用byType方式。

  Dependeney_cheching 依赖检查 通常和自动装配配套使用 四种类型:name,simple,object ,all

缺点:spring不必定能很准确的找到javaBean的依赖对象,大型应用通常不用,且配置文件可读性差

 

 

8,BeanFactoryAware和BeanNameAware

实现 BeanFactoryAware 接口的 bean 能够直接访问 Spring 容器,被容器建立之后,它会拥有一个指向 Spring 容器的引用。

BeanFactoryAware 接口只有一个方法void setBeanFactory(BeanFactorybeanFactory)。配置和通常的bean同样

 

若是某个 bean 须要访问配置文件中自己的 id 属性,则能够使用 BeanNameAware 接口,该接口提供了回调自己的能力。实现

该接口的 bean,能访问到自己的 id 属性。该接口提供一个方法:void setBeanName(String name)。

 

9,spring2.5标签的使用(新特性)对属性,方法的注入 减小配置文件是工做量

 1)属性,方法,构造函数的标签注入

  1)@Autowired  @Autowired按byType自动注入 是对属性的注入,按照类型匹配原则(set和constructors)

2)@Resource(name="target"):@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分别是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。因此若是使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。若是既不指定name也不指定type属性,这时将经过反射机制使用byName自动注入策略。--à经常使用

3)bean lifecycle  :@PostConstruct--àinit注入  @PreDestroy ----àdestory方法注入

4)ClassPath 类路径扫描,就是注入bean

2)Bean的标签注入spring2.5为咱们引入了组件自动扫描机制,他能够在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类归入进spring容器中管理。它的做用和在xml文件中使用bean节点配置组件是同样的。要使用自动扫描机制,咱们须要打开如下配置信息:     

@Service用于标注业务层组件bean、@Service("studentBiz")。 @Controller用于标注控制层组件(如struts中的action)、

@Repository用于标注数据访问组件,即DAO组件。@Repository("dao")

而@Component泛指组件,当组件很差归类的时候,咱们能够使用这个注解进行标注,即就是通常的bean。

 

 

二,AOP相关术语

  1

▲AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面的编程。并非所有的AOP框架都是同样的。他们链接点模型的功能可能有强弱之分,有些能够字段,方法,构造函数级别的,有些只能是方法的好比spring aop 最主要的三种aop框架:AspectJ     Jboss AOP   Spring Aop  前面两种均可以对字段方法构造函数的支持。Sping和AspectJ有大量的协做

▲Aop添加的主要功能有:事务管理,安全,日志,检查,锁 等

▲Spring对Aop支持的4种状况:

  ★经典的基于代理的Aop(各个版本的spring) ★@AspectJ注解驱动的切面(spring 2.0)

★纯POJO切面(spring 2.0)                ★注入式AspectJ切面(各个版本的spring)

 

2 名词解释:

☆关注点 (Concern):关注点就是咱们要考察或解决的问题。如订单的处理,用户的验证、用户日志记录等都属于关注点。

关注点中的核心关注点 (Core Concerns) ,是指系统中的核心功能,即真正的商业逻辑。如在一个电子商务系统中,订单处理、客户管理、库存及物流管理都是属于系统中的核心关注点。

还有一种关注点叫横切关注点 (Crosscutting Concerns) ,他们分散在每一个各个模块中解决同同样的问题,跨越多个模块。如用户验证、日志管理、事务处理、数据缓存都属于横切关注点。

在 AOP 的编程方法中,主要在于对关注点的提起及抽象 。咱们能够把一个复杂的系统看做是由多个关注点来有机组合来实现,一个典型的系统可能会包括几个方面的关注点,如核心业务逻辑、性能、数据存储、日志、受权、安全、线程及错误检查等,另外还有开发过程当中的关注点,如易维护、易扩展等。

☆切面 (Aspect):切面是通知和切入点的结合,通知和写入点定义了切面的所有内容—它的功能,在什么时候何地完成功能。在Spring 2.0 AOP中,切面能够使用通用类(基于模式的风格XML Schema 的风格) 或者在普通类中以 @Aspect 注解(@AspectJ风格)来实现。

下面的例子是基于 xml schema 风格来定义一个 Aspect( 红字部分 ) :

<aop:aspect id="aspectDemo" ref="aspectBean">

< aop:pointcut id = "myPointcut" expression = "execution(* package1.Foo.handle*(..)" />

< aop:before pointcut -ref = "myPointcut" method = "doLog" />

</aop:aspect >

这个定义的意思是:每执行到 package1.Foo 类的以 handle 开头的方法前,就会先执行 aspectBean 的 doLog 方法

 

☆链接点 (Join point):链接点就是在程序执行过程当中某个特定的点,好比某方法调用的时候或者处理异常的时候。这个点能够

是一个方法、一个属性、构造函数、类静态初始化块,甚至一条语句。切面代码能够经过这些点插入到程序的通常流程之中,从而添加新的行为。 而对于 SPRING 2.0 AOP 来讲他是基于动态代理的,故

只支持方法链接点,这个必定要记住~!每个方法均可以当作为一个链接点,(AspectJ和Jboss能够提供其余aop的实现如,

字段构造函数等)只有被归入某个Point Cut的 JointPoint 才有可能被 Advice 。 经过声明一个org.aspectj.lang.JoinPoint

类型的参数能够使通知(Advice)的主体部分得到链接点信息。JoinPoint 与CutPoint 之间的关系见下面的CutPoint 的讲解

 

☆切入点 (Pointcut):若是说通知定义了切面的“什么”和“什么时候”那么切入点就定义了“何地”。切入点指一个或多个链接点,能够理解成链接电点的集合 .咱们一般使用明确的类和方法或是利用正则表达式定义这些切入点。 Advice 是经过 Pointcut 来链接和介入进你的 JointPoint 的。

好比在前面的例子中,定义了

< aop:pointcut id = "myPointcut" expression = "execution(* package1.Foo.handle*(..)" />  那个类的那个方法使用

那么这就是定义了一个PointCut ,该Pointcut 表示“在package1.Foo类全部以handle开头的方法”

假设package1.Foo类里相似于:

    Public class Foo {

       public handleUpload(){..}

       public handleReadFile(){..}

    }

那么handleUpload 是一个JointPoint ,handleReadFile 也是一个Joint,那么上面定义的id=”myPointcut” 的PointCut 则

是这两个JointPoint 的集合

☆通知 (Advice):通知定义了切面是什么,以及什么时候使用,去了描述切面要完成的工做,通知还要解决什么时候执行这个工做的问题。它应该在某个方法以前调用仍是以后调用,或者抛出一个异常。故通知有各类类型Advice。定义了切面中的实际逻辑(即实现 ) ,好比日志的写入的实际代码。换一种说法Advice 是指在定义好的切入点处,所要执行的程序代码 。

通知有如下几种:

§前置通知( Before advice ) :在切入点匹配的方法执行以前运行使用@Before 注解来声明。implements MethodBeforeAdvice实现的方法是public void before(Method method, Object[] args, Object target)

§返回后通知( After returning advice ) :在切入点匹配的方法返回的时候执行。使用 @AfterReturning 注解来声明

§抛出后通知( After throwing advice ) : 在切入点匹配的方法执行时抛出异常的时候运行。使用 @AfterThrowing 注解来声明

§后通知( After (finally) advice ) :不论切入点匹配的方法是正常结束的,仍是抛出异常结束的,在它结束后(finally)后通知(After (finally) advice)都会运行。使用 @After 注解来声明。这个通知必须作好处理正常返 回和异常返回两种状况。一般用来释放资源。

§环绕通知( Around Advice ) :环绕通知既在切入点匹配的方法执行以前又在执行以后运行。而且,它能够决定这个方法在何时执行,如何执行,甚至是否执行。在环绕通知中,除了能够自由添加须要的横切功能之外,还须要负责主动调用链接点 ( 经过 proceed) 来执行激活链接点的程序 。 请尽可能使用最简单的知足你需求的通知。(好比若是前置通知也能够适用的状况下,就不要使用环绕通知)

§环绕通知使用 @Around 注解来声明。并且该通知对应的方法的第一个参数必须是 ProceedingJoinPoint 类型 。在通知体内(即通知的具体方法内),调用 ProceedingJoinPoint 的 proceed() 方法来执行链接点方法 。

 

☆引入 (Introduction):引入是指给一个现有类添加方法或字段属性,引入还能够在不改变现有类代码的状况下,让现有的 Java 类实现新的接口 (以及一个对应的实现 )。相对于 Advice 能够动态改变程序的功能或流程来讲,引入 (Introduction) 则用来改变一个类的静态结构 。好比你能够使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。举例来讲,咱们能够建立一个Audiable通知类,记录对象在最后一次被修改是时的状态,这很简单,只要一个方法,setLastModified(Date),和一个实例变量来保存这个状态,这个新的方法和实例变量而后就能够引入到如今的类,从而在不修改他们的状况下让他们有新的行为和状态。

☆目标对象( Target Object )被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫作 被通知(advised) 对象。 既然Spring AOP是经过运行时代理实现的,这个对象永远是一个 被代理(proxied )对象。

 

☆AOP 代理( AOP Proxy )“代理”是向目标对象应用通知以后被建立的对象,对客户端来讲目标对象和代理对象是同样的。AOP框架建立的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)。 在Spring中,AOP生成被代理的类有两种:若是目标对象实现的是一个接口则是用JDK的  java.lang.reflect.Proxy动态代理;若是不是接口则用CGLIB库生成目标生成目标类的子类在建立这个子类的时候spring织入通知,而且把这个子类的调用委托给子类,这样就要注意两点,1 最好是用接口实现代理,cglib只是实现没有接口也能够通知的状况。2,被标记final的方法和类不能通知由于没法建立子类。。

 

☆织入( Weaving )把切面(aspect)链接到其它的应用程序类型或者对象上,并建立一个被通知(advised)的对象,这样一个行为就叫作Weaving。 这些能够在编译时(例如使用AspectJ 编译器),类加载时和运行时完成。 Spring 和其余纯 Java AOP 框架同样,在运行时完成织入 。

其实织入的方式有3种:

一、编译器织入: 切面在目标类编译时植入,这须要特殊的编译器。AspectJ 主要就是是使用这种织入方式 。

二、类加载器织入: -切面在目标类加载到JVM的时候进行织入,这须要特殊的ClassLoader。它能够在目标类被加载到程序以前加强类的字节代码。好比AspectWerkz ( 已并入 AspecJ ) 及 JBoss 就使用这种方式 。

三、运行时织入: -即在 java运行的过程当中,使用Java提供代理来实现织入。根据代理产生方式的不一样,运行时织入又能够进一步分为J2SE动态代理及动态字节码生成两种方式。因为J2SE动态代理只能代理接口,所以,须要借助于一些动态字节码生成器来实现对类的动态代理。大多数 AOP 实现都是采用这种运行时织入的方式,包括 Spring 。

 

3:AOP的工做模式

 

   代理主要有静态代理和动态代理

      静态代理:在代理中实现接口并建立实现类对象,在对实现类的方法增长功能(不经常使用)

      动态代理:实现implements InvocationHandler接口。实现方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{

   System.out.println("=========");

      Object o=method.invoke(this.ins, args);

      System.out.println("---------");

      return o;

}

 

 

流程图:在配置文件的配置

 

  配置文件代码:

<!-- pointcut definition -->

                   <p:bean id="cf" class="com.kettas.spring.aop.day4.MyClassFilter">

                      <p:property name="classes">

                            <p:set>

                                  <p:value>com.kettas.spring.ioc.day1.HelloIF</p:value>   ---

                            </p:set>

                      </p:property>

                   </p:bean>

                   <p:bean id="mm" class="com.kettas.spring.aop.day4.MyMethodMatcher">

                      <p:property name="methodNames">

                            <p:set>

                                  <p:value>sayHello</p:value>

                            </p:set>

                      </p:property>

                   </p:bean>

                   <p:bean id="pc" class="com.kettas.spring.aop.day4.MyPointcut">

                      <p:property name="classFilter" ref="cf"></p:property>

                      <p:property name="methodMatcher" ref="mm"></p:property>

                   </p:bean>

                  

                   <!--advice   要继承implements MethodInterceptor-->

                   <p:bean id="timingAdvice" class="com.kettas.spring.aop.day4.TimingInterceptor"></p:bean>

                  

                   <!-- advisor  把通知和切入点结合在一块儿- 最好给代理增长功能->

                   <p:bean id="timingAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">

                      <p:property name="advice" ref="timingAdvice"></p:property>

                      <p:property name="pointcut" ref="pc"></p:property>

                   </p:bean>

                  

                   <!—target 目标 -->

                   <p:bean id="helloTarget" class="com.kettas.spring.ioc.day1.HelloIFImpl">

                      <p:property name="cal">

                            <p:bean class="java.util.GregorianCalendar"></p:bean>

                      </p:property>

                      <p:property name="user" value="world"></p:property>

                   </p:bean>

                   <!-- proxy -->

                   <p:bean id="hello" class="org.springframework.aop.framework.ProxyFactoryBean">

                      <p:property name="target" ref="helloTarget"></p:property>

                      <p:property name="interceptorNames">

                            <p:list>

                                  <p:idref bean="timingAdvisor"/>   增长一种服务

<p:idref bean="xxxAdvisor"/>   增长另外一种服务

                            </p:list>

                      </p:property>

                      <p:property name="proxyInterfaces">    要和目标类实现共同的接口

                            <p:value>com.kettas.spring.ioc.day1.HelloIF</p:value>

                      </p:property>

                   </p:bean>

</p:beans>

简化配置:有可能只是目标类不同,其余的都是同样的。解决每个目标类都须要一个复杂的代理过程配置的问题,能够简化配置的问题 抽象ProxyFactoyBean的方法  如:

<!--  抽象proxy --定义抽象的类,只是没有目标类,其余的通知和接口都同样>

<p:bean id="helloBase" class="org.springframework.aop.framework.ProxyFactoryBean" abstract=“true”>

                      <p:property name="interceptorNames">

                            <p:list>

                                  <p:idref bean="timingAdvisor"/>   增长一种服务

<p:idref bean="xxxAdvisor"/>   增长另外一种服务

                            </p:list>

                      </p:property>

                      <p:property name="proxyInterfaces">    要和目标类实现共同的接口

                            <p:value>com.kettas.spring.ioc.day1.HelloIF</p:value>

                      </p:property>

                   </p:bean>

</p:beans>

    真正的代理

<!—target 目标 继承抽象方法  只用写目标类就能够了 -->

                  

                   <!-- proxy -->

                   <p:bean id="hello" parent=” helloBase”>

                      <p:property name="target" ref="helloTarget"></p:property>

                   </p:bean>

4:AOP的自动代理

Spring的aop机制提供两类方式实现类代理。一种是单个代理,一种是自动代理

   单个代理经过ProxyFactoryBean来实现(就如上面的配置),

自动代理:自动代理可以让切面定义来决定那个bean须要代理,不须要咱们为特定的bean明确的建立代理从而提供一个更完整的aop实现 经过BeanNameAutoProxyCreator或者 DefaultAdvisorAutoProxyCreator实现。

 

◆采用单个代理方式 (费时费力,配置复杂臃肿)

下面就采用自动代理

   实现代理bean的两种方式:

      1,“基于Spring上下文的里声明的通知者bean的基本自动代理”:通知者的切点表达式用于决定哪一个bean和那些方法须要被代理

      2,”基于@AspectJ注释驱动切面的自动代理”:切面里包含的通知里指定的切点将用于选择哪一个bean和哪一个方法要被代理

第一种:<!——自动代理增长此行,容器会自动根据通知要匹配的切入点,为包含切入点的类建立 代理。注意这个bean没有id,由于永远都不会直接引用它——>

     <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/> feedom.net     

        第二种 自动代理@AspectJ切面

 

  然而aspectJ提供可一种基于jdk1.5注解技术的方式,使得配置文件更少,更方便。可以把POJO类注释为切面这一般称为

@AspectJ.咱们利用@AspectJ注释,咱们不须要声明任何额外的类或Bean就能够把POJO转换成一个切面例如: 

@Aspect  定义切面再也不是普通的POJO了 在POJO类中加注释

public class AspectJMixAspect {    

private Log logger = LogFactory.getLog(AspectJMixAspect.class);

@Pointcut("execution(* *..HelloIF.*(..)) || execution(* *..TestBeanIF.*(..))")定义切入点那些类的那些方法添加

public void allMethods() {     }    

@Pointcut("execution(* *..TestBeanIF.toDate(..)) && args(dateStr)")

public void toDate(String dateStr) {

}                 

@Around("allMethods()")   环绕通知

public Object timing(ProceedingJoinPoint pjp) throws Throwable {

long begin = System.currentTimeMillis();    

Object ret = pjp.proceed();

long end = System.currentTimeMillis();

String methodName = pjp.getSignature().getName();

String targetClass = pjp.getTarget().getClass().getName();   

logger.info("Around advice: It took " + (end - begin) + "ms to call "

                                  + methodName + " on " + targetClass);

                   return ret;

                   }

@Before("allMethods()")

public void logBefore(JoinPoint jp) {

logger.info("Before advice: " + jp.getSignature().toLongString()); 

}                 

@AfterReturning(value="toDate(dateStr)", returning = "date", argNames = "date, dateStr")  

public void afterReturning(Date date, String dateStr) {

logger.info("call method toDate(" + dateStr + ") and return " + date);  

}                 

@AfterThrowing(value="toDate(dateStr)", throwing="ex", argNames="dateStr, ex")  

public void afterThrowing(String dateStr, ParseException ex){方法名任意但参数要和argNames=""中的参数顺序同样,

}

}

配置文件

<?xml version="1.0" encoding="UTF-8"?>

<p:beans xmlns:aop="http://www.springframework.org/schema/aop"

                   xmlns:p="http://www.springframework.org/schema/beans"

                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">

                   <!-- target -->

                   <p:bean id="hello" class="com.kettas.spring.ioc.day1.HelloIFImpl">

                      <p:property name="cal">

                            <p:bean class="java.util.GregorianCalendar"></p:bean>

                      </p:property>

                      <p:property name="user" value="world"></p:property>

                   </p:bean>

                   <p:bean id="testBean" class="com.kettas.spring.aop.day5.TestBean">

                      <p:property name="pattern" value="yyyy-MM-dd"></p:property>

                   </p:bean>

                   <!-- apsect bean -->

                   <p:bean id="aspectJAspect" class="com.kettas.spring.aop.day5.AspectJMixAspect"></p:bean>

<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 声明自动代理bean须要命名空间:aop="http://www.springframework.org/schema/aop"

</p:beans>

 

5,定义纯粹的POJO切面 不在普通的bean中加注释,而是在配置文件中配置

   <!-- target -->

<bean xxx ></bean>

ß-Pojo bean-->

<bean id =” aspectJAspect”class=” com.kettas.spring.aop.day5.AspectJMixAspect”/>

<aop:config>

  <aop:aspect ref=” aspectJAspect”> 将aspectJAspect定义为切面   下面定义加方法的类和方法

<aop:pointcut id="allMethods" expression="execution(* *..HelloIF.*(..)) or execution(* *..TestBeanIF.*(..))"/>  

  <aop:advisor pointcut-ref="allMethods" advice-ref="timingAdvice" />

  <aop:advisor pointcut-ref="allMethods" before-method=“logBefore” />

  <aop:advisor pointcut-ref="allMethods" advice-ref="logAfterAdvice" /> 引入外部的通知

  <aop:advisor pointcut="execution(* *..TestBeanIF.toDate(..))" advice-ref="logThrowingAdvice" />

  </aop:config>

 

  14,注入AspectJ切面 

    为何要用AspectJ:AspectJ提供了Spring AOP不少不能实现的多种切点类型(好比属性,构造方法切入,因为不能实现构造方法的切入spring aop就不能实现对象建立过程的通知)

   AspectJ是一个代码生成工具(Code Generator)。AspectJ有本身的语法编译工具,编译的结果是Java Class文件,运行的时候,classpath须要包含AspectJ的一个jar文件。AspectJ是AOP最先成熟的Java实现,它稍微扩展了一下Java语言,增长了一些Keyword等

public aspect TestAspectJ { 

    public TestAspectJ();

  public pointcut writeOperations():

    execution(public boolean Worker.createData()) ||

    execution(public boolean Worker.updateData()) ||

    execution(public boolean AnotherWorker.updateData()) ;

  before() : writeOperations() {

    XXXXXX; advice body

  }

  after() : writeOperations() {

    XXXX;// advice body

  }

}

配置文件

<bean class=”xxx/TeatAspectJ” factory-method=”aspectof”>

  <property name=”” ref=””/></bean>

说明机制:这个<bean>和其余的bean并无太多区别,只是多了 factory-nmthod属性 要想得到切面的实例,就必须使用factory-method来调用 aspectof()方法,而不是调用TestAspectJ的构造方法,简单来讲Spring不使用《bean》声明来建立TestAspectJ实例,它已经被AspectJ运行时建立了,Spring经过aspectof()工厂方法得到切面的引用,而后利用<bean>元素对她执行属性注入

 

上述代码关键点是pointcut,意味切入点或触发点,那么在那些条件下该点会触发呢?是后面红字标识的一些状况,在执行

Worker的createData()方法,Worker的update方法等时触发

Pointcut相似触发器,是事件Event发生源,一旦pointcut被触发,将会产生相应的动做Action,这部分Action称为Advice。

  Advice在AspectJ有三种:before、 after、Around之分,上述aspect Lock代码中使用了Advice的两种before和after。

  因此AOP有两个基本的术语:Pointcut和Advice。你能够用事件机制的Event和Action来类比理解它们

其中advice部分又有:

Interceptor - 解释器并无在AspectJ出现,在使用JDK动态代理API实现的AOP框架中使用,解释有方法调用或对象构造或者字段访问等事件,是调用者和被调用者之间的纽带,综合了Decorator/代理模式甚至职责链等模式。

Introduction - 修改一个类,以增长字段、方法或构造或者执行新的接口,包括Mixin实现。

 

 

Spring2.5 aop新特性

在配置文件中的配置:就和POJO中的配置同样

在java类中的配置:就和自动代理类配置同样 ,只是在配置的时候注意加上<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

注意 execution(* *..HelloIF.*(..)))的含义  任意权限(*),任意返回值(*),任意包下(。。),类名(HelloIF),任意方法(*),任意参数(。。)。   星号(*)表明之间没有逗号和点号,(。。)表明能够有逗号和点号

 

5,  切入点指示符:前面的execution就是一个切入点指示符。Spring AOP还支持的切入点指示符有

Within:配置特定的链接点  。  this:Aop代理必须是指定类型的实例 如this(org.crazyit.service.AccountService)匹配实现了AccountService接口的全部链接点.  Target:和this的表达相似。实现限定目标对象必须是指定类型的实例。

Bean:匹配实例内方法执行的链接点 bean(tradeService)能够用* 通配符

 

 

 

 

 

 

 三:Data Access 数据库的模板操做

    1,好处:支持事务的管理 2有统一的异常处理 RuntimeException  3 Support各类数据库

    2,数据源的配置:在spring中数据源的配置有

★有JDBC驱动程序定义的数据源 :在org.springframework.jdbc.datesource包有两个实现类

                               DriverManagerDateSouce。每一个请求时都创建一个链接

                              或者SingleConnectionDataSource  配置api中的set方法,用户名,密码,url driver

★由JNDI查询的数据源  :在tomcate配置数据源,还有Jbose等均可以 经过jndi引用就能够了

                        <bean id=”dataSource” class=”…jndi.jndiObjectFactory”>

                          <property name=”jndi” value=”/jdbc/rantzDataSource”/>

                            <property name=”resourceRef” value=”true”/>

★链接池的数据源:Spring 没有提供数据源链接池,可是DBCP项目提供了一个,下载相关的jar到lib中

                 配置相似第一种JDBC驱动的配置

 

    3 JDBC 咱们知道,Spring JDBC的主要目标是为了简化JDBC的编程,方便咱们构建健壮的应用程序。这里,它的一个基

本设计理念,就是将JDBC编程中变化的和不变化的分开。  在JDBC中,什么是变化的?毫无疑问,SQL语句是变

化的。那什么是不变化的?正确的使用JDBC的方式是不变化的。使用JDBC模板

提供了三个模板:JdbcTemplate 最基本的jdbc模板  使用索引参数查询数据库

NamedParameterJdbcTemplate ,查询时把值绑定到SQL里的命名参数而不是使用索引参数

SimpleJdbcTemplate利用java5的特性,好比自动装箱,通用,可变参数列表来简化JDBC模板的使用

         以JdbcTemplate为例子说明:在已经配置datasource的状况下就能使用 JdbcTemplate有相关的查询,插入,等方法

            在xml中配置模板JdbcTemplate  bean

            <bean id=”jdbcTemplate” class=”org.springframework.jdbc.core.JdbcTemplate”>

                 < property name=”dataSource” ref=”dataSource”>

              </bean>

           在dao层的bean中加入JdbcTemplate引用就能够了,这样就能够使用它来访问数据库

              如:class JdbcDao{

                       Private JdbcTemplate jdbcTemplate

                        //setJdbcTemplate 方法注入

                       Public User getUserById(long id){

                         List users=jdbcTemple.query(sql,new Object[]{Long.valueOf(id)}),new RowMapper(){

 Public Object mapRow(ResultSet rs,int rowNum) throws SQLException

      User user=new User();

       user.setId(rs.getInt(1)); ….;

        return user;  

}

                        Return users.size()>0?(user)users.get(0):null;

}

}

说明:一个字符串,包含用于从数据库里选择数据的 SQL 语句。

      一个 Object 数组,包含与查询里索引参数绑定的值。Sql几个问号就绑定几个值

一个 RowMapper 对象,它从ResultSet 里提取数值并构造一个域对象。封装对象返回结果

而后像下面的设置同样注入模板JdbcTemplate属性就能够了

 <bean id=”jdbcDao”class=”…/JdbcTemplate”>

                     <property name=” JdbcTemplate” ref=” jdbcTemplate”></bean>

 

            JdbcDaoSupport

               注意:能够使用Spring 对JDBC 的DAO 支持类 JdbcDaoSupport

     思想: 所有 DAO 对象建立一个通用父类,在其中设置JdbcTemplate 属性,而后让所有DAO 继承这个

类,使用父类的JdbcTemplate 进行数据访问,这样能够减小配置量。Spring 的JdbcDaoSupport 就是用于编写基于JDBC 的DAO 类的基类,咱们只需让本身的DAO 类继承它便可 例如上面的

                 class JdbcDao extends JdbcDaoSupport{                   

                       Public User getUserById(long id){

                         List users=getJdbcTemple().query(sql,new Object[]{Long.valueOf(id)}),new RowMapper(){

 Public Object mapRow(ResultSet rs,int rowNum) throws SQLException

      User user=new User();

       user.setId(rs.getInt(1)); ….;

        return user;  

}

                        Return users.size()>0?(user)users.get(0):null;

}

}

在配置文件与配置不继承JdbcDaoSupport 的DAO 没有什么区别

<bean id=”jdbcDao”class=”…/JdbcTemplate”>

                     <property name=” JdbcTemplate” ref=” jdbcTemplate”></bean>

 

4 在Spring 里集成Hibernate

    1下载相关的Hibernante的jar包到lib文件 注意最好是3.0版本以上

    2使用Hibernate 模板  HibernateTemplate 有各类增删改查的方法

▲与 Hibernate 进行交互的主要接口是org.hibernate.Session。这个Session 接口提供了基本的数据访问功

能,好比从数据库保存、更新、删除和加载对象。得到 Hibernate Session 对象引用的标准方式是实现。Hibernate 的SessionFactory 接口。SessionFactory负责打开、关闭和管理Hibernate Session,以及其余一些功能。

3)为了让事情简单一些,Spring 提供了HibernateDaoSupport,用法相似JdbcDaoSupport,它可以让咱们把会话工厂Bean 直接装配到DAO 类

   两种得到session的配置 bean.xml

<!-- 本身加载 hibernate -->

  <bean id="dataSource"[U26]   class="org.apache.commons.dbcp.BasicDataSource">

    <property name="driverClassName">

       <value>oracle.jdbc.driver.OracleDriver</value>

    </property>

    <property name="url">

       <value>jdbc:oracle:thin:@localhost:1521:XE</value>

    </property>

    <property name="password">

       <value>kettas</value>

    </property>

    <property name="username">

        <value>kettas</value>

     </property>

  </bean>

  <bean id="factory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

      <property name="dataSource">

          <ref  bean="dataSource"/>

      </property>

      <property name="mappingResources">

         <list>

            <value>com/kettas/entity/shoppingcart.hbm.xml</value>[U27] 

         </list>

      </property>

      <property name="hibernateProperties[U28] ">

         <props>

             <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>

             <prop key="hibernate.show_sql">true</prop>

             <prop key="hibernate.format_sql">true</prop>

         </props>     

      </property>

  </bean>

  <!-- use 外面的 hibernate.cfg.xml

  <bean id="factory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

           <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>

      </bean>-->

 

<bean  id="DaoSupport" class="com.kettas.dao.impl.Hibernate2DaoSupportImpl">  

     <property name="sessionFactory[U29] ">                                        

       <ref bean="factory"/>

     </property>

  </bean>

 

  <bean id="template"

class="org.springframework.orm.hibernate3.HibernateTemplate">

<property name="sessionFactory">  模板注入sessionFactory

<ref bean="factory" />

</property>

</bean>

 

HibernateTemplate中经常使用的方法:getHibernateTemplate().delete(o); update() 。。。。;

super.getHibernateTemplate().executeFind(

                                  new HibernateCallback() {  回调使用hibenate的方法

                                       public Object doInHibernate(Session session)

                                                  throws HibernateException, SQLException { 。。。。}

 

3,  使用Hibernate 3 上下文会话

   若是使用 Hibernate 2,那么就只能使用HibernateTemplate。

􀂄 Hibernate 上下文会话的主要好处在于把DAO 实现与Spring 解耦。

􀂄 Hibernate 上下文的主要缺点是它们抛出Hibernate 特有的异常。虽然HibernateException 是运行

时异常,但这个异常体系是Hibernate 特有的,并且不像Spring 存留异常体系那样与ORM 无关,

这可能会在程序向不一样ORM 迁移时产生问题。

   HibernateTemplate 的缺点是具备必定的侵入性,HibernateDaoSupport),HibernateRantDao 类都被耦合到Spring API。

咱们还有另一种办法。Hibernate 3 引入的上下文会话能够管理每事务一个会话,也就不须要让HibernateTemplate 来确

保这种状况了。因此,咱们能够在DAO 里装配一个Hibernate SessionFactory 来取代HibernateTemplate

 

public class HibernateRantDao implements RantDao {

private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory) {

this.sessionFactory = sessionFactory; }

public void saveRant(Rant rant) {

sessionFactory.getCurrentSession().saveOrUpdate(rant);

}}

 

<bean id="rantDao" class="com.roadrantz.dao.hibernate.HibernateRantDao">

<property name="sessionFactory" ref="sessionFactory" />

</bean>

 

 

4,  JPA 是个基于POJO 的存留机制,不只从Hibernate 和Java 数据对象(JDO)吸收了观念,还适当地混合了Java 5 的注解功能。用法相似Hibernate。基于JPA 的程序使用EntityManagerFactory 的一个实现来获取EntityManager 的实例,他用entityManagerFactory进行管理,至关sessionFactory。能够在persistence.xml,相似hibernate的hibernate.cfg.xml配置打他source等资源,也能够直接在spring的配置文件配置(使用见EJB)

在spring中的配置

<bean id="entityManagerFactory"

class="org.springframework.orm.jpa.

➥   LocalEntityManagerFactoryBean">

<property name="persistenceUnitName" value="rantzPU"[U30]  />

</bean>

<bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">

<property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>

  得到jpa的模板,用法相似Hibernate,就很少说,Ejb中再讨论

 

 

 

四:事务管理

    1,事务 (见hibernate的ACID): Spring和EJB同样,不只提供对程序控制事务管理的支持(手动事务),也对提供声明式事务管理的支持(容器管理事务),可是Spring对程序控制事务管理的支持与EJB很不同。EJB的事务管理和Java Transaction API(JPA)密不可分。和Ejb不一样的是Spring采用的是一种回调机制,把真实的事务从事务代码中抽象出来,那么Spring就不须要JPA的实现。选择手动事务仍是容器管理,就是在细微控制和简便操做之间作出选择。想精确控制事务就能够选择手动事务,不用那么精确就能够容器管理事务。

 

事务管理器:无论你是在bean中代码编写事务仍是用切面(aspect aop)那样声明事务,都须要Spring的事务管理器链接特定平台的事务实现,每一种访问形式都有一个事务管理器。好比:

    

jdbc.datasource.DataSourceTransactionManager:jdbc链接的事务管理,iBATIS也支持

orm.hibernate3. HibernateTransactionManager  :hibernate3的事务支持

orm.jpa.JpaTransactionManager :jpa的事务支持

orm.jdo.JdoTransactionManager   :Jdo事务管理支持

 

这些事务管理器分别充当了某个特定的事务实现门面,这样你就只要和Spring的事务打交道,而不用关心实际上的事务是怎么实现的(门面模式)

 

各类事务管理器的配置,以Hibernate 3为例:

<bean id="transactionManager" class="org.springframework.

➥ orm.hibernate3.HibernateTransactionManager">

<property name="sessionFactory" ref="sessionFactory[U31] "/>

</bean>

 

JDBC事务管理

<bean id="transactionManager" class="org.springframework.jdbc.

➥ datasource.DataSourceTransactionManager">  ---à DataSourceTransactionManager调用Connection来管理事务

<property name="dataSource" ref="dataSource"/> 

</bean>

 

4,在spring中手动编写事务

    利用事务模板TransactionTemplate来手动添加事务

 

public void addRant(Rant rant) {

transactionTemplate.execute(-àtransactionTemplate是注入transactionManager获得的

new TransactionCallback() {-à TransactionCallback()只有一个方法实现doInTransaction,用一个匿名内部类实现

public Object doInTransaction(TransactionStatus ts) {  ------à在事务内执行

try {

rantDao.saveRant(rant);

} catch (Exception e) {

ts.setRollbackOnly();------------------à出现异常就回滚

}return null;

}

}

配置文件

<bean id="rantService"

class="com.roadrantz.service.RantServiceImpl">

<property name="transactionTemplate[U32]  ">

<bean class="org.springframework.transaction.support.

➥ TransactionTemplate">

<property name="transactionManager"

ref="transactionManager" />

</bean>

</property>

</bean>

 

 

5,声明式事务

   能够把事务想成一个切面,那么就能够用事务性边界包裹Biz层的方法,而后注入事务

   Spring提供了三种在配置文件声明事务性边界的方式:★经常使用的Spring aop代理 bean来支持事务。★但在Spring 2中增长了两种新的方式:简单的XML声明(xml-declared)事务和★注释驱动事务

 

   1)代理事务:声明式事务管理经过使用Spring的TransactionProxyFactoryBean代理POJO来完成。TransactionProxyFactoryBean是ProxyFactoryBean的一个特化,他知道如何经过事务性边界包裹一个POJO的方法来代理他们。

 

<bean id="rantService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="target" ref="rantServiceTarget" />      --à装配事务目标,至关给biz层的方法加事务

<property name="proxyInterfaces" value="com.roadrantz.service.RantService" />

<property name="transactionManager" ref="transactionManager" />   --à提供适当的事务管理器

<property name="transactionAttributes[U33] ">

<props>

<prop key="add*">PROPAGATION_REQUIRED</prop>

<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>

</props>

</property>

</bean>

事务传播行为:

 PROPAGATION_REQUIRED 当前方法必须有一个事务,有事务则运行该事务,没有则开始新的事务。---à最经常使用

 PROPAGATION_MANDATORY:该方法必须有事务,没有事务则抛出异常

PROPAGATION_NESTED :该方法运行在嵌套事务中。若是封装事务不存在则就像第一种PROPAGATION_REQUIRED

PROPAGATION_NEVER  :该方法不能有事务,有事务则抛出异常。

PROPAGATION_NOT_SUPPORTED:该方法不能有事务,若是有事务,则将该方法在运行期间挂起。

PROPAGATION_REQUIRES_NEW:方法必须运行在事务里,

PROPAGATION_SUPPORTS:表示当前方法不须要事务性上下文,可是若是有一个事务已经在运行的话,他能够在这个事务里运行。

 

PROPAGATION,   ISOLATION,     readOnly,     -Exception, +Exception

     (传播行为)    (隔离级别 可选)  (事务只读 可选)  (回滚规则  可选)

 

  能够建立事务模板简化配置  :创建事务的抽象声明

 <bean id="TXServiceTemplate" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"

 abstract=“true”>[U34] 

<property name="transactionManager" ref="transactionManager" />   --à提供适当的事务管理器

<property name="transactionAttributes[U35] ">

<props>

<prop key="add*">PROPAGATION_REQUIRED</prop>

<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>

</props>

</property>

</bean>

<bean id=”ranBiz” parent=” TXServiceTemplate[U36] ”>

  <property name="proxyInterfaces" value="com.roadrantz.service.RantService" />

<property name="transactionManager" ref="transactionManager" />   --à提供适当的事务管理器

</bean>

 

2)在Spring2.0声明事务 <tx>上面的方法会致使配置很臃肿,下面就是更简单的配置

   在Spring2.0中专门为声明事务提供了一些新的标签 tx名称空间下

xmlns:tx=http://www.springframework.org/schema/tx

xmlns:aop[U37] ="http://www.springframework.org/schema/aop"

     http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

<tx:advice[U38]  id="txAdvice" transaction-manager="txManager">

<tx:attributes>

<tx:method name="get*" read-only="true"/>

<tx:method name="create*" />

<tx:method name="join*"/>

</tx:attributes>

</tx:advice>

                  

<aop:config>

      <aop:advisor[U39]  pointcut="execution(* *..Roster.*(..))" advice-ref="txAdvice"/>

</aop:config>

 

3)定义注释驱动的事务,@Transactional能够在源代码中注释来进一步简化配置

@Transactional[U40] (propagation=Propagation.SUPPORTS, readOnly=true)

@Service("roster")

public class RosterImpl implements Rosterpublic

@Transactional                  --------------- --------à方法层面的事务

Public  Player createPlayer(Player p) {

      playerDao.save(p);

      return p;

}

 

<context:component-scan

base-package="com.kettas.spring.dao.day5.roster.dao,com.kettas.spring.dao.day5.roster.biz">

</context:component-scan>

<tx:annotation-driven/>  自动搜索@Transactional的bean 而后把事务通知告诉它。

 

 

五:Spring的MVC

          目前比较好的MVC,老牌的有Struts、Webwork。新兴的MVC 框架有Spring MVC、

Tapestry、JSF等。这些大可能是著名团队的做品,另外还有一些边缘团队的做品,也至关出色,

如Dinamica、VRaptor等。

 

六:Spring的安全机制 Spring Security:它提供全面的安全性解决方案,同时在Web请求和方法调用处理身份确认和受权,利用依赖注入和aop技术。主要名词:

1安全拦截器:至关应用的一把锁,可以阻止对应用程序中保护资源的访问(一般是用户名和密码 正确才能打开锁)

          2 认证管理器:经过用户名和密码来作到这点的,负责肯定用户的身份。是由

          3:访问决策管理器:根据你的身份来肯定你是否拥有对资源的访问,即受权管理

          4:运行身份管理器:运行身份管理器能够用来使用另外一个身份替换你的身份,从而容许你访问应用程

序内部更深处的受保护对象。

 5:调用后管理器:访问结束后还能够返回取得相关资源,其余安全管理器组件在受保护资源

被访问以前实施某种形式的安全措施强制执行,而调用后管理器则是在受保护资源被访问以后执行安全措

施。

 

         认证管理器是由org.acegisecurity. AuthenticationManager 接口定义的

ProviderManager 是认证管理器的一个实现,它将验证身份的责任委托给一个或多个认证提供者

DaoAuthenticationProvider 是一个简单的认证提供者,它使用数据存取对象(DAO)来从关系数据库

中检索用户Spring Security 支持经过LdapAuthenticationProvider 根据LDAP 进行身份验证,

LdapAuthenticationProvider 是一个知道如何根据LDAP 仓库查看用户凭证的认证提供信息(包括用户的密码)

身份验证只是Spring Security 安全保护机制中的第一步。一旦Spring Security 弄清用户的身份后,它必须

决定是否容许用户访问由它保护的资源

Spring Security 对Web 安全性的支持大量地依赖于Servlet 过滤器。这些过滤器拦截进入请求,而且

在你的应用程序处理该请求以前进行某些安全处理。Spring Security 提供有若干个过滤器,它们可以拦截

Servlet 请求,并将这些请求转给认证和访问决策管理器处理,从而加强安全性。

 

七:Spring的远程调用:Spring远程支持是由普通(Spring)POJO实现的,这使得开发具备远程访问功能的服务变得至关容易

       四种远程调用技术:

       ◆ 远程方法调用(RMI)       ◆ Caucho的Hessian和Burlap 

 ◆Spring本身的Http invoker    ◆使用SOAP和JAX-RPC的web Services

Spring对上面的远程服务调用都有支持

       Spring远程调用支持6种不一样的RPC模式:远程方法调用(RMI)、Caucho的Hessian和Burlap、Spring本身的HTTP invoker、

EJB和使用JAX-RPC 的Web Services。表6.1归纳地论述了每一个模式,并简略讨论它们在不一样状况下的用处。

表6.1                                  Spring远程调用所支持的RPC模式

RPC模式

在何种状况下有用

远程方法调用(RMI)

不考虑网络限制(如防火墙)时,访问/公开基于Java的服务

Hessian或 Burlap

考虑网络限制时,经过HTTP访问/公开基于Java的服务

HTTP invoker

考虑网络限制时,访问/公开基于Spring的服务

EJB

访问用EJB实现的遗留的J2EE系统

JAX-RPC

访问Web Services

 

 

远程方法调用(RMI)。经过使用 RmiProxyFactoryBean 和 RmiServiceExporter,Spring同时支持传统的RMI(使用java.rmi.Remote接口和java.rmi.RemoteException)和经过RMI调用器实现的透明远程调用(支持任何Java接口)。

Spring的HTTP调用器。Spring提供了一种特殊的容许经过HTTP进行Java串行化的远程调用策略,支持任意Java接口(就像RMI调用器)。相对应的支持类是 HttpInvokerProxyFactoryBean 和 HttpInvokerServiceExporter。

Hessian。经过 HessianProxyFactoryBean 和 HessianServiceExporter,能够使用Caucho提供的基于HTTP的轻量级二进制协议来透明地暴露服务。

Burlap。 Burlap是Caucho的另一个子项目,能够做为Hessian基于XML的替代方案。Spring提供了诸如 BurlapProxyFactoryBean 和 BurlapServiceExporter 的支持类。

JAX RPC。Spring经过JAX-RPC为远程Web服务提供支持。

 

客户端发起对代理的调用,好像是代理提供了这些服务的功能同样。代理表明客户端和远程服务交流。它处理链接的具体状况,

并向远程服务发起远程调用。在Spring里,远程服务是被代理的,因此他们能像通常的Bean那样置入到客户端的代码里

 [U41] 

八:Spring的Web服务

Spring支持:使用JAX-RPC暴露服务   访问Web服务

除了上面所说的支持方法,你还能够用XFire xfire.codehaus.org 来暴露你的服务。XFire是一个轻量级的SOAP库,目前在Codehaus开发。

使用JAXI-RPC暴露服务

Spring对JAX-RPC Servlet的端点实现有个方便的基类 - ServletEndpointSupport。为暴露咱们的Account服务,咱们继承了Spring的ServletEndpointSupport类来实现业务逻辑,这里一般把调用委托给业务层。

访问服务:

Spring有两个工厂bean用来建立Web服务代理,LocalJaxRpcServiceFactoryBean 和 JaxRpcPortProxyFactoryBean。前者只返回一个JAX-RPT服务类供咱们使用。后者是一个全功能的版本,能够返回一个实现咱们业务服务接口的代理。本例中,咱们使用后者来为前面段落中暴露的AccountService端点建立一个代理。你将看到Spring对Web服务提供了极好的支持,只须要不多的代码 - 大多数都是经过相似下面的Spring配置文件:

     <bean id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">

        <property name="serviceInterface" value="example.RemoteAccountService"/>

        <property name="wsdlDocumentUrl" value="http://localhost:8080/account/services/accountService?WSDL"/>

        <property name="namespaceUri" value="http://localhost:8080/account/services/accountService"/>

        <property name="serviceName" value="AccountService"/>

        <property name="portName" value="AccountPort"/>

     </bean>

XFire一个Codehaus提供的轻量级SOAP库。在写做这个文档时(2005年3月)XFire还处于开发阶段。虽然Spring提供了稳定的支持,可是在将来应该会加入更多特性。暴露XFire是经过XFire自身带的context,这个context将和RemoteExporter风格的bean相结合,后者须要被加入到在你的WebApplicationContext中。

 

 

九:Spring的消息 Java Message Service (JMS)

   前面的RMI,Hesian ,Burlap,HTTP invoker web服务的间通讯,都是程序之同步,即当客户端调用远程方法时必须在方法完成以后才能继续执行。

   JMS是一种异步消息传递的标准API,客户端不须要等待服务端处理消息,客户端发送消息,会继续执行,这是由于客户端假设服务端最终可以收到并处理这条消息。相似Ajax

 

   发送消息 使用JMS的模板JsmTemplate  接收消息

 

 

十:Spring和EJB的整合:

        Spring有两种方法提供对EJB的支持:

Spring能让你在Spring的配置文件里,把EJB做为Bean来声明。这样,把EJB引用置入到其余Bean的属性里就成为可能了,好像EJB就是另外一个POJO。

  Spring能让你写EJB,让EJB成为Spring配置的Bean的代理的工做。

Spring提供了两个代理工厂Bean,来代理EJB的访问:

   LocalStatelessSessionProxyFactoryBean——用来访问本地EJB(EJB和它的客户端在同一个容器中)。

   SimpleRemoteStatelessSessionProxyFactoryBean——用来访问远程EJB(EJB和它的客户端在独立的容器中)。

 

 

 

 

十一:访问企业服务:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

                                               SSH和Ajax的整合

 

一:准备工做

    把Hibernate的jar包 ,spring的jar 包  ,Struts的jar包 ajax中的jar包好比dwr。

 

二:配置文件说明

   Web.xml

<listener[U42] >

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/classes/com/kettas/config/springBean.xml</param-value>

</context-param>

<servlet>

<servlet-name>action[U43] </servlet-name>

<servlet-class> org.apache.struts.action.ActionServlet</servlet-class>

<init-param>

<param-name>config</param-name>

        <param-value>/WEB-INF/struts-config.xml</param-value>

</init-param>

<init-param>

<param-name>debug</param-name>

<param-value>3</param-value>

</init-param>

<init-param>

<param-name>detail</param-name>

<param-value>3</param-value>

</init-param>

<load-on-startup>0</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

 

  <servlet>

    <servlet-name>dwr[U44] </servlet-name>

    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>

    <init-param>

       <param-name>debug</param-name>

       <param-value>true</param-value>

    </init-param>

  </servlet>

  <servlet-mapping>

    <servlet-name>dwr</servlet-name>

    <url-pattern>/dwr/*</url-pattern>

  </servlet-mapping>

 

struts-config.xml

 <form-beans>

<form-bean name="dynaActionForm"

              type="org.apache.struts.action.DynaActionForm">

<!-- admin formBean -->

<form-property name="loginName" type="java.lang.String" />

</form-bean>

</form-beans>

<global-exceptions />

<global-forwards />

<action-mappings>

<action path="/adminLogin" name="dynaActionForm" parameter="adminLogin"

type="org.springframework.web.struts.DelegatingActionProxy[U45] ">

<forward name="ok" path="/admin/admin.html" redirect="true" />

<forward name="error" path="/error.jsp" />

</action>

</action-mappings>

<!--message-resources

parameter="com.yourcompany.struts.ApplicationResources" /-->

<plug-in

className="org.springframework.web.struts.ContextLoaderPlugIn[U46] ">

<set-property property="contextConfigLocation"

value="/WEB-INF/classes/beans.xml" />

</plug-in>

 

Spring.xml

 

<bean id="sessionFactory"[U47]  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>

</bean>

<bean id="template" class="org.springframework.orm.hibernate3.HibernateTem