jbase虚拟M层的设计

news2025/1/10 20:20:26

对于只是自己产品内部使用的打印程序来说(比如打印收费单,打印结算单等),打印逻辑写在js,获取其他层都是没毛病的。但是对于类型检验报告这种打印来说,打印格式控制逻辑写在js层是百分百不行的。因为检验报告的打印不光检验内部用,还要给his、自助机、病案、支付宝、微信等用,你不可能要求第三方都有js执行环境。所以逻辑写在js的方案可以直接pass。

同时由于报告格式多样性和经常调整,把打印格式控制逻辑直接写在dll也是不合适的,你总不能改个格式就要求his、自助机等更新你的dll。

所以最完美的方案就是给第三方提供文件或者提供不包含业务逻辑的dll,对外dll只负责按元素绘制执行打印,内部不包含任何业务逻辑,dll通过数据库连接串调用服务器的脚步得到绘制数据绘制,这样改格式不影响第三方使用,在自己服务器内部就能完成打印格式控制。

设计参照打印设计

这种设计方案虽然很完美,但是也得有类似M的服务器脚本支撑,用Cache数据库完全没问题,换到关系库由于没有M的存在,所以这个方案就不行了,为此设计虚拟M层。

虚拟M层旨在提供一个类型M的脚步层,在虚拟M层,开发人员可以写和M的Query一样的逻辑,同时提供脚本化的效果,这样就可以借助虚拟M层完成很多事情,比如:控制输出打印元素、查询excel导出数据、启动TCP连接设备等,虚拟M的前提是框架实现脚本化。

首先实现虚拟M的主入口,到时候使用的地方就配置该ashx的路径来调用虚拟M

import LIS.Core.Dto.OutParam;
import LIS.Core.MultiPlatform.LISContext;
import LIS.Model.Bussiness.Parameters;
import appcode.BaseHttpHandlerNoSession;
import appcode.Helper;

import java.io.File;
import java.io.PrintWriter;
import java.lang.reflect.Method;

/**
 * 虚拟M层的调用入口实现类,由该类对外提供http的虚拟M服务。通过java业务脚本实现和M方法或者Query一样的输入输出约定,来供业务调用,进而基于
 * 此基础上实现打印和导出Excel等功能,vm概念很重要,打印、导出、连仪器都离不开
 */
public class VMService extends BaseHttpHandlerNoSession {

    /**
     * 供外部http调用的请求入口
     *
     * @return
     */
    public String GetData() {
        //类名
        String ClassName = Helper.ValidParam(LISContext.GetRequest(Request, "ClassName"), "");
        //方法名
        String FuncName = Helper.ValidParam(LISContext.GetRequest(Request, "FuncName"), "");
        //参数
        String Param = Helper.ValidParam(LISContext.GetRequest(Request, "Param"), "");
        //会话串
        String Session = Helper.ValidParam(LISContext.GetRequest(Request, "Session"), "");
        //调用虚拟M代码
        return GetVMData(ClassName, FuncName, Param, Session);
    }

