当前位置: 首页 > article >正文

仓颉编程入门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 = value
            map[a[0]]=a[1]                                      //a[0]是key  ,a[1]是value,存储到hashmap
            s=sr.readln()??""                                   //读取下一行
        }
        println(map)                                            //输出一下
        fs.close()
 }

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

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

class MyServer{

    let server

    public init(){
        let ip=Config.Instance.getString("serverIP")            //读取ip
        let 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:Server
    let run:Bool=true
    public init(){
        let ip=Config.Instance.getString("serverIP")            //读取ip
        let 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>()    //存储配置文件的map

    static 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 = value
            map[a[0]]=a[1]                                      //a[0]是key  ,a[1]是value,存储到hashmap
            s=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=true
    public init(){
        let ip=Config.Instance.getString("serverIP")            //读取ip
        let port=UInt16(Config.Instance.getInt("port"))         //读取端口需要转出UInt16 实际就是unsigend short
        server=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.kler.cn/a/319494.html

相关文章:

  • Linux如何更优质调节系统性能
  • 使用etl工具kettle的日常踩坑梳理之二、从Hadoop中导出数据
  • 《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
  • 图片画廊 day2 (可复制源码)
  • 基于Python+Django+Vue3+MySQL实现的前后端分类的商场车辆管理系统
  • 万字长文解读深度学习——ViT、ViLT、DiT
  • 基于数据挖掘的航空客户满意度分析预测系统
  • 安卓系统常见问题如native crash,卡顿卡死定位工具命令技巧-android framework实战开发
  • Java_Day05学习
  • 搜维尔科技:通过xsens动作捕捉为影视角色注入生命
  • 前端框架的对比和选择
  • MySQL备份与恢复详解
  • Anaconda/Miniconda的删除和安装
  • rapidocr 提取汇总
  • 可以写自动化测试工具的AI工具
  • [笔记]交流接触器
  • UR机器人坐标系转化
  • C++系列-Stackqueue
  • Qt中多语言的操作(以QtCreator为例)
  • Android个性名片界面的设计——约束布局的应用
  • 「iOS」——单例模式
  • Angular面试题三
  • javascript的闭包学习
  • Vue报错 ‘vite‘ 不是内部或外部命令,也不是可运行的程序或批处理文件
  • 电路板上电子元件检测系统源码分享
  • Spring Boot 配置全流程 总结