仓颉编程入门2,启动HTTP服务

上一篇配置了仓颉sdk编译和运行环境,读取一个配置文件,并把配置文件简单解析了一下。

前面读取配置文件,使用File.readFrom(),这个直接把文件全部读取出来,返回一个字节数组。然后又创建一个字节流,给文件字节写进去,又创建了一个StringReader,相当的麻烦。

后来又尝试使用File.openRead(),可以直接返回一个文件流,直接被StringReader使用。优化的代码如下:

public init(){let fs=File.openRead('./config.ini')                    //创建一个文件流let sr=StringReader(fs)                                 //创建一个字符串流读取对象var s=sr.readln()??""                                   //读取一行,如果没有内容就是空while(s.size>0){                                        //如果这一行有数据let a=s.split("=")                                  //对这一行分割 key = valuemap[a[0]]=a[1]                                      //a[0]是key  ,a[1]是value,存储到hashmaps=sr.readln()??""                                   //读取下一行}println(map)                                            //输出一下fs.close()}

接下来,启动一个http服务,按照官方给的代码示例:

咱们创建一个MyServer类,里面有一个属性是server,有初始化,有启动服务。注意配置文件类,已经修改为单例模式。

class MyServer{let serverpublic init(){let ip=Config.Instance.getString("serverIP")            //读取iplet port=Config.Instance.getInt("port")                 //读取端口server=ServerBuilder().addr(ip).port(port).build()                                //返回一个Server对象}func service(){//注册监听server.distributor.register("/index", {httpContext =>httpContext.responseBuilder.body("Hello 仓颉!")})// 启动服务server.serve()}}

接下来是main函数调用一下,代码如下:

main()
{println("cangjie http") let svr=MyServer()                              //创建myserver对象spawn {svr.service()                               //在子线程中运行http服务}while(true){                                    //主线程不能退,退了子线程也要退出println("cangjie http service")sleep(Duration.second)  // sleep for 1s.}}

 编译,.....不出所料,报错了。

报错的意思大概是let server,没有初始化,也没有类型说明,这样不行。那就给一个类型把。类型到底是什么呢?到这里我还是不知道的,那就随便写一个吧。let server:ServerBuilder,先写这个把,因为官方给的代码里面,看不出来到底是啥类型。继续编译:

又报了两个错,第一个错误,端口号应该是UInt16,那就转一下。

let port=UInt16(Config.Instance.getInt("port"))                 //读取端口 ,转换为UInt16 实际就是unsigned short

继续编译,还是报错。。。。。。。

到这个错误,基本明白了,serverBuiler返回的是一个Server类型的对象。下面那两个错误,是说ServerBuilder没有这两个方法。

意思就是给前面let server:serverBuilder 改成let server:Server。 前面为啥不直接写出Server呢?因为看官方的代码,真看不出来类型。这次编译通过了!!!!!!!

这里要吐槽一下,这种不用声明的方式,虽然用起来方便,但是对于初学者非常不友好,完全不清楚是啥类型的,也不知道应该去调用这个类型的什么方法,或者去找这个类的帮助文档。

(有可能用仓颉的开放插件会好点,目前是装逼阶段,暂时不用)

强烈建议官方出示例代码,带上类型。

强烈建议官方出示例代码,带上类型。

强烈建议官方出示例代码,带上类型。

运行截图如下:

现在实现了一个接口/index,尝试再增加一个/stop,当访问stop的时候,app.exe退出。在MyServer里面增加一个Bool类型的run,如果run等于true,那么主线程就继续,否则就退出。代码如下:

class MyServer{let server:Serverlet run:Bool=truepublic init(){let ip=Config.Instance.getString("serverIP")            //读取iplet port=UInt16(Config.Instance.getInt("port"))                 //读取端口server=ServerBuilder().addr(ip).port(port).build()                                //返回一个Server对象}func service(){//注册监听server.distributor.register("/index", {httpContext =>httpContext.responseBuilder.body("Hello 仓颉!")})//注册监听server.distributor.register("/stop", {httpContext =>httpContext.responseBuilder.body("再见 仓颉!")run=false})// 启动服务server.serve()}}

 编译.......又报错了,大致意思,let 声明的变量一般不能修改,想修改需要给func增加mut。或者直接用var。这么说,用var 就行了。

再次编译,没有问题,访问/stop。页面返回正常,app.exe主线程退出。

完整代码:

import std.io.*
import std.fs.*
import std.collection.*
import std.convert.*
import net.http.*
import std.sync.*
import std.time.*
/**
*配置文件类
*/
class Config
{let map:HashMap<String,String>=HashMap<String,String>()    //存储配置文件的mapstatic let  Instance:Config=Config()                        //单例模式public init(){let fs=File.openRead('./config.ini')                    //创建一个文件流let sr=StringReader(fs)                                 //创建一个字符串流读取对象var s=sr.readln()??""                                   //读取一行,如果没有内容就是空while(s.size>0){                                        //如果这一行有数据let a=s.split("=")                                  //对这一行分割 key = valuemap[a[0]]=a[1]                                      //a[0]是key  ,a[1]是value,存储到hashmaps=sr.readln()??""                                   //读取下一行}println(map)                                            //输出一下fs.close()                                              //关闭流}public func getString(key:String):String{                   //获取一个字符串配置return map[key]}public func getInt(key:String):Int32{                       //获取一个整数配置return Int32.parse(map[key])                             //字符转换为整数}
}class MyServer{                                                 //自定义服务类let server:Server                                           //声明server对象,必须带类型,但是不能初始化,因为要从var run:Bool=truepublic init(){let ip=Config.Instance.getString("serverIP")            //读取iplet port=UInt16(Config.Instance.getInt("port"))         //读取端口需要转出UInt16 实际就是unsigend shortserver=ServerBuilder().addr(ip).port(port).build()                                //返回一个Server对象}func service(){//注册监听/index,反回一个字符串server.distributor.register("/index", {httpContext =>httpContext.responseBuilder.body("Hello 仓颉!")})server.distributor.register("/stop", {                  //注册监听/stop。访问以后,就会退出应用httpContext =>httpContext.responseBuilder.body("再见 仓颉!")run=false})server.serve()                                           // 启动服务}}main()
{println("cangjie http")                                                    let svr=MyServer()                                       //创建myserver对象spawn {svr.service()                                        //在子线程中运行http服务}while(svr.run){                                          //主线程增加退出条件,退了子线程也要退出println("cangjie http service ${svr.run}")sleep(Duration.second)  // sleep for 1s.}}

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

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

相关文章

Apache James配置连接达梦数据库

项目场景&#xff1a; Apache James配置连接达梦数据库&#xff0c;其他配置中不存在的数据库也可参考此方案。 配置步骤 1、把需要的jar包导入到James 把DmJdbcDriver18.jar复制到下面lib目录下 james-2.3.2\lib 2、 修改连接配置 james-2.3.2\apps\james\SAR-INF\confi…

Dockerfile部署xxljob

使用Dockerfile部署xxljob 1. 背景 我们在使用定时任务调度时&#xff0c;通常会使用xxljob容器化部署xxljob&#xff0c;通常使用 docker pull xuxueli/xxl-job-admin:2.4.0 拉取镜像并启动容器。这种方式对于x86架构服务器来说&#xff0c;没有任何问题。但是在arm架构的服…

springboot项目引入了第三方jar包

应该把jar包放在resource目录下&#xff0c;新建一个lib目录放进去&#xff0c;不然打包的时候会报错找不到jar包&#xff0c;放入jar包&#xff0c;右键添加到库&#xff0c;才可以使用。 _g().startMarquee();

MapReduce基本原理

目录 整体执行流程​ Map端执行流程 Reduce端执行流程 Shuffle执行流程 整体执行流程 八部曲 读取数据--> 定义map --> 分区 --> 排序 --> 规约 --> 分组 --> 定义reduce --> 输出数据 首先将文件进行切片&#xff08;block&#xff09;处理&#xff…

【C语言】猜数字游戏

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 前言1. 随机数生成1.1 rand1.2 srand1.3 time1.4 设置随机数的范围 2. 猜数字游戏实现2.1 游戏菜单2.2 主函数部分2.3 game函数部分2.4 附代码2.5 优化代码 前言 前面学习的这些知识&#xff0c;我们就可以写一些稍微…

常见统计量与其抽样分布

什么是统计量 我们首先给出统计量的定义:设 X 1 , X 2 , ⋯ , X n X_1,X_2,\cdots,X_n X1​,X2​,⋯,Xn​ 为来自于总体X的一个样本&#xff0c; g ( X 1 , X 2 , ⋯ , X n ) g(X_1,X_2,\cdots,X_n) g(X1​,X2​,⋯,Xn​) 为关于 X 1 , X 2 , ⋯ , X n X_1,X_2,\cdots,X_n X…

C++ STL容器(三) —— 迭代器底层剖析

本篇聚焦于STL中的迭代器&#xff0c;同样基于MSVC源码。 文章目录 迭代器模式应用场景实现方式优缺点 UML类图代码解析list 迭代器const 迭代器非 const 迭代器 vector 迭代器const 迭代器非const迭代器 反向迭代器 迭代器失效参考资料 迭代器模式 首先迭代器模式是设计模式中…

linux网络编程7

24.9.24学习目录 一.网络通信过程&#xff08;续&#xff09;1.路由器 二.原始套接字&#xff08;SOCK_RAW&#xff09;1.创建原始套接字2.数据包解析 一.网络通信过程&#xff08;续&#xff09; 1.路由器 路由器是用于连接多个逻辑上分开的网络&#xff1b; 具有判断网络地…

React-Native 中使用 react-native-image-crop-picker 在华为手机上不能正常使用拍照功能

背景: React-Native 0.66 中使用 react-native-image-crop-picker 在安卓 华为手机上不能正常使用拍照功能, 其他品牌正常 代码如下: import ImagePicker from react-native-image-crop-picker;ImagePicker.openCamera(photoOptions).then(image > {callback(image);}) …

不靠学历,不拼年资,怎么才能月入2W?

之前统计局发布了《2023年城镇单位就业人员年平均工资情况》&#xff0c;2023年全国城镇非私营单位和私营单位就业人员年平均工资分别为120698元和68340元。也就是说在去年非私营单位就业人员平均月薪1W&#xff0c;而私营单位就业人员平均月薪只有5.7K左右。 图源&#xff1a;…

DownShift: Tuning Shift Reduction With Reliability for Racetrack Memories

目录 DownShift: Tuning Shift Reduction With Reliability for Racetrack Memories文章摘要&#xff1a;文章的主要贡献包括&#xff1a;文章的结构如下&#xff1a;DownShiftDownShift通过以下方式改进了现有的数据放置策略&#xff1a; GROGU&#xff08;Generating Reliabi…

简单题94. 二叉树的中序遍历 (python)20240921

问题描述&#xff1a; python&#xff1a; # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution(object…

【重学 MySQL】三十七、聚合函数

【重学 MySQL】三十七、聚合函数 基本概念5大常用的聚合函数COUNT()SUM()AVG()MAX()MIN() 使用场景注意事项示例查询 聚合函数&#xff08;Aggregate Functions&#xff09;在数据库查询中扮演着至关重要的角色&#xff0c;特别是在处理大量数据时。它们能够对一组值执行计算&a…

图书管理系统实现

图书管理系统实现 图书管理系统作用图书管理系统绘图创建Book创建BookListOperation包下代码User包AdminUserNomalUser Main方法整体代码&#xff08;带有注释&#xff09;Opertaion包下的代码IOpertaion&#xff08;接口&#xff09;Add添加图书代码Dele删除图书代码Borrow借阅…

PyTorch 池化层详解

在深度学习中&#xff0c;池化层&#xff08;Pooling Layer&#xff09;是卷积神经网络&#xff08;CNN&#xff09;中的关键组成部分。池化层的主要功能是对特征图进行降维和减少计算量&#xff0c;同时增强模型的鲁棒性。本文将详细介绍池化层的作用、种类、实现方法&#xf…

C++——多线程编程(从入门到放弃)

进程&#xff1a;运行中的程序 线程&#xff1a;进程中的进程 线程的最大数量取决于CPU的核心数 一、将两个函数添加到不同线程中 demo&#xff1a;两个函数test01()和test02()&#xff0c;实现将用户输入的参数进行打印输出1000次 将这两个函数均放到独立的线程t1和t2中&…

vue3+element-plus icons图标选择组件封装

一、最终效果 二、参数配置 1、代码示例 <t-select-icon v-model"selectVlaue" />2、配置参数&#xff08;Attributes&#xff09;继承 el-input Attributes 参数说明类型默认值v-model绑定值string-prefixIcon输入框前缀iconstringSearchisShowSearch是否显…

从角速度向量的角度理解姿态角速度和机体角速度的转换公式

一、什么是姿态角速度 这是我从《多旋翼飞行器设计和控制》上截取的关于欧拉角的定义。无人机的姿态角速度即偏航角、俯仰角、滚转角的一次导数&#xff0c;分别是、、。 二、什么是机体角速度 这是我在网上随便找的图&#xff0c;展示了机体坐标系。这个坐标系与飞机固定连接&…

【软件测试】详解测试中常用的几种测试方法

目录 一、集成测试二、 系统测试三、验收测试四、回归测试 总结 一、集成测试 术语 集成测试是继组件测试之后的又一个层次。集成测试假定交给这个层次的测试对象已经经过了组件测试&#xff0c;并且任何组件内部的缺陷都已经尽可能地被纠正。 集成 开发人员、测试人员和专…

6种常见位运算符+异或运算符的使用(加密、解密)

一、位运算符 位运算符进行的是整数与整数之间的运算 1、右移运算符&#xff1a;>> &#xff08;1&#xff09;相当于对整数除以2 &#xff08;2&#xff09;举例&#xff1a; int num 2; System.out.println(num >> 1); 2、左移运算符&#xff1a;<< …