    /**
     * 得到数据,调用者和Web在一个程序预时候直接通过接口调用,避免post的性能损失
     *
     * @param ClassName 类名 vm.his.printbarcode
     * @param FuncName  方法名 GetData
     * @param Param     P0-P14的参数json串
     * @param Session   会话串
     * @return
     */
    public String GetVMData(String ClassName, String FuncName, String Param, String Session) {
        StringBuilder objStream = new StringBuilder();
        try {
            PrintWriter writer = Response.getWriter();
            String[] funArr = FuncName.split("^");
            String[] sessArr = Session.split("^");
            String FunModul = "";
            if (funArr.length > 1) {
                FunModul = funArr[1];
            }
            String RowCount = "";
            FuncName = funArr[0];
            String OutPutType = "";
            if (sessArr.length > 6) {
                OutPutType = sessArr[6];
            }
            Parameters ParamObj = (Parameters) Helper.Json2Object(Param, Parameters.class);
            //转换M的类名为java的类名称
            ClassName = LISContext.WebBasePath + File.separator + ClassName.replace(".", File.separator);
            //反射得到类型
            Object objDeal = GetBllObjService.GetObjectByConfString(ClassName, writer, "", "");

            //没有实现类
            if (objDeal == null) {
                String errStr = "类" + ClassName + "不存在";
                //编译报错信息
                if (GetBllObjService.BuildingResHash.containsKey(ClassName)) {
                    errStr = GetBllObjService.BuildingResHash.get(ClassName).toString();
                }
                objStream.append("<Response>");
                objStream.append("<SQLResult><SQL><FunRet></FunRet></SQL></SQLResult><RetVal>-1</RetVal><Error>" + errStr + "</Error><Node>" + ClassName + "</Node><RowCount>0</RowCount>");
                objStream.append("</Response>");
                return objStream.toString();
            }
            //获得类型
            Class type = objDeal.getClass();
            //得到方法
            Method method = type.getMethod(FuncName);
            //没有实现方法
            if (method == null) {
                objStream.append("<Response>");
                objStream.append("<SQLResult><SQL><FunRet></FunRet></SQL></SQLResult><RetVal>-1</RetVal><Error>" + ClassName + "里面不存在:" + FuncName + "方法</Error><Node>" + ClassName + "</Node><RowCount>0</RowCount>");
                objStream.append("</Response>");
                return objStream.toString();
            }
            //会话对象,可能带出数据
            OutParam SessionOut=new OutParam();
            SessionOut.Message=Session;
            //返回行数对象,可能带出数据
            OutParam RowCountOut=new OutParam();
            RowCountOut.Message=RowCount;
            Object[] paraObj = new Object[16];
            paraObj[0] = ParamObj.P0;
            paraObj[1] = ParamObj.P1;
            paraObj[2] = ParamObj.P2;
            paraObj[3] = ParamObj.P3;
            paraObj[4] = ParamObj.P4;
            paraObj[5] = ParamObj.P5;
            paraObj[6] = ParamObj.P6;
            paraObj[7] = ParamObj.P7;
            paraObj[8] = ParamObj.P8;
            paraObj[9] = ParamObj.P9;
            paraObj[10] = ParamObj.P10;
            paraObj[11] = ParamObj.P11;
            paraObj[12] = ParamObj.P12;
            paraObj[13] = ParamObj.P13;
            paraObj[14] = SessionOut;
            paraObj[15] = RowCountOut;


            objStream.append("<Response>");
            int ResType = 0;
            String retJson = "";
            String Err = "";
            //调用方法直接返回串
            if (FuncName.substring(FuncName.length() - 4) == "MTHD" || FunModul == "MTHD") {
                //执行返回数据
                Object retObj = method.invoke(objDeal, paraObj);
                Session = SessionOut.GetString();
                RowCount = RowCountOut.GetString();
                retJson = retObj.toString();
                ResType = 1;
            }
            //方法直接输出Json串
            else if (FuncName.length() > 10 && FuncName.substring(FuncName.length() - 10) == "JSONStream" || FunModul == "JSONStream") {

                //执行返回数据
                Object retObj = method.invoke(objDeal, paraObj);
                Session = SessionOut.GetString();
                RowCount = RowCountOut.GetString();
                ResType = 1;
                retJson = retObj.toString();
                objStream.append("<" + FuncName + "Result>");
                objStream.append(DealXml(retJson));
                objStream.append("</" + FuncName + "Result>");
                objStream.append("<RetVal>0</RetVal><Error></Error><Node>" + FuncName + "</Node><RowCount>" + RowCount + "</RowCount><ResType>" + ResType + "</ResType>" + "<RetSession>" + Session + "</RetSession>");
                objStream.append("</Response>");
                return objStream.toString();
            }
            //方法输出List顶替Query
            else {
                //执行返回数据
                Object retObj = method.invoke(objDeal, paraObj);
                Session = SessionOut.GetString();
                RowCount = RowCountOut.GetString();
                retJson = retObj.toString();
                if (FuncName.substring(FuncName.length() - 4) == "JSON") {
                    ResType = 1;
                } else {
                    ResType = 2;
                }
            }
            objStream.append("<" + FuncName + "Result>" + DealXml(retJson) + "</" + FuncName + "Result>");
            objStream.append("<RetVal>0</RetVal><Error>" + Err + "</Error><Node>" + FuncName + "</Node><RowCount>" + RowCount + "</RowCount><ResType>" + ResType + "</ResType>" + "<RetSession>" + Session + "</RetSession>");
            objStream.append("</Response>");
            return objStream.toString();
        } catch (Exception ex) {
            objStream.append("<Response>");
            objStream.append("<SQLResult><SQL><FunRet></FunRet></SQL></SQLResult><RetVal>-1</RetVal><Error>调用:" + DealXml(ClassName + ",方法:" + FuncName + ",参数:" + Param + ",会话:" + Session + "发生异常!" + Helper.Object2Json(ex)) + "</Error><Node>" + ClassName + "</Node><RowCount>0</RowCount>");
            objStream.append("</Response>");
            return objStream.toString();
        }
    }

