仓颉编程入门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.mzph.cn/bicheng/54905.shtml

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

相关文章

C语言实现常见的数据结构

栈 栈是一种后进先出&#xff08;LIFO, Last In First Out&#xff09;的数据结构 #include <stdio.h> #include <stdlib.h>#define MAX 100typedef struct {int data[MAX];int top; } Stack;// 初始化栈 void init(Stack *s) {s->top -1; }// 判断栈是否为空…

kafka 消息位移提交几种方式:消息重复消息、消息丢失的关键

消费位移 Kafka 中的位移&#xff08;offset&#xff09;是用来记录消息在分区中的位置的标志&#xff0c;简单说就是记录消费者的消费进度&#xff0c;每次消息消费后需要更新消费进度&#xff0c;也就是位移提交 由此可见一旦位移提交发生异常&#xff0c;会导致消费进度不正…

VBA技术资料MF204:右键多按钮弹出菜单中使用图标

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

p,div等里面支持br换行 对应后台换过来的textarea的富文本内容

如何使用CSS来支持或者允许<br>标签在HTML中创建换行。<br>标签是一个空元素&#xff0c;它的存在表示在HTML中的那个位置需要一个换行。 在CSS中&#xff0c;使用white-space属性来控制文本的换行行为。设置white-space: pre-wrap; 这样的属性&#xff0c;这样就…

【python】【绘制小程序】动态爱心绘制

背景介绍 参考链接&#xff1a;https://blog.csdn.net/Python_HUHU/article/details/139703289点的背景颜色在开始修改&#xff1b;文字的颜色在最后修改。文字内容可以修改。 python 代码 import tkinter as tk import random from math import sin, cos, pi, log from PIL…

学习篇 | Jupyter 使用(notebook hub)

1. JupyterHub 1.1 快速尝试 jupyterhub -f/path/jupyter_config.py --no-ssl1.2 长期后台运行 bash -c "nohup jupyterhub -f/path/jupyter_config.py --no-ssl" > ~/jupyterhub.log 2>&1 &1.3 帮助 jupyterhub --help2. Jupyter Notebook 2.1 快…

Cocos 3.8.3 实现外描边效果(逃课玩法)

本来想着用Cocos 的Shader Graph照搬Unity的思路来加外描边&#xff0c;发现不行&#xff0c;然后我就想弄两个物体不就行了吗&#xff0c;一个是放大的版本&#xff0c;再放大的版本上加一个材质&#xff0c;这个材质面剔除选择前面的面剔除就行了&#xff0c;果不其然还真行。…

如何使用ssm实现基于java web的防疫工作志愿者服务平台的设计与实现

TOC ssm693基于java web的防疫工作志愿者服务平台的设计与实现jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进…

详细解读,F5服务器负载均衡的技术优势

在现代大规模、高流量的网络使用场景中&#xff0c;为应对高并发和海量数据的挑战&#xff0c;服务器负载均衡技术应运而生。但凡知道服务器负载均衡这一名词的&#xff0c;基本都对F5有所耳闻&#xff0c;因为负载均衡正是F5的代表作&#xff0c;换句通俗易懂的话来说&#xf…

makefile和CMakeLists/C++包管理器

make 大家可能会很奇怪&#xff0c;都什么年代了&#xff0c;还学makefile&#xff0c;cmake都有些过时了&#xff0c;为什么还要再学这个呢&#xff1f; 我是这么看待这个问题的&#xff0c;cmake跨平台性还是很有有优势的&#xff0c;有着多年积累的底蕴&#xff0c;借助大模…

海尔嵌入式硬件校招面试题及参考答案

使用 QT 的经验及对控件和信号与槽机制的了解 我使用 QT 有一段时间了,在项目开发中积累了较为丰富的经验。 QT 中的控件丰富多样,涵盖了各种常见的界面元素需求。例如按钮、文本框、列表框、进度条等。这些控件具有良好的可定制性,可以通过属性设置、样式表等方式来调整外观…

基于springboot的驾校预约管理系统的设计与实现 (含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的驾校预约管理系统5拥有三种角色&#xff1a;管理员、教练、学员 管理员&#xff1a;学员管理、教练管理、车辆管理、车辆关联、维修管理等 教练&#xff1a;学员查看/毕…

再次重温 Spring 中 Bean 的生命周期

Bean的生命周期 Spring中的bean的生命周期主要包含四个阶段&#xff1a;实例化Bean --&#xff1e; Bean属性填充 --&#xff1e; 初始化Bean --&#xff1e;销毁Bean 首先是实例化Bean&#xff0c;当客户向容器请求一个尚未初始化的bean时&#xff0c;或初始化bean的时候需要…

Java 序列化:为什么你应该手动定义 serialVersionUID?@Serial 注解有什么作用?

最近在优化一个Java项目时&#xff0c;遇到了一个关于类序列化的问题。项目中有一个需要实现 Serializable 接口的类&#xff0c;我发现有一段代码使用了 Serial 注解&#xff0c;并且还定义了 serialVersionUID&#xff0c;具体如下&#xff1a; Serial private static final…

hive-拉链表

目录 拉链表概述缓慢变化维拉链表定义 拉链表的实现常规拉链表历史数据每日新增数据历史数据与新增数据的合并 分区拉链表 拉链表概述 缓慢变化维 通常我们用一张维度表来维护维度信息&#xff0c;比如用户手机号码信息。然而随着时间的变化&#xff0c;某些用户信息会发生改…

SpringSecurity-用户认证

1、用户认证 1.1 用户认证核心组件 我们系统中会有许多用户&#xff0c;确认当前是哪个用户正在使用我们系统就是登录认证的最终目的。这里我们就提取出了一个核心概念&#xff1a;当前登录用户/当前认证用户。整个系统安全都是围绕当前登录用户展开的&#xff0c;这个不难理…

数字安全二之密钥结合消息摘要

HMACSHA256的定义 HMACSHA256是一种使用 SHA-256 哈希算法的 HMAC&#xff08;基于哈希的消息认证码&#xff0c;Hash-based Message Authentication Code&#xff09; 机制。它结合了【散列函数】 和 【密钥】&#xff0c;用于确保消息的完整性和真实性 HMAC 与 SHA-256 的作…

大数据新视界 --大数据大厂之HBase 在大数据存储中的应用与表结构设计

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

如何进行Ubuntu磁盘空间深度清理?

近期使用AutoDL算力云&#xff0c;发现系统盘只有30G&#xff0c;数据盘只有50G&#xff0c;跑一个稍微大一点的模型&#xff0c;马上空间就拉爆了&#xff0c;现在做一个磁盘深度清理操作&#xff0c;看看效果。 清理前磁盘占用如下&#xff1a; 在 Ubuntu 系统中进行磁盘深度…

如何选择适合的编程工具提高工作效率

---  随着科技的发展&#xff0c;编程已经成为各行各业不可或缺的一部分。在忙碌的工作环境中&#xff0c;如何选择合适的编程工具成为了每个开发者提升工作效率的关键。智能的代码编辑器、强大的版本控制工具、还是那些让你事半功倍的自动化脚本&#xff1f;让我们一起探讨&…