今天说一下通过静态代理和rm方式实现远程调用,这里面主要想说一下这个静态代理的方式,它是通过一个匿名类的方式来实现的。通过这个案例来实现一个简易的RPC远程调用的装置。先来说一下provider服务提供者的这一方。在Provider这个类中,定了一个静态的内部类?通过spring管理的方式,创建了一个orderService的一个服务。然后初始化iniprtocol2() 方法来初始化服务端,然后通过system.in.read()方法,对服务端进行挂起。在这个iniprtocol2的方法中,首先new一个InfoServiceImpl类。这个方法体中加入匿名内部类,实际上,这个匿名的内部类与InfoServiceImpl类的关系,我们暂时可以看作是父子的关系,也就是说我们的这个匿名内部类是这个InfoServiceImpl类的子类。在这个子类中调用父类的方法passInfo方法,然后调用反射原理。通过反射来调用具体的业务方法,具体的业务方法的信息封装在了info这个map集合中。实际上,这个new方法,返回的是InfoServiceImpl这个类的子类,然后把这个服务与端口号IP,进行绑定,然后,打印一句话初始化了rm i绑定
package com.enjoy;
import com.alibaba.fastjson.JSON;
import com.enjoy.service.InfoService;
import com.enjoy.service.InfoServiceImpl;
import com.enjoy.service.OrderService;
import com.enjoy.service.OrderServiceImpl;
import com.enjoy.utils.InvokeUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.Map;
public class Provider {
@Configuration
static class ProviderConfiguration {
@Bean
public OrderService orderService() {
return new OrderServiceImpl();
}
}
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
ctx.start();
System.out.println("---------spring启动成功--------");
initProtocol2(ctx);
System.in.read();
}
public static void initProtocol2(ApplicationContext ctx) throws RemoteException, AlreadyBoundException, MalformedURLException, AlreadyBoundException {
InfoService infoService = new InfoServiceImpl(){
public Object passInfo(Map<String, String> info) {//对象,方法,参数
super.passInfo(info);//info内包含的信息,是反射需要的信息
Object result = InvokeUtils.call(info,ctx);
System.out.println("测试InvokeUtils.call调用功能,调用结果:" + JSON.toJSONString(result));
return result;
}
};
//注冊通讯端口
LocateRegistry.createRegistry(InfoService.port);
//注冊通讯路径
Naming.bind(InfoService.RMI_URL, infoService);
System.out.println("初始化rmi绑定");
}
}
我们在看客户端的方法调用在客户端的方法中通过 Naming.lookup(InfoService.RMI_URL);方法来,通过查找IP的方法来获得服务端绑定的服务infoService,通过infoService 调用OrderService方法获得OrderService服务,之后调用getDetail方法,来获得远端的信息。这里的getService方法,用了一个匿名内部类的方式来实现的,同样,在这个方法体里面new了一个接口,重写该接口中getDetail方法。实际上,这个匿名的内部类,重写了OrderService接口中的getDetail方法,对方法进行了重写,在方法中,我们往一个map集合中,切入了我们想要调用的业务接口的信息
//写死了反射的目标,静态代理
info.put("target","orderService");//对象名
info.put("methodName","getDetail");//方法名
info.put("arg",id);//参数列表名
把封装好的map集合,传入到passinfo,这个方法中获取一个结果,这个结果就是从远端获取的,这一步只是相当于注册了这个匿名内部类。然后回到main方法中,得到的这个OrderService对象,调用getDetail方法,这时候才真正的调用匿名内部类里面的getDetail方法。。
rmi,这是一个jdk底层用的方法。。它的使用非常简单,需要在接口中进行继承操作,在时间内中,基层操作。
package com.enjoy.utils;
import com.alibaba.fastjson.JSON;
import com.enjoy.entity.OrderEntiry;
import com.enjoy.service.InfoService;
import com.enjoy.service.OrderService;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
public class RmiClient {
public static void main(String[] args) throws RemoteException, MalformedURLException {
InfoService infoService = null;
try {
//取远程服务实现
infoService = (InfoService) Naming.lookup(InfoService.RMI_URL);
// //静态代理方法
OrderService service = getService(infoService);
Object result2 = service.getDetail("1");//透明化调用,不增加开发人员的负担
System.out.println("测试远程调用功能,调用结果:" + JSON.toJSONString(result2));
} catch (NotBoundException e) {
e.printStackTrace();
}
}
/**
* 静态代理,动态编译类来实现
*/
public static OrderService getService(InfoService infoService){
OrderService service = new OrderService(){
@Override
public OrderEntiry getDetail(String id) {
Map<String,String> info = new HashMap();
//写死了反射的目标,静态代理
info.put("target","orderService");//对象
info.put("methodName","getDetail");//方法
info.put("arg",id);//参数
OrderEntiry result = null;
try {
result = (OrderEntiry)infoService.passInfo(info);
} catch (RemoteException e) {
e.printStackTrace();
}
return result;
}
};
return service;
}
}
反射方法封装
package com.enjoy.utils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
/**
* Created by Peter on 8/28 028.
*/
public class InvokeUtils {
public static ClassPathXmlApplicationContext context;
/**
* java反射
* @param target 目标对象
* @param methodName 目标方法
* @param argTypes 方法参数类型
* @param args 实参
* @return
*/
public static Object call(Object target,String methodName,
Class[] argTypes,Object[] args)
throws NoSuchMethodException, InvocationTargetException,
IllegalAccessException {
Method method = target.getClass().getMethod(methodName, argTypes);
return method.invoke(target, args);
}
public static Object call(Map<String,String> info, ApplicationContext ctx){
String targetStr = info.get("target");
String methodName = info.get("methodName");
String arg = info.get("arg");
try {
return call(ctx.getBean(targetStr), methodName,new Class[]{String.class},new Object[]{arg});
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
InfoService业务接口
package com.enjoy.service;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Map;
public interface InfoService extends <span style="color:#ff0000;">Remote</span> {//继承remote接口
String RMI_URL = "rmi://127.0.0.1:9080/InfoService";
int port = 9080;
Object sayHello(String name) throws RemoteException;
Object passInfo(Map<String,String> info) throws RemoteException;
}
InfoService 实现类
package com.enjoy.service;
import com.alibaba.fastjson.JSON;
import com.enjoy.utils.InvokeUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
public class InfoServiceImpl extends UnicastRemoteObject implements InfoService {
public InfoServiceImpl() throws RemoteException {
super();
}
@Override
public Object sayHello(String name) {
return name+",你好,调通了!";
}
@Override
public Object passInfo(Map<String, String> info) {
System.out.println("恭喜你,调通了,参数:"+JSON.toJSONString(info));
info.put("msg","你好,调通了!");
return info;
}
}
OrderService接口
package com.enjoy.service;
import com.enjoy.entity.OrderEntiry;
public interface OrderService {
OrderEntiry getDetail(String id);//目标对象,方法,参数
}
OrderServiceImpl业务实现类
package com.enjoy.service.impl;
import com.enjoy.dao.OrderDao;
import com.enjoy.entity.OrderEntiry;
import com.enjoy.service.OrderService;
import com.enjoy.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductService productService;
@Override
public OrderEntiry getDetail(String id) {
System.out.println(super.getClass().getName()+"被调用一次:"+System.currentTimeMillis());
OrderEntiry orderEntiry = orderDao.getDetail(id);
orderEntiry.addProduct(productService.getDetail("P001"));
orderEntiry.addProduct(productService.getDetail("P002"));
return orderEntiry;
}
}
业务接口
package com.enjoy.service;
import com.enjoy.entity.ProductEntiry;
public interface ProductService {
ProductEntiry getDetail(String id);
ProductEntiry modify(ProductEntiry product);
boolean status(String id, boolean upDown);
}
package com.enjoy.service.impl;
import com.enjoy.dao.ProductDao;
import com.enjoy.entity.ProductEntiry;
import com.enjoy.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.Map;
public class ProductServiceImpl implements ProductService {
private static Map<String,ProductEntiry> productMap = new HashMap<>();
static {
ProductEntiry product = new ProductEntiry();
product.setId("P001");
product.setName("iponex");
product.setPrice(10000);
productMap.put(product.getId(),product);
product = new ProductEntiry();
product.setId("P002");
product.setName("大疆无人机");
product.setPrice(100000);
productMap.put(product.getId(),product);
}
@Autowired
private ProductDao productDao;
@Override
public ProductEntiry getDetail(String id) {
System.out.println(super.getClass().getName()+"被调用一次:"+System.currentTimeMillis());
ProductEntiry product = productMap.get(id);
if (null != product){
return product;
}
return productDao.getDetail(id);
}
@Override
public ProductEntiry modify(ProductEntiry product) {
return productDao.modify(product);
}
@Override
public boolean status(String id, boolean upDown) {
return productDao.status(id,upDown);
}
}
实体类
package com.enjoy.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Peter on 11/12 012.
*/
public class OrderEntiry implements Serializable {
private String id;
private long money;
private String userId;
private int status = 0;
private List<ProductEntiry> productlist = new ArrayList<>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getMoney() {
return money;
}
public void setMoney(long money) {
this.money = money;
}
public List<ProductEntiry> getProductlist() {
return productlist;
}
public void setProductlist(List<ProductEntiry> productlist) {
this.productlist = productlist;
}
public void addProduct(ProductEntiry productEntiry){
productlist.add(productEntiry);
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}