    /**
     * 替换xml干扰串
     *
     * @param str
     * @return
     */
    private String DealXml(String str) {
        return str.replace("&", "&amp;").replace("'", "&apos;").replace("\"", "&quot;").replace(">", "&gt;").replace("<", "&lt;");
    }


}

然后实现两个虚拟M的示例
打印初步结构

import LIS.Core.Dto.OutParam;
import appcode.BaseHttpHandlerNoSession;

/**
 * 输出符合打印元素绘制协议的打印元素数据,来供打印执行层打印
 */
public class PrintBarCodeTest extends BaseHttpHandlerNoSession {
    /**
     * 按传入的RowID输出符合打印元素绘制协议的数据来实现打印控制
     * @param RowID 业务主键
     * @param P1
     * @param P2
     * @param P3
     * @param P4
     * @param P5
     * @param P6
     * @param P7
     * @param P8
     * @param P9
     * @param P10
     * @param P11
     * @param P12
     * @param P13
     * @param Session
     * @param Output
     * @return
     */
    public String GetData(String RowID, String P1, String P2, String P3, String P4, String P5, String P6, String P7, String P8, String P9, String P10, String P11, String P12, String P13, OutParam Session, OutParam Output) {
        //先包一个打印元素绘制协议数据生成的工具类来解决元素约束问题,工具类实现了调用工具类得到标签,条码,文本等
        return "[]";
    }
}

导出的示例

import LIS.Core.Dto.OutParam;
import LIS.Model.Entity.BTTestCode;
import appcode.BaseHttpHandlerNoSession;
import appcode.Helper;

import java.util.List;

/**
 * 输出符合Query约定的数据供导出Excel用,所有的虚拟M方法参数约定就是这个样子
 */
public class ExportExcelTest extends BaseHttpHandlerNoSession {
    /**
     * 查询所有项目数据导出到Excel
     * @param P0
     * @param P1
     * @param P2
     * @param P3
     * @param P4
     * @param P5
     * @param P6
     * @param P7
     * @param P8
     * @param P9
     * @param P10
     * @param P11
     * @param P12
     * @param P13
     * @param Session
     * @param Output
     * @return
     */
    public String QryTestCode(String P0, String P1, String P2, String P3, String P4, String P5, String P6, String P7, String P8, String P9, String P10, String P11, String P12, String P13, OutParam Session, OutParam Output) throws Exception{
        BTTestCode dto=new BTTestCode();
        //返回的参数,供Excel模板使用
        Session.Message="项目数据导出^"+LIS.Core.Util.TimeParser.GetNowDate()+"^zhanglianzhu";
        //查询项目数据
        List<BTTestCode> retList=EntityManager().FindAll(dto,null,"",-1,-1);
        //数组转json就是等价Query的
        return Helper.Object2Json(retList);
    }
}

