21天学会Java

ccp3170

贡献于2014-11-18

字数:0 关键词: Java开发 Java

1 第章 的类第一章 Java的类 2 第章J 的类第一章 Java的类 • 1.1 有关面向对象的概念 语言的特点• 1.2 Java语言的特点 • 1.3 Java的开发环境1.3 Java的开发环境 • 1.4 第一个Java程序 • 1.5 Java类型系统 • 1 6 Java中字符串的类1.6 Java中字符串的类 • 1.7 Java中的类、方法和变量 • 1.8 Java名空间及访问规则 • 1 9 Java中的抽象类 接口和程序包• 1.9 Java中的抽象类、接口和程序包 • 1.10 对象的构造函数 3 11有关面向对象的概念1.1 有关面向对象的概念 • 面向对象程序设计围绕的几个主要概念:面向对象程序设计围绕的几个主要概念: • 抽象数据类型、类、类型层次(子类),继 承性 多态性承性、多态性。 4 11有关面向对象的概念1.1 有关面向对象的概念 • 数据抽象类型数据抽象类型 class Car { int color_number; int door_number; int speed;现实生活 void brake() { … } 现实生活 中的对象 void speedUp() {…}; void slowDown() { … }计算机中 }的对象的原型 5 11有关面向对象的概念1.1 有关面向对象的概念 • 什么是类?什么是类? • 类是描述对象的“基本原型”,它定义一种 对象所能拥有的数据和能完成的操作 在面向对象所能拥有的数据和能完成的操作,在面向 对象的程序设计中,类是程序的基本单元。 variables• 程序中的对象 是类的一个实例,是类的 个实例, 是一个软件单元, 它由一组结构化 methods 它由 组结构化 的数据和在其上 的 组操作构成的一组操作构成。 6 11有关面向对象的概念1.1 有关面向对象的概念 • 变量:即指对象的所知道的状态 • 方法:指对象的功能单元。 什么是消息?• 什么是消息? • 软件对象通过相互间传递消息来相互作用和 通信 • 一个消息由三部分组成: message • 个消息由三部分组成: • 1. 接受消息的对象 • 2. 要完成方法的名字 • 3 方法需要的参数 对象B • 3. 方法需要的参数 对象 A 7 11有关面向对象的概念1.1 有关面向对象的概念 • 一个例子 class Hello {{ private String s; )public void showString () { System.out.println(s);} } public void changeString(String str) { s=str; return s;} • 在程序中操作对象是类的一个实例:即对象 } • 创建一个对象 Hello obj=new Hello(); 调用方法 bj h St i (“H ll W ld!”)• 调用方法 obj.showString(“Hello World!”) 8 11有关面向对象的概念1.1 有关面向对象的概念 • 什么是封装?什么是封装? • 封装把对象的所有组成部分组合在一起,封 装定义程序如何引用对象的数据 封装实际装定义程序如何引用对象的数据,封装实际 上使用方法将类 私有数据 上使用方法将类 的数据隐藏起来, 控制用户对类的 数据 公有数据 私有数据 控制用户对类的 修改和访问数据 的程度方法方法 的程度。方法 对象A 对象B 9 11有关面向对象的概念1.1 有关面向对象的概念 • 什么是子类? • 子类是作为另一个类的扩充或修正所定义的 一个类个类. bicycle (super class) sub classsub class Mountain bikes Racing bikes Tandem bikes 10 11有关面向对象的概念1.1 有关面向对象的概念 • 什么是继承? • 继承是子类利用父类中定义的方法和变量就 像它们属于子类本身一样.像它们属于子类本身 样 class Car { int color number; class Trash_Car extends Car{ int color_number; int door_number; int speed; extends Car { double amount; int speed; push break() { } fill_trash() { … } }push_break() { … } add_oil() { … } } } } 11 11有关面向对象的概念1.1 有关面向对象的概念 • 什么是方法的覆盖?什么是方法的覆盖? • 在子类中重新定义父类中已有的方法。 class Car { int color_number; class Trash_Car extends Car int door_number; int speed; { double amount; push_break() fill_trash() { … } push_break() { speed=0; } add_oil() { … } } { speed=speed-10; } } } 12 11有关面向对象的概念1.1 有关面向对象的概念 • 什么是方法的重载(多态性)?什么是方法的重载(多态性)? • 在同一个类中至少有两个方法用同一个名字, 但有不同的参数但有不同的参数。 idh (itit ) 类 void show(int int_num) void show(double double num) 123 1.23类 void show(double double_num) void show(int int num float float num) 123,1.23 void show(int int_ num, float float_num) 13 12J 语言的特点1.2 Java语言的特点 • Java是什么? Java= “C++”--“复杂性和奇异性”+“安全性和可移植性”复杂性和奇异性 安全性和可移植性 • Java由那些特性? (1) 面向对象• (1) 面向对象 • 封装性、多态性、继承性、动态链接 • (2) 操作平台无关性 • 严格的语言定义:“没有依据机器的不同而不• 严格的语言定义: 没有依据机器的不同而不 同” 或“由编译器决定”等字眼,最后的目标 码都是一致的 初值都是确定的码都是 致的,初值都是确定的 14 12J 语言的特点1.2 Java语言的特点 • 两种工作模式的比较 Java编译器 二进制 编译器 二进制Java解释器 P Powerpc 源 程 Powerpc 中间 码 Powerpc 源 程 Powerpc Powerpc 序 pentium 码 pentium 程 序 pentium pentium SPARC SPARC SPARC SPARC 15 12J 语言的特点1.2 Java语言的特点 • .. 编译,没有绝对地址 调入包含,继承所用 道的所有类, 内存分, 配确定,编程真正可 执行的机器码 Java源程序 (.java文件) Bytecode 载入器 存在伪 的指 Java编译器 字节码校验器 不存在伪造的指针 不违反访问权限 不非法访问对象 Java Bytecode (class文件) Bytecode 解释器 不非法访问对象 不导致操作栈溢出 (.class文件) 系统执行平台 16 12J 语言的特点1.2 Java语言的特点 • Java虚拟机 不同的操作系统有不同的虚Java虚拟机 Java Just-in-time 不同的操作系统有不同的虚 拟机. 它类似 个小巧而高效的interpreter compiler 它类似一个小巧而高效的CPU. byte-code代码是与平台无关的 是虚拟机的机器指令Runtime System 是虚拟机的机器指令. Java字节代码运行的两种方式: 解释方式 Operating System interpreter(解释方式) Just-in-time(即时编译):有代码 生成器将字节代码转换成本机 Hardware 生成器将字节代码转换成本机 的机器代码,然后可以以较高速 度执行度执行. 17 12J 语言的特点1.2 Java语言的特点 • (3) 安全问题(3) 安全问题 • Java是在网络环境下使用的语言 • 一个安全的网络至少要防止以下几种破坏的 可能性:可能性 • 毁灭系统资源 消耗系统资源• 消耗系统资源 • 挖掘系统或个人机密挖掘系统或个人机密 • 骚扰正常工作的进行 18 12J 语言的特点1.2 Java语言的特点 public protected 限定对象的 存取权限 系统堆栈溢出p private final 系统堆栈溢出 参数类型一致 Java源程序 (.java文件) Bytecode 载入器语言定义 Bytecode检查 Java编译器 Bytecode 解释器取消指针 自动回收 垃圾 y 检查 程序执行系统 Java Bytecode (.class文件) 系统执行平台 垃圾 程序执行系统 WWW浏览器 限制Java小应用程序 的不正当使用的不正当使用 19 12J 语言的特点1.2 Java语言的特点 • (4) 多线程 • Java提供现成的类Thread,只要继承这个类就可以 编写多线程的程序。编写多线程的程序 • (5) Java与C及C++的区别 不再有 和 等于处理功能• 不再有#include 和#define 等于处理功能 • 不再有structure,union及typedef, yp • 不再有函数、不再有指针、不再有多重继承 不再有 t• 不再有goto • 不再有操作符重载(Operatior Overloading) • 取消自动类型转换,要求强制转换 20 13J 的开发环境1.3 Java的开发环境 • Java开发环境 JDKJava开发环境 JDK • JDK中有Java编译器和bytecode解释器 Alti 是小应用程序的bt d解释Applwtviewer是小应用程序的bytecode解释 器 • JDK的安装 • 直接执行JDK exe• 直接执行JDK.exe 21 13J 的开发环境1.3 Java的开发环境 产生如下目录结构 含件java\bin的目录下包含义下主要文件: javac: Java编译器, 用来将java程序编译成j 编译 , 用来将j 程序编译成 Bytecode java: Java编译器 执行已经转换成Bytecode的java: Java编译器,执行已经转换成Bytecode的 java应用程序. jdb J 调试器 用来调试j 程序jdb: Java调试器, 用来调试java程序 javap: 反编译,将类文件还原回方法和变量. 文档生成器 创建 文件javadoc:文档生成器,创建HTML文件 appletviwer : Java解释器, 用来解释已经转换成pp , Bytecode的java小应用程序. 22 13J 的开发环境1.3 Java的开发环境 • \java\lib子目录\java\lib子目录 • 库函数,其中classese.zip不要解开. • 在autoexec.bat中加入以下两条命令 1. PATH c:\…\java\bin1. PATH c:\…\java\bin 2. SET CLASSPATH=. ; c:\...\lib\classes.zip; c:\myclasses; 23 13J 的开发环境1.3 Java的开发环境 C:\ java bin lib classes.zip 用户类文件 所在目录 l 当前目录 p javac appletviewer myclasses java 24 13J 的开发环境1.3 Java的开发环境 • vj1.1++的使用vj1.1 的使用 • 1.进入vj,创建一个project • 2.加入java文件 • 3 编辑java文件3. 编辑java文件 • 4. 编译java文件 • 5. Build一个project文件 • 6 运行java程序• 6. 运行java程序 --如果是小应用程序,则直接在VJ环境下运行 --如果是应用程序,则在dos下运行 25 14你的第 个J 程序1.4 你的第一个Java程序 • Java应用和Java小应用程序 class HelloWorldApp { public static void main(String args[]) { System.out.println(“Hi, ”+args[0]); } 编辑存盘 类名 含有 法 } } • 编辑存盘:主类名(含有main方法)和 文件名要一致性 HelloWorldApp.javapp j • 编译程序 : javac HelloWorldApp.java • 运行程序 : java HelloWorldApp “myjava”运行程序 : java HelloWorldApp myjava • 运行结果 : Hi, myjava 26 14你的第 个J 程序1.4 你的第一个Java程序 public class HelloWorldApppublic class HelloWorldApp { public static void main(String args[]) { System.out.println(“Hi, ”+args[0]); }} { public static void main(String args[]) { System.out.println(“Hi, ”+args[0]); }} 1 声明 个类 bli l H ll W ldA {}1. 声明一个类 : public class HelloWorldApp{} , 类名的第一个字母要大写 2. 一个类中可有很多方法, main方法是运行程 序的第一个方法,方法名的第一个字母要小序第个方 方 第 个字母要 写. 3. System.out.println是向屏幕输出,相当于C中3. System.out.println是向屏幕输出,相当于C中 的printf(); 27 14你的第 个J 程序1.4 你的第一个Java程序 public class HelloWorldApppublic class HelloWorldApp { public static void main(String args[]) { System.out.println(“Hi, ”+args[0]); }} { public static void main(String args[]) { System.out.println(“Hi, ”+args[0]); }} 4. 命令行参数的获取 c:>java HelloWorldApp myjava!c:>java HelloWorldApp myjava! 6. 字符串的拼接 28 14你的第 个J 程序1.4 你的第一个Java程序 Java小应用程序不能直接执行和使用,必须要在 浏览器中执行 import java.applet.Applet; import java.awt.*; public class HelloApplet extends Applet { public void paint(Graphics g) { g.drawString(“Hello World”,0,50); } } 编辑存盘: 主类名(extends Applet)和文件名一致 编译代码 : javac HelloApplet java编译代码 : javac HelloApplet.java 编写HTML文件 : HelloApplet.html 29 14你的第 个J 程序1.4 你的第一个Java程序 •运行applet程序: •运行applet程序: 1. appletviwer HelloApplet.html 2. 在浏览器中运行 • 运行结果:运行结果: Hello World! 30 14你的第一个Java程序1.4 你的第 个Java程序 import java.applet.Applet; import java.awt.*; public class HelloApplet extends Applet { public void paint(Graphics g) {Si(“”)}{ g.drawString(“Hello World”,0,50); } } • 理解程序 1 import语句相当于C语言中的include每1. import语句相当于C语言中的include每 2. 每一个applet都是java.applet.Applet的子类pp jpppp 用extends继承 3lt中没有 i 方法3. applet中没有main方法 31 14你的第 个J 程序1.4 你的第一个Java程序 import java.applet.Applet; import java.awt.*; public class HelloApplet extends Applet { public void paint(Graphics g) {Si(“”)}{ g.drawString(“Hello World”,0,50); } } 4. 当applet被浏览器运行时,paint语句自动执行 5 在 lt中与屏幕输出有关的操作通过Ghi对5. 在applet中与屏幕输出有关的操作通过Graphics对 象来实现 6. 一个Java源文件内最多只能有一个public 类,称为 主类,且必须和文件名同名主类,且必须和文件名同名 32 15J 类型系统1.5 Java类型系统 Java type system primitive reference null char numeric boolean class interface array integral floating-point byte short int long float doublebyte short int long float double 33 15J 类型系统1.5 Java类型系统 • byte 8 位 2 的补码 (byte) 0byte 8 位 2 的补码 (byte) 0 • short 16位 2 的补码 (short) 0 • int 32 位 2 的补码 0 • long 64位 2 的补码 0Llong 64位 2 的补码 0L • float 32位 IEEE 754浮点数标准 0.0f • double 64位 IEEE 754浮点数标准 0.0d • char 16位 同一码字符集 ‘\u0000’• char 16位 同码字符集 \u0000 • (Unicode character) 34 15J 类型系统1.5 Java类型系统 • 程序:保留字 标识符(类名、域名、方法名、程序:保留字,标识符(类名、域名、方法名、 符号常量、局部变量,标号、…),操作符、 界定符,字面常量。 声明 个变量• 声明一个变量 • int data=10; Boolean isAlived;int data 10; Boolean isAlived; • Java中的操作符:与C基本一致 • Java中不再有指针了 35 15J 类型系统1.5 Java类型系统 • 在Java中”引用“是指向一个对象在内存中 的位置,在本质上是一种带有很强的完整性和 安全性的限制的指针.安全性的限制的指针 • 当你声明某个类,接口或数组类型的一个变量 时 那个变量的值总是某个对象的引用或者是时,那个变量的值总是某个对象的引用或者是 null引用. • 指针就是简单的地址而已,引用除了表示地址 而外,还象被引用的数据对象的缩影,还提供其而外,还象被引用的数据对象的缩影,还提供其 他信息. 指针可以有 运算 引用不可以运算• 指针可以有++,--运算,引用不可以运算. 36 15J 类型系统1.5 Java类型系统 1 10001 ti例: String s1;String s2; s1 s2 10001 a string 10001 s1=“a string”; 例: String s1;String s2; s2s2=s1; 10001 class Mydateclass Mydate { int year; int month; 0int month; int day; } 0 0 10008today } Mydate today=new MyDate() 0 37 15J 类型系统1.5 Java类型系统 • 能够动态取得的内存有两种,一种是对象实体,能够动态取得的内存有两种, 种是对象实体, 一种数组. • Java用new申请内存 不需要自己释放不用的• Java用new申请内存,不需要自己释放不用的 内存. 在J 中 定义数组时不必给出数组的大小• 在Java中,定义数组时不必给出数组的大小, 因为Java的数组是动态分配的。 • 数组变量实际上是一个引用变量,因此要实 例化才能使用。 • 例:int Array[]; Array=new int[8]; 38 15J 类型系统1.5 Java类型系统 • 例:String arrayOfString[]=new String[10]; 每个数组元素包含 个对字符串对象的引用每个数组元素包含一个对字符串对象的引用, 此时值分配了包含字符串引用的空间,并没此时值分配了包含字符串引用的空间,并没 有对字符串本身分配内存,此时不能访问。 arrayOfString arrayOfString[0] arrayOfString[1] 对 字 arrayOfString[8] arrayOfString[9] 对数组的引用 符 串 的 for(int i=0;i 2. Browser loads 2. Browser loads HTML document Applet class 3. Browser loads lt lApplet class applet classes Lti http://someLocation/file htmlLocation: http://someLocation/file.html 4. Browser run applet Loading... 5 21所有小应用程序的根源2.1 所有小应用程序的根源 • Applet的限制 BrowserSERVER 本地程序 applet Applet被下载的 applet file SERVER local 与 lt无关的与applet无关的 本地方法 6 21所有小应用程序的根源2.1 所有小应用程序的根源 • 2.1.2 applet的生命周期 Java.applet.Applet public void init() public void destroy() public void start() public void stop() public void paint(Graphics g) • paint()虽不在生命周期内,但它的作用相当于 applet的灵魂applet的灵魂 7 21所有小应用程序的根源2.1 所有小应用程序的根源 • 一个applet的可视周期 init start stop 离开web页面 重新装入或改变页面 大小或返回Web页面stop destroy 8 21所有小应用程序的根源2.1 所有小应用程序的根源 • 有关paint()方法 • Applet本身是一个容器,因此任何输出都必须 用图形方法paint()用图形方法paint() • 当小应用首次被装载,以及每次窗口放大、 缩小 刷新时都要调用 it方法缩小、刷新时都要调用paint方法 • paint()是由浏览器调用的, 而不是由程序调用,p() , 当程序希望调用paint方法时,用repaint命令 • paint方法的参数是Graphics类的对象 g 它• paint方法的参数是Graphics类的对象 g,它 在java.awt.Graphics内 • paint(Graphicd g){。。。} 9 21所有小应用程序的根源2.1 所有小应用程序的根源 AWT thread(waiting) repaint() Exposure update() {l Exposure { clear arae call paint() paint() 10 22小试身手2.2 小试身手 • 2.2.1 起始页上的时间和日期 0Mon Dec 07 14:23:50 GMT+08:00 1998 • 介绍两个类: 1. 类名:Date 创建一个实例 Date timeNow=new Date();创建 个实例 Date timeNow=new Date(); 2. 类名Font 创建一个实例 Font msgFont=new Font(“TimesRoman” Font ITALIC 30);Font(“TimesRoman”,Font.ITALIC,30); 11 22小试身手2.2 小试身手 看下面的例子,想一想生命周期的四个方法哪去了? itjt*itjtilDtimport java.awt.*; import java.util.Date; public class showDate extends java.applet.Applet { Date timeNow=new Date(); Font msgFont=newFont msgFont new Font(“TimesRoman”,Font.ITALIC,30); bli id i t(G hi )public void paint(Graphics g) { g.setFont(msgFont); g.setColor(Color.blue); g.darwString(timeNow.toString(),5,50);g.darwString(timeNow.toString(),5,50); } 12 22小试身手2.2 小试身手 2.2.2 在起始页中加入applet 中有关的代码• html中有关的代码 • CODEBASE的作用 当class文件与起始页文件不在同一个目录下当class文件与起始页文件不在同 个目录下 时,使用CODEBASE说明 width 600 height 80 CODEBASE=“\myjava\class” 13 22小试身手2.2 小试身手 CODEBASE “\mjaa\class” C:\C:\CODE=“showdate.class” width=600 height=80> /CODEBASE=“\myjava\class” myjavamyjava public classjavacodepublic classjavacodepublic classjavacode Index html showdate Index.html showdate Index.html showdate 14 22小试身手2.2 小试身手 • ALIGN,HSPACE,VSPACE Java applet 其它文字 hs pJava applet vspace p ace 其它文字 vspace g vspace=100 hspace=100 15 22小试身手2.2 小试身手 • 向applet传递参数的两个步骤 1. 在起始页中要有标签 2 在applet中要有getParameter方法2. 在applet中要有getParameter方法 在起始页中有: 在applet中有: string title=getParameter(rem); 在显示时间的命令中加入title:在显示时间的命令中加入title: g.drawString(title+timeNow.toString(),5,50); 16 22小试身手2.2 小试身手 import java.awt.*; import java.util.Date; bli l h D t t d j l t A l tpublic class showDate extends java.applet.Applet { Date timeNow=new Date(); String title; Font msgFont=new Font(“TimesRoman”,Font.ITALIC,30);ot( eso a ,ot. C,30); public void init()public void paint(Graphics g) p() {title=getParameter (“rem”); pp(pg) { g.setFont(msgFont); g.setColor(Color.blue); (); if (title==null) title=“”; g( ); g.darwString(title+ timeNow.toString(),5,50); ; } g(), , ); } 17 22小试身手2.2 小试身手 • 例:利用一个可以显示运行字符串的类,显示自 己的字符串己的字符串 (htmlpara.html) applet code htmlpara.class width 300 heigh 200 < FONT l "BOLD"> 18 22小试身手2.2 小试身手 public void init() { String paramete; parameter=getParameter("MESSAGE"); if ( ! )if (parameter!=null) message=parameter; (" O ")parameter=getParameter("FONT"); if (parameter!=null) ffont_to_use=parameter; parameter=getParameter("POINT_SIZE"); if ( ! ll)if (parameter!=null) point_size=Integer.parseInt(parameter); }} 19 23图形处理2.3 图形处理 2.3.1图形坐标系统 任何与绘图有关的操作 第一个要用的是 x0 第 个要用的是 java.awt.Graphics类 Graphics类的对象不是 由new产生的 而是由系 y 由new产生的,而是由系 统或其他方式直接将生好的Graphics对象当作 方法的参数,再交给程序设计者去处理.例如: paint(Graphics g)paint(Graphics g) 20 23图形处理2.3 图形处理 • Graphics的方法 paint(Graphics g) { g clearRect(); g copyArea(); g drawAre() ;{ g.clearRect(); g.copyArea(); g.drawAre() ; g.drawLine(); g.drawOval();g.drawRect(); g.drawPolygon(); g.fillArc(); g.fillOval(); g fillPolygen(); g fillRect(); g getColor();g.fillPolygen(); g.fillRect(); g.getColor(); g.getFont() g.setFont(); g.setColor(); FMi()g.getFontMetrics() g.fillRoundRect()g() } 21 23图形处理2.3 图形处理 2.3.2 字型和颜色的设置 2.3.2.1 字型设置的方法 Font font=newFont font=new Font(“TimesRoman”,Font.ITALIC,24); g.setFont(font); • 在小应用程序中显示输出的方法• 在小应用程序中显示输出的方法 g.drawString(String, int x, int y); g.drawChars(char data[], int offset, int length, int int );int x, int y); 22 23图形处理2.3 图形处理 g.drawBytes(byte data[],int offset, int length, int x, int y); 例:g drawString(“This is a test” 5 10);例:g.drawString( This is a test ,5,10); • 获取字体的属性 Font font=g.getFont(); • Font类中常用的方法• Font类中常用的方法 GetFamily() getName() getSize() getStyle() isItalic() isPlain() isBold() toString() 23 23图形处理2.3 图形处理 import java.awt.Graphics; import java.awt.Font; public class drawtext extends java.applet.Applet { Font fn=new Font("TimesRoman",Font.ITALIC,20); public void paint(Graphics g) { g setFont(fn);{ g.setFont(fn); g.drawString(”Font demo”,5,10); } } Font demo 24 23图形处理2.3 图形处理 •获取更详细的数据 请查阅有关FontMetrics类的方法 fontMetrics=getFontMetrics(font);fontMetrics=getFontMetrics(font); •FontMetrics中比较重要的方法有: stringWidth, charWidth, getAscent, getDescent, getLeading getHeighgetLeading, getHeigh 25 23图形处理2.3 图形处理 2.3.2.2 颜色的调整 • Color对象的使用 创造自己的颜色:创造自己的颜色: Color mycolor=new Color(int red, int blue, int green); • g.setColor(Color.yellow) • g setColor(mycolor);g.setColor(mycolor); • 例:随机产生颜色,并画圆 26 23图形处理2.3 图形处理 import java.awt.Graphics; import java.awt.Color; bli l d i l t d j l t A l t {public class drawcircle extends java.applet.Applet { public void paint(Graphics g) { int red,green,blue,x; for (x=0;x<370;x+=30){o ( 0; 370; 30){ red=(int)Math.floor(Math.random()*256); green (int)Math floor(Math random()*256);green=(int)Math.floor(Math.random()*256); blue=(int)Math.floor(Math.random()*256); g.setColor(new Color(red,green,blue)); g.fillOval(x,0,30,30); }}}g (,,,);}}} 27 2 4 URL类2.4 URL类 2.4.2 构造URL类 (全名java.lang.URL) 绝 构法• 绝对URL的构造方法: URL(String spec)URL(String spec) 例: URL url=new URL (http://www.hit.edu.cn/cv/index.html”) • 相对URL的构造方法:相对URL的构造方法: 某绝对地址:http://rainy.hit.edu.cn/test.html 在该目录下有两个文件在该目录下有两个文件 mywork.html myfamily.htmlyyy 28 2 4 URL类2.4 URL类 URL base=new URL(“http://rainy.hit.edu.cn”); URL url1=new (base, “mywork.html”); URL l2 (b “ k ht l”)URL url2=new (base, “mywork.html”); • 其他URL的构造方法:其他 的构造方法 URL url=new URL (“http”, “www.hit.edu.cn”,“/~dyf/test.html”); 29 2 4 URL类2.4 URL类 2.4.3 获取小应用程序HTML页面的URL和小 应用程序本身的应用程序本身的URL • URL html=getDocumentBase();g (); • System.out.print(html); • URL codebase=getCodeBase();• URL codebase=getCodeBase(); • System.out.print(codebase); htmlweb page 浏览器 applet 浏览器 服务器 30 2 4 URL类2.4 URL类 • 2.4.4 URL异常(MalformedURLException) 当创建URL时发生错误,系统会产生异常 try{ URL url=new URL(str);try{ URL url=new URL(str); }catch(MalformedURLException( e) { DisplayErrorMessage();} 245URL类的基本方法• 2.4.5 URL类的基本方法 String getProtocol(), String getHost(),String getProtocol(), String getHost(), ing getPort(), String getFile(), String getRef() 31 2 4 URL类2.4 URL类 • 构造URL的实例 import java.net.URL; import java.net.MalformedURLException;po j v . e . o edU cep o ; public class Test { URL url1,url2,url3;{,,; void test() { try { url1= new URL(“file:/D:/image/example.gif”);{y{ ( g pg); url2= new URL(“http://www.hit.edu.cn/cv/”); url1= new URL(url2, “hit.gif”);(, g); }catch (MalformedURLException e); //处理例外处理例外 } }} 32 2.5 载入现有图像文件2.5 载入现有图像文件 Image类 • java支持gif和jpg两种格式的图像 • 图像文件的URL:• 图像文件的URL: URL picurl= new URL (“http://xxx.yyy.edu/Applet/img1.gif”); 取 幅图像构成图像对象• 取一幅图像构成图像对象 Image img1 = getImage(picurl);g g g g (p ); Image img2 = getImage(getCodeBase(), “img2.gif”); 33 2.5 载入现有图像文件2.5 载入现有图像文件 • 显示一幅图像: g.drawImage(img1, x, y, this); g drawImage(img1 x y Color red this);g.drawImage(img1, x, y,Color.red, this); g.drawImage(image1, x, y,x2,y2,Color.red, this); 规定背景规定尺寸 34 2.5 载入现有图像文件2.5 载入现有图像文件 • 完整的过程 不要忘记AWT包 定义Image对象了吗? 在类中 指定图像的URL了吗? 把图像取出来吧. 在init0中 还记得画图像用什么方法和命令吗? 在paint0中 35 2.5 载入现有图像文件2.5 载入现有图像文件 import java.applet.*;import java.awt.*; public class image extends Applet { Image img; public void init() {img=getImage(getCodeBase() "img0001 gif");}{ img getImage(getCodeBase(), img0001.gif );} public void paint(Graphics g) { int width=img.getWidth(this); int height=img.getHeight(this); g.drawRect(52,52,width+30,height+30); g drawImage(img 57 57 width+20 height+20 this);}}g.drawImage(img,57,57,width+20,height+20,this);}} 36 26动态效果---线程的应用2.6 动态效果 线程的应用 2.4 动态效果---线程的应用 • 什么是线程? 线程是执行中的程序中的单个顺序控制流线程是执行中的程序中的单个顺序控制流. • Java支持多线程 开始 显示进度 数学运算数学运算 引出最后结果 线程1 线程2 37 26动态效果---线程的应用2.6 动态效果 线程的应用 • 静态的情况 import java.applet.*; import java.awt.Graphics; public class maguee extends Applet { public void paint(Graphics g){ public void paint(Graphics g) { g.drawString("Hello, Java!",0,0); } } 38 26 动态效果---线程的应用2.6 动态效果 线程的应用 • 动态的情况(不是多线程) public void init() { x=size().width; y=size().height/2; width=x; }} public void paint(Graphics g) { while(true) { g.drawString("Hello, Java!",x,y); x-=10; if(x<0) x=width; }if(x<0) xwidth; } } 39 26动态效果---线程的应用2.6 动态效果 线程的应用 • 实现一个线程实现 个线程 让Applet类去实现Runable接口,创建一个线程类让 pp 类去实现 接口,创建 个线程类 改写方法 tt在其中产生 个新的线程来工作改写方法start,在其中产生一个新的线程来工作 改写 方法 在其中编写结束线程的程序代码改写stop方法,在其中编写结束线程的程序代码 新的 法 将分给线的作到 中引入新的方法,将分给线程的工作写到run中 40 26动态效果---线程的应用2.6 动态效果 线程的应用 第一步:实现Runable接口 public class xc extends java.applet.Applet implements Runnableimplements Runnable { Thread smallthread=null; … }} Thread是一个类,只有是它的实例才能具有线程 的功能的功能 主函数中要定义一个线程变量主函数中要定义 个线程变量 41 26动态效果---线程的应用2.6 动态效果 线程的应用 第二步:改写方法start ()public void start() { if(smallthread == null) { smallthread= new Thread(this); smallthread start();smallthread.start(); //从现在开始程序由两个线程在执行 }} 第三步:改写stop方法 public void stop() { smallthread stop(); //停止线程{ smallthread.stop(); //停止线程 smallthread = null; //释放线程对象} 42 26动态效果---线程的应用2.6 动态效果 线程的应用 第四步:新的方法run 将让线程要做的事放run中 public void run()public void run() { while (true) { repaint(); try {Thread sleep(1000);}try {Thread.sleep(1000);} catch(InterruptedException e){} } }} 43 26动态效果---线程的应用 import java.applet.*; import java.awt.Graphics; public class MovingCharacter extends Applet 2.6 动态效果 线程的应用pg pp implements Runnable { int x=200; Thread my thread=null;Thread my_thread=null; //------------------------------------------------- public void start()public void start() { my_thread=new Thread(this); my thread start();my_thread.start(); } bli id ()public void run() { while(true) { i t(){ repaint(); try { Thread.sleep(100); }th(It tdEti){}} catch(InterruptedException e){} }} 44 26动态效果---线程的应用2.6 动态效果 线程的应用 • .public void stop()public void stop() { my_thread.stop(); } public void paint(Graphics g) { g.drawString("Hello, Java!",x,y); x-=10; if(x<0) x=200; } 45 26动态效果---线程的应用2.6 动态效果 线程的应用 • 跳动的小球 up false;up=false; x=x-10; if(x<0) x=width; if (up) y=y+10;else y=y-10; if (y<0) up=true;(y ) p ; if (y>height) up=false; g setColor(Color red);g.setColor(Color.red); g.fillOval(x,y,30,30); 46 26动态效果---线程的应用2.6 动态效果 线程的应用 例:起始页上的小时钟 一个必须用到的类----Date类,给出系统时间 Date NowTime new Date();Date NowTime=new Date(); NowTime.getHours(), NowTime.getMinutes() 自己需要写什么样的类?自己需要写什么样的类? Clock---把数字时间成图形表示 (Hour*60*60+minute*60+second)/43200*2.0*PI (minute*60+second)/3600*20*PI(minute 60+second)/3600 2.0PI second/60*2.0*PI 47 26动态效果---线程的应用2.6 动态效果 线程的应用 主类 取时间 paint() {} lk类clock类 clock(){} Show(){} drawNiddle(){} 换算弧度 画图初始化 48 26动态效果---线程的应用class Clock2.6 动态效果 线程的应用class Clock {int hours,minutes,second,radius; Cl k(i h i i i )Clock(int hrs,int min,int sec) { hours=hrs%12; minutes=min; second=sec; } void show(Graphics g, int x, int y,int redius) { int hrs len=(int)(radius*05);{ int hrs_len (int)(radius 0.5); int min_len=(int)(radius*0.7); it l (it)(di*085)int sec_len=(int)(radius*0.85); double theta; g.drawOval(x ,y, radius*2, radius*2); 49 26动态效果---线程的应用theta=(double)(hours*60*60+minutes*60+second)/2.6 动态效果 线程的应用theta (double)(hours 60 60+minutes 60+second)/ 43200.0*2.0*Math.PI; d Niddl ( C l bl h l h )drawNiddle(g,Color.blue, x, y, hrs_len, theta); theta=(double)(minutes*60-second)/3600.0*2.0*Math.PI; drawNiddle(g,Color.blue, x, y, min_len,theta); theta=(double)second/60 0*20*Math PI;theta (double)second/60.02.0Math.PI; drawNiddle(g,Color.red, x, y, sec_len, theta); }} 50 26动态效果---线程的应用2.6 动态效果 线程的应用 private void drawNiddle(Graphics g, Color c, int x, int y, int len, double theta) { g.setColor(c); g.drawLine(x,y,(int)(x+len*Math.sin(theta)), (int)(y-len*Math cos(theta))); }(int)(y-len Math.cos(theta))); } } 51 26动态效果---线程的应用itjt*itjtilDt2.6 动态效果 线程的应用import java.awt.*;import java.util.Date; public class ClockDemo extends java.applet.Applet { public void paint() { Date timeNow = new Date();{ Date timeNow new Date(); Clock myClock = new Cl k(ti N tH ()Clock(timeNow.getHours(), timeNow.getMinutes(), timeNow.getSeconds()); myClock.show(g,100,100,100);myClock.show(g,100,100,100); } }} 52 26动态效果---线程的应用2.6 动态效果 线程的应用 主类 生成时间对象,取时间 生成 对象 将时间传 paint() {} 生成Clock对象,将时间传 递给Clock对象 lk类clock类 clock(){} Show(){} drawNiddle(){} 换算弧度 画图初始化 53 26动态效果---线程的应用2.6 动态效果 线程的应用 主类 start() stop() run()paint() 启动新线程 停止线程 生成clock类实例 repaint() clock类 成 类实例 p() clock(){} Show(){} drawNiddle(){} 换算弧度 clock(){} 初始化 Show(){} drawNiddle(){} 换算弧度 画图初始化 54 2.6 动态效果---线程的应用2.6 动态效果 线程的应用 例: 在主页上显示 字符串并且颜色从左至右不断变化 让我们来想一想: 需要那些数据成员?让我们来想 想: 需要那些数据成员? String msg, Font fnt, Color clr, spot_clr; Thread thread; String Msg="Welcome to HIT"; 需要哪些方法? init, start, stop, run, paint; public void init()public void init() { fnt= new Font("TimeRoman",Font.PLAIN,30); clr=new Color(255,0,0); spot_clr=new Color(0,0,255); Thread thread;} 55 26动态效果---线程的应用2.6 动态效果 线程的应用 run()中做什么? 反复调用repaint public void run() { while(true) { repaint(); try{Thread sleep(50);}try{Thread.sleep(50);} catch(InterruptedException e) {} } } 56 26动态效果---线程的应用2.6 动态效果 线程的应用 paint()中做什么? 输出两次字符串 第次用种颜色第次用另种颜输出两次字符串,第一次用一种颜色,第二次用另一种颜 色(该颜色只作用于指定的区域 ) You are Welcome to HIT g.clipRect(x,y,width,height) public void paint(Graphics g)public void paint(Graphics g) { FontMetrics fntM=g.getFontMetrics(); int font_height=fntM.getHeight(); int base line=size().height/2+font height/2;_ () g _ g; 57 26动态效果---线程的应用2.6 动态效果 线程的应用 g.setFont(fnt); g.setColor(clr); gdrawString(Msg0baseline);g.drawString(Msg,0,base_line); g.clipRect(strPt-50,0,str_bk_size,size().height); g.setColor(spot_clr); gdrawString(Msg0baseline);g.drawString(Msg,0,base_line); strPt=(strPt+1)%(size().width+100); } }} 58 26动态效果---线程的应用2.6 动态效果 线程的应用 在Java中播放动画 1.需要多张图片 2 调用图片的方法? getImage2 调用图片的方法? getImage, 3.将多幅图像存入图像对象数组 Image frame[]=new Image[10]; for (int i=0;ijview throwsExceptionc:>jview throwsException In Situation 0 no Exception caughtpg In Situation 1 Catch j l A IdOtOfBdEti10java.lang.ArrayIndexOutOfBoundsException:10 224.5 抛出异常  抛弃异常: 不是出错产生,而是人为地抛出  throw ThrowableObject; throw ThrowableObject;  throw new ArithmeticException();  例:编写程序人为抛出(JavaThrow.prj) ArithmeticE ceptionArithmeticException, ArrayIndexOutOfBoundsExceptionyp StringIndexOutOfBoundsException A method Exception Another method throw caughtthrow g 234.5 抛出异常class JavaThrow { public static void main(String args[]){ p ( g g []) { try{ throw new ArithmeticException();} catch(ArithmeticException ae)catch(ArithmeticException ae) { System.out.println(ae); } t{thtry{ throw new ArrayIndexOutOfBoundsException();} catch(ArrayIndexOutOfBoundsException ai)catch(ArrayIndexOutOfBoundsException ai) { System.out.println(ai); } try { throw new Si IdOOfBdE i ()}StringIndexOutOfBoundsException();} catch(StringIndexOutOfBoundsException si){ { System out println(si); }{ System.out.println(si); } 244.6 创造自己的异常  不是由Java系统监测到的异常(下标越界,被 0-除等),而是由用户自己定义的异常.除等),而是由用户自 定义的异常  用户定义的异常同样要用try--catch捕获,但 必须由用户自己抛出 throw new必须由用户自己抛出 throw new MyException.  异常是一个类,用户定义的异常必须继承自 Throwable或Exception类,建议用Throwable或Exception类,建议用 Exception类. 254.6 创造自己的异常  形如: ii class MyException extends Exception  {….};  例1 :计算两个数之和,当任意一个数超出范围时, 抛出自己的异常抛出自 的异常 public class NumberRangeException extendspublic class NumberRangeException extends Exception { public NumberRangeException(String msg){ public NumberRangeException(String msg) { super(msg); } }} 264.6 创造自己的异常  . public boolean action(Event evt, Object arg) {t {{ try { int answer = CalcAnswer(); ans erStr String al eOf(ans er);answerStr = String.valueOf(answer); }catch (NumberRangeException e) { answerStr e getMessage(); }{ answerStr = e.getMessage(); } repaint(); return true;return true; } 274.6 创造自己的异常public int CalcAnswer() throws NumberRangeException { int int1, int2; int answer = -1;  .String str1 = textField1.getText(); String str2 = textField2.getText(); t{it1It It(t1)try { int1 = Integer.parseInt(str1); int2 = Integer.parseInt(str2); if ((int1 < 10) || (int1 > 20) ||if ((int1 < 10) || (int1 > 20) || (int2 < 10) || (int2 > 20)) { NumberRangeException e = {gp new NumberRangeException (”Numbers not within the specified range."); throw e; } it1+it2answer = int1 + int2; }catch (NumberFormatException e) { answerStr = e toString(); }{ answerStr = e.toString(); } return answer; } 284.6 创造自己的异常  例2 :在定义银行类时,若取钱数大于余额 则作为异常处理则作为异常处理 (InsufficientFundsException).  思路:产生异常的条件是余额少于取额, 因 此是否抛出异常要判断条件此是否抛出异常要判断条件  取钱是withdrawal方法中定义的动作,因 此在该方法中产生异常此在该方法中产生异常.  处理异常安排在调用withdrawal的时候,处理异常安排在调用 tdaa的时候, 因此withdrawal方法要声明异常,由上级 方法调用方法调用  要定义好自己的异常类 294.6 创造自己的异常class Bank { double balance;  . {; public void deposite(double dAmount) { if(dAmount>0.0) {balance+=dAmount;}} public void withdrawal(double dAmount) throws InsufficientFundsException { if (balance0.0) {balance+=amount;}}  void withdrawal(long amount)  {if( t00&& t bl ) { if(amount>0.0 &&amount <= balance)  { balance-=amount;}  } }  public long show_balance()  { t (l )b l } { return (long)balance; }  } 845.6 各种构件的应用实例--综合练习 public class BankDemo 实 { public static void main(String agrs[]) { Bank account1=new Bank(); Bank account2=new Bank();Bank account2 new Bank(); account1.deposite(100); account2.withdrawal(50); account1.show_balance(); account2.show_balance(); } }} 855.6 各种构件的应用实例--综合练习实 WelCome to Bank 100 Create account Show nbalance DitDeposit Withdrawal 865.6 各种构件的应用实例--综合练习 主类Bankapp (Frame的子类) 辅类Bank 辅类Warningbox 实 ( ) Bank() 创建账户 main() 定义并显示窗口 Warningbox(String str) 布局安排 显示对话框 show_balance 定义并显示窗口 Bankapp() 布局安排,显示对话框 显示警告信息 diposite() a app() 布局安排 action() 关闭对话框 withdrawal() handleEvent() 关闭窗口 关闭对话框 它是模态的 action() 根据按钮做处理 不满足Bank要求 满足Bank要求 875.6 各种构件的应用实例--综合练习实 public static void main(String args[])p(gg) { Bankapp frame=new Bankapp(); frame.setTitle("Bank Application");pp frame.resize(200,200); frame.show(); } 885.6 各种构件的应用实例--综合练习实 public Bankapp() { tL t( G idL t(6 1)){setLayout(new GridLayout(6,1)); Label lb=new Label("welcome to Bank",Label.CENTER); tf=new TextField("0",15); add(lb);add(tf);tf new TextField( 0 ,15); add(lb);add(tf); b1=new Button("create account"); add(b1); b2 B tt (" h b l ") dd(b2)b2=new Button("show balance"); add(b2); b3=new Button("diposite"); add(b3); b4=new Button("withdrawal"); add(b4); resize(450,100); } resize(450,100); } 895.6 各种构件的应用实例--综合练习 public boolean handleEvent(Event evt) 实 { switch(evt.id) { case Event.WINDOW_DESTROY: dispose(); System.exit(0); return true; case Event.ACTION_EVENT: return action(evt, evt.arg); default: return super.handleEvent(evt); } } 905.6 各种构件的应用实例--综合练习 public boolean action(Event evt,Object arg) {if(evt.target instanceof Button)实{( g ) { String targetLabel=tf.getText(); long amount=Long.valueOf(targetLabel).longValue();g g ( g ) g (); if (arg=="diposite") { if (!haveAccount)() {wb=new WarningBox(this,"create a account first!"); wb.show(); }(); } else { if(amount==0) { wb=new WarningBox(this,”need the amount");{g(,); wb.show(); } else { bank.deposite(amount); tf.setText("0"); }}{p();();}} return true; }} return false; } 915.6 各种构件的应用实例--综合练习 public WarningBox(Frame parent,String str) { super(parent,"Warning!",true);实{p(p, g, ); Panel panel=new Panel(); panel.setLayout(new GridLayout(2,1));p y ( y ( , )); panel.add(new Label(str,Label.CENTER)); panel.add(new Button("OK"));p ( ( )); add(info_panel); }} public boolean action(Event evt,Object arg) { if (evt.target instanceof Button){( g ) { this.dispose(); return true;; } return false; } 925.6 各种构件的应用实例--综合练习 class Bank { long balance; 实{g ; public Bank() { balance=50; }{;} public void deposite(long amount)pp(g) { if(amount>0.0) {balance+=amount;}} void withdrawal(long amount) { if(amount>0.0 &&amount <= balance){( ) { balance-=amount;} }} public long show_balance()pg_() { return (long)balance; } } 935.7 总结  5.8 总结  1 使用AWT构件的应用实例  2 事件的传递 了解类及其常用方法  2 事件的传递  3 外观的管理与控制 了解类及其常用方法 创建类的实例设计好容 创建输出管理器 new器层次 setLayout 加到上一级容器中 add 定义事件的处理 action 94作业  将文本行的输入加入到文本域中 追加 第6章 数据流的运用 2 第6章 数据流的运用第 章 数据流的 用  6.1 输入输出方法 62 输入输出流的基类 6.2 输入输出流的基类  6.3 File I/O  6.4 数据输入输出流  6.5 随机存取文件65 随机存取文件  6.6 文件的其它操作 6 7 java中的unicode 6.7 java中的unicode  6.8 管道流  6.9 对象流  6.10 流的分类流的分类  6.11 小结 3 6.1 输入输出方法输输出方法  什么是数据流 ? 文件文件起 终 文件,字符串 存储区 程序 终端 程序 网络端点 数据流 起 点 终 点 数据流 网络端点 数据流是指所有的数据通信通道 数据流是指所有的数据通信通道  在java中有关流的操作使用java.io.*在java中有关流的操作使用java. o.  出于安全的考虑,小应用不能实现文件I/O流 4 6.1 输入输出方法输输出方法  System类管理标准输入输出流和错误流y  System.out:  把输出送到缺省的显示(通常是显示器) 把输出送到缺省的显示(通常是显示器)  System.in  从标准输入获取输入(通常是键盘)  System.erry  把错误信息送到缺省的显示  每当main方法被执行时 就自动生成上述三个 每当main方法被执行时,就自动生成上述三个 对象 5 6.1 输入输出方法输输出方法 public class ReadHello { public static void main(String args[]) { char inchar;{ System.out.println(“Enter a character:”); try{ inChar=(char)System.in.read();try{ inChar (char)System.in.read(); Syste.out.println(“ “+ inChar); }catch(IOException e)}catch(IOException e) { Sytem.out.println(“Error reading from user”); }} } } 6 6.1 输入输出方法输输出方法 import java.io.*; lIOTtclass IOTest { public statics void main(String args[]) {try { byte bArray[]=new byte[128]; System.out.println(“Enter something:”);Syste .out.p t ( te so et g: ); System.in.read(bArray); S stem o t print(“Yo entered:”);System.out.print(“You entered:”); System.out.println(bArray); }catch(IOException ioe) { System.out.println(ioe.toString()); } stream\Iostream.class---f4.bat { y p ( g()); } } } 7 6.1 输入输出方法输输出方法  为什么输入的是字符,输出是乱码?,  原因:System.out.println(bArray)输出的是数组 的地址而不是字符的地址而不是字符  改进:将字符数组变换成字符串 原来是 S t t i tl (bA ) 原来是:System.out.println(bArray);  现在为:String s=new String(bArray,0);  System.out.println(s);  System.in是属于BufferedInputStream类型 System.in是属于BufferedInputStream类型  System.out是属于PrintStream类型 St 也是属于PitSt 类型 System.err也是属于PrintStream类型 8 6.2 输入输出流的基类输输出流的类  Java中每一种流的基本功能依赖于基本类 InputStream和OutputStreamInputStream和OutputStream  它们是抽象类,不能直接使用 属于 类的方法有 属于InputStream类的方法有:  read():从流中读入数据  skip():跳过流中若干字节数  available():返回流中可用字节数 available():返回流中可用字节数  mark():在流中标记一个位置 返回标记过得位置 reset():返回标记过得位置  markSupport():是否支持标记和复位操作  close():关闭流 9 6.2 输入输出流的基类输输出流的类  方法read()提供了三种从流中读数据的方法.()  int read():读一个整数  int read(byte b[]):读多个字节到数组中 int read(byte b[]):读多个字节到数组中  int read(byte,int off,int len);  属于OutputStream类的方法有:  write(int b):将一个整数输出到流中()  write(byte b[]):将数组中的数据输出到流中  write(byte b[] int off int len):将数组b中从off指 write(byte b[], int off,int len):将数组b中从off指 定的位置开始len长度的数据输出到流中 10 6.2 输入输出流的基类输输出流的类  flush():将缓冲区中的数据强制送出()  close():关闭流.  PrintStream类 PrintStream类  println()不属于OutputStream类,它是 PitSt 类的子类 能提供复杂的输出PrintStream类的子类,能提供复杂的输出  PrintStream类的方法有:  write, flush, checkError,print, println,close.  其中println可以输出多种形式的数据.例如: 其中println可以输出多种形式的数据.例如:  println(String s), println(char c)等 11 6.3 File I/O  文件对象的建立  File fp=new File(“tempfile.txt”);  对文件操作要定义文件流 对文件操作要定义文件流  FileInputStream类用来打开一个输入文件  FileOutputStream类用来打开一个输出文件 输出文件 输入文件 read write 输出文件 输入文件 12 6.3 File I/O  文件流的建立  FileInputStream in=new FileInputStream(fp);  FileOutputStream out=new FileOutputStream out=new FileOutputStream(fp);  例:文件拷贝(注意要捕获文件异常)  输入流的参数是用于输入的文件名  输出流的参数是用于输出的文件名 file1.txt file2.txt输入流 输出流 13 6.3 File I/O import java.io.*; class filestream { bli t ti id i (St i []){ public static void main(String args[]) { try{ Fil i Fil Fil (”fil 1 t t")File inFile=new File(”file1.txt"); File outFile=new File(”file2.txt"); FileInputStream fis=new FileInputStream(inFile); FileOutputStream fos=new FileOutputStream(outFile); int c; while((c=fis.read())!=-1) fos.write(c); fis.close(); fos.close();(); (); }catch(FileNotFoundException e) { System.out.println("FileStreamsTest: "+e);System.out.println( FileStreamsTest: +e); }catch(IOException e) { System err println("FileStreamsTest: "+e);System.err.println( FileStreamsTest: +e); }}} 14 6.3 File I/O  增加缓冲区流,减少访问硬盘的次数,提高效率, , fil 1 i输入缓冲区 输出缓冲区file1.txt file2.txt 输入流 输出流 输入缓冲区 输出缓冲区 文件 文件流 缓冲区流文件流 缓冲区流 15 6.3 File I/O  缓冲区流:  BufferedInputStream和 BufferedInputStream和 BufferedOutputStream 将它们与文件流相接 将它们与文件流相接  FileInputStream in=new FileInputStream(“file1 txt”); FileInputStream(“file1.txt”);  BufferedInputStream bin=  new BufferedInputStream(in,256)  int len; byte bArray[]=new byte[256];;y y[] y[ ];  len=bin.read(bArray);  len中得到是长度 bArray中得到的是数据 len中得到是长度, bArray中得到的是数据 16 6.3 File I/O  只有缓冲区满时,才会将数据送到输出流.  Java在输出数据流中,当对方尚未将数据取走时, 程序就会被阻塞.  有时要人为地将尚未填满的缓冲区中的数据送 出,使用flush()方法.出,使用 ()方法 文件 17 6.4 数据输入输出流数据输 输出流  什么时候需要数据输入输出流?  文件流和缓冲区流的处理对象是字节或字节数 组,利用数据输入输出流可以实现对文件的不组,利用数据输入输出流可以实现对文件的不 同数据类型的读写.  DataInputStream DataOutputStream DataInputStream、DataOutputStream  一种较为高级的数据输入输出方式,除了字节和 字节数组 还可以处理itfltb l 等类型字节数组,还可以处理int,float,boolean等类型.  还可以用readLine方法读取一行信息  可使用的方法:  write,writeBoolean…,read,readByte…等 write,writeBoolean…,read,readByte…等 18 6.4 数据输入输出流数据输 输出流  数据流的建立  FileOutputStream fos=  new FileOutputStream(”file2 txt")); new FileOutputStream( file2.txt ));  DataInputStream dis=  new DataInputStream(fos)  数据输出流可以是一个已经建立好的输入数据 流对象,例如网络的连结,文件等.流对象,例如网络的连结,文件等.  下面的例子显示如何利用数据输入输出流往文 件中写不同类型的数据件中写不同类型的数据 19 6.4 数据输入输出流 class datainput_output { public static void main(String args[]) throws IOException数据输 输出流{ public static void main(String args[]) throws IOException { FileOutputStream fos=new FileOutputStream(“a.txt”); DtOt tSt d DtOt tSt (f)DataOutputStream dos=new DataOutputStream (fos); try{ dos.writeBoolean(true); dos.writeByte((byte)123); dos.writeChar('J');dos.writeChar( J ); dos.writeDouble(3.141592654); d it Fl t(2 7182f)dos.writeFloat(2.7182f); dos.writeInt(1234567890); dos.writeLong(998877665544332211L); dos.writeShort((short)11223);dos.writeShort((short)11223); }finally{ dos.close(); } 20 6.4 数据输入输出流 DataInputStream dis=new DataInputStream( new FileInputStream(”a.txt"));数据输 输出流new FileInputStream( a.txt )); try{ System.out.println("\t "+dis.readBoolean()); S t t i tl ("\t "+di dB t ())System.out.println("\t "+dis.readByte()); System.out.println("\t "+dis.readChar()); System.out.println("\t "+dis.readDouble()); System.out.println("\t "+dis.readFloat());System.out.println( \t +dis.readFloat()); System.out.println("\t "+dis.readInt()); S t t i tl ("\t "+di dL ())System.out.println("\t "+dis.readLong()); System.out.println("\t "+dis.readShort()); }finally{dis.close();} }} Stream\datainputandoutput--->f5.bat }} 21 6.4 数据输入输出流数据输 输出流  DateLine(InputStream in)(计算字符和行数)  { DataInputStream data=new { DataInputStream data=new  DataInputStream(in); String c rrentLine; String currentLine;  int lineCount=0; int charCount=0;  while((currentLine=dataIn.readLine())!=null)  { ++lineCount;{;  charCount+=currentLine.length();  } }  return (charCount/(float)lineCount);  } } 22 6.5 随机存取文件随机存取文件  类RandomAccessFile  zip文件需要用随机方法处理  文件目录给出个文件的入口 可以随机读取 文件目录给出个文件的入口,可以随机读取.  创建一个随机文件  new RandomAccessFile(“file1.txt”, “r”);  new RandomAccessFile(“file2.txt”, “rw”);(,);  随机文件可以同时完成读和写操作. 文件目录zip文件 23 6.5 随机存取文件随机存取文件  支持随机文件操作的方法:  readXXX()或writeXXX()  skipBytes();将指针乡下移动若干字节 skipBytes();将指针乡下移动若干字节  seek():将指针调到所需位置 pos  getFilePointer():返回指针当前位置  length():返回文件长度g()  利用seek(long pos)方法查找随机文件中的信息  例:把若干个32位的整数写到一个名为 例:把若干个32位的整数写到 个名为 “temp.dat”的文件中,然后利用seek方法,以相 反的顺序再读取这些数据反的顺序再读取这些数据 24 6.5 随机存取文件 public class random_file { public static void main(String args[])随机存取文件{ public static void main(String args[]) { int data_arr[]={12,31,56,23,27,1,43,65,4,99}; t{RdA Fildftry { RandomAccessFile randf=new RandomAccessFile(“temp.dat”); for (int i=0;i>data_arr.length;i++) randf.writeInt(data arr[i]);randf.writeInt(data_arr[i]); for(int i=data_arr.length-1;i>=0;i--) { df k(i*4){ randf.seek(i*4); System.out.println(randf.readInt()); } randf.close(); }catch (IOException e)}catch (IOException e) { System.out.println(“File access error: “+e);} } } 25 6.6 文件的其它操作文件的其 操作  使用文件类获取文件的路径信息使用文件类获取文件的路径信息  设f是一个文件对象  File f=new File(“data”,temp.dat”);  f getName():返回文件名 temp dat f.getName():返回文件名 temp.dat  f.getParent():返回文件所在目录名 data  f.getPath():返回文件路径 data\temp.dat  f getAbsolutePath():返回绝对路 f.getAbsolutePath():返回绝对路 c:\myprog\data\temp.dat 26 6.6 文件的其它操作文件的其 操作  例: 获取当前目录下所有文件名和文件的尺寸: itji* import java.io.*;  public class file_size  { public static void main(String args[])  { File files=new File(“.”);{();  String file_list[]=files.list();  for(int i 0;i +MySerialNum);yp(jy ) System.out.println("thread "+threadNum+ "bye.");}} 217.4 多线程问题---如何写多线程 1.分别定义不同的线程类,在各自的run方法中 定义线程的工作 class mythread1 extends Thread { public void run{….} }{p { } } class mythread2 extends Thread { public void run{….} }{ public void run{….} } 2. 在主类中实例化各线程类,并启动线程. public class demo extends Appletpublic class demo extends Applet { public void init() { th d t1 th d1(){ mythread t1=new mythread1(); mythread t2=new mythread2(); t1.start(); t2.start();} } 22 7.4 多线程问题---如何写多线程 练习:将窗口分为上下两个区,分别运行两个 线程,一个在上面的区域中显示由右向左游动 的字符串,另一个在下面的区域从左向右游动 的字符串. 方法一: 一个线程,在paint方法中使用两个输, p 出字符串的语句 public void paint(Graphics g)pp(pg) { if y1<0 y1=200 else y1=y1-10; if y2>200 y2=0 else y2=y2+10;yy yy; g.drawString(“hello, Java!”,20,y1,); g.drawString(“hello, Java!”,40,y2,);g.drawString( hello, Java! ,40,y2,); } 23 7.4 多线程问题---如何写多线程  方法二:定义两个类,运行各自的线程,各自有自 己的 i t()方法己的paint()方法.  注意: 两个小应用程序必须是panel类或者是 类 将小应用的区域分成两块 否则不能canvas类,将小应用的区域分成两块,否则不能 运行paint语句. 247.4 多线程问题---线程间的通信 1. 线程间的通信可以用管道流,. 线程 Pi dO t tSt Pi dI tSt 线程2 创建管道流 线程1 PipedOutputStream PipedInputStream 输出流outStream 输入流inStream 线程2 创建管道流: PipedInputStream pis=new PipedInputStream(); PipedOutputStream pos=new PipedOutputStream(pis);PipedOutputStream(pis); 或: PipedOutputStream pos=newPipedOutputStream pos new PipedOutputStream(); PipedInputStream pis=newPipedInputStream pis=new PipedInputStream(pos); 257.4 多线程问题---线程间的通信  管道流不能直 接读写 printStream DataInputStream PrintStream p = new PrintStream( pos ); itl(“hll”) pSe pu S e p.println(“hello”); DataInputStream d=new DataInputStream(pis); d.readLine();  2. 通过一个中间类来传递信息. 2. 通过 个中间类来传递信息. 线程线程1 中间类m ss 线程2线程1 中间类m m write(s) s=m.read()m.write(s) () write() read() 26 7.4 多线程问题--线程间的通信  管道流可以连接两个线程间的通信  下面的例子里有两个线程在运行,一个往外输出 信息,一个读入信息.信息, 个读入信息  将一个写线程的输出通过管道流定义为读线程 的输入的输入. outStream = new PipedOutputStream(); iS PidIS(S)inStream = new PipedInputStream(outStream); new Writer( outStream ).start(); new Reader( inStream ).start(); 27 7.4 多线程问题--线程间的通信 主类Pipethread 辅类 Writer 辅类 管 道 作为参数传给Writer Writer( outStream )Writer 线 程 辅类 Reader 线 道 流 将数据写 类 线 程 类 将数据写 到输出流 输入流 从流中读数据  (thread\Pipethread.class--f3.bat) 28 7.4 多线程问题--线程间的通信 public class Pipethread { public static void main(String args[])  . { public static void main(String args[]) { Pipethread thisPipe = new Pipethread(); thisPipe process(); }thisPipe.process(); } public void process() {Pi dI tSt i St{ PipedInputStream inStream; PipedOutputStream outStream; PrintStream printOut; try{ outStream = new PipedOutputStream(); inStream = new PipedInputStream(outStream); new Writer( outStream ).start();( ) (); new Reader( inStream ).start(); }catch( IOException e ){ }}catch( IOException e ){ } } } 29 7.4 多线程问题---线程间的通信 class Reader extends Thread { private PipedInputStream inStream;//从中读数据 public Reader(PipedInputStream i) { inStream = i; } bli id ()public void run() { String line; DataInputStream d; boolean reading = true;boolean reading = true; try{ d = new DataInputStream( inStream ); while( reading && d != null){(g ){ try{line = d.readLine(); if( line != null ){ System.out.println( ”Read: " + line ); } else reading = false; } t h( IOE ti ){ } }}catch( IOException e){ } } catch( IOException e ){ System.exit(0); } try{ Thread sleep( 4000 );}try{ Thread.sleep( 4000 );} catch( InterruptedException e ){}}} 30 7.4 多线程问题--线程间的通信 class Writer extends Thread { private PipedOutputStream outStream;//将数据输出  . { private PipedOutputStream outStream;//将数据输出 private String messages[ ]= { "Monday", "Tuesday ", "Wednsday""Thursday""Friday :"Wednsday , Thursday , Friday : , "Saturday:","Sunday :"}; bli W it (Pi dO t tSt )public Writer(PipedOutputStream o) { outStream = o; } public void run() { PrintStream p = new PrintStream( outStream ); for (int i = 0; i < messages.length; i++) { p.println(messages[ i ]);p p ( g [ ]); p.flush(); System.out.println("WrIte:" + messages[i] ); }System.out.println( WrIte: + messages[i] ); } p.close(); p = null; }} 31 7.3 多线程问题---资源协调 1. 数据的完整性 线程1 资源 线程2 变量 线程10 withdrwal() withdrwal()余额 透支透支 32 7.3 多线程问题---资源协调  对共享对象的访问必须同步,叫做条件变量.  Java语言允许通过监视器(有的参考书称其为 管程)使用条件变量实现线程同步.  监视器阻止两个线程同时访问同一个条件变量. 它的如同锁一样作用在数据上.  线程1进入withdrawal方法时,获得监视器(加 锁);当线程1的方法执行完毕返回时,释放监视 器(开锁) 线程2的 ihd l方能进入器(开锁),线程2的withdrawal方能进入. 监视器 线程2 withdrawal() 线程1 监视器 33 7.3 多线程问题---资源协调  用synchronized来标识的区域或方法即为监视 器监视的部分器监视的部分。  一个类或一个对象由一个监视器,如果一个程 序内有两个方法使用synchronized标志,则他 们在一个监视器管理之下. 监线程1 线程2 read write 监 视 器  一般情况下,只在方法的层次上使用关键区 347.3 多线程问题---资源协调 此处给出的例子演示两个线程在同步限制下工作的情况. class Account { statics int balance=1000; //为什么用static?{;为什么用 statics int expense=0; public synchronized void withdrawl(int amount)public synchronized void withdrawl(int amount) { if (amount<=balance) { balance-=amount; expense+=amount;}p;} else { System out println(“bounced: “+amount);}{ System.out.println(“bounced: “+amount);} } } 35 7.3 多线程问题---资源协调  2. 等待同步数据等待 步数据 生产者 消费者 . 共享对象 消费者 . 共享对象 write read 可能出现的问题可能出现的问题: • 生产者比消费者快时,消费者会漏掉一些数据 没有取到 • 消费者比生产者快时,消费者取相同的数据., • notify()和wait ()方法用来协调读取的关系. • notify()和wait ()都只能从同步方法中的调用.notify()和wait ()都只能从同步方法中的调用. 36 7.3 多线程问题---资源协调  notify的作用是唤醒正在等待同一个监视器的 线程线程.  wait的作用是让当前线程等待  信息版例子  read()方法在读信息之前先等待 直到信息可 read()方法在读信息之前先等待,直到信息可 读,读完后通知要写的线程. it ()方法在写信息之前先等待 直到信息被 write()方法在写信息之前先等待,直到信息被 取走,写完后通知要读的进程.  DemoWait.class--->f4.bat 37 7.3 多线程问题---资源协调 writer reader aaaa bbbbb aaaaaaaaaaaaaaaa aaaa aaaa bbbbb bbbbbbbbbb cccc bbbbb cccccccccccccccc bbbbb cccc 38 7.3 多线程问题---资源协调  class WaitNotifyDemo {  public static void main(String[] args) {  { MessageBoard m = new MessageBoard();  Reader readfrom_m = new Reader(m);  Writer writeto m=new Writer(m); Writer writeto_mnew Writer(m);  readfrom_m.start();  writeto_m.start();  }  } 39 7.3 多线程问题---资源协调 class MessageBoard { { private String message; private boolean ready = false;(信号灯) public synchronized String read() { while (ready == false) { try { wait(); } catch (InterruptedException e) { } } ready = false; notify(); //起始状态先写后读 return message; } public synchronized void write(String s) { while (ready == true) { try { wait(); } catch (InterruptedException e) { } } message = s; ready = true; notify(); }} 40 7.3 多线程问题---资源协调 class Reader extends Thread { private MessageBoard mBoard;{p g ; public Reader(MessageBoard m) { mBoard = m; }{ mBoard m; } public void run() {Strings="";{ String s = ; boolean reading = true; hil ( di ){while( reading ){ s = mBoard.read(); System.out.println("Reader read: " + s); if( s.equals("logoff") ) reading = false; } System.out.println("Finished: 10 seconds..."); try{ sleep( 10000 ); }y{ p( ); } catch (InterruptedException e) { } } } 41 7.3 多线程问题---资源协调 class Writer extends Thread { private MessageBoard mBoard; private String messages[ ]= { "Monday :------------------------", “”“…..”, "Sunday : ----------------------"}; public Writer(MessageBoard m) { mBoard = m; }{;} public void run() { { for (int i = 0; i < messages.length; i++) { mBoard.write(messages[ i ]); S t t i tl ("W it t " + [i] )System.out.println("Writer wrote:" + messages[i] ); try { sleep((int)(Math.random() * 100)); } catch (InterruptedException e) { }} catch (InterruptedException e) { } } mBoard.write("logoff"); } } 42 7.3 多线程问题---资源协调  多线成问题---资源的协调和锁定 死锁问题1. 死锁问题 把“pen”给我,我 才能给你 线程2线程1 t 才能给你“note” 如果你的持有 个锁并试图获取另 个锁时 就 pennote 把“note”给我,我 才能给你“pen” 如果你的持有一个锁并试图获取另一个锁时,就 有死锁的危险. 解决死锁问题的方法:给条件变量施加排序 43 7.3 多线程问题---daemon线程  什么是daemon(守护)?  在客户/服务器模式下,服务器的作用是等待用 户发来请求,并按请求完成客户的工作, 客户端 服务器端request daemon  守护线程是为其它线程提供服务的线程  守护线程一般应该是一个独立的线程,它的 守护线程 般应该是 个独立的线程,它的 run()方法是一个无限循环.  守护线程与其它线程的区别是,如果守护线程 守护线程与其它线程的区别是,如果守护线程 是唯一运行着的线程,程序会自动退出 44 7.4 小结 1. 实现线程有两种方法: 实现 接 实现Ruannable接口  继承Thread类 2. 在小应用中通常在start中创建线程 3 当新线程被启动时 java调用该线程的run方3.当新线程被启动时,java调用该线程的run方 法,它是Thread的核心. 4 线程由四个状态:新生 运行 暂停 死亡4. 线程由四个状态:新生,运行,暂停,死亡 5. 线程间的通信方式由三种:完全共享数据,通 过监视器 通过过监视器,通过join. 45 7.4 小结 6. 两个或多个线程竞争资源时,需要用同步的方法 协调资源协调资源. 7. 多个线程执行时,要用到同步方法,即使用 synchronized的关键字设定同步区 8. wait和notify起协调作用和 y起协调作用 9. 守护进程的特点是当程序中只剩它自己时,会 自动中止自动中止. 46 作业  创建两个线程的实例,分别将一个数组从小大大 和从达到小排列 输出结果和从达到小排列.输出结果. 第 章网络功能第8章网络功能 2第8章网络功能  8.1 Java与internet  8.2 使用URL  8.3 访问cgi访问 g  8.4 URL连接  8 5 Socket 8.5 Socket  8.6 internet应用  8.7 数据报  8.8 JDBC  8.9 小结 38.1 Java与网络  Java语言取得成功的领域之一就是网络  (其他语言)数页代码 >(Java)一条语句 (其他语言)数页代码---->(Java) 条语句  TCP/IP(传输控制协议/网间协议)是internet的主 要协议 定义了计算机和外设进行通信所使用的要协议,定义了计算机和外设进行通信所使用的 规则(应用层,传输层,网络层,链路层). 大多数基于 的应用程序被看作 协 大多数基于internet的应用程序被看作TCP/IP协 议的上一层. 如 : ftp, http, smtp, pop3, telnet, 等nntp等  IP地址:TCP/IP网络中的每台计算机都有唯一的 地址--IP地址.  在Java中,有一个用来存储internet地址的类叫在Java中,有 个用来存储internet地址的类叫 InetAddress. 48.1 Java与网络  例:获取本机的IP地址 import java net *;import java.net. ; public class getLocalHostTest { public static void main(String args[]){ public static void main(String args[]) { InetAddress myIP=null; t{ IPItAdd tL lH t() }try {myIP=InetAddress.getLocalHost();} catch{UnknownHostException e){} System.out.println(myIP); } }} 创建inetAddress类不用构造函数(不用new) 5 8.1 Java与网络 下面的例子演示java如何根据域名自动到DNS 上查找IP地址(与DNS服务器的连接减至 行)上查找IP地址(与DNS服务器的连接减至一行) import java.net.*; public class getIP { public static void main(String args[]){ pub c stat c vo d a (St g a gs[]) { InetAddress pku=null; tr { pktry{ pku= InetAddress.getByName(“www.pku.edu.cn”); }catch(UnknowHostException e) {} System.out.println(pku); }y p (p ); } } 6 8.1 Java与网络  Java提供的网络功能有三大类: URL, Socket, Datagram.  URL是三大功能中最高级的一种 通过URL URL是三大功能中最高级的 种,通过URL Java程序可以直接送出或读入网络上的数据.  Socket是传统网络程序最常用的方式,可以想象 为两个不同的程序通过网络的通信信道.为两个不同的程序通过网络的通信信道.  Datagram是更低级的网络传输方式,它把数据 的目的纪录在数据包中 然后直接放在网络上的目的纪录在数据包中,然后直接放在网络上. 7 8.2 使用URL  8.2.3 通过URL读取WWW服务器上的数据  将URL位置的数据转成一个数据流  URL url=new (http://www.pku.edu.cn/index.html”  DataInputStream data=new DataInputStream data new  DataInputStream(url.openStream()); 从数据流中读出数据 从数据流中读出数据  String line=data.readLine() DataInputStream  while(line!=null) line=data.readLine() URL Java 程序 88.2 使用URL http://www pku edu cn/http://www.pku.edu.cn/ < > 例:从给定的位置中读数据(ReadURLData prj) <...> 例:从给定的位置中读数据(ReadURLData.prj) connect 主类TtFild action Frame主类 str=a getText() TextArea cTextField a action Button str=a.getText() line_str=b.readLine() c.appendText(line str);URL url=new URL(str) URL url uo bl St() pp ( _ );URL url=new URL(str) DataInputStream bURL url b=url.openStream() DataInputStream b 98.2 使用URLpublic boolean action(Event evt, Object arg) { try{ String line; String str=textfield.getText(); url=new URL(str); data=new DataInputStream(url.openStream()); while((line=data.readLine())!=null){ textarea.appendText(line); } data.close(); }catch(MalformedURLException me){ System.out.println("Error URL"); }catch(IOException ie){ System.out.println("Error IO"); } return true; } 10 8.3 访问cgi  起始页上的计数器及cgi程序(script) 欢迎来访,你是第 个来访者!1 2 7 你是第个 来访者来访者 客户端 服务器端cgi程序名客户端 HTML 服务器端 CGI程序 num+ + cgi程序名 img 11 8.3 访问cgi Your name 服务器 数据库 服务器 Web服务器 cgi程序 form send reset
12 8.3 访问cgi  cgi(公共网关)程序可以用任何一种变成语言来 写写.  cgi将web与外部程序连接起来(数据库查询等)  cgi程序要放在指定的目录下cgi-bin目录.  cgi通常以GET或POST接收数据 cgi通常以GET或POST接收数据, 13 8.3 访问cgi  从小应用中运行CGI程序(GET) Socket runcgi=newSocket runcgi=new Socket(“www.jamsa.com”,80); OutputStream os=runcgi.getOutputStream(); PrintStream ps=new PringtStream(os); ps.println(“GET/cgi-bin/testcgi? arg1=val1& args2=val2&arg3=val3”);args2 val2&arg3 val3 );  http://<机器名>/?<查询串> 14 8.3 访问cgi  get方法把数据作为命令行中的参数传递给此 适用于少量参数的情况cgi (适用于少量参数的情况)  Java cgi程序通过main方法的串参数接受命令 行.  C cgi程序通过访问环境变量中的查询串g 程序通过访问环境变量中的查询串 QUERY_STRING,来获得查询串中的信息.  例如在C程序中:char*str; 例如在C程序中: char str;  str=getevn(QUERY_STRING); 15 8.3 访问cgi import java.io.*; import java.net.*; public class test cgip _ g { public static void main(String[] args) throws Exception { URL url = new URL{ ("http://pact518.hit.edu.cn/~wangqb/CGI- BIN/test 2.cgi?012345678"); _ g); URLConnection connection = url.openConnection(); }} } #include "stdio.h” main() { char *Query_String;{ Q y_ g; Query_String = getenv("QUERY_STRING"); /*treatment*/ } 16 8.3 访问cgi  从小程序中运行CGI程序(post) 方法通过标准输出向 传送参数 适合参数 post方法通过标准输出向cgi传送参数(适合参数 较多的情况)  用post方法要有数据输出流  Socket runcgi=new Socket(“www jamsa com” 80); Socket runcgi new Socket( www.jamsa.com ,80);  建立socket连接  DataOutputStream ds=runcgi.getOutputStream();  建立输入流  ds.println(“POST/cgi-bin/guestbook.pl”);  运行cgi程序 运行cgi程序 17 8.3 访问cgi  通知发送的数据类型  ds.println(“Content-type:plain/text”);  通知发送的数据长度通知发送的数据长度  String data=“Hello world”  ds println(“Content length”+data length+”\n”); ds.println(“Content-length”+data.length+”\n”);  发送数据  ds.println(data); 18 8.3 访问cgi  cgi接收post方法送来的数据,就像从标准输入读 数据 样数据一样.  getchar();gets();(C语言的情况)(要建立数据流)  cgi返回数据时要指明数据类型等信息:  printf(“Content-type:text/plain\n\n”); printf( Content-type:text/plain\n\n);  或 printf(“Content-type:text/html\n\n”); 或 i f(“C i/if\ \ ”) 或 printf(“Content-type:image/gif\n\n”);  cgi规定服务器与外部程序交换信息的协议. 198.3 访问cgi DtI tSt 客户端 j 程序 服务器端 i程序 URL连接 返回结果 DataInputStreamjava程序 cgi程序 String count_srt URL l 返回结果 URL url=new URL(“http://202.118.239.38/cgi-bin/count.cgi”); DataInputStream data=new DataInputStream(url.openStrean()); count_str=data.readLine();(此处读入的是cgi程序的输出) g.drawstring(“You are the “+count str+ ”visitor”);gg( _ ); 20 8.4 URL连接  URL双向通信(URLConection)  URLConnection是一个一http为中心的类 1. 建立连接建连接 URL url=new URL(“http://www yahoo com/”);URL( http://www.yahoo.com/ ); URLConnection con=url.openConnection(); 2 向服务器端送数据2. 向服务器端送数据 PrintStream outStream=new PrintStream(con.getOutputStream()); outStream println(string data);outStream.println(string_data); 21 8.4 URL连接 3. 从服务器读数据 DataInputStream inStream=new DataInputStream(con.getInputStream());p ( g p ()); inStream.readLine();  从URL中得到的输出流通常与一个CGI程序结 从URL中得到的输出流通常与一个CGI程序结 合一起工作 客户端 DataOutputStream CGI程序STDIN服务器 th () java程序 DataInputStream ( 排序 sort.cgi) connectiuon getchar() putchar() STDOUT g) 22 8.4 URL连接  URLConnection同时支持get和post两种机制一 般的格式般的格式.  缺省情况下位post method方式  URL和URLConnection的区别在于前者代表一 个资源的位置,后者代表一种连接个资源的位置,后者代表 种连接  下面的例子中Java程序访问cgi程序,并传给它 10个数据 cgi程序胡接收后 排序 并传送回来10个数据,cgi程序胡接收后,排序,并传送回来.  连接的建立、数据流的建立、java如何发数据、 如何接收数据 cgi程序如何发送和接收如何接收数据、cgi程序如何发送和接收 23 8.4 URL连接 import java.io.*; import java.net.*; public class test_cgi {public static void main(String[] args) throws Exception{public static void main(String[] args) throws Exception { URL url = new ("h // 518 hi d / b/ i bi / i")URL("http://pact518.hit.edu.cn/~wangqb/cgi-bin/test.cgi"); URLConnection connection = url.openConnection(); connection.setDoOutput(true); PrintStream out = newPrintStream out new PrintStream(connection.getOutputStream()); t i tl ("0123456789")out.println("0123456789"); out.close(); 24 8.4 URL连接 DataInputStream in = new DataInputStream(connection.getInputStream()); String inputLine;gp ; while ((inputLine = in.readLine()) != null) System out println(inputLine);System.out.println(inputLine); System.in .read (); in.close(); 25 8.4 URL连接 #include "stdio.h" main() { int array[10]; int i,j,k; printf("Content-type:text/plain\n\n");p( yp p ) for(i=0;i<=9;i++) array[i]=getchar(); //read data from InputStreamy[ ] g (); p for(i=0;i<=8;i++) { for(j=i;j<=9;j++){(j;j;j) { if(array[i]myclient----f8 bat myserver <-------->myclient----f8.bat  myserver2<-------->myclient2----f9.bat Server1(1111) client(1111) client(2222)Server2(2222) Computer 1 40 8.5 Socket  第二种方案: serverthreadserverthread  (支持多客户) S client1 Server client2 将服务器写成多线程的,不同的线程为不同的客 户服务.户服务. main()只负责循环等待 线程负责网络连接,接收客户输入的信息线程负责网络连接,接收客户输入的信息 41 8.5 Socket  . 客户1 线程()线程()客户1 客户2 服务器 线程()线程( ) 客户2 线程2线程( ) 42. 8.5 Socket定义数据成员 定义数据成员 创建服务器(端口号) 创建Socket实例 waiting for user 1111 服务器等待 网络连接 建立socket流 waiting for user 网络连接 建立socket流 读socket流 (看到提示)建立socket流 提 户输 客户名 (看到提示) connetcting client... 读客户 端信息 提示用户输入客户名 送用户名给 服务器 读客户 端信息 读socket流User :java 关闭流提示用户登录成功 43 8.5 Socket public static void main(String args[]) {ServerSocket serverSocket=null;{ServerSocket serverSocket null; try{serverSocket=new ServerSocket(1111); }th(Eti){}catch(Exception e){ System.out.println(”Error”+e);System.exit(1);} while(true) {Socket clientSocket=null;{Socket clientSocket null; System.out.println("waiting for users..."); t { li tS k t S k t t()try{ clientSocket=serverSocket.accept(); }catch(IOException e){ System.out.println("accept failed:"+e);} new serverThread(clientSocket).start();new serverThread(clientSocket).start(); }} 44 8.5 Socket class serverThread extends Thread { DataInputStream input; PrintStream output; String user; Socket clientSocket; serverThread(Socket clientSocket) { this clientSocket=clientSocket; }{ this.clientSocket=clientSocket; } public void run() { try{ input=new DataInputStream{y{p p (clientSocket.getInputStream()); output=System.out; user=input.readLine(); Si("C!")System.out.println(user+" Connected!"); }catch(IOException e){ } try {while(true) { String string;try {while(true) { String string; if((string=input.readLine())==null) break; output.println(user+string); output.flush(); }p p ( g); p (); } }catch(Exception e){ return; } System.out.println(user+ "has disconnected."); { li S k l () i l ()try{ clientSocket.close(); input.close(); }catch(Exception e){ return; } }} 45 8.5 Socket  例:通过服务器交换信息(exchangebyserver) Hello 1076Hello 1071 babc def server WAIT GO bWAIT GO…def WAIT GO…abc 46 8.5 Socket 服务器  . (1111) accept 客IP client1客 IP client2accept socket 客 户 客 户 线程 线程 服务器一端为了能接收多个客户的信息,它的输 入流,输出流都是数组型的., ServerSocket.accept()等待用户连接,一旦连接上, 则调用服务程序. 服务程序的主要内容是网络的读写,多客户的原 因,网络读写的功能用多线程实现,因此将此部分 功能单独分离出来,构成线程类 47 8.5 Socket • 服务器端 client1 serverServerSocket Socket 服务器端 accept()client1 client2 iR t accept() serviceRequest getInputStream read_net_input getOutputStream gp reader.start() write_net_output() reader.run reader.run 48 8.5 Socket client() 客户端 socket tI tSt客户端 getLocalPort() getInputStream getOutputStream write_net_output() writer.start() 服write.run d t i t() 服 务 器read_net_input() 器 paint() close_server() 49 8.7 Datagram  TCP/IP传输层由两个并列的协议:TCP,UDP.  一般套接字(TCP)提供一个可靠的传输模型作 为两个网络端点的字节流,有纠错能力.  UDP没有保持的连接和数据流,数据报是一个 网络上发送的独立信息,它的到达,到达时间,以网络 发送的独 信息,它的到达,到达时间,以 及内容不能得到保证. socketsocket server client datagram iserver client 50 8.7 Datagram  TCP提供高可靠性服务,适用于一次要传输交换 大量报文的情况 信道上传递的包不需要源地址大量报文的情况,信道上传递的包不需要源地址 和目的地址  UDP提供高效率服务,适用于依次传输交换少 量报文的情形 (如数据库查询),每个数据包要包 含目的地址和端口号.  数据报文的使用以包为中心:打包,拆包. 数据报文的使用以包为中 打包,拆包  Java.net包支持两种不同的在网络上送数据的 方法:一般套接字和数据报文套接字方法: 般套接字和数据报文套接字. 51 8.7 Datagram  发出报文的标准步骤如下:  1 定义数据成员 1. 定义数据成员  DatagramSocket socket;  DatagramPacket packet;  InetAddress address;(用来存放接收方的地址)  int port; ;(用来存放接收方的端口号)  2 创建数据报文Socket对象 2. 创建数据报文Socket对象  try {socket=new DatagramSocket(1111);}  catch(java.net.SocketException e) {}  socket 绑定到一个本地的可用端口,等待接收客 户的请求. 52 8.7 Datagram  3.分配并填写数据缓冲区(一个字节类型的数组)  byte[] Buf=new byte[256];  存放从客户端接收的请求信息.存放从客户端接收的请求信息  4.创建一个DatagramPacket  packet=new DatagramPacket(buf 256); packet=new DatagramPacket(buf, 256);  用来从socket接收数据,它只有两个参数  5. 服务器阻塞  socket.receive(packet);(p );  在客户的请求报道来之前一直等待 53 8.7 Datagram  6. 从到来的包中得到地址和端口号  InetAddress address=packet.getAddress();  int port=packet.getPort();p p g ();  7. 将数据送入缓冲区  或来自文件 或键盘输入 或来自文件,或键盘输入  8. 建立报文包,用来从socket上发送信息  packet=new DatagramPacket  (buf,buf.length, address,port);(, g, ,p);  9. 发送数据包 10.关闭socket  socket send(packet); socket close(); socket.send(packet); socket.close(); 54 8.7 Datagram  客户端接收包的步骤如下: 1. 定义数据成员 int port; InetAddress address;p; ; DatagramSocket socket; DatagramPacket packet;DatagramPacket packet; byte[] sendBuf=new byte[256]; 2. 建立socket socket=new DatagramSocket();g (); 55 8.7 Datagram  3. 向服务器发出请求报文  address=InetAddress getByName(args[0]); address=InetAddress.getByName(args[0]);  port=parseInt(args[1]); kt packet=new  DatagramPacket(sendBuf,256,address,port);  socket.send(packet);  这个包本身带有客户端的信息  4. 客户机等待应答  packet=new DatagramPacket(sendBuf 256); packet=new DatagramPacket(sendBuf,256);  socket.receive(packet);(如果没有到就一直等待,因 此实用程序要设置时间限度)此实用程序要设置时间限度) 56 8.7 Datagram 5. 处理接收到的数据 String received=new String(packet.getData(),0);  System.out.println(received);  数据报套接字首先是强调发送方和接收方的区 数据报套接字首先是强调发送方和接收方的区 别,同时也指出服务器和客户之间的不同: 一个客户机必须事先知道服务器的地址和端口 一个客户机必须事先知道服务器的地址和端口, 以便进行出事连接 个服务器从它接收到的数据报文中读取客户 一个服务器从它接收到的数据报文中读取客户 端的地址和端口. 57 8.7 Datagram  .建立数据报socket(); 建立数据报socket 建立一个报文包packet 建立一个请求包 等待请求报文 发出请求 获得对方地址 创建接收包 构成信息包 等待接收构成信息包 发送出去发送出去 58 8.8 小结  实现网络功能要靠URL类, URLConection类, 类和 类Socket类和DatagramSocket类  网络上的数据传送是将网络连接转换成输入输 出流  DataInputStream和DataOutputStream p 和 p (PrintStream)是网间流的载体.  URL适用于web应用 如访问http服务器是高层 URL适用于web应用,如访问http服务器是高层 服务  URLConection的另一边通常是cgi程序 URLConection的另一边通常是cgi程序  cgi程序完成客户端与外部程序的交互 59 8.6 小结  向cgi传送数据有get和post两种方法  cgi通过访问环境变量或读标准输入获得数据  回绕地址可用于在本地机器上调试网络程序回绕地址可用于在本地机器 调试网络程序  Socket适用于面向连接的,可靠性要求高的应用  Datagram适用于效率要求高的应用 Datagram适用于效率要求高的应用  Socket是由IP和端口构成的一种网上通信链路 的端的一端  Socket通信要分别运行服务器和客户程序  服务器程序是多线程的,可处理多个客户的请求 60作业  编写一个会话程序  要求:  会话双方可以自由通话,看到对方发来“bye”则会话双方可以自由通话,看到对方发来 y 则 退出 9.6 一个RMI的分布式应用的实例 北京 大 • 用RMI编写一个分布式应用,核心有以下三方面: • 定位远程对象大 学 计 定位远程对象 – 1. 一个应用可以利用RMI的名字服务功能注册器远程 对象。计 算机 系 对象 – 2. 可以象操作普通对象一样传送并返回一个远程对象 的引用(指针)。系 • 与远程对象通信: – 底层的通信由RMI实现,对于系统开发人员来说,远代亚 非 底层的通信由RMI实现,对于系统开发人员来说,远 程调用和标准的Java方法调用没有什么区别。 • 为需要传递的对象装载类的字节码非 为需要传递的对象装载类的字节码 – RMI允许调用者向远程对象传递一个对象,因此 RMI 提供这种装载对象的机制。 1 提供这种装载对象的机制 9.6 一个RMI的分布式应用的实例 北京 大大 学 计 Web Server Client 计 算机 系 RMIURL protocol 系 Server RMIURL protocol 代亚 非 RMI非 Web Server registry URL protocol 2 9.6 一个RMI的分布式应用的实例 北京 大 一、问题的提出 大 学 计 task 计 算机 系 Remote object Client 系 Compute engin task 代亚 非 ServerClient 非 task 3Client 9.6 一个RMI的分布式应用的实例 北京 大 • 分布特点:大 学 计 – engin开发,先运行,task后定义.写engin时不对执行什么 任务作任何规定.任务可以是任意定制的. 前提条件 计 算机 系 • 前提条件: – 定义任务的类,要规定任务的实现步骤,使得这个任务 能够提交给 去执行 使用 上的 资源 系 能够提交给engin去执行.使用server上的 CPU资源. • 技术支持: 代亚 非 – RMI的动态装载功能. 非 4 9.6 一个RMI的分布式应用的实例 北京 大 远程方法 A.m1() compute engine大 学 计 远程对象 A m1 远程方法 engine Compute Task计 算机 系 远程对象 client server A executeTask execute系 远程对象必须继承远程接口 确定那些方法是远程方法 为此定义远程接口代亚 非 确定那些方法是远程方法,为此定义远程接口 远程接口只负责提供方法名,不一共实现细节,因此必须由一个对 象来实现接口非 象来实现接口 5 9.6 一个RMI的分布式应用的实例 北京 大 • 二、设计一个服务器 • 核心协议:提交任务,执行任务,返回结果大 学 计 核心协议:提交任务,执行任务,返回结果 li 计 算机 系 clientclient 在j 中远程调用是通过定义远程接口来实现的 系 • 在java中远程调用是通过定义远程接口来实现的, 一个接口只能有一个方法 代亚 非 • 不同类型的任务,只要他们实现了Task类型,就可 以在engin上运行.非 • 实现这个接口的类,可以包含任何任务计算需要的 数据以及和任何任务计算需要的方法. 6 数据以及和任何任务计算需要的方法 9.6 一个RMI的分布式应用的实例 北京 大 (1)定义远程接口 • 第一个接口:compute大 学 计 p package compute; import java.rmi.Remote; compute engine计 算机 系 pj ; import java.rmi.RemoteException; public interface Compute extends Remote { Oj () Compute Task系 { Object executeTask(Task t) throws RemoteException;} executeTask execute 代亚 非 package compute; import java io Serializable; 第二个接口:定义一个task类型, 作为参数传给executeTask方法非 import java.io.Serializable; public interface Task extends Serializable 作为参数传给executeTask方法, 规定了engin与它的任务之间的 接口 以及如何启动它的任务 它 7 Serializable { Object execute(); } 接口,以及如何启动它的任务.它 不是一个远程接口 9.6 一个RMI的分布式应用的实例 北京 大 • Compute engin的设计要考虑以下问题: • 1 compute engine是一个类 ComputeEngine 它实现大 学 计 • 1. compute engine是个类ComputeEngine ,它实现 了 Compute接口,只要调用该类的方法executeTask, 任务就能提交上来计 算机 系 任务就能提交上来. • 2. 提交任务的Client 端程序并不知道任务是被下载 到 i 上执行的 因此 li t在定义任务时并不需要系 到engin上执行的.因此client在定义任务时并不需要 包含如何安装的server端的代码. 返回类型是对象 如果结果是基本类型 需要转化代亚 非 • 3. 返回类型是对象,如果结果是基本类型,需要转化 成相应的对等类.非 • 4. 用规定任务如何执行的代码填写execute方法. 8 9.6 一个RMI的分布式应用的实例 北京 大 (2)实现远程接口大 学 计 • 一般说来,实现一个远程接口的类至少有以下步骤: • 1. 声明远程接口计 算机 系 声明远程接 • 2. 为远程对象定义构造函数 • 3 实现远程方法系 • 3. 实现远程方法 engin中创建对象的工作可以在实现远程接口类的 i 函数中实现代亚 非 main函数中实现: • 1. 创建并安装安全管理器非 • 2. 创建一个或更多的远程对象的实例 • 3 至少注册一个远程对象 9 3. 至少注册 个远程对象 9.6 一个RMI的分布式应用的实例 package engine; import java.rmi.*; import java.rmi.server.*; import compute.*; p blic class Comp teEngine e tends UnicastRemoteObject北京 大 public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException 大 学 计 {p p g () p { super(); } public Object executeTask(Task t) 计 算机 系 { return t.execute(); } public static void main(String[] args) 系 { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } 代亚 非 String name = "//host/Compute"; try { Compute engine = new ComputeEngine();非 Naming.rebind(name, engine); System.out.println("ComputeEngine bound"); 10 yp pg } catch (Exception e) { System.err.println("ComputeEngine exception: " + e.getMessage()); e.printStackTrace(); }} 9.6 一个RMI的分布式应用的实例 北京 大 • 在构造函数中,通过super(), a UnicastRemoteObject 被启动 即它可以侦听客户端来的请求输入 大 学 计 被启动,即它可以侦听客户端来的请求输入 • 只有一个远程方法,参数是客户端远程调用这个方法计 算机 系 时传来的任务.这个任务被下载到engin,远程方法的 内容就是调用客户端任务的方法,并把结果回送给调系 用者.实际上这个结果是在客户的任务的方法中体现 的. compute代亚 非 compute engine callexecuteTask(task) 非 Compute TaskcallexecuteTask(task) 11 executeTask execute 9.6 一个RMI的分布式应用的实例 北京 大 • 参数传递规则: • 1. 远程对象通常通过引用传递.一个远程对象的引大 学 计 1. 远程对象通常通过引用传递. 个远程对象的引 用是一个stub,它是客户端的代理.它实现远程对象 中的远程接口的内容计 算机 系 中的远程接口的内容 • 2. 本地对象通过串行化拷贝到目的. 如果不作制 定 对象的所有成员都将被拷贝系 定,对象的所有成员都将被拷贝. 代亚 非非 12 9.6 一个RMI的分布式应用的实例 北京 大 • 通过引用传递一个对象,意味着任何由于远程调 用引起的变化都能反映在原始的对象中 大 学 计 用引起的变化都能反映在原始的对象中。 • 当传递一个远程对象时,只有远程接口是可用的,计 算机 系 而在实现类中定义的方法或者是非远程接口中的 方法,对接收者来说是不可用的系 • 在远程方法调用中,参数,返回值,异常等非对 象是值传送. 这意味着对象的拷贝被传送到接受代亚 非 象是值传送 这意味着对象的拷贝被传送到接受 方。任何在对象上发生的变化不影响原始的对象 • 一旦服务器用rmi注册了,main方法就存在了,非 旦服务器用rmi注册了,main方法就存在了, 不需要一个守护线程工作维护服务器的工作状态, 只要有一个computer engin的引用在另一个虚拟 13 只要有 个computer engin的引用在另 个虚拟 机,computer engin就不会关闭 9.6 一个RMI的分布式应用的实例 北京 大 三、实现一个客户程序大 学 计 • 目标:创建一个任务,并规定如何执行这个任务。 计 算机 系 clientpackage compute; public interface Task extends 系 Pi computePijava.io.Serializable { Object execute(); }代亚 非 } • task不是远程接口 但是需要传递到服务器 因 ExecuteTask()execute() 非 • task不是远程接口,但是需要传递到服务器,因 此用串行化 14 9.6 一个RMI的分布式应用的实例 北京 大 • computePi的作用 装载安全管理器 大 学 计 装载安全管理器 生成一个远程对象 comp Look up(ComputeEngin),获得了stubs计 算机 系 成 个远程对象 p 生成任务对象 Look up(ComputeEngin),获得了stubs Pi task=new Pi()系 调用ComputeEngin的远程方法 获得计算结果 Comp.executeTask(task) 代亚 非非 15 9.6 一个RMI的分布式应用的实例package client; import java.rmi.*; import java.math.*; import compute.*;北京 大 public class ComputePi { public static void main(String args[]) {大 学 计 p(gg){ if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); }计 算机 系 { y y g ( y g ()); } try { String name = "//" + args[0] + "/Compute"; Compute comp = (Compute) Naming.lookup(name);系 pp(p)gp(); Pi task = new Pi(Integer.parseInt(args[1])); BigDecimal pi = (BigDecimal) (comp.executeTask(task));代亚 非 BigDecimal pi (BigDecimal) (comp.executeTask(task)); System.out.println(pi); } catch (Exception e) {非 } catch (Exception e) { System.err.println("ComputePi exception: " + e.getMessage()) e.printStackTrace(); 16 e.printStackTrace(); } } } 9.6 一个RMI的分布式应用的实例 北京 大 • Pi的作用 rmiregistry大 学 计 computepi Compute 实现Task接口 计 算机 系 engin实现execute算法 系 代亚 非非 17 9.6 一个RMI的分布式应用的实例package client; import compute.*; import java.math.*;北京 大 import compute. ; import java.math. ; public class Pi implements Task { i t t ti fi l Bi D i l ZERO 大 学 计 private static final BigDecimal ZERO = BigDecimal.valueOf(0);计 算机 系 private static final BigDecimal ONE = BigDecimal.valueOf(1);系 BigDecimal.valueOf(1); private static final BigDecimal FOUR = Bi D i l l Of(4)代亚 非 BigDecimal.valueOf(4); private static final int roundingMode = 非 BigDecimal.ROUND_HALF_EVEN; public Pi(int digits) 18 public Pi(int digits) { this.digits = digits; } 9.6 一个RMI的分布式应用的实例 北京 大 public Object execute() { return computePi(digits); }大 学 计 *************************************************** * pi/4 = 4*arctan(1/5) - arctan(1/239)计 算机 系 **************************************************** public static BigDecimal computePi(int digits) {系 int scale = digits + 5; BigDecimal arctan1_5 = arctan(5, scale); 代亚 非 BigDecimal arctan1_239 = arctan(239, scale); BigDecimal pi非 arctan1_5.multiply(FOUR).subtract(arctan1_239).multiply(FOUR); return pi.setScale(digits, BigDecimal.ROUND_HALF_UP); 19} 9.6 一个RMI的分布式应用的实例/** * Compute the value, in radians, of the arctangent of 北京 大 * the inverse of the supplied integer to the speficied * number of digits after the decimal point. The value大 学 计 gp * is computed using the power series expansion for the * arctangent:计 算机 系 g * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + * (x^9)/9 ...系 () */ 代亚 非非 20 9.6 一个RMI的分布式应用的实例public static BigDecimal arctan(int inverseX, int scale) { BigDecimal result, numer, term; 北京 大 BigDecimal invX = BigDecimal.valueOf(inverseX); BigDecimal invX2 = Bi D i l l Of(i X * i X) 大 学 计 BigDecimal.valueOf(inverseX * inverseX); numer = ONE.divide(invX, scale, roundingMode); lt i t i 1 计 算机 系 result = numer; int i = 1; do { numer =numer.divide(invX2, scale, roundingMode); intdenom=2*i+1;系 int denom = 2 * i + 1; term = numer.divide(BigDecimal.valueOf(denom), scale, roundingMode);代亚 非 scale, roundingMode); if ((i % 2) != 0) { result = result.subtract(term); } else { result = result.add(term); }非 {();} i++; } while (term.compareTo(ZERO) != 0); 21 p return result; }} 9.6 一个RMI的分布式应用的实例 北京 大 • 由于Rmi的存在,系统可以做到:大 学 计 • 1、可以直接通过名字定位远程方法的位置 • 2、以参数的形式将一个对象传递给一个远程方计 算机 系 、以参数的形式将 个对象传递给 个远程方 法 • 3、可以使一个对象到另外一个虚拟机上运行系 3、可以使 个对象到另外 个虚拟机上运行 • 4、计算结果可以返回 代亚 非非 22 9.6 一个RMI的分布式应用的实例 北京 大 • 将接口,远程对象,客户代码分成三个程序包:大 学 计 • 1. compute ( Compute and Task interfaces) • 2. engine ( ComputeEngine implementation class 计 算机 系 g( p g p and its stub) • 3 client ( ComputePi client code and Pi task系 3. client ( ComputePi client code and Pi task implementation) 代亚 非非 23 9.6 一个RMI的分布式应用的实例 北京 大 • 接口compute对于编程双方都是需要的,通常将接 口文件打成包 分发给 和 的开发者 大 学 计 口文件打成包,分发给server和client的开发者: • 假设接口的开发者将写好的接口程序放在计 算机 系 c:\home\waldo\src\compute目录下 • cd c:\home\waldo\src系 cd c:\home\waldo\src • javac compute\Compute.java j \Tkj代亚 非 • javac compute\Task.java • jar cvf compute.jar compute\*.class非 24 9.6 一个RMI的分布式应用的实例 北京 大 • 类文件必须是网络可访问的,rmi利用URL定位类 文件大 学 计 • 假设 ComputeEngine.java 存放在 c:\home\ann\src\engine计 算机 系 c:\home\ann\src\engine • 假设 compute.jar存放在 \h \ \ bli ht l\ l系 c:\home\ann\public_html\classes. • 设置环境变量 代亚 非 • CLASSPATH=c:\home\ann\src;c:\home\ann\publ ic_html\classes\compute.jar非 _ pj 25 9.6 一个RMI的分布式应用的实例 北京 大 • 编译 ComputeEngine.java,产生一个 stub,并使 stub是网络可访问的. 大 学 计 • 产生stub的命令是rmic,生成的文件形式为: className Stubs.class和className skeleton.class计 算机 系 className_Stubs.class和className_skeleton.class • 命令如下: d \h \ \系 • cd c:\home\ann\src • javac engine\ComputeEngine.java 代亚 非 • rmic -d . engine.ComputeEngine • md c:\home\ann\public html\classes\engine非 md c:\home\ann\public_html\classes\engine • copy engine\ComputeEngine_*.class \h \ \ bli ht l\ l \ i 26 c:\home\ann\public_html\classes\engine 9.6 一个RMI的分布式应用的实例 北京 大 • 展开接口文件大 学 计 • cd c:\home\ann\public_html\classes • jar xvf compute.jar计 算机 系 jpj 系 代亚 非非 27 9.6 一个RMI的分布式应用的实例 北京 大 • 执行程序 • 1 在启动‘compute engine’之前 首先要启动RMI的大 学 计 • 1. 在启动 compute engine 之前, 首先要启动RMI的 registry。 unset CLASSPATH计 算机 系 – unset CLASSPATH – start rmiregistry 2 启动S系 • 2. 启动Server. • 确认compute.jar文件和实现远程对象的类在指定的 路径代亚 非 class路径下 – set CLASSPATH=非 c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar 28 9.6 一个RMI的分布式应用的实例 北京 大 • 启动 compute engine时,要规定服务器端的类在什 么情况下是可用的 启动’ 大 学 计 么情况下是可用的。启动’Compute engine’ – java -Djava.rmi.server.codebase=计 算机 系 file:/c:\home\ann\public_html\classes/ -Djava.rmi.server.hostname=系 zaphod.east.sun.com -Djava.security.policy=java.policy 代亚 非 engine.ComputeEngine 非 • 29 9.6 一个RMI的分布式应用的实例 北京 大 3. 启动 Client 指定类(pi)的位置大 学 计 指定类(pi)的位置 –set CLASSPATH= c:\home\jones\src;计 算机 系 c:\home\jones\src; c:\home\jones\public_html\classes\compute.jar -java -Djava rmi server codebase=系 -java -Djava.rmi.server.codebase= file:/c:\home\jones\public_html\classes/ Djava security policy=java policy代亚 非 -Djava.security.policy=java.policy –client.ComputePi localhost 20 输入完上述命令后 得到结果非 •输入完上述命令后,得到结果 • 3.14159265358979323846 30 9.6 一个RMI的分布式应用的实例 北京 大大 学 计计 算机 系系 代亚 非非 31 9.7 基于CORBA的分布式应用系统的实例 北京 大 windowsNT大 学 计 windowsNT (C++)计 算机 系 Sunclient系 (Java)client 代亚 非 Netscape (COBOL)非 (COBOL) 32 9.7 基于CORBA的分布式应用系统的实例 北京 大 • CORBA技术和Java技术的结合--Java IDL • 什么是IDL?大 学 计 • IDL是CORBA规范中的接口定义语言,不依赖于 任何具体的编程语言.计 算机 系 任何具体的编程语言. • CORBA提供了到各种不同语言的IDL映射. JIDL是CORBA到J 的映射 使J 也支持系 • Java IDL是CORBA到Java的映射,使Java也支持 CORBA规范 和 非常相似 支持代亚 非 • Java IDL和Java RMI非常相似,RMI只支持Java 语言写的分布对象,Java IDL可以和CORBA支持 的任何 种 言编写的 对象进行交 非 的任何一种语言编写的ORB对象进行交互 • Java RMI和Java IDL目前使用的通信协议不同, 33分别是JRMP和IIOP. 9.7 基于CORBA的分布式应用系统的实例 北京 大 • 在Java IDL中,客户端通过引用与远程的对象进行 交互 即客户机使用 对远程服务器上的对象 大 学 计 交互,即客户机使用stubs对远程服务器上的对象 进行操作,但并不拷贝服务器上的对象.计 算机 系 • Java RMI即可以通过引用,也可以将对象下载到 本地机上运行(因为有串行化功能).系 • Java实现简单,但语言不兼容 • Java IDL则可以充分发挥语言无关的优势代亚 非 Java IDL则可以充分发挥语言无关的优势 非 34 9.7 基于CORBA的分布式应用系统的实例 北京 大 • IDL Java的技术组成: – IDL至Java的编译器:idltojava大 学 计 IDL至Java的编译器:idltojava – 生成客户端的stubs和服务器端的skeleton – CORBA API 和 ORB计 算机 系 CORBA API 和 ORB – 一个简单的名字服务 系 代亚 非非 35 9.7 基于CORBA的分布式应用系统的实例 北京 大大 学 计 客户应用计 算机 系 IDL Stub C++, Java编译器 客户程序 应 用 系 IDL接口 IDL编译器 (C++, Java) 用 开 发 者代亚 非 服务程序 Skeleton C++, Java编译器 者 非 服务程序 对象实现 , 编译器 36 9.7 基于CORBA的分布式应用系统的实例 北京 大大 学 计 从反应式Agent的角度看 计 算机 系 对象实现应用开发者 事件处理部分 系 IDL SkeletonIDL文件 IDL编译器 事件处理分发部分 代亚 非 ORB内核 BOA 事件感知部分 事件适配部分 非 ORB内核 事件感知部分 37 9.7 基于CORBA的分布式应用系统的实例 北京 大 • CORBA编程实例 • 运行在浏览器中的客户对象与远程的服务对象交大 学 计 • 运行在浏览器中的客户对象与远程的服务对象交 互,客户端的表现是在浏览器中点击一个button, 就会在一个文本域中返回服务端的时间 同时也计 算机 系 就会在 个文本域中返回服务端的时间,同时也 在服务端的标准输出上打印该时间。 系 The data in id i 时间是一个对象 代亚 非 server side is 2000.6.1 12:56:00 server非 button 38 9.7 基于CORBA的分布式应用系统的实例 北京 大大 学 计 CLIENT SERVER OBJECT REFERENCE SERVANT 计 算机 系 CLIENT STUBS SKELETONS SERVER IIOP 系 ORB ORB IIOP 代亚 非 METHOD REQUEST 非 39 9.7 基于CORBA的分布式应用系统的实例 1 首先是定义交互接口 在文件d t it idl中北京 大 1. 首先是定义交互接口,在文件dateit.idl中。 – module TheDate (相当于包)大 学 计 – { interface DateIt – { string dateit(); };计 算机 系 – }; 2. 用IDL接口到Java语言的映射系 – jidl dateit.idl 该命令会生成几个相关的java文件: – DateIt.java代亚 非 j – DateItHelper.java – DateItHolder.java非 j – _DateItImplBase.java – StubForDateIt.java 40 j 9.7 基于CORBA的分布式应用系统的实例 北京 大 3. 编写服务对象的程序,在文件DateIt_impl.java中 package TheDate; // jidl 产生的Java文件放在TheDate包中大 学 计 import org.omg.CORBA.*; import java.io.*; import java.awt.*;import java.util.Date;计 算机 系 import java.lang.System; public class DateIt_impl extends _DateItImplBase系 //扩展了 jidl 生成的抽象类_DateItImplBase { String date_time;代亚 非 {g_; public String dateit() { date time=(new Date()).toString(); //获取时间非 { _ ( ()) g(); 获取时 System.out.println(date_time); return date time;// 向客户端返回时间串 41 _ ; 向客户端返回时间串 } } 9.7 基于CORBA的分布式应用系统的实例 北京 大 4. 编写服务方的程序,在文件Server.java中。 package TheDate; 大 学 计 import org.omg.CORBA.*;import java.io.*; public class Server 计 算机 系 { public static void main(String args[]) {try {系 // 创建ORB和BOA对象实例 ORB orb = ORB.init(args, new java.util.Properties());代亚 非 ( g , j p ()); // 生成服务对象实例 BOA boa = orb.BOA init(args);非 _ (g); DateIt_impl p = new DateIt_impl(); //创建服务对象实 例 42 9.7 基于CORBA的分布式应用系统的实例 北京 大 // 保存引用 try { String ref = orb.object_to_string(p); 大 学 计 //将对象编码成字符串 String refFile = "date.ref"; 计 算机 系 FileOutputStream file = new FileOutputStream(refFile); PrintStream out = new PrintStream(file);系 () out.println(ref); //存入文件date.ref中 out.flush(); file.close(); 代亚 非 (); (); }catch(IOException ex) { System.err.println("Can't write to" +ex.getMessage());非 { y p ( g g ()); System.exit(1); } 43 } 9.7 基于CORBA的分布式应用系统的实例 北京 大 //将引用存入html文件中,参见后面列出的date.html 文大 学 计 try { String ref = orb.object_to_string(p); String refFile = "c:\\Inetpub\\wwwroot\\Docs\\date.html";计 算机 系 FileOutputStream file = new FileOutputStream(refFile); PrintStream out = new PrintStream(file);系 out.println("");非 44 9.7 基于CORBA的分布式应用系统的实例//指由Client.java编译成的class文件 out.println(""); 北京 大 //将由服务对象转化成的字符串存入超文本文件中 out.println(""); out.println("");计 算机 系 name=org.omg.CORBA.ORBSingletonClass " + "value out.println("");系 out.flush(); file.close(); //这样浏览器调入该超文本页面时,会运行Client.class的 并将包含标识服务对象的字符串由参数 传递给代亚 非 applet,并将包含标识服务对象的字符串由参数ior传递给 applet。 }th(IOEti){ 非 } catch(IOException ex) { System.err.println(“Can't write to ”+ex.getMessage()+“”); Si(1)} 45 System.exit(1); } 9.7 基于CORBA的分布式应用系统的实例 北京 大 // 服务对象就绪,准备接受请大 学 计 boa.impl_is_ready(null); System.exit(0);计 算机 系 } catch(SystemException ex) { System.err.println(ex.getMessage());系 ex.printStackTrace(); System.exit(1); 代亚 非 } }非 } 46 9.7 基于CORBA的分布式应用系统的实例 北京 大 • 5. 编写客户方的程序,在文件Client.java中。大 学 计 package TheDate;//由于jidl产生的JAVA文件放在package TheDate中,因此该语句是必须的计 算机 系 import org.omg.CORBA.*; import java.io.*;系 import java.awt.*; import java.util.Date; 代亚 非 import java.lang.System; 非 47 9.6 各种主流技术的主要开发过程--CORBA 北京 大 public class Client extends java.applet.Applet { private DateIt serverdate;大 学 计 {p ; private Button button; private TextField outdate;计 算机 系 p vate e t e d outdate; public void init()系 public void init() { String ior = getParameter("ior"); //Applet 只能从包含它的HTML文件获取IOR串 见Server java代亚 非 //Applet 只能从包含它的HTML文件获取IOR串 见Server.java. // 产生ORB实例 ORB orb = ORB init(this null);非 ORB orb ORB.init(this, null); // Create client object org omg CORBA Object obj = orb string to object(ior); 48 org.omg.CORBA.Object obj = orb.string_to_object(ior); 9.6 各种主流技术的主要开发过程--CORBA 北京 大 //串到对象的转化大 学 计 if(obj == null) throw new RuntimeException(); serverdate = DateItHelper.narrow(obj); 产生对象实例 其实是服务对象的映射 计 算机 系 //产生对象实例,其实是服务对象的映射 // 添加serverdate按钮和文字域系 button = new Button("Dateis"); outdate = new TextField("",30); 代亚 非 this.add(button); this.add(outdate);非 } 49 9.6 各种主流技术的主要开发过程--CORBA 北京 大 // 事件处理大 学 计 // public boolean action(Event event, java.lang.Object arg) { if(event.target == button)计 算机 系 { outdate.setText("please wait..."); outdate.setText(serverdate.dateit());系 //调用服务对象的函数,返回服务端的时间 return true; 代亚 非 } else非 return super.action(event, arg); } 50 }

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档

相关文档