【填空题】
public class Reverse {
//throws Exception表示本方法内所有可能发生的异常都声明抛出给系统
public static void main(String[] args) throws Exception {
Scanner input1= new Scanner(____);
//创建URL,用于连接本地机运行的一个Web应用程序
URL web = new ____("http://localhost:8080/ServerWeb/ReverseServlet");
URLConnection con = ____.openConnection();
con.setDoOutput(true);//允许连接进行输出操作
//通过URLConnection对象获取网络输出流,用于向URL所代表的Web服务器发送数据
OutputStreamWriter out = new OutputStreamWriter(____.getOutputStream());
//输出“string=”和键盘输入的字符串
____.write("string=" + input1.nextLine());
out.close();
//通过URLConnection对象获取网络输入流,用于接收Web服务器返回的数据
BufferedReader input = new BufferedReader(new InputStreamReader(____.getInputStream()));
String decodedString;
//每次接收一行字符串
while ((decodedString = ____.readLine()) != null) {
System.out.println(decodedString);
}
input1.close();
input.close();
}
}
正确答案:
第一空:
System.in
第二空:
URL
第三空:
web
第四空:
con
第五空:
out
第六空:
con
第七空:
input
基于TCP协议的网络编程可以实现C/S结构的程序,C客户端发送数据,S服务器端接收数据后发回给客户端,客户端接收后输出到屏幕。客户端通过创建Socket连接服务器,服务器端监听到连接后,也创建Socket,两端的Socket连在一起,形成一个输入输出流,客户端发送消息,用输出流,服务器端接收消息用输入流,反之亦然。
客户端代码tcp. EchoClient
知识点
思路
运行时,先运行服务器端,再运行客户端,在客户端输入数据,发送给服务器,服务器接收后再返回给客户端,客户端接收后打印到屏幕。
客户端界面:
服务器端界面:
该例子可以实现多个客户端的聊天室功能,即任何一个客户端发送消息给服务器,服务器会转发给所有与它连接的客户端。因为服务器要维护与多个客户端的连接,这里用线程实现,每个客户端和服务器端连接后,服务器端都会开启一个线程,用于接收当前这个客户端的消息,并转发给所有的客户端。
该例子由3个Java类实现,客户端:tcp. EchoMultiClient,服务器端:tcp. EchoMultiServer,tcp.EchoServerThread(服务器端使用的线程类)。
客户端类,该客户端发送消息和接收消息分别在一个线程中进行:
服务器端代码,该代码中每监听到客户端的一个连接,就调用线程类创建并启动一个线程对象。
服务器端代码:
服务器端使用的线程类代码:
该程序运行时,先启动服务器端代码,再多次启动客户端。
例如以下运行效果,启动了服务器端后,启动了3次客户端,3个客户端分别发送消息,效果如下:
服务器端的输出:
客户端1的输出:
客户端2的输出:
客户端3的输出:
练习
//基于TCP协议编程的服务器端
package 填空题.tcp;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
//服务器端,IP地址是10.5.1.5
public class EchoServer {
public static void main(String[] args) throws Exception {
// 创建服务器端套接字,打开端口,用于监听来自客户端的连接请求
ServerSocket serverSocket = new ____(4450);
// 监听客户端的连接请求,如果监听到连接,则返回一个新的套接字
Socket server = ____.accept();
// 用新的套接字打开输出流
PrintWriter output = new PrintWriter(____.getOutputStream(), true);
// 用新套接字打开输入流
BufferedReader input = new BufferedReader(new InputStreamReader(____.getInputStream()));
String inputLine;
while ((inputLine = ____.readLine()) != null) {// 从输入流接收客户端传过来的数据
// 输出客户端的数据到控制台屏幕
____.println("来自客户端: " + inputLine);
// 发送数据回客户端
____.println(inputLine);
} } }
//基于TCP协议编程的客户端
package 填空题.tcp;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
//单客户端,在应用中后运行
public class EchoClient {
public static void main(String[] args) throws Exception {
// 客户端通过创建Socket,连接服务器
Socket client = new Socket("____", ____);
// 通过该Socket获取输入输出流和服务器端通信
PrintWriter out = new PrintWriter(____.getOutputStream(), true);
BufferedReader input1 = new BufferedReader(new InputStreamReader(____.getInputStream()));
//创建输入流用于键盘输入
BufferedReader input2 = new BufferedReader(new InputStreamReader(____));
String userInput;
// 接收键盘传过来的数据
while ((userInput = ____.readLine()) != null) {// 按ctrl+z结束键盘输入
// 向服务器发送消息
____.println(userInput);
// 接收服务器发过来的消息,并输出到屏幕
System.out.println("echo: " + ____.readLine());
} } }
正确答案:
第一空:
ServerSocket
第二空:
serverSocket
第三空:
server
第四空:
server
第五空:
input
第六空:
System.out
第七空:
output
第八空:
10.5.1.5
第九空:
4450
第十空:
client
第十一空:
client
第十二空:
System.in
第十三空:
input2
第十四空:
out
第十五空:
input1
基于UDP协议的网络编程通信原理和TCP协议不同,基于TCP协议的通信是客户端和服务器端建立连接管道,这个管道就像一个输出输出流,发送消息使用输出流,接收消息使用输入流;基于UDP协议的通信不建立连接,一端向另一端发送消息需要创建数据报,数据报中包含目标地址和要发送的内容。
该例实现了客户端向服务器端发送消息,服务器端收到后,提取出内容和客户端的地址,把消息再发回给客户端。
客户端代码,udp. EchoClient:
思路
注意:
发送的数据报需要四个参数:字节数组,字节数组大小,InetAddress对象的IP地址,数据报的端口号
接收的数据报需要二个参数:字节数组及其长度大小
从以上代码可以看出,客户端和服务器端发送和接收消息的原理类似,区别只是服务器端绑定了固定的端口号,而客户端不用绑定固定端口号。
先运行服务器端代码,再运行客户端代码,效果如下:
服务器端:
客户端:
基于UDP协议,可以发送广播数据报,即发送一个数据报出去,目标地址是多台主机。接收广播数据报需要使用MulticastSocket类。
该例的客户端实现了两个线程,一个线程使用DatagramSocket发送数据报给服务器;另一个线程使用MulticastSocket绑定固定端口4446,加入广播地址230.0.0.1,接收来自服务器的广播数据。
该例的服务器端接收到客户端的数据报后,把内容封装成广播数据报,广播地址是230.0.0.1,把广播数据报发送出去。该例的客户端可以接收到。
客户端代码,udp. BroadcastClient:
服务器端代码,udp. BroadcastServer:
该例运行时,先启动服务器端,再启动客户端。
服务器端:
客户端:
练习
//基于UDP协议的网络编程
//服务器端代码
package 填空题.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
//基于UDP通信的服务器端,假定服务器端的IP地址是10.3.35.10,绑定端口4455
//循环实现先接收一个数据报,再键盘输入一行字符串发送回去
public class UdpServer {
public static void main(String[] args) {
DatagramSocket server = null;
Scanner scanner=null;
try {
//创建一个DatagramSocket对象
server = new ____(____);
scanner=new Scanner(System.in);
while (true) {
byte[] buf = new byte[256];
// 创建用于接收数据的空数据报
DatagramPacket p = new DatagramPacket(____,
buf.length);
____.receive(____);//用套接字接收数据包
//获取发送数据报的客户端的地址
InetAddress clientAddress = p.getAddress();
//获取发送数据报的客户端的端口号
int clientPort = ____.getPort();
System.out.println(
new String(p.getData()).trim()
+ " 来自:" + clientAddress.getHostAddress()
+ ":" + clientPort);
byte[] buf2=scanner.nextLine().getBytes();
// 创建要发送的数据报(包含发送的数据,客户端地址和端口号),发送回客户端
DatagramPacket p2 = new ____(buf2, buf2.length,
clientAddress, clientPort);
____.send(____);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(server!=null)server.close();
if(scanner!=null)scanner.close();
}
}
}
//客户端代码
package 填空题.udp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
//基于UDP协议的网络通信客户端,循环实现先发送一个数据报到服务器,再接收一个数据报
public class UdpClient {
public static void main(String[] args) {
DatagramSocket client = null;
String sendStr;
try {
// 创建一个DatagramSocket,使用系统提供的端口
client = new DatagramSocket();
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
// 通过键盘输入字符串,如果结束循环输入ctrl+z
while ((sendStr = ____.readLine()) != null) {
// 把键盘输入的字符串转成字节数组
byte[] buf = ____.getBytes();
// 把表示服务器端IP地址的字符串转换成InetAddress对象
InetAddress address = InetAddress.getByName("____");
// 使用要发送的字节数组,目标IP地址和端口号,构造数据报
DatagramPacket packet = new DatagramPacket(buf, buf.length, ____, ____);
// 使用DatagramSocket对象发送数据报
____.send(____);
byte[] buf1 = new byte[256];
// 使用空字节数组构造空数据报
packet = new DatagramPacket(buf1, buf1.length);
// 使用DatagramSocket对象接收数据到空数据报中
____.receive(packet);
// 根据数据报的数据和长度构造字符串
String received = new String(packet.getData(), 0, packet.getLength());
// 显示接收到的字符串和远端的IP地址和端口号,trim方法表示删除字符串前后的空格
System.out.println("接收到的信息: " + received.trim() + " 来自" + packet.getAddress().getHostAddress() + ":"+ packet.getPort());
}
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (client != null)
client.close();
}
}
}
正确答案:
第一空:
DatagramSocket
第二空:
4455
第三空:
buf
第四空:
server
第五空:
p
第六空:
p
第七空:
DatagramPacket
第八空:
server
第九空:
p2
第十空:
stdIn
第十一空:
sendStr
第十二空:
10.3.35.10
第十三空:
address
第十四空:
4455
第十五空:
client
第十六空:
packet
第十七空:
client
小结
了解基于TCP/IP四层网络体系结构的网络通信原理
掌握使用URL进行网络编程的方法
掌握基于TCP协议的网络编程用到的类Socket和ServerSocket及编程方法
掌握基于UDP协议的网络编程用到的类DatagramSocket、DatagramPacket、MulticastSocket及编程方法
熟读并能注释和编写本章所有案例
RefEx类中使用反射的方法获取了String类型的修饰符、泛型参数、父类、实现的接口、类的注解、构造方法、属性、方法等定义String类的各种信息。
同学们可修改代码,查看其它类的各种定义信息。例如,要查看System类的各种定义信息,要如何改代码?
运行结果:
该Test类是一个反射技术的综合应用,该类中使用反射技术访问了“类.Student”类,包含了如何获取Student类的Class实例;获取Student类中指定的某个属性,给属性赋值,获取属性的值;获取Student类中某个指定的方法,调用方法并输出方法的返回值;获取Student类中某个指定的构造方法,并调用构造方法创建类对象等。
Student类代码如下:
Test类代码如下:
运行结果:
xiaolin
null
Student [name=xiaohong, age=21]
Student [name=Mary, age=20]
其中第1行输出的是name属性的值
第2行输出的是setName方法的返回值,该方法没有返回值,所以输出null
第3行输出的是用第一种方法创建的Student对象的toString方法的值
第4行输出的是用第二种方法创建的Student对象的toString方法的值
反射重点掌握Class、Field、Method、Constructor等类在反射中的使用
练习
反射编程。已知以下类Student,在Test类中用反射技术操作该类,创建对象,访问属性,调用方法和构造方法。
//Student类
package 填空题.reflect;
public class Student {
// Field(别名:属性,成员变量,数据成员,字段)
private String name;
// Constructor(别名:构造方法,构造函数)
public Student(String name) {
super();
this.name = name;
}
public Student() {
super();
}
// Method(别名:方法,成员方法,成员函数)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName() {
this.name = "zhangsan";
}
// 继承的方法
@Override
public String toString() {
return "Student [name=" + name + "]";
}
}
//Test类
package 填空题.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) throws Exception {
// 获取Student类的Class实例
Class c = Class.forName("____");
// 第一种用反射创建类对象的方法,相当于调用类的无参数构造方法
Object obj = ____.newInstance();
// 使用反射访问类对象obj的name属性,并赋值为“tom”
// 根据Field名,获得Field对象
Field field = ____.getDeclaredField("name");
field.setAccessible(true);
field.set(____, "tom");
// 用反射获取obj的name属性的值,并输出到屏幕
System.out.println(____.get(obj));
// 使用反射获取Student类对象obj的名为setName的一个参数的方法,并调用该方法,参数是“mary”
Method method = ____.getDeclaredMethod("setName", ____);
____.invoke(____, "mary");
// 使用反射获取Student类对象obj的名为toString的方法,并调用该方法,输出方法调用的返回值
Method methoda = c.getDeclaredMethod("toString");
Object vObject = methoda.invoke(____);
System.out.println(____);
// 使用反射获取Student类有1个参数的构造方法。
Constructor constructor = c.getDeclaredConstructor(____);
// 调用该构造方法,实参是“linda”,创建了Student类对象stu
Object stu = ____.newInstance("linda");
// 使用反射输出stu对象的toString方法调用的返回值
System.out.println(methoda.invoke(____));
}
}
正确答案:
第一空:
填空题.reflect.Student
第二空:
c
第三空:
c
第四空:
obj
第五空:
field
第六空:
c
第七空:
String.class;Class.forName("java.lang.String")
第八空:
method
第九空:
obj
第十空:
obj
第十一空:
vObject
第十二空:
String.class;Class.forName("java.lang.String")
第十三空:
constructor
第十四空:
stu
小结
掌握为什么用反射
在运行中才知道类名,也能创建这个类对象,访问类对象的成员!
反射是实现框架的基础
掌握Class、Field、Method、Constructor等类在反射中的使用(重点通过案例test.Test分析以上4者的使用)
该案例包含3个文件,一个是注解的定义文件(注解.MyAnnotation),一个是使用注解的类(使用注解的类.UseMyAnnotation),一个是解析注解的类(解析注解的类. ParseMyAnnotation)。通过该例子,请大家掌握定义注解的方法,使用注解的方法,解析一个类中使用的注解的方法。
1、注解.MyAnnotation,掌握如何定义注解,各个元注解是什么意思?
2、使用注解的类.UseMyAnnotation,掌握使用注解的语法格式
3、解析注解的类. ParseMyAnnotation,掌握如何获取类前、属性前、方法前的注解,掌握如何获取注解元素的值。注意,解析注解需要用到反射技术。
运行解析注解的类,输出类前注解元素的值,属性前注解元素的值,并判断方法前注解元素的值如果是“xiaolin”,则调用方法:
练习
反射和注解。下列代码实现了自定义一个运行时方法注解,注解名为A,该注解有一个元素value,int型,默认值为1。在Book类的print方法前使用了注解A,注解元素使用默认值,在Test类中获取Book类所有方法前的A注解,判断注解元素的值是否为1,若为1,则调用该方法。
//自定义的注解
package 反射与注解;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target( ____ )
public @interface ____ {
int ____ default 1;
}
//Book类
package 反射与注解;
public class Book {
private String name;
public Book() {
name = "Java高级应用编程";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
____
public void print() {
System.out.print(name);
}
}
//Test类
package 反射与注解;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception{
Class c = Class.forName( ____ );
Method[] ms = ____.getDeclaredMethods();
for (Method m : ms) {
A a = m.getAnnotation(____ );
if (a != null &&____.value()==1) {
____.invoke(____.newInstance());
} } }
}
正确答案:
第一空:
METHOD;{METHOD};value={METHOD}
第二空:
A
第三空:
value()
第四空:
@A
第五空:
"反射与注解.Book"
第六空:
c
第七空:
A.class
第八空:
a
第九空:
m
第十空:
c
小结
了解什么是注解,注解有什么用
掌握5中元注解,理解每种元注解的定义文档
掌握自定义注解的方法(重点掌握)
了解几种常见预定义注解的功能
掌握定义重复注解的方法
掌握编程解析运行时注解的方法(重点掌握,要结合案例代码去理解,会编码)
编程步骤
Test类是可执行类,该类中调用DB类的静态方法实现查询或修改数据库。DB类中封装了对数据库操作的全流程代码。后面的2.3节会详细介绍JDBC访问数据库的流程及关键代码。
dao.DB类中封装了两个静态方法,每个静态方法都包含了JDBC访问数据库的全流程,一个方法执行查询数据库的操作,一个方法执行更新(增删改)数据库的操作。
Test类的运行结果:
bean.Student类是一个表示学生信息的抽象类,一个对象和数据库中的表的一行信息对应。
dao.StuDao类是访问数据库的类,实现数据库的连接、增、删、改、查、关闭。该例中使用PreparedStatement对象执行SQL语句。
test.Test3类是测试类,用于测试StuDao类的功能。
运行Test3类查看结果。
bean.Student类:
dao.StuDao类:
test.Test3类:
//该代码访问安装在10.5.1.5这台机器上的MySQL数据库,数据库名为stu,表名为student,表包含3个字段(id 整型,主键,数据库自增赋值;name 字符串;age 整型)。
public class Ex3 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection c = DriverManager.getConnection("jdbc:mysql://____:3306/____?" + "useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8",
"test", "test");
Statement st = ____.createStatement();
ResultSet r = ____.executeQuery("select * from ____ ");
while (____.next()) {
System.out.println(r.getInt(1) + "\t" + ____.getString(2) + "\t" + r.getInt(3));
}
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b= sc.nextInt();
//创建PreparedStatement对象,把id为b变量值那行的age的值改为a变量的值
PreparedStatement pt=____.prepareStatement(
"update ____ set age=? where id=?");
pt.setInt(1, ____);
pt.setInt(2,____);
____.executeUpdate();
sc.close(); pt.close(); pt=null;
r.close(); r = null;
st.close(); st = null;
c.close(); c = null;
}
正确答案:
第一空:
10.5.1.5
第二空:
stu
第三空:
c
第四空:
st
第五空:
student
第六空:
r
第七空:
r
第八空:
c
第九空:
student
第十空:
a
第十一空:
b
第十二空:
pt
练习2
在Microsoft SQL Server数据库的students数据库中创建一个表,表名为tstudent,其中包含3个字段(id 整型,主键,数据库自增赋值;name 字符串;age 整型),SQL Server数据库安装在IP地址为10.5.1.2的机器上,端口号是1433,提供了用户名Mary和密码111111供编程者使用。以下代码访问的数据库和数据表都是students库中的tstudent表。使用PreparedStatement对象执行插入操作,向tstudent表中插入3条记录。其中数据的值是通过键盘输入的。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
public class Ex1 {
public static void main(String[] args) throws Exception {
String driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver";
Class.forName(____);
// 连接数据库
Connection con = DriverManager.getConnection(
"jdbc:sqlserver://____:1433; databaseName= ____;", "Mary", "____");
//创建PrepareStatement执行插入操作
PreparedStatement ptmst=____.prepareStatement("INSERT INTO ____ (name,age) VALUES (?,?)");
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < ____ ; i++) {
String name = scanner.next();
int age = scanner.nextInt();
ptmst.setString(1, ____ );
ptmst.setInt(____ , age );
____ .executeUpdate();
}
ptmst.close(); ptmst=null;
con.close(); con = null;
scanner.close();
}}
正确答案:
第一空:
driverClass
第二空:
10.5.1.2
第三空:
students
第四空:
111111
第五空:
con
第六空:
tstudent
第七空:
3
第八空:
name
第九空:
2
第十空:
ptmst
小结:
掌握什么是JDBC
掌握使用JDBC编程访问数据库
1、对不同的数据库,如何连接?
2、执行增删改查的SQL语句,用Statement对象和PrepareedStatement对象的区别?
3、ResultSet是什么?如何使用?
1.Java:字节流和字符流(输入流和输出流)
2.线程创建的三种方式
3.线程创建的四种方式
4.网络编程TCP UDP URL参考资料网址
5.反射学习网址
6.注解学习网址
7.JDBC参考资料网址