jbase虚拟M层的设计

对于只是自己产品内部使用的打印程序来说(比如打印收费单,打印结算单等),打印逻辑写在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存放的目录
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【proverif】proverif的语法-各种密码原语的介绍和具体编码

proverif-系列文章目录 【proverif】proverif的下载安装和初使用【proverif】proverif的语法-解决中间人攻击-代码详解【proverif】proverif的语法2-各种密码原语的编码 &#xff08;本文&#xff09; 文章目录 proverif-系列文章目录前言铺垫知识一、对称加密二、非对称加密三…

大模型幻觉成应用落地难题 最新评测文心一言解决幻觉能力最好

大模型中的幻觉问题 “林黛玉倒拔垂杨柳”、“月球上面有桂树”、“宋江字武松”……相信经常使用大语言模型都会遇到这样“一本正经胡说八道”的情况。这其实是大模型的“幻觉”问题&#xff0c;是大模型行业落地的核心挑战之一。例如幻觉会影响生成内容的可靠性&#xff0c;…

大数据基础设施搭建 - Hadoop

文章目录 一、下载安装包二、上传压缩包三、解压压缩包四、配置环境变量五、测试Hadoop5.1 测试hadoop命令5.2 测试wordcount案例5.2.1 创建wordcount输入文本信息5.2.2 执行程序5.2.3 查看结果 六、分发压缩包到集群中其他机器6.1 分发压缩包6.2 解压压缩包6.3 配置环境变量 七…

TDengine Restful Authorization 自定义Token

Restful 接口是 TDengine 最常用的接口&#xff0c;仅次于 JDBC。TDengine 支持 HTTP 和 HTTPS&#xff0c;但通常情况下&#xff0c;大家不想搞证书&#xff0c;又在内网环境中&#xff0c;采用 HTTP 方式比较多。但 HTTP 是明文传输&#xff0c;只要抓个包就知道账号密码了。…

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;它们都是 …

YOLOv5项目实战(4)— 简单三步,教你按比例划分数据集

前言:Hello大家好,我是小哥谈。本节课就教大家如何去按照比例去划分数据集,希望大家学习之后可以有所收获!~🌈 前期回顾: YOLOv5项目实战(1)— 如何去训练模型 YOLOv5项目

万字长文:从 C# 入门学会 RabbitMQ 消息队列编程

RabbitMQ 简介 RabbitMQ 是一个实现了 AMQP 协议的消息队列&#xff0c;AMQP 被定义为作为消息传递中间件的开放标准的应用层协议。它代表高级消息队列协议&#xff0c;具有消息定位、路由、队列、安全性和可靠性等特点。 目前社区上比较流行的消息队列有 kafka、ActiveMQ、Pul…

freeRTOS--软件定时器

一、什么是定时器&#xff1a; 简单可以理解为闹钟&#xff0c;到达指定一段时间后&#xff0c;就会响铃。STM32 芯片自带硬件定时器&#xff0c;精度较高、达到定时时间后会触发中断&#xff0c;也可以生成 PWM 、输入捕获、输出比较&#xff0c;等等&#xff0c;功能强大&am…

基于黄金正弦算法优化概率神经网络PNN的分类预测 - 附代码

基于黄金正弦算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于黄金正弦算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于黄金正弦优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

从0开始学习数据结构 C语言实现 1.前篇及二分查找算法

一、前篇 1、什么是数据结构&#xff1f; 数据结构是带有结构特性的数据元素的集合&#xff0c;它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系 2、时间复杂度与空间复杂度 大O符号是用于描述函数渐进行为的数学符号 常用函数的增长表 阶乘O(n!) > 指数…

基于蝠鲼觅食算法优化概率神经网络PNN的分类预测 - 附代码

基于蝠鲼觅食算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于蝠鲼觅食算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于蝠鲼觅食优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

Spring Boot 中使用 ResourceLoader 加载资源的完整示例

ResourceLoader 是 Spring 框架中用于加载资源的接口。它定义了一系列用于获取资源的方法&#xff0c;可以处理各种资源&#xff0c;包括类路径资源、文件系统资源、URL 资源等。 以下是 ResourceLoader 接口的主要方法&#xff1a; Resource getResource(String location)&am…

VSCode 运行java程序中文乱码

现象描述 java文件中包含中文&#xff0c;运行java程序后&#xff0c;乱码报错。 解决方法 原本运行指令为 cd "d:\programProjects\Java_proj\" ; if ($?) { javac Solution.java } ; if ($?) { java Solution } 需要添加 编码格式 -encoding utf8 cd &quo…

python数据处理作业6:随机生产一个服从正态分布长度为1000的数组,将这个数组划分为25个区间,画出数组的直方图和密度图

每日小语 我只有忘掉自己&#xff0c;才能津津有味地进行沉思和遐想。——卢梭 gpt代码 import numpy as np import matplotlib.pyplot as plt from scipy.stats import norm# 随机生成一个服从正态分布的长度为1000的数组 data np.random.randn(1000)# 划分为25个区间 num_…

【Linux】U盘安装的cfg引导文件配置

isolinux.cfg文件 default vesamenu.c32 timeout 600display boot.msg# Clear the screen when exiting the menu, instead of leaving the menu displayed. # For vesamenu, this means the graphical background is still displayed without # the menu itself for as long …

什么是好用的HR人才测评?

对于HR来说&#xff0c;选用一个合适的测评工具&#xff0c;我想不外乎以下几点&#xff1a; 1、成本可控 不是所有的HR都能申请到足够的资金&#xff0c;去做专业的人才测评&#xff0c;尤其是中小企业&#xff0c;这可是一笔不小 的开支。即使是基层普通岗位的成本&#xf…

redis运维(十一) python操作redis

一 python操作redis ① 安装pyredis redis常见错误 说明&#xff1a;由于redis服务器是5.0.8的,为了避免出现问题,默认最高版本的即可 --> 适配 ② 操作流程 核心&#xff1a;获取redis数据库连接对象 ③ Python 字符串前面加u,r,b的含义 原因&#xff1a; 字符串在…

视频一键转码:批量转换MP4视频的技巧

随着数字媒体设备的普及&#xff0c;视频文件在生活中扮演着越来越重要的角色。而在处理视频文件时&#xff0c;有时需要将其转换为不同的格式以适应不同的需求。其中&#xff0c;MP4格式因其通用性和高质量而备受青睐。本文详解云炫AI智剪如何一键转码的技巧&#xff0c;帮助批…

基础课6——开放领域对话系统架构

开放领域对话系统是指针对非特定领域或行业的对话系统&#xff0c;它可以与用户进行自由的对话&#xff0c;不受特定领域或行业的知识和规则的限制。开放领域对话系统需要具备更广泛的语言理解和生成能力&#xff0c;以便与用户进行自然、流畅的对话。 与垂直领域对话系统相比…

msvcp140.dll是什么东西以及如何解决其文件缺失问题

当我们在使用Windows电脑的过程中&#xff0c;有时候可能会遇到一些由于系统文件缺失或者损坏而导致的问题。其中&#xff0c;"msvcp140.dll缺失"就是一种常见的错误提示。msvcp140.dll究竟是什么&#xff1f;为什么它会缺失&#xff1f;又该如何解决这个问题呢&…