rmi通信rpc框架实现远程调用

今天说一下通过静态代理和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;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值