1.业务场景

   当下主系统衍生子业务系统已经成为常态,像京东的物流和金融,阿里的支付宝和淘宝。

   子业务系统需要对主系统的资源进行访问,这里的资源我具体化为数据库数据,但日常业务中可能不只是数据。

   抽象服务给子业务系统进行调用访问? 各种各样子业务系统可能会出现千奇百怪的需求,主系统只有不断增加服务去拥抱变化。

   创建多个数据库子账号给子业务系统?无法统一监控,而且很容易导致数据库瓶颈,到时候就需要加服务器资源。

   权衡利弊和自己技术栈之后开始实践之路,大体目标:

   a.通用方式获取主系统数据,且新增需求时主系统访问方式依然不变,在对应的子业务系统进行数据的处理;

   b.进行统一监控,把控对外数据,收集日志并进行数据分析和挖掘;

2.技术细节

  核心为 Hibernate DetachedCriteria 离线查询对象,对于 DetachedCriteria 我这里就不说了请自行百度

  当下 JavaEE 服务方式有很多,restful/soap/spring http invoker 等等,看你项目具体的服务框,这里我不赘述。

  我将自身项目中抽取中该场景关键代码,剔除繁琐的业务代码,展示 hiber 通用查询带来的便利性和可扩展性。

  实例中服务采用 cxf webservice,spring 做为托管容器,Base64 编码查询条件进行参数的传递。

  主系统服务核心代码:

@Component
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class CommonQueryWsImpl implements CommonQueryWs {

    @Resource
    private SessionFactory sessionFactory;

    @Override
    @Transactional(readOnly = true)
    public String getPo(String poName, List<String> andList) {
        DetachedCriteria detachedCriteria = getDetachedCriteria(poName, andList);

        Object result = detachedCriteria.getExecutableCriteria(sessionFactory.getCurrentSession()).setMaxResults(1).uniqueResult();
        return ObjectUtil.isNull(result) ? "{}" : JSONUtil.toJsonStr(result);
    }

    @Override
    @Transactional(readOnly = true)
    public String listPo(String poName, List<String> andList) {
        DetachedCriteria detachedCriteria = getDetachedCriteria(poName, andList);

        List list = detachedCriteria.getExecutableCriteria(sessionFactory.getCurrentSession()).list();
        return JSONUtil.toJsonStr(list);
    }

    /**
     * 获取 hiber 离线查询对象
     *
     * @param poName  biber 实体对象
     * @param andList andSql 列表
     * @return 离线查询对象
     */
    private DetachedCriteria getDetachedCriteria(String poName, List<String> andList) {
        DetachedCriteria detachedCriteria = DetachedCriteria.forEntityName(poName);

        String[] split;
        for (String andStr : andList) {
            split = Base64.decodeStr(andStr).split("#");
            String andSql = split[0];
            String andParam = split[1];

            if (andParam.contains(",")) {
                String[] andParams = andParam.split(",");
                Type[] types = new Type[andParams.length];
                for (int i = 0; i < types.length; i++) {
                    types[i] = StringType.INSTANCE;
                }

                detachedCriteria.add(Restrictions.sqlRestriction(andSql, andParams, types));
            } else {
                detachedCriteria.add(Restrictions.sqlRestriction(andSql, andParam, StringType.INSTANCE));
            }
        }
        return detachedCriteria;
    }
}
View Code

相关文章: