zoukankan      html  css  js  c++  java
  • 本地服务调用

    本地服务是部署在同一个jvm中相同的模块或者不同的模块之间的服务调用。

    因各模块有自己的运行空间,拥有独立的ClassLoader,因此模块间的服务调用也会存在差异。

    模块内的服务调用,类似Spring,获取Bean的实例,并调用相关方法:

    @Service("AuthService")

    public class AuthService  extends AbstractService{

    public Data auth(@Param(value="principal",required=true)Principal principal,

    @Param(value="url",required=true)String url) throws Exception {

    User user = (User)principal;

    MenuService ms = module.getService(MenuService.class);

    Data menu = ms.findByUrl(url);

    long perm_id = menu.getLong("perm_id", 0);

    if(perm_id == 0) return new Data("authResult", true); //not protected url

    List<String> perm_ids = user.getData().get("perm_ids");

    for(String pid: perm_ids) {

    if(Long.parseLong(pid) == perm_id)

    return new Data("authResult", true);

    }

    return new Data("authResult", false);

    }

    }

    这种使用的优势:

    1、MenuService的引用非常清晰,如果后续发生重构等,也会跟着完成重构。

    2、MenuService的方法findByUrl(url)显式被调用,更易于阅读;

    缺点,只能在当前模块中调用,否则会出现ClassNotFoundException的。

    模块间的服务调用,无论是模块内部或者模块间都可以采用这种方式:

    public abstract class ServiceHelper {

    private static Map<String, Map<String, Map<String, Object>>> cache = Utils.newHashMap();

    public static Data invoke(String moduleId, String serviceId, Data request) throws Exception {

    return Application.getInstance().getModules().getModule(moduleId).invoke(serviceId, request);

    }

    }

    调用时:ServiceHelper.invoke("pas","AuthService:auth",new Data("principal",principalInstance,"url","http://localhost:8080/pas/index.shtml"));

    参数pas:是服务所在的模块

    参数AuthService:auth:服务ID和调用的服务方法,中间使用英文冒号分开

    参数Data:auth方法需要的参数

    关注红色的principal和url,这个跟参数的Param注解声明的必须是一致的,参考上面auth方法的声明。

    优势:太方便了

    不足:在可读性上存在一些缺陷,但是考虑到你正在用别人的service,这样已经很方便了,不是吗。

    实现,LocalModule中的invoke方法:

    public Data invoke(String serviceId, Data request) {

    LocalModule currentModule = ThreadContext.getContext().getModule();

    ClassLoader threadClassLoader = Thread.currentThread().getContextClassLoader();

    String sid = ThreadContext.getContext().getServiceId();

    Data req = ThreadContext.getContext().getRequest();

    Principal p = ThreadContext.getContext().getPrincipal();

    Data response = null;

    try {

    Thread.currentThread().setContextClassLoader(this.getClassLoader());

    ThreadContext.getContext().reset(this, serviceId, request, p);

    response = ModuleServiceInvoker.invoke(this, request, serviceId);

    return response;

    } finally {

    Thread.currentThread().setContextClassLoader(threadClassLoader);

    ThreadContext.getContext().reset(currentModule, sid, req, p);

    }

    }

    注意红色部分ClassLoader切换,因此可以在不同的模块间调用服务。

    框架源码:https://github.com/hifong/flying

    博客空间:http://www.cnblogs.com/hifong/

    Demo应用:https://github.com/hifong/pas

    技术QQ群:455852142

  • 相关阅读:
    线性滤波器(linear filter)与非线性滤波器(non-linear filter)
    线性滤波器(linear filter)与非线性滤波器(non-linear filter)
    80后开网店卖故事:1500多位为感觉而埋单
    [置顶] think in java interview-高级开发人员面试宝典(一)
    Android ToggleButton Example--开关按钮
    UVA 10012 How Big Is It?(暴力枚举)
    Windows远程连接的实现
    系统集成项目管理之项目采购管理
    UVA 165 Stamps (DFS深搜回溯)
    EF操作增删改查
  • 原文地址:https://www.cnblogs.com/hifong/p/5440651.html
Copyright © 2011-2022 走看看