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顶替Queryelse {//执行返回数据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.rhkb.cn/news/195582.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

合众汽车选用风河Wind River Linux系统

导读合众新能源汽车股份有限公司近日选择了Wind River Linux 用于开发合众智能安全汽车平台。 合众智能安全汽车平台(Hozon Automo-tive Intelligent Security Vehicle Plat-form)是一个面向高性能服务网关及车辆控制调度的硬件与软件框架&#xff0c;将于2024年中开始投入量产…

线性表的概念

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

【面试】测试/测开(未完成版)

1. 黑盒测试方法 黑盒测试&#xff1a;关注的是软件功能的实现&#xff0c;关注功能实现是否满足需求&#xff0c;测试对象是基于需求规格说明书。 1&#xff09;等价类&#xff1a;有效等价类、无效等价类 2&#xff09;边界值 3&#xff09;因果图&#xff1a;不同的原因对应…

《硅基物语.AI写作高手:从零开始用ChatGPT学会写作》《从零开始读懂相对论》

文章目录 《硅基物语.AI写作高手&#xff1a;从零开始用ChatGPT学会写作》内容简介核心精华使用ChatGPT可以高效搞定写作的好处如下 《从零开始读懂相对论》内容简介关键点书摘最后 《硅基物语.AI写作高手&#xff1a;从零开始用ChatGPT学会写作》 内容简介 本书从写作与ChatG…

如何在Docker部署Draw.io绘图工具并远程访问

文章目录 前言1. 使用Docker本地部署Drawio2. 安装cpolar内网穿透工具3. 配置Draw.io公网访问地址4. 公网远程访问Draw.io 前言 提到流程图&#xff0c;大家第一时间可能会想到Visio&#xff0c;不可否认&#xff0c;VIsio确实是功能强大&#xff0c;但是软件为收费&#xff0…

matlab二维曲面散点图插值方法

在 MATLAB 中&#xff0c;你可以使用以下函数进行二维曲面散点插值&#xff1a; griddata: 该函数可以在散点数据上进行二维插值&#xff0c;生成平滑的曲面。它支持多种插值方法&#xff0c;包括三次样条插值、最近邻插值、线性插值和自然邻近法插值。 scatteredInterpolant:…

大数据基础设施搭建 - Hadoop

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

Go ZIP压缩文件读写操作

创建zip文件 golang提供了archive/zip包来处理zip压缩文件&#xff0c;下面通过一个简单的示例来展示golang如何创建zip压缩文件&#xff1a; func createZip(filename string) {// 缓存压缩文件内容buf : new(bytes.Buffer)// 创建zipwriter : zip.NewWriter(buf)defer writ…

flowable消息事件

一&#xff1a;启动事件 定义消息。 引用消息。 <startEvent id"msgStart" name"消息启动事件" isInterrupting"true"><messageEventDefinition messageRef"myMsgStart"></messageEventDefinition> </startE…

【ROS导航Navigation】五 | 导航相关的消息 | 地图 | 里程计 | 坐标变换 | 定位 | 目标点和路径规划 | 激光雷达 | 相机

致谢&#xff1a;ROS赵虚左老师 Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 参考赵虚左老师的实战教程 一、地图 nav_msgs/MapMetaData 地图元数据&#xff0c;包括地图的宽度、高度、分辨率等。 nav_msgs/OccupancyGrid 地图栅格数据&#…

reactive和effect,依赖收集触发依赖

通过上一篇文章已经初始化项目&#xff0c;集成了ts和jest。本篇实现Vue3中响应式模块里的reactive方法。 前置知识要求 如果你熟练掌握Map, Set, Proxy, Reflect&#xff0c;可直接跳过这部分。 Map Map是一种用于存储键值对的集合&#xff0c;并且能够记住键的原始插入顺…

【6】Spring Boot 3 集成组件:knift4j+springdoc+swagger3

目录 【6】Spring Boot 3 集成组件&#xff1a;knift4jspringdocswagger3OpenApi规范SpringFox Swagger3SpringFox工具&#xff08;不推荐&#xff09; Springdoc&#xff08;推荐&#xff09;从SpringFox迁移引入依赖配置jAVA Config 配置扩展配置&#xff1a;spring securit…

Linux安装DMETL5与卸载

Linux安装DMETL5与卸载 环境介绍1 DM8数据库配置1.1 DM8数据库安装1.2 初始化达梦数据库1.3 创建DMETL使用的数据库用户 2 配置DMETL52.1 解压DMETL5安装包2.2 安装调度器2.3 安装执行器2.4 安装管理器2.5 启动dmetl5 调度器2.6 启动dmetl5 执行器2.7 启动dmetl5 管理器2.8 查看…

计算机毕业设计选题推荐-一周穿搭推荐微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

系列二十六、idea安装javap -c

一、概述 javap -c是一个能够将.java文件反编译为.class文件的指令&#xff0c;例如我在idea中编写了一个Car.java文件&#xff0c;我想看看这个类被编译后长什么样的&#xff0c;就可以使用该指令进行查看。 二、配置 2.1、 Java Bytecode Decompiler File>Settings>Pl…

TMS320F28335使用多个串口时,SCIRXST Register出现错误

TMS320F28335使用多个串口时&#xff0c;SCIRXST Register出现错误 void ClearErrorState(void) {if((SciaRegs.SCIRXST.bit.FE 1)||(SciaRegs.SCIRXST.bit.BRKDT 1)){SciaRegs.SCICTL1.bit.SWRESET 0;SciaRegs.SCICTL1.bit.SWRESET 1;}if((ScibRegs.SCIRXST.bit.FE 1)||(S…

报错资源不足,k8s使用containerd运行容器修改挂载点根目录换成/home

运行k8s一段时间发现存储不足报错 发现这里用的是根路径的挂载&#xff0c;修改一下

交易者最看重什么?anzo Capital这点最重要!

交易者最看重什么&#xff1f;有人会说技术&#xff0c;有人会说交易策略&#xff0c;有人会说盈利&#xff0c;但anzo Capital认为Vishal 最看重的应该是眼睛吧&#xff01; 29岁的Vishal Agraval在9年前因某种原因失去了视力&#xff0c;然而&#xff0c;他的失明并未能阻…

Databend 与海外某电信签约:共创海外电信数据仓库新纪元

为什么选择 Databend 海外某电信面临的主要挑战是随着业务量的增加&#xff0c;传统的 Clickhouse Hive 方案在数据存储和处理上开始显露不足。 原来的大数据分析采用的 Clickhouse Hive 方案进行离线的实时报表。但随着业务量的上升后&#xff0c;Hive的数据存储压力变大&…

LangGPT作者教你编写高质量提示词

CoT和ToT能够提升表现&#xff0c;但是会使得模型的使用变复杂。在对话的场景下容易消耗人的耐心&#xff1b;实际应用的场景下&#xff0c;比较消耗人的token。 还有一点需要说明的是&#xff0c;我们在写自己的prompt的时候&#xff0c;不应该盲目地追求和堆砌提示词技巧&am…