cobol和java_现代化历险:策略+将COBOL转换为Java的示例

cobol和java

在Keyhole Software,我们在很大程度上是一家现代化公司。 我们有一些顾问,专门研究将旧的代码迁移到新的,翻新的残旧代码库,并为大多数已经被供应商锁定的企业设计更光明的未来。

作为这些经验的一个有趣的副作用,我们遇到了一些重复的模式和策略,以了解如何实现遗留系统的现代化。

在此博客中,我们将介绍一种看起来非常流行的策略,即Re-Platforming ,并将用我们开发的Keyhole Labs产品进行演示。 这篇文章的基本流程是:

  • 现代化概论
  • 重新平台战略的高层定义
  • 使用Keyhole语法树变压器进行重新平台化的示例
  • 结束语
  • 摘要

“我要进行一次现代化……不等,也许要两个……”

当我们第一次围绕现代化主题吸引客户时,我们会看到他们在此过程中实际想要完成的工作的定义各不相同。 这些范围包括从大型机应用程序退出,从ESB /经典SOA架构过渡到基于云的PaaS实施,再到从供应商锁定/分层架构迁移到DevOps /微服务架构。

随着十年前最近更新其技术堆栈的公司遇到成功运营或成长的一些关键问题,所有这些情况的发生频率越来越高:

  • 部署问题:所有内容都必须作为一个单元进行部署,这是一个痛苦的过程,并且/或者与其所有基础架构紧密耦合
  • 可伸缩性问题:可伸缩性的垂直极限受到了打击–这意味着机器无法足够快地变大以应对容量的增加
  • 性能问题:系统中消息/事务的数量正在增加延迟,在某些情况下会导致级联故障
  • 资源问题:使用该系统的工程师和计算机科学家本来就不在或即将退休,并且不再在学校教授编程语言


因此,请进入现代化计划。 让我们首先回顾一下“重平台”策略及其优缺点。

这就像修理我的靴子吗?”

重新平台有时也称为升降机。 从根本上讲,重新平台是将一种代码语言转换为另一种代码语言,即进行翻译。 作为现代化策略,这意味着将较旧的代码语言转换为较新的代码语言。

由于各种原因,大型机在一些大型企业中仍然很普遍,因此,像COBOL这样的旧代码库也仍然存在。 脱离这些较旧的代码库和大型机的原因通常是以下之一:

  • 资源问题(如上所述):大型机程序员正变得稀缺,并且这些语言集并没有深入地涵盖在现代课程中。 招聘新开发人员比较困难,尤其是在快速变化和技术选择日趋广泛的情况下。 更少的员工愿意研究某些被淘汰的技术。
  • 对于任何规模的企业而言,大型机都是一笔巨大的费用,而垂直增长则是唯一的增长选择–有时这是昂贵的。
    大多数现代体系结构中常见的灾难恢复和高可用性策略可能会对大型机造成成本上的限制。
  • 程序语言构造(OOP,函数式编程,响应式编程等)中不能轻易利用更新的编程模式-因此限制了选择的范围。
  • SDLC的变化–即从瀑布过渡到敏捷过程以保持竞争力。

因此,长话短说-说“重新平台化”实际上是什么意思?

在此过程中,将分析较旧的代码库以确定代码库中的语法或模式。

