rpc之阿里dubbo简单demo

最近为了学习dubbo照着网上怼了一个简单demo与大家分享

版本
jdk11,dubbo为阿里版,zookeeper3.4,目前是在windows下使用

zookeeper环境详见本人另一篇文章
windows安装zookeeper

apacheDubbo见本人另一篇文章
springboot整合dubbo

一、RPC

远程方法调用,就是像调用本地方法一样调用远程方法

二、上代码

1.dubboInterface主要存放接口和实体类,pom文件没有什么依赖
接口项目结构

接口

1.RpcInvoker
这个是消费者和生产者的的共同接口

public interface RpcInvoker {
    ApiResult invoke(ApiResult tingContext);
    ApiResult asyncInvoke(ApiResult tingContext);
}

2 UserService 这个接口不允许直接调用,通过RpcInvoker的实现类来反射调用

public interface UserService {
    User getUserRoleByUser(User user);
    User getUserById(Integer uid);
}

实现类和实体类

1.实体类

//用户类
public class User implements Serializable {
    private static final long serialVersionUID = 3570930855800498567L;
    private Integer id;//用户ID
    private Integer age;//用户年龄
    private String sex;//用户性别
    private String name;//用户姓名
    private List<Role> roles;//用户角色集合
}
//角色类
public class Role implements Serializable {
    private static final long serialVersionUID = -2328451803818677889L;
    private Integer id;//角色id
    private String name;//角色名称
    private String desc;//角色描述
}

//vo类,这里省略get和set方法
public class ApiResult implements Serializable {

    private static final long serialVersionUID = -2328451803818677569L;

    /**
     * 状态码
     */
    private Integer code;
    /**
     * 返回消息
     */
    private String msg;

    /**
     * 返回实体
     */
    private Object object;

    /**
     * 用来接收参数
     */
    private Map<String,Object> map;
    }

2.实现类

public class UserServiceImpl implements UserService {
    @Override
    public User getUserRoleByUser(User user) {
        if(user.getId()==null)throw new RuntimeException("用户id不可为空");
        System.out.println("正在查询数据库");
        Role role1 = new Role();role1.setId(1);role1.setName("财务");role1.setDesc("发工资的");
        Role role2 = new Role();role2.setId(2);role2.setName("hr");role2.setDesc("招人的");
        Role role3 = new Role();role3.setId(3);role3.setName("开发");role3.setDesc("写代码的");
        ArrayList<Role> roles = new ArrayList<>();
        roles.add(role1);roles.add(role2);roles.add(role3);
        user.setRoles(roles);
        System.out.println("查询完毕,总共三条结果");
        return user;
    }
}


public class RpcInvokerImpl implements RpcInvoker {

    /**
     * 反射接收 类名、方法名、参数
     * @param apiResult
     * @return
     */
    @Override
    public ApiResult invoke(ApiResult apiResult) {
        Map<String, Object> map = apiResult.getMap();
        String className =  (String)map.get("className");
        String methodName =  (String)map.get("methodName");
        Object param = map.get("param");
        Object obj = null;
        try {
            Class clazz = Class.forName(className);
            //Method method = clazz.getMethod(methodName);
            Method[] methods = clazz.getMethods();
            //获取方法
            Method method = Arrays.stream(methods).filter(m->m.getName().equals(methodName)).findAny().get();
            Object o = clazz.getConstructors()[0].newInstance();
            //反射执行
            obj = method.invoke(o, param);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }  catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //返回结果
        apiResult.setObject(obj);
        return apiResult;
    }
	
	//异步目前的操作一样
    @Override
    public ApiResult asyncInvoke(ApiResult apiResult) {
        Map<String, Object> map = apiResult.getMap();
        String className =  (String)map.get("className");
        String methodName =  (String)map.get("methodName");
        Object param = map.get("param");
        Object obj = null;
        try {
            Class clazz = Class.forName(className);
            //Method method = clazz.getMethod(methodName);
            Method[] methods = clazz.getMethods();
            Method method = Arrays.stream(methods).filter(m->m.getName().equals(methodName)).findAny().get();
            Object o = clazz.getConstructors()[0].newInstance();
            obj = method.invoke(o, param);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }  catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        apiResult.setObject(obj);
        return apiResult;
    }
}

### 测试类
public class ProviderMain {
	public static void main(String[] args) {
		//spring框架
		ClassPathXmlApplicationContext context=new
				ClassPathXmlApplicationContext("classpath:applicationContext-provider.xml");
		System.out.println("服务启动");
		context.start();
		while(true)
		{}
	}
}

依赖和配置