这样客户端执行层再对接虚拟M调用后就可以完成以前在M层实现的效果了,为了支持虚拟M层,把业务脚本化的实现下沉到jar包层,虚拟M和Web调用共用业务脚本化基础

在这里插入图片描述

虚拟M存放的目录
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1220998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构-哈希表(C语言)

哈希表的概念 哈希表就是&#xff1a; “将记录的存储位置与它的关键字之间建立一个对应关系&#xff0c;使每个关键字和一个唯一的存储位置对 应。” 哈希表又称&#xff1a;“散列法”、“杂凑法”、“关键字&#xff1a;地址法”。 哈希表思想 基本思想是在关键字和存…

Express.js 与 Nest.js对比

Express.js 与 Nest.js对比 自从 Node.js 发布以来&#xff0c;Javascript 在后端领域的使用有所增加。由于 Node.js 的使用越来越多&#xff0c;每天都会有新的框架和工具发布。Express 和 Nest 是使用 Node.js 创建后端应用程序的最著名的框架之一&#xff0c;在本文中&…

数据结构与算法之美学习笔记:20 | 散列表(下):为什么散列表和链表经常会一起使用?

目录 前言LRU 缓存淘汰算法Redis 有序集合Java LinkedHashMap解答开篇 & 内容小结 前言 本节课程思维导图&#xff1a; 今天&#xff0c;我们就来看看&#xff0c;在这几个问题中&#xff0c;散列表和链表都是如何组合起来使用的&#xff0c;以及为什么散列表和链表会经常…

【代码随想录】算法训练计划21、22

day 21 1、530. 二叉搜索树的最小绝对差 题目&#xff1a; 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝对值。 思路&#xff1a; 利用了二叉搜索树的中序遍历特性用了双指…

线性表的概念

目录 1.什么叫线性表2.区分线性表的题 1.什么叫线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是…

2.4 矩阵的运算法则

矩阵是数字或 “元素” 的矩形阵列。当矩阵 A A A 有 m m m 行 n n n 列&#xff0c;则是一个 m n m\times n mn 的矩阵。如果矩阵的形状相同&#xff0c;则它们可以相加。矩阵也可以乘上任意常数 c c c。以下是 A B AB AB 和 2 A 2A 2A 的例子&#xff0c;它们都是 …

JSplacement丨随机生成置换贴图

界面很简单&#xff0c;虽然是英文&#xff0c;但基本也能看懂&#xff0c;参数调一调&#xff0c;随机生成不重复的8K高清图片。 这种图片可能对普通人感觉很奇怪&#xff0c;有什么用呢&#xff1f;会C4D建模渲染的同学应该会明白&#xff0c;特别是建一些科技类的场景背景&a…

短期经济波动:均衡国民收入决定理论(三)

短期经济波动&#xff1a;国民收入决定理论(三) 文章目录 短期经济波动&#xff1a;国民收入决定理论(三)[toc]1 总需求曲线及其变动1.1 总需求曲线含义1.2 总需求曲线推导1.2.1 代数推导1.2.2 几何推导 1.3 AD曲线及其变动1.3.1 扩张性财政政策1.3.2 扩张性货币政策 2 总供给曲…

2023年AI生成音频研究报告

第一章 行业概况 1.1 定义 AI音频生成行业&#xff0c;作为人工智能生成内容&#xff08;AIGC&#xff09;技术渗透的关键领域&#xff0c;正迅速成为技术革新的前沿阵地。这一领域专注于运用先进的人工智能技术和复杂算法来创造音频内容&#xff0c;覆盖了语音合成、音乐制作…

常见面试题-HashMap源码

了解 HashMap 源码吗&#xff1f; 参考文章&#xff1a;https://juejin.cn/post/6844903682664824845 https://blog.51cto.com/u_15344989/3655921 以下均为 jdk1.8 的 HashMap 讲解 首先&#xff0c;HashMap 的底层结构了解吗&#xff1f; 底层结构为&#xff1a;数组 链…

