sylar源码阅读笔记-配置系统-练习demo

文章讲述了如何从yaml文件中正确加载用户配置信息(如用户名、年龄和密码)以及系统配置(如IP、MAC和端口),并展示了如何使用`YAML::LoadFile`和自定义转换模板类`LexicalCast`来处理复杂的数据结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从yaml文件中加载配置,配置的信息包括用户(包含属性:用户名,年龄,用户密码),可以有多个用户(vector),其他配置信息包括系统IP地址、系统mac地址、端口号,要求定义函数,将这些变量的值从yaml中加载,赋值给System类。
yaml文件内容如下:

  system:
    port: 8080
    ip: 192.168.131.136
    mac: 10:7B:44:80:F4:6A
    user_vec: 
     - name: zje
       age: 31
       passwd: qwerqwer
     - name: zje
       age: 31
       passwd: edceedce
     - name: zje
       age: 31
       passwd: hjkjhghj

一开始我写的yaml文件不是这样子的 =.=,下成下面这样了,然后转换的时候一只报错,尝试转换vector不报错,转换User不报错,但是转换vector报错了,找了挺长时间的bug,最后发现时yaml文件中列表写错了,写成下面这个样子了(虽然花费挺长时间,但是对整个代码了解了很多,继续加油)

  system:
    port: 8080
    ip: 192.168.131.136
    mac: 10:7B:44:80:F4:6A
    user_vec: 
     - user_1:
          name: zje
          age: 31
          passwd: qwerqwer
     - user_2:
          name: zje
          age: 31
          passwd: edceedce
     - user_3:
          name: zje
          age: 31
          passwd: hjkjhghj

练习代码如下:

#include <string>
#include "config.h"
#include "log.h"
#include "util.h"
#include <yaml-cpp/yaml.h>

namespace sylar
{

    class User
    {
    public:
        User() {}

        User(std::string m_name, int m_age, std::string m_passwd)
            : name(m_name), age(m_age), passwd(m_passwd)
        {
        }

        std::string getName() const
        {
            return name;
        }

        void setName(std::string m_name)
        {
            name = m_name;
        }

        int getAge() const
        {
            return age;
        }

        void setAge(int m_age)
        {
            age = m_age;
        }

        std::string getPasswd() const
        {
            return passwd;
        }

        void setPasswd(std::string m_passwd)
        {
            passwd = m_passwd;
        }

        std::string toString() const
        {
            std::stringstream ss;
            ss << "[ " + name + " " + std::to_string(age) + " " + passwd + "" + " ]";
            return ss.str();
        }

    private:
        std::string name = "";
        int age = 0;
        std::string passwd = "";
    };

    /**
     * 存放系统的一些配置信息
     */
    class System
    {
        // 从yaml文件中加载配置,配置的信息包括用户(包含属性:用户名,年龄,用户密码)
        // 可以有多个用户,其他配置信息包括系统IP地址、系统mac地址、端口号,要求定义函数,将这些变量的值从yaml中加载。
    public:
        System()
        {
        }

        void init()
        {
        }

        /**
         * 从yaml文件中加载配置
         */
        void LoadfromYaml(std::string yaml_path)
        {
            // 向系统中初始化设置一些键
            // ip
            ConfigVar<std::string>::ptr config_ip = Config::Lookup("system.ip", std::string(), "system ip address");
            // mac
            ConfigVar<std::string>::ptr config_mac = Config::Lookup("system.mac", std::string(), "system ip mac");
            // port
            ConfigVar<int>::ptr config_port = Config::Lookup("system.port", (int)80, "system port");
            // user_vec
            ConfigVar<std::vector<User>>::ptr config_user_vec = Config::Lookup("system.user_vec", std::vector<User>{User()}, "system user_vec");

            // ConfigVar<std::vector<int>>::ptr config_int_vec = Config::Lookup("system.int_vec", std::vector<int>{1, 2, 3}, "system int_vec");
            ConfigVar<User>::ptr config_user = Config::Lookup("system.user", User(), "system user");

            // 加载yaml文件
            YAML::Node root = YAML::LoadFile(yaml_path);
            // 从yaml文件中加载配置信息,存放到了s_datas中
            sylar::Config::LoadFromYaml(root);

            // 从s_datas中获取值,放入System类中
            ip = config_ip->getValue();
            mac = config_mac->getValue();
            port = config_port->getValue();
            user_vec = config_user_vec->getValue();

            // auto it = config_int_vec->getValue();
            // for (auto i : it)
            // {
            //     std::cout << i << std::endl;
            // }

            // std::cout << config_user->toString() << std::endl;
        }

        std::string toString()
        {
            std::stringstream ss;
            ss << "[ip:" + ip + " " + " mac:" + mac + " " + " port:" + std::to_string(port) + " " + "]\n";
            for (auto i = user_vec.begin(); i != user_vec.end(); i++)
            {
                ss << i->toString() << "\n";
            }
            return ss.str();
        }

    private:
        std::string ip;
        std::string mac;
        int port;
        // 用户列表
        std::vector<User> user_vec;
    };

    // ***************user start****************
    // 定义User类的转换偏特化模板类
    /**
     * 数据类型转换-user偏特化版本
     * string -> user
     */
    template <>
    class LexicalCast<std::string, User>
    {
    public:
        User operator()(const std::string &v)
        {
            // loads the input string as a single YAML document
            YAML::Node node = YAML::Load(v);
            User p;
            p.setName(node["name"].as<std::string>());
            p.setAge(node["age"].as<int>());
            p.setPasswd(node["passwd"].as<std::string>());
            return p;
        }
    };

    /**
     * 数据类型转换-user偏特化版本
     * user -> string
     */
    template <>
    class LexicalCast<User, std::string>
    {
    public:
        std::string operator()(const User &v)
        {
            SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "user to string"
                                             << "\n";
            YAML::Node node;
            node["name"] = v.getName();
            node["age"] = v.getAge();
            node["passwd"] = v.getPasswd();
            std::stringstream ss;
            ss << node;
            return ss.str();
        }
    };

    // ***************user end****************
}

int main()
{
    std::string yaml_path = "/root/c_plus_plus_project/sylar/bin/conf/system.yaml";
    sylar::System system;
    system.LoadfromYaml(yaml_path);
    std::cout << system.toString();
    // 从yaml文件中加载配置
}

这是自己写的,感觉实际使用配置系统肯定不是这样的,还有待改进,接下来听配置系统与日志系统的整合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值