1.消费者和生产者依赖一样

<!-- pom依赖-->
	<dependencies>
		<dependency>
			<groupId>com.git</groupId>
			<artifactId>dubboInterface</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>dubbo</artifactId>
			<version>2.5.8</version>
		</dependency>
		<dependency>
			<groupId>com.github.sgroschupf</groupId>
			<artifactId>zkclient</artifactId>
			<version>0.1</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.5</version>
			<scope>compile</scope>
		</dependency>
	</dependencies>

2.生产者配置

<!-- xml  -->
	<!-- 1. 设置应用名称-->
	<dubbo:application name="provider-of-cart"/>
		<!-- 2.配置zookeeper地址 -->
		<dubbo:registry address="zookeeper://127.0.0.1:2181">
		</dubbo:registry>
		<!-- 3.配置服务的端口号 -->
		<dubbo:protocol port="20888" name="dubbo">
		</dubbo:protocol>
		<!-- 4.配置实现类的类名 -->
		</bean>
	<bean class="com.git.soc.RpcInvokerImpl" id="rpcInvoker">
	</bean>
		<!-- 5.配置接口名,开放服务 -->
	</dubbo:service>
	<dubbo:service interface="com.git.inter.RpcInvoker" ref="rpcInvoker"></dubbo:service>
	</beans>

消费者

1.xml配置


	<!-- 1,应用名称 -->
	<dubbo:application name="consumer-of-cart"/>
	<!-- 2,zookeeper -->
	<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
	<!-- 3,配置那些接口由dubbo来执行 -->
	<dubbo:reference interface="com.git.inter.RpcInvoker" id="rpcInvoker"></dubbo:reference>

2.测试

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-consumer.xml");
        ApiResult api = new ApiResult(0, "msg", null);
        Map<String, Object> map = new HashMap<>();       map.put("className","com.git.soc.inter.impl.UserServiceImpl");
        map.put("methodName","getUserRoleByUser");
        User user = new User();
        user.setId(2);
        user.setAge(25);
        user.setName("张三");
        user.setSex("男");
        map.put("param",user);
        api.setMap(map);
        System.out.println("start consumer");
		//获得代理实现类
		RpcInvoker rpcInvoker = (RpcInvoker) context.getBean("rpcInvoker");
		//调用服务
		api = rpcInvoker.invoke(api);
        //api = RpcInvokeStrategy.startInvoker(api);
        System.out.println("服务消费者/客户端:"+api.toString());
    }

异步和回调配置

回调接口采用Function接口

//接口
public interface RoleService {
    Role checkRole2(Role role, Function<Role,Role> function);
}
//生产者
public class RoleServiceImpl implements RoleService {
    @Override
    public Role checkRole2(Role role, Function<Role, Role> function) {
        System.out.println("function函数处理");
        if(role==null) throw new RuntimeException("角色不可为空");
        if(role.getName().equals("财务")){
            System.out.println("角色名字应该为为管理员");
            return function.apply(role);
        }
        return role;
    }

}

xml配置

<dubbo:service interface="com.git.inter.RoleService" ref="roleSevice" connections="1" callbacks="1000" ><!-- 还可以配置异步async="true"-->
		<dubbo:method name="checkRole2">
			<dubbo:argument index="1" callback="true" />
			<!--也可以通过指定类型的方式-->
			<!--<dubbo:argument type="com.demo.CallbackListener" callback="true" />-->
		</dubbo:method>
	</dubbo:service>

测试

public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-consumer.xml");
        context.start();
        CallbackService callbackService = (CallbackService) context.getBean("callbackService");
        RoleService roleService =  context.getBean(RoleService.class);
        Role role = new Role();
        role.setName("财务");
        System.out.println("===================角色调用开始===================");
        Role role1 = roleService.checkRole2(role, r->{
            System.out.println("===================开始修正===================");
            System.out.println("===================修正之前===================");
            System.out.println(r);
            r.setName("管理");
            r.setDesc("搞管理的");
            return r;
        });

        System.out.println("===================角色调用完毕===================");
        System.out.println("===================修正之后===================");
        System.out.println(role1);
    }

重新描述一下思路:
1.接口invoker,从消费者发出需要调用的类和方法,生产者通过反射调用
2.这么做是有项目借鉴的,可以在中间做一些网关等
3.简单调用到此结束,下一篇将采用springboot2.2与apacheDubbo整合,这里的坑比较多

本文为作者原创,转载请注明出处
github地址

发布了42 篇原创文章 · 获赞 13 · 访问量 8306

猜你喜欢

转载自blog.csdn.net/weixin_43328357/article/details/103089442