C语言--给定一行字符串,获取其中最长单词【图文详解】

一.问题描述 给定一行字符串,获取其中最长单词。 比如&#xff1a;给定一行字符串&#xff1a; hello wo shi xiao xiao su 输出&#xff1a;hello 二.题目分析 “打擂台算法”&#xff0c;具体内容小伙伴们可以参考前面的内容。 三.代码实现 char* MaxWord(const char* str)…

初始MySQL(七)(MySQL表类型和存储引擎,MySQL视图,MySQL用户管理)

目录 MySQL表类型和存储引擎 MyISAM MEMORY MySQL视图 我们先说说视图的是啥? 视图的一些使用细节 MySQL用户管理 原因 常见操作 MySQL表类型和存储引擎 -- 查看所有的存储引擎 SHOW ENGINES 我们常见的表有MyISAM InnoDB MEMORY 1.MyISAM不支持事务,也不支持外…

群晖7.2版本安装CloudDriver2(套件)挂载alist(xiaoya)到本地

CloudDrive是一个强大的多云盘管理工具&#xff0c;为用户提供包含云盘本地挂载的一站式的多云盘解决方案。挂载到本地后&#xff0c;可以像本地文件一样进行操作。 一、套件库添加矿神源 二、安装CloudDriver2 1、搜索安装 搜索框输入【clouddrive】&#xff0c;搜索到Clou…

抖音快手判断性别、年龄自动关注脚本,按键精灵开源代码!

这个是支持抖音和快手两个平台的&#xff0c;可以进入对方主页然后判断对方年龄和性别&#xff0c;符合条件的关注&#xff0c;不符合条件的跳过下一个ID&#xff0c;所以比较精准&#xff0c;当然你可以二次开发加入更多的平台&#xff0c;小红书之类的&#xff0c;仅供学习&a…

YOLO目标检测——PCB缺陷数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;电子制造过程的质量控制、生产线的自动化检测、以及产品可靠性验证等方面数据集说明&#xff1a;PCB缺陷检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量…

修完这个 Bug 后,MySQL 性能提升了 300%

最近 MySQL 官方在 8.0.35 上修复了一个 bug&#xff1a; 这个 bug 是由 Mark Callaghan 发现的。Mark 早年在 Google MySQL 团队&#xff0c;后来去了 Meta MySQL&#xff0c;也主导了 RocksDB 的开发。 Mark 在 #109595 的 bug report 给出了非常详细的复现步骤 在官方修复后…

反转字符串中的单词

给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。 注意&#xff1a;输入字符串 s中可能会存在前导空格、尾随空格…

一键转换bmp到jpg,轻松优化你的图片管理

在数字世界中&#xff0c;图片是我们日常工作和生活中的重要组成部分。然而&#xff0c;不同的文件格式可能会给我们的图片管理带来诸多不便。这时&#xff0c;我们就需要一个简单而强大的工具来帮助我们轻松转换图片格式。今天&#xff0c;我们为大家带来了一款全新的bmp到jpg…

Paypal发布公开信,三月已过,PYUSD发展如何?

2023年8月8日&#xff0c;美国支付巨头Paypal正式宣布推出其稳定币PYUSD&#xff0c;成为美国传统大型金融机构发行稳定币的首家企业。 当时&#xff0c;正值美国SEC与加密交易所Coinbase、Binance的诉讼白热化&#xff0c;Paxos被迫停止发行BUSD的阶段&#xff0c;在此背景下&…

【计算机网络学习之路】网络基础1

文章目录 前言一. 计算机网络发展局域网和广域网 二. 网络协议三. OSI七层模型四. TCP/IP四层&#xff08;五层&#xff09;模型五. 计算机体系结构与网络协议栈六. 协议形式及局域网通信数据包封装与分用 七. 跨网络通信八. MAC地址与网络通信的理解结束语 前言 本系列文章是…