一旦定义了语法树或一组代码模式,便会通过某些单步或多步编译器软件运行原始代码库(即COBOL),以将旧代码转换为所需的最终状态(通常是Java, C#或更高版本的等效语言。

从业务角度来看,这可能非常有吸引力。 无需让产品所有者和开发人员组成团队来逐渐用新语言重新编写每个旧代码位,此方法有望通过几次按钮操作来完成所有繁重的工作。 听起来不错!

好吧,教授,请稍等一下-在继续进行之前,这种方法存在一些固有的问题,需要提到。 最难的事情是:

代码翻译不一定能解决技术问题!

在某些情况下,这些旧代码库可能已经存在了20多年。 这可能是20多年的错误决定,或者是特定于大型机的决策被嵌入到您的代码中。

所有的翻译过程都将为您提供那些潜在的代码地雷,这些地雷现在正在使用一种新的语言,它们可能无法从大型机的某些慷慨和能力中受益。

代码可能看起来比大型机差!

在此过程中运行代码有时可能最终看起来像是被削木机扔掉了。 某些大型机和遗留代码构造/行为无法很好地或根本无法转化为较新的代码库。 (例如:在一个最近的客户处,我们找到了一个示例,其中在一个代码库中x / 0的数学运算返回0!)

即使代码可以转换并看起来不错,这也不意味着它将始终运行!

仅仅翻译成另一种语言并不能保证执行成功–一次成功的翻译通常意味着没有语法错误。

可能需要一些调整,其他基础结构来帮助代码工作和构建。

正在运行!=正在执行

同样,如果我们让它运行和构建,那么在我们的试验性转换中,一切似乎都很棒。 一旦我们处理了数百万笔交易和记录,您就会发现其中的所有漏洞。

这个过程很可能不会降低复杂性!

在此过程中,您很可能会从处理其所有复杂性的过程(在某些情况下,几乎没有或没有I / O损失)过渡到对资源的​​慷慨解囊。

将这些代码库转移到较新的语言中,通常涉及一些关注点分离:

  • 与内联SQL语句相对的数据访问层
  • 与基于文件的数据存储相反的潜在新关系数据存储
  • 表示层,与直接在其中烘焙的UI代码相对
  • 服务/业务逻辑层作为自己的层

可能需要一些其他基础架构来处理大型机免费提供的功能

像消息传递,容器或虚拟机编排,队列和AD / LDAP / OAuth集成等。

因此,现在您可能会感觉就像您刚走进一家医药商业广告,我在那儿说:

“这种小药丸可以解决您所有的背痛和黄色的趾甲问题。 潜在的副作用可能包括呕吐,眼睛和/或耳朵出血,暂时性视力丧失,自发性脱发以及对字母“ A”的痛苦敏感性。”

但是,如果您专注于以下方面,这可能是一个成功的旅程:

  1. 如果您有使用旧版/大型机语言编写的大型代码库,则此过程可以使您的代码库很快地转变为更现代的代码库。
  2. 从这一点开始,仅凭他们现在可以读取代码的事实,您的开发团队就可以更有能力在所需的最终状态下更新应用程序。

如果您选择一个可以将语法树用于初始转换的过程,则……

您只需调整语法并重新运行即可快速调整和调整更新后的输出。

有时基于模式的转换是唯一的选择。 但是,在许多情况下,可以生成语法树–然后您只需调整语法即可,而不是一次性调整输出或单个模式。

Keyhole的Syntax Tree Transformer及其专有的COBOL语法解析器基于语法,并且可以做到这一点!

这是使您分阶段实施的可行选择。

尤其是如果您的组织没有人员来处理可能将数千个程序转换为新堆栈的工作。

通过在短时间内转换所有旧代码,您可以更快地淘汰旧技术。 然后,您可以重新分配这些资源,以分析和重新编写或清理具有最大业务价值和ROI的代码部分。

这使组织可以对业务真正重要的方面做出更有目的的决策。

提供对您的代码库中应用的业务逻辑的宝贵见解和分析。

在某些情况下,业务逻辑可能与代码库一样古老,并且不再适用。 大多数客户从中发现了很多价值,最终仅通过分析活动就将他们的代码库减少了10-25%。

有机会引入DevOps作为转换的一部分。

根据所需的代码最终状态,在转换过程之外,有机会引入DevOps作为转换的一部分可能会有所帮助。 有时,“有能力”站起来使用某些工具或实施新流程最终会成为机会,可以注入最佳实践,而无需经历太多繁琐的工作或走闸。

这些新的流程和工具可以被业务的其他领域所利用,并通过提高敏捷性和引起某些文化转变来增加价值。

这个过程可以是短期预算双赢。

大型机和较旧技术具有快速转换和弃用的潜力,因此可以收回资本支出和维护成本。

使代码进入转换后状态的总开发成本通常比手动团队重写要小。

需要注意的是,从长远来看,这可能是一项更昂贵的工作,因为现在新语言和基础架构中的代码量很大–可能需要新的/额外的资源来维护和扩展代码库。 –但是至少您应该能够找到它们!

该策略的要点是:

如果您确定自己意识到该流程实际上可以做什么,并选择一个强大的基于语法的工具(例如Keyhole语法树变形器和我们的Parser –只是说出来),那么您将获得可预测的结果,从而节省预算和时间获胜。

既然我们已经了解了实施此策略的定义和利弊,那么实际上让我们轻描淡写吧。 本文的用例将使用Keyhole语法树转换器从COBOL转换为JAVA。

“让我们已经重新平台了!”

为了开始这个示例,我们将从COBOL的样本位开始,该样本已被我们的专有语法解析器转换为JSON语法树。 COBOL程序仅读取DB2数据存储并返回员工列表。 我们将不会显示COBOL到JSON的实际转换-而是从已经转换的COBOL程序开始。

(对不起,这是博客文章的秘诀–因此,我们将以这种烹饪表演风格为出发点,并从昨晚已经准备好的火鸡开始!如果您对组织的流程感兴趣或想要演示–请与我们联系 )。

首先,我们需要介绍几个设置项目:

  • 对于此示例,您将需要克隆此存储库: https : //github.com/in-the-keyhole/khs-syntax-tree-transformer
  • 您将需要使用支持Docker的机器(Windows 10,各种版本的Linux,Mac)。 这是针对DB2示例的,如果您不想弄混Docker,则在回购中有一个简单的COBOL示例。
  • 这是一个人为的例子! 它并不意味着可以治愈任何疾病或在任何生产环境中使用! 它旨在演示该机制,并说明如何从语法树到Java应用程序。

好的,让我们开始吧!

步骤1:
克隆存储库后,将其作为Maven项目导入Eclipse,STS或Intellij。

第二步:
使用JSON输入文件的命令行参数和发出的Java包名称执行main方法。 像这样:

这将在项目目录中生成一个发出的Program.java program

package khs.res.example.Programpublic class Program   {private Double CONST-PI = null;  private Double WORK-1 = 0;  private Double WORK-2 = 0;  private Double PRINT-LINE = null;  public void static main(String[] args) {Program job = new Program ();job.A-PARA ();}   public void A-PARA () {WORK-1 = 123.46WORK-2 = WORK-2+2WORK-2 = WORK-3*3C-PARA()}public void B-PARA () {CONST-PI = Math.PI;EDT-ID = ZERO}public void C-PARA () {B-PARA()}}

以下是我们的程序将使用的秘密酱汁分析器创建的输入demo.json

{"name" : "Program","typeName" : "CLASS","variables" : [ {"name" : "CONST-PI","typeName" : "VARIABLE","value" : null,"isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "WORK-1","typeName" : "VARIABLE","value" : "ZERO","isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "WORK-2","typeName" : "VARIABLE","value" : "ZERO","isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "PRINT-LINE","typeName" : "VARIABLE","value" : null,"isLocal" : false,"isWorking" : true,"isArray" : true,"fileLevel" : null,"variables" : [ {"name" : "EDT-ID","typeName" : "VARIABLE","value" : "SPACES","isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "FILLER","typeName" : "VARIABLE","value" : "' Perimeter '","isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "EDT-3-15-CIR","typeName" : "VARIABLE","value" : null,"isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "FILLER","typeName" : "VARIABLE","value" : "' Radius '","isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "EDT-3-15-RAD","typeName" : "VARIABLE","value" : null,"isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "FILLER","typeName" : "VARIABLE","value" : "' Pi '","isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]}, {"name" : "EDT-1-15-PI","typeName" : "VARIABLE","value" : null,"isLocal" : false,"isWorking" : true,"isArray" : false,"fileLevel" : null,"variables" : [ ]} ]} ],"functions" : [ {"name" : "A-PARA","typeName" : "FUNCTION","methods" : [ {"name" : "123.46TOWORK-1","typeName" : "METHOD","type" : {"name" : null,"typeName" : "MOVE","varName" : "WORK-1","value" : "123.46"}}, {"name" : "2TOWORK-2","typeName" : "METHOD","type" : {"typeName" : "ADD","value" : "2","var1" : "WORK-2","var2" : null}}, {"name" : "3GIVINGWORK-3","typeName" : "METHOD","type" : {"typeName" : "MULTI","value" : "3","var1" : "WORK-2","var2" : "WORK-3"}}, {"name" : "C-PARA","typeName" : "METHOD","type" : {"name" : "C-PARA","typeName" : "CALL"}} ]}, {"name" : "B-PARA","typeName" : "FUNCTION","methods" : [ {"name" : "PITOCONST-PI","typeName" : "METHOD","type" : {"name" : null,"typeName" : "MOVE","varName" : "CONST-PI","value" : "PI"}}, {"name" : "ZEROTOEDT-ID","typeName" : "METHOD","type" : {"name" : null,"typeName" : "MOVE","varName" : "EDT-ID","value" : "ZERO"}} ]}, {"name" : "C-PARA","typeName" : "FUNCTION","methods" : [ {"name" : "B-PARA","typeName" : "METHOD","type" : {"name" : "B-PARA","typeName" : "CALL"}} ]} ]
}

DB2示例

现在,在持久性方面迈出了一步,我们将转换简单的DB2程序以演示使用DB2 Express的Java代码。

这是示例DB2 Cobol应用程序:

* --------------------------------------------------------------
* Selects a single employee into a record's detail fields, and
* then displays them by displaying the record.
*
* Demonstrates Cobol-to-Java translation of a DB2 SELECT INTO
* the detail fields of a parent record.
*
* Java has no native notion of a record aggregate. A SQL
* SELECT INTO similarly lacks a record construct.
*
* Lou Mauget, January 31, 2017
* --------------------------------------------------------------IDENTIFICATION DIVISION.PROGRAM-ID. COBOLDB2.DATA DIVISION.WORKING-STORAGE SECTION.EXEC SQLINCLUDE SQLCAEND-EXEC.EXEC SQLINCLUDE EMPLOYEEEND-EXEC.EXEC SQL BEGIN DECLARE SECTIONEND-EXEC.01 WS-EMPLOYEE-RECORD.05 WS-EMPNO PIC XXXXXX.05 WS-LAST-NAME PIC XXXXXXXXXXXXXXX.05 WS-FIRST-NAME PIC XXXXXXXXXXXX.EXEC SQL END DECLARE SECTIONEND-EXEC.PROCEDURE DIVISION.EXEC SQLSELECT EMPNO, LASTNAME, FIRSTNMEINTO :WS-EMPNO, :WS-LAST-NAME, :WS-FIRST-NAME FROM EMPLOYEEWHERE EMPNO=200310END-EXEC.IF SQLCODE = 0DISPLAY WS-EMPLOYEE-RECORDELSEDISPLAY 'Error'END-IF.STOP RUN.

使用我们的Antlr解析器已将其转换为JSON语法树。 使用khs.transformer.CommandLine.java对象将语法树JSON转换为以下Java应用程序。

/*** Java source, file COBOLDB2.java generated from Cobol source, COBOLDB2.cbl** @version 0.0.3* @author Keyhole Software LLC*/
public class COBOLDB2   {private static Logger Log = LoggerFactory.getLogger("COBOLDB2");// SQLCAprivate int sqlcode;// Level 05private String v_ws_empno;// Level 05private String v_ws_last_name;// Level 05private String v_ws_first_name;// Level 01private InItem[] v_ws_employee_record = new InItem[]{ () -> v_ws_empno, () -> v_ws_last_name, () -> v_ws_first_name };// Procedure division entry:public static void main(String[] args) {try {COBOLDB2 instance = new COBOLDB2();instance.m_procdiv();} catch (Exception e) {e.printStackTrace();}}private void m_procdiv () throws Exception {final String sql = "SELECT EMPNO, LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPNO=200310";final OutItem[] into = new OutItem[]{s -> v_ws_empno = (String)s,s -> v_ws_last_name = (String)s,s -> v_ws_first_name = (String)s};sqlcode = Database.getInstance().selectInto( sql, into );if ( sqlcode == 0 ) {Display.display( v_ws_employee_record );} else {Display.display( "Error" );}// EXIT ...System.exit(0);}}

以下步骤描述了如何设置DB2以执行该应用程序。 DB2 Express在Docker容器中运行。 没有池连接。 这只是一个演示。 ☺

Docker DB2 Express容器

确保您有权访问Docker 。

使用此Docker映像进行初始DB2绑定: https : //hub.docker.com/r/ibmcom/db2express-c/

docker run --name db2 -d -it -p 50000:50000 -e DB2INST1_PASSWORD=db2inst1-pwd -e LICENSE=accept -v  $(pwd)/dbstore:/dbstore ibmcom/db2express-c:latest db2start
docker exec -it db2 bash

创建运行中的Docker DB2 Express容器守护程序,并登录到bash会话,如上所示。

发行su db2inst1
发出db2sampl (花一些时间来创建数据库“ SAMPLE”)。

[db2inst1@6f44040637fc /]$ db2samplCreating database "SAMPLE"...Connecting to database "SAMPLE"...Creating tables and data in schema "DB2INST1"...Creating tables with XML columns and XML data in schema "DB2INST1"...'db2sampl' processing complete.

完成烟雾测试安装后:

以Java运行: khs.transformer.CheckDb2Connection

控制台上显示以下内容:

一旦在Docker容器上安装并验证了数据库,就可以执行转换后的Cobol / DB2到Java程序khs.res.db2demo.COBOLDB2.java 。 一旦执行该程序,我们将得到以下输出:


基本上是魔术!
同样,这是人为的,但是我们采用了一个COBOL程序,该程序被转换为JSON语法树,然后最终得到了一个Java应用程序,该程序从DB2数据库返回了我们的数据–正是COBOL程序所做的!

结论

希望在本文和上面的示例之后,我们都对重新平台战略有了更好的了解。 此策略是否适合您的组织是另一个话题(顺便提一下,我们很乐意与您联系)。

我要打动的重点是,即使听起来很酷,代码转译也不是遗留代码狼的灵丹妙药! 我还想告诉您,虽然充满了危险,但是如果正确使用正确的方法并使用可靠的工具(ahem – 锁Kong语法树变压器和解析),这可能是一个非常可行的策略。

“那么,我们在这里完成了什么?”

总而言之,我们涵盖了以下内容:

  • 现代化简介
  • 回顾现代化的重平台战略
  • 使用Keyhole语法树变压器的重新平台示例
  • 关于此策略的价值/风险的其他总结想法

我们肯定希望您能像我们一样喜欢它。 请,如果您有任何问题或反馈,请在下面发布或直接与我们联系。

谢谢,记得负责任地现代化!

资源/参考:也可以在这里找到此演示: https : //github.com/in-the-keyhole/khs-syntax-tree-transformer

翻译自: https://www.javacodegeeks.com/2017/02/adventures-modernization-strategy-example-converting-cobol-java.html

cobol和java

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

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

相关文章

c# mysql sdr_C#结合数据库实现验证识别ID卡内容的方法

本文所述实例为C#结合数据库,来验证所识别的ID卡内容,通过本实例代码,用户可以轻松实现对ID卡会员信息的验证。该实例代码可实现读取数据库,进而逐步实现数据库连接,数据库读取,ID卡读取,ID卡信…

递归算法 流程图_什么是算法?如何学习算法?算法入门的学习路径

什么是算法?有一个很著名的公式 “程序数据结构算法”。曾经跟朋友吃饭的时候我问他什么是算法,他说算法嘛,就是一套方法,需要的时候拿过来,套用就可以,我吐槽他,他说的是小学数学题的算法&…

java webmethod 参数_java详解Spring接收web请求参数的方式

本篇文章给大家带来的内容是java详解Spring接收web请求参数的方式 。有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助。1 查询参数请求格式:url?参数1值1&参数2值2...同时适用于GET和POST方式spring处理查询参数的方法又…

envoy重试_具有Envoy代理的微服务模式,第二部分:超时和重试

envoy重试该博客是系列文章的一部分,该系列文章更深入地介绍了Envoy Proxy和Istio.io ,以及它如何实现一种更优雅的连接和管理微服务的方式。 跟随我christianposta ,紧跟这些博客文章的发布。 什么是Envoy代理 ,它如何工作&…

python中字符串格式化的形式_Python中format函数字符串格式化入门

格式化在程序开发中非常常见,大家肯定不陌生,Python中也存在多重格式化方式,format函数就是其中一种。函数原型format(value[, format_spec])参数意义value: 需要被格式化的字符串format_spec: 格式化的格式函数定义与…

Java的超类/基类Object

文章目录简介主要方法equals简介 所有的类都继承了 Object,即 Object 是所有类的父类,所以所有的 Java 类都继承了 Object 的所有方法。 比如你写一个类如下: public class Question { ... }实际上这个类是继承自 Object 的,默…

网络研讨室_即将举行的网络研讨会:调试生产中Java的5种最佳实践

网络研讨室您的团队是否花费超过10%的时间在生产中调试Java? 将新代码部署到生产中是一项艰巨的任务。 在您的本地环境中起作用的东西在生产中的作用并不相同,您可以通过用户来了解。 不理想吧? 生产中的调试是一个关键要素&…

window部署python项目_Django在Window下的部署

转载 : codingsoho.com前言本文主要介绍利用apache去部署Django项目,所有步骤均在本机Window7和阿里云验证通过。配置本例的基本配置如下:工作目录: C:/virtualenv/zakkabag项目名称: zakkabag最终的安装版本如下,后面…

chrome gwt1.7_快速提示:使用Chrome开发工具调试GWT应用程序

chrome gwt1.7调试是软件开发的重要方面。 拥有正确的工具可以节省大量时间和头痛。 在GWT Super Dev模式之前,经典的Dev模式允许使用JVM调试。 开发人员可以在其IDE中设置断点,并使用调试模式来跟踪错误和错误。 现在,在超级开发模式下&…

java事件编程_java基础 ---Swing事件编程

java基础 ---Swing事件编程GUI的设计就剩个菜单组建,这个组件也是想当于容器套容器,在设计方面没有什么难度,主要是一些事件的响应。还有另一种事件的监听方式,也就是适配器监听方法。1、菜单要设计一个菜单那么有三大组件是不可或…

python3鄙视python2_Python3 正在毁灭 Python的原因分析

Python 3毫不费力地成为发生在Python社区里最糟糕的事。我还记得第一次使用Python的时候,我还在花大量时间在C这块上,而Python就像是我的一次开光。我可以打开文本编辑器用几秒钟或者几分钟写出一个可以工作的程序,而不是用几小时或几天。我记…

Java如何加载类的呢?

JVM加载类 首先查看内存中是否存在该类(内存中所有类都是以Class的实例对象存在),若不存在则会通过环境变量中的路径值在电脑或者其它设备的硬盘中找到该类(即.class文件),然后JVM会将其读取到内存中&…

brew卸载jenv_使用brew,cask和jenv在MacOSX上设置多个Java JRE / JDK

brew卸载jenv昨天在Java9的Jigsaw HackTheTower事件中,我意识到我需要加强我的游戏并改善我现有的机制,以在我的机器上维护几个不同的JDK。 我曾经手动下载jdk,或使用brew cask来安装它们,我会在我的〜/ bash_profile中设置bash …

java过滤器api_springboot集成过滤器

封装自定义接口filter包含两个方法,第一个过滤的路径数组,第二个为过滤器执行的顺序.spring boot 会按照order值的大小,从小到大的顺序来依次过滤。package com.theeternity.common.baseFilter;import javax.servlet.Filter;/*** program: ApiBoot* description: 封…

Servlet 运行原理

文章目录Servlet 如何运行演示 Servlet 运行原理Servlet 如何运行 用户向浏览器地址栏输入:http://ip:port/helloweb/sayHello?namezs 浏览器使用 ip:port(端口号)连接服务器 浏览器将请求数据按照 http 协议打成一个数据包(请求数据包)发送给服务器 请求数据包…

python dicom 器官分割_python+opencv阈值分割

37 #获取像素点的最大值和最小值38 arr_temp np.reshape(img_arr,(lens,))39 max_val max(arr_temp)40 min_val min(arr_temp)41 #图像归一化42 img_arr (img_arr-min_val)/(max_val-min_val)43 #绘制图像并保存44 #保存图片时去掉周围白边45 plt.axis(off)46 fig plt.gcf()47…

解析浏览器访问服务器 Servlet 应用程序的交互过程(Servlet 容器如何处理请求资源路径)

案例 1: 请求资源路径:http://localhost:8080/web01/greeting?namezs 浏览器通过 localhost:8080 连接服务器;服务器在 webapps 目录下寻找 web01 目录,找到后进入web01 目录内寻找 WEB-INF 目录,在进入 WEB-INF 目…

java github_GitHub Research:超过50%的Java记录语句写错了

java github为什么生产日志无法帮助您找到错误的真正根本原因? 询问您是否使用日志文件监视您的应用程序几乎就像询问…您是否喝水。 我们都使用日志,但是我们如何使用它们则是一个完全不同的问题。 在下面的文章中,我们将对日志进行更深入…

yolov5论文_YOLOv5的妙用:学习手语,帮助听力障碍群体

编辑:魔王、杜伟计算机视觉可以学习美式手语,进而帮助听力障碍群体吗?数据科学家 David Lee 用一个项目给出了答案。如果听不到了,你会怎么办?如果只能用手语交流呢?当对方无法理解你时,即使像订…

python制作系统程序与html交互_python+html语音人物交互_flask后台与前端(html)交互的两种方法...

基于python flask框架搭建webflask后台与前端(html)交互的两种方法:方法1 使用flask-wtf 提供的表单用常见的登录为例:// An highlighted blockfrom flask_wtf import Formclass LoginForm(Form): # 登录表单ROLE SelectField(角色, choices[(s, 管理员…