匿名内部类
Person类
package day14.AnnonymouseClass;
public class Person {
public String name;
public int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void say() {
System.out.println(this.name);
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
chinese类基础于Person类
package day14.AnnonymouseClass;
public class Chinese extends Person{
@Override
public void say() {
System.out.println("我是中国人"+this.name);
}
}
匿名内部类demo
package day14.AnnonymouseClass;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
//普通类的匿名内部类,不用建一个类文件,可以直接在类体内部写
public class AnnonymouseClass {
public static void main(String[] args) {
Person person = new Person();
person.name = "人";
Chinese chinese = new Chinese();
chinese.name = "铁蛋";
Person p = new Person() {
}; // Person的子类,匿名。。//多态:父类的变量来引用子类的对象
Person p2 = new Person() {
public void say() {
System.out.println("我是美国人:" + this.name);
}
};
p2.name = "Tom";
person.say();
chinese.say();
p2.say();
/**
* 对接口使用匿名内部类
*/
Person person2 = new Person("zhang", 18);
Person person3 = new Person("li", 20);
// 对list中的对象按照某个属性进行排序
ArrayList<Person> list = new ArrayList<>();
list.add(person2);
list.add(person3);
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
if (p1.getAge() < p2.getAge()) {
return 1;
}
return -1;
}
});
for (Person pp : list) {
System.out.println(pp);
}
}
}
反射的基本用法以及配置文件的应用
接口类:
package day14.reflectAndProxy;
public interface LoginService {
public void say();
public void say(String name);
public void eat();
public String speak(String name);
}
实现类:
package day14.reflectAndProxy;
public class LoginServiceImpl implements LoginService {
public void say() {
System.out.println("你好:");
}
public void say(String name) {
System.out.println("你好:" + name);
}
public void eat() {
System.out.println("吃饭了");
}
public String speak(String name) {
return "hello" + name;
}
}
配置文件内容:
文件名:xx.properties
内容:
type=day14.reflectAndProxy.LoginServiceImpl
func=say
paramType=java.lang.String
反射的用法:
package day14.reflectAndProxy;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
//普通的调用
// LoginServiceImpl impl = new LoginServiceImpl();
//
// impl.say();
// impl.say("zhang");
// impl.eat();
//
// String speak = impl.speak("lisi");
// System.out.println(speak.toUpperCase());//变为大写
/*
* 反射的方式构造对象,调用方法
*
*/
// String type = "day14.reflect.LoginServiceImpl";
// String func = "say";
// String paramType = "java.lang.String";
//通过加载配制文件来获取要调用的类名、方法以及参数
Properties props = new Properties();
// props.load(new FileInputStream("D:/"))从绝对路径加载
// 从工程的类的相对路径中加载
props.load(ReflectDemo.class.getClassLoader().getResourceAsStream("xx.properties"));
String type = props.getProperty("type");
String func = props.getProperty("func");
String paramType = props.getProperty("paramType");
//通过类名和方法、方法参数类型,来反射的构造的方法构造对象,并调用方法
// 类本身是一个java文件,在运行的时候会变成一个Class文件
// 所以我们可以根据类名拿到一个类的Class
Class<?> forName = Class.forName(type);// class
Object instance = forName.newInstance();// 用class调用它的构造方法,产生一个LoginServiceImpl的对象----------class.newInstance()得到一个类的对象
Method method = forName.getMethod(func, Class.forName(paramType));// 类名,,,参数类类名的Class----class.getMethod()得到一个类的方法(类名,参数类的class)
method.invoke(instance, "哈哈哈");// 调用方法是在对象上调用,参数-------------方法调用--对象---参数
}
}
动态代理
根据一个或者多个接口,用jdk的Proxy框架构造出一个“动态代理类”的对象(动态代理对象)
那么,这个动态代理对象上就具备那些接口上的方法
只不过,这些方法的具体逻辑,是定义在InvocationHandler实现类的invoke()方法中;
接口类
package day14.reflectAndProxy;
public interface LoginService {
public void say();
public void say(String name);
public void eat();
public String speak(String name);
}
接口实现类
package day14.reflectAndProxy;
public class LoginServiceImpl implements LoginService {
public void say() {
System.out.println("你好:");
}
public void say(String name) {
System.out.println("你好:" + name);
}
public void eat() {
System.out.println("吃饭了");
}
public String speak(String name) {
return "hello" + name;
}
}
动态代理类
package day14.reflectAndProxy;
/*
* 动态代理就是在已知接口上 可以自己让接口中的方法做什么,类似于实现接口,方法都封装在了InvocationHandler()接口的实现类中
*
*/
import java.lang.reflect.Proxy;
public class ProxyDemo {
public static void main(String[] args) {
//构造一个LoginService接口的动态代理对象,,该方法是在jdk中定义的。注意参数前两个都和代理的接口有关,第三个参数是处理逻辑的类的对象,该类需要实现InvocationHandler接口
LoginService o = (LoginService) Proxy.newProxyInstance(LoginService.class.getClassLoader(), new Class<?>[] {LoginService.class},new MyInvocationHandler());
o.eat();
String speak = o.speak("haha");//传参到动态代理的实现类中然后在方法中调用接口的实现类的方法
System.out.println(speak);
o.say();
o.say("我是参数");
}
}
动态代理逻辑封装类–接口InvocationHandler的实现类MyInvocationHandler
package day14.reflectAndProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断调用的是哪个方法
if(method.getName().equals("eat")) {
System.out.println("我一点也不喜欢吃");//调用该方法所做的事,可以自己定义
}
if(method.getName().equals("speak")) {
String speak = new LoginServiceImpl().speak((String)args[0]); //在此也可调用接口实现类的方法
return speak;
}
if(method.getName().equals("say")) {//判断方法名
if(method.getParameters().length>0) {//判断是否有参数
System.out.println("你调用的是say():"+args[0]);
}else {
System.out.println("你调用的是say(),没有参数");
}
}
return null;
}
}
动态代理封装RPC框架
核心思想:给客户端一个动态代理对象,客户就以为拿到了服务端的一个实现类的对象,就愉快地凋起了方法,他还以为真的在他的机器上调到了这个方法
而本质上,他的调用行为被我们提供的动态代理对象上的invoke所拦截,在invoke中向远程服务器进行了通信交互,拿到结果,再返回给用户
客户端用的是day13.fin中的客户端
先是保存数据:
package day13.find;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class SaveData {
public static void main(String[] args) throws Exception {
Product p0 = new Product(0, "苹果", 10.5f);
Product p1 = new Product(1, "泰国榴莲", 16.5f);
Product p2 = new Product(2, "菠萝", 20.5f);
Product p3 = new Product(3, "菠萝蜜", 30.5f);
Product p4 = new Product(4, "香蕉", 19.5f);
save(p0);
save(p1);
save(p2);
save(p3);
save(p4);
}
public static void save(Product p) throws Exception {
// 将数据按照既定的规则存入文件中
// id占4个字节,name占20字节,price占4个字节
DataOutputStream dout = new DataOutputStream(new FileOutputStream("d:/p.dat",true));
dout.writeInt(p.getId()); //写入id
byte[] bytes = p.getName().getBytes("GBK");
byte[] b = new byte[20];
// jdk提供的数组拷贝工具方法: 参数1:源数据数组 参数2:从源数组的第几个位置开始拷贝
// 参数3 :目标数组 参数4:目标数组中放数据的起始位置 参数5:拷贝的长度
System.arraycopy(bytes, 0, b, 0, bytes.length);
dout.write(b); // 将商品名写入文件,占20个字节
dout.writeFloat(p.getPrice()); //将价格按照float数写入文件,占4个字节
dout.close();
}
}
读取数据类:
package day13.find;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
public class ReadData {
/**
* 根据id查找商品
*
* @param id
* @return
* @throws Exception
*/
public Product findProductById(int id) throws Exception {
// 可以从文件中任何位置开始读数据的工具:RandomAccessFile
RandomAccessFile raf = new RandomAccessFile("d:/p.dat", "r");
// 读id为2的那个商品的数据
long pos = id * 28;
// 让raf的读取位置跳到指定的pos位置
raf.seek(pos);
// 然后开始读数据即可
// 先读4个字节返回一个整数
int pId = raf.readInt();
// 再读20个字节
byte[] b = new byte[20];
int read = raf.read(b);
// 然后将这20个字节转成字符串,但是尾部有大量空格
String string = new String(b);
// 去掉首尾的空格
String name = string.trim();
// 再读价格
float price = raf.readFloat();
raf.close();
Product prodcut = new Product(pId, name, price);
return prodcut;
}
/**
* 根据名称查找商品
*
* @throws Exception
**/
public List<Product> findProductByName(String keyword) throws Exception {
ArrayList<Product> pList = new ArrayList<>();
// 可以从文件中任何位置开始读数据的工具:RandomAccessFile
RandomAccessFile raf = new RandomAccessFile("d:/p.dat", "r");
int i = 0;
while ((i + 1) * 28 <= raf.length()) {
raf.seek(4 + 28 * i); // 将读取位置定位到名称字段的起始位置
byte[] b = new byte[20];
raf.read(b);
String name = new String(b).trim();
if (name.contains(keyword)) {
raf.seek(i * 28); // 回到这条数据的起始位置
int id = raf.readInt(); // 读id数据
raf.read(b); // 读名称字段
float price = raf.readFloat(); // 读价格字段
pList.add(new Product(id, name, price)); // 将符合条件的这条数据加入list中
}
i++;
}
return pList;
}
/**
* 根据价格查找商品
**/
}
Produnct类
package day13.find;
import java.io.Serializable;
public class Product implements Serializable {
private int id;
private String name;
private float price;
public Product(int id, String name, float price) {
this.id = id;
this.name = name;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@Override
public String toString() {
return "Product [id=" + id + ", name=" + name + ", price=" + price + "]";
}
}
服务器一方:
package day13.find;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 数据库服务器
*
* @author ThinkPad
*
*/
public class NewBiDbServer {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(3305);
ReadData readData = new ReadData();
while (true) {
Socket sc = ss.accept();
new Thread(new FindDataRunnable(sc,readData)).start();
}
}
}
服务器功能的封装类:
package day13.find;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.List;
public class FindDataRunnable implements Runnable {
Socket sc;
ReadData readData;
public FindDataRunnable(Socket sc, ReadData readData) {
this.sc = sc;
this.readData = readData;
}
@Override
public void run() {
try {
InputStream in = sc.getInputStream();
OutputStream out = sc.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
/**
* 客户端发过来的请求有两种情况: 1、SELECT * FROM p.dat WHERE id=3 // 想根据id查询商品数据 2、SELECT *
* FROM p.dat WHERE name like 菠萝 // 根据名称关键字查询商品数据
*/
byte[] b = new byte[1024];
int num = in.read(b);
String command = new String(b, 0, num);
if (command.contains("id")) {
// 根据id去帮用户查找商品
String idStr = command.substring(command.indexOf("=") + 1);
int id = Integer.parseInt(idStr);
Product p = readData.findProductById(id);
//发送一个对象
oos.writeObject(p);
out.close();
sc.close();
oos.close();
in.close();
} else {
// 根据名称关键字去查找商品
String[] split = command.split(" ");
String keyWord = split[split.length - 1];
List<Product> pList = readData.findProductByName(keyWord);
// 返回数据给客户端
oos.writeObject(pList);
// TODO
out.close();
oos.close();
in.close();
sc.close();
}
} catch (Exception e) {
}
}
}
加客户端一方:
封装ReadData功能的接口
package day14.rpc.clientServiceinday13;
import java.util.List;
import day13.find.Product;
public interface ReadData {
Product findProductById(int id) throws Exception;
List<Product> findProductByName(String keyword) throws Exception;
}
读取服务端数据的工具类ReadDataUtil--------在动态代理中实现网络的连接
package day14.rpc.clientServiceinday13;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.util.List;
import day13.find.Product;
public class ReadDataUtil {
public ReadData getInstance() {
ReadData d = (ReadData) Proxy.newProxyInstance(ReadData.class.getClassLoader(),
new Class<?>[] { ReadData.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if (name.equals("findProductById")) {
Socket sc = new Socket("127.0.0.1", 3305);
//发送请求
OutputStream out = sc.getOutputStream();
out.write(("id="+args[0]).getBytes());
//接受结果
InputStream in = sc.getInputStream();
ObjectInputStream ois = new ObjectInputStream(in);
Product p = (Product) ois.readObject();
in.close();
out.close();
sc.close();
ois.close();
return p;
} else {
Socket sc = new Socket("192.0.0.1", 10000);
//发送请求
OutputStream out = sc.getOutputStream();
out.write(("name= "+args[0]).getBytes());
//接受结果
InputStream in = sc.getInputStream();
ObjectInputStream ois = new ObjectInputStream(in);
List<Product> plist = (List<Product>)ois.readObject();
in.close();
out.close();
ois.close();
sc.close();
return plist;
}
}
});
return d;
}
}
测试类—在客服端调用服务端的方法来查询服务端的数据
package day14.rpc.clientServiceinday13;
import day13.find.Product;
public class Test {
public static void main(String[] args) throws Exception {
ReadDataUtil util = new ReadDataUtil();
ReadData readData = util.getInstance();
Product p = readData.findProductById(4);
System.out.println(p);
}
}