├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── README.md ├── config.json ├── main.cpp ├── utils ├── serialize.hpp └── utils.hpp └── xmart.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | build 11 | lbuild 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | *.smod 25 | 26 | # Compiled Static libraries 27 | *.lai 28 | *.la 29 | *.a 30 | *.lib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "xfinal"] 2 | path = xfinal 3 | url = https://github.com/xmh0511/xfinal.git 4 | [submodule "xorm"] 5 | path = xorm 6 | url = https://github.com/xmh0511/xorm.git 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | set(project_name xmart) 3 | project(${project_name}) 4 | set(CMAKE_BUILD_TYPE Release) 5 | SET(ENABLE_CLIENT_SSL OFF) 6 | SET(ENABLE_XORM ON) 7 | SET(ENABLE_MYSQL ON) 8 | SET(ENABLE_SQLITE OFF) 9 | SET(ENABLE_SQLITE_CODEC OFF) 10 | #SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 11 | if (MSVC) 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++11 /utf-8 /bigobj") 13 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 14 | else () 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -std=c++11") 16 | endif () 17 | 18 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) 19 | set(CMAKE_INSTALL_RPATH "/usr/local/lib:") 20 | #set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 21 | 22 | if(ENABLE_XORM) 23 | add_definitions(-D_ENABLE_XORM_) 24 | if(ENABLE_MYSQL) 25 | add_definitions(-DXORM_ENABLE_MYSQL) 26 | endif() 27 | if(ENABLE_SQLITE) 28 | add_definitions(-DXORM_ENABLE_SQLITE) 29 | if(ENABLE_SQLITE_CODEC) 30 | add_definitions(-DSQLITE_HAS_CODEC) 31 | endif() 32 | endif() 33 | endif() 34 | 35 | add_definitions(-DASIO_STANDALONE) 36 | 37 | if(ENABLE_CLIENT_SSL) 38 | add_definitions(-DXFINAL_ENABLE_CLIENT_SSL) 39 | endif() 40 | 41 | if (ENABLE_CLIENT_SSL) 42 | find_package(OpenSSL REQUIRED) 43 | endif() 44 | 45 | 46 | set(Xmart xmart.hpp main.cpp) 47 | 48 | add_executable(${project_name} ${Xmart}) 49 | 50 | if(ENABLE_XORM) 51 | if(ENABLE_MYSQL) 52 | if(MSVC) 53 | target_link_libraries(${project_name} libmysql) 54 | else() 55 | target_link_libraries(${project_name} mysqlclient) 56 | endif() 57 | endif() 58 | if(ENABLE_SQLITE) 59 | target_link_libraries(${project_name} sqlite3) 60 | endif() 61 | endif() 62 | 63 | 64 | if(ENABLE_CLIENT_SSL) 65 | include_directories(${CMAKE_SOURCE_DIR}/xfinal ${CMAKE_SOURCE_DIR}/xorm ${CMAKE_SOURCE_DIR}/xfinal/asio/asio/include ${CMAKE_SOURCE_DIR}/xfinal/xfinal/ghc ${OPENSSL_INCLUDE_DIR}) 66 | else() 67 | include_directories(${CMAKE_SOURCE_DIR}/xfinal ${CMAKE_SOURCE_DIR}/xorm ${CMAKE_SOURCE_DIR}/xfinal/asio/asio/include ${CMAKE_SOURCE_DIR}/xfinal/xfinal/ghc) 68 | endif() 69 | 70 | 71 | if(ENABLE_CLIENT_SSL) 72 | target_link_libraries(${project_name} uuid ${OPENSSL_LIBRARIES}) 73 | else() 74 | target_link_libraries(${project_name} uuid) 75 | endif() 76 | 77 | install(TARGETS ${project_name} DESTINATION include) 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xmart 2 | 3 | ## 环境 4 | 只需要支持c++11的编译器 5 | 6 | 7 | ## 特性 8 | 1. 跨平台支持 9 | 2. 易于使用的web库 (xfinal) [基本使用](https://github.com/xmh0511/xfinal) 10 | 3. 易于使用的orm库 (xorm) [基本使用](https://github.com/xmh0511/xorm) 11 | 4. 完整的处理工具 (utils) 12 | 13 | 14 | ### 移植程序 15 | ldd 程序名 | awk '{print $3}' | xargs -i cp -L {} 依赖保存路径 16 | 17 | ## 演示 18 | 19 | ```` 20 | #include "xmart.hpp" 21 | using namespace xmart; 22 | 23 | struct test { 24 | mysql::Integer id; 25 | mysql::Integer a; 26 | std::string b; 27 | mysql::MysqlDateTime time; 28 | mysql::MysqlDate date; 29 | mysql::MysqlTime tm; 30 | mysql::Double money; 31 | }; 32 | REFLECTION(test, id, a, b, time, date, tm, money) 33 | 34 | int main() { 35 | bool r = false; 36 | // 从配置文件初始化xmart 37 | http_server& server = init_xmart("./config.json", r); 38 | if (!r) { 39 | return 0; 40 | } 41 | 42 | //从form表单写入数据库 43 | server.router("/write", [](request& req, response& res) { 44 | auto data = map_from_query(req); 45 | dao_t dao; 46 | dao.insert(data); 47 | res.write_string("hello,world"); 48 | }); 49 | //从url参数写入数据库 50 | server.router("/writeparams", [](request& req, response& res) { 51 | auto data = map_from_params(req); 52 | dao_t dao; 53 | dao.insert(data); 54 | res.write_string("hello,world"); 55 | }); 56 | //从提交的json写入数据库 57 | server.router("/writejson", [](request& req, response& res) { 58 | auto json_str = req.body(); 59 | auto json = json::parse(json_str); 60 | auto data = map_from_json(json); 61 | dao_t dao; 62 | dao.insert(data); 63 | res.write_string("json insert"); 64 | }); 65 | 66 | //获取数据并通过json数据交互返回给客户端 67 | server.router("/list", [](request& req, response& res) { 68 | dao_t dao; 69 | auto pr = dao.query("where 1=1"); 70 | json root; 71 | if (pr.first) { 72 | auto& vec = pr.second; 73 | for (auto& iter : vec) { 74 | root["list"].push_back(serializer::to_json(iter)); 75 | } 76 | } 77 | root["success"] = true; 78 | res.write_json(root); 79 | }); 80 | 81 | server.run(); 82 | } 83 | ```` 84 | 85 | 86 | # Donation 87 | 88 | ### alipay: 89 | ![image](https://github.com/xmh0511/donation/blob/master/alipay.png) 90 | ### wechat: 91 | ![image](https://github.com/xmh0511/donation/blob/master/wechat.png) 92 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "http_host": "0.0.0.0", 3 | "http_port": "8080", 4 | "http_thread": 0, 5 | "http_read_timeout":30, 6 | "http_write_timeout":30, 7 | "http_keepalive_timeout":10, 8 | "db_configs":[ 9 | { 10 | "db_index_key":"xorm", 11 | "db_host": "127.0.0.1", 12 | "db_port": 3306, 13 | "db_name": "xorm", 14 | "db_user": "root", 15 | "db_pass": "root", 16 | "db_reconnumber": 1, 17 | "db_timeout": -1, 18 | "db_conn_number": 2, 19 | "db_character_encoding": "utf8" 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "xmart.hpp" 2 | using namespace xmart; 3 | 4 | struct test { 5 | mysql::Integer id; 6 | mysql::Integer a; 7 | std::string b; 8 | mysql::MysqlDateTime time; 9 | mysql::MysqlDate date; 10 | mysql::MysqlTime tm; 11 | mysql::Double money; 12 | std::string d; 13 | }; 14 | REFLECTION(test, id, a, b, time, date, tm, money,d) 15 | 16 | int main() { 17 | bool r = false; 18 | auto server_ptr = init_xmart("./config.json", r, [](std::string const& message) { 19 | std::cout << std::to_string(std::time(nullptr)) << " : " << message << "\n"; 20 | }); 21 | 22 | auto&& server = *server_ptr; 23 | 24 | if (!r) { 25 | std::cout<<"config has some error"<("/write", [](request& req, response& res) { 30 | auto data = map_from_query(req); 31 | dao_t dao{"xorm"}; 32 | dao.insert(data); 33 | res.write_string("form insert"); 34 | }); 35 | 36 | server.router("/writeparams", [](request& req, response& res) { 37 | auto data = map_from_params(req); 38 | dao_t dao{ "xorm" }; 39 | dao.insert(data); 40 | res.write_string("params insert"); 41 | }); 42 | 43 | server.router("/writejson", [](request& req, response& res) { 44 | auto json_str = req.body(); 45 | auto json = json::parse(json_str); 46 | try { 47 | auto data = map_from_json(json); 48 | dao_t dao{ "xorm" }; 49 | dao.insert(data); 50 | } 51 | catch (std::exception const& ec) { 52 | std::cout << ec.what() << std::endl; 53 | } 54 | res.write_string("json insert"); 55 | }); 56 | 57 | server.router("/list", [](request& req, response& res) { 58 | dao_t dao{ "xorm" }; 59 | auto pr = dao.query("where 1=1"); 60 | json root; 61 | if (pr.success) { 62 | auto& vec = pr.results; 63 | root["list"] = list_to_json(vec); 64 | } 65 | root["success"] = true; 66 | res.write_json(root); 67 | }); 68 | 69 | server.run(); 70 | } -------------------------------------------------------------------------------- /utils/serialize.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #ifdef _ENABLE_XORM_ 4 | #include 5 | #include 6 | namespace xmart { 7 | using namespace xorm; 8 | } 9 | #endif 10 | namespace xmart { 11 | namespace serializer { 12 | template::type>::value>::type> 13 | inline nlohmann::json to_json(T && obj, nlohmann::json & json); 14 | template::type>::value>::type> 15 | inline nlohmann::json to_json(T && obj); 16 | 17 | template::type>::value>::type> 18 | inline typename std::remove_reference::type to_object(T && t, nlohmann::json const& json); 19 | template::type>::value>::type> 20 | inline typename std::remove_reference::type to_object(nlohmann::json const& json); 21 | } 22 | template 23 | struct each_auto_params_lambda_to_json_v { 24 | each_auto_params_lambda_to_json_v(nlohmann::json& json_):json(json_){ 25 | 26 | } 27 | template 28 | void operator()(T&& t, U&& name, Y&& offset) { 29 | Class::to_json_v((t.*offset), name, json); 30 | } 31 | private: 32 | nlohmann::json& json; 33 | }; 34 | template 35 | struct each_auto_params_lambda_to_object_v { 36 | each_auto_params_lambda_to_object_v(nlohmann::json const& json_):json(json_) { 37 | 38 | } 39 | template 40 | void operator()(T&& t, U&& name, Y&& offset) { 41 | if (json.find(name) != json.end()) { 42 | Class::to_object_v((t.*offset), json[name]); 43 | } 44 | } 45 | private: 46 | nlohmann::json const& json; 47 | }; 48 | class serialize_ { 49 | template 50 | friend nlohmann::json serializer::to_json(T&& obj, nlohmann::json& json); 51 | template 52 | friend nlohmann::json serializer::to_json(T&& obj); 53 | template 54 | friend typename std::remove_reference::type serializer::to_object(T&& t, nlohmann::json const& json); 55 | template 56 | friend typename std::remove_reference::type serializer::to_object(nlohmann::json const& json); 57 | 58 | template 59 | friend struct each_auto_params_lambda_to_json_v; 60 | template 61 | friend struct each_auto_params_lambda_to_object_v; 62 | private: 63 | template 64 | static typename std::enable_if::type>::value>::type to_json_v(T&& obj, std::string const& name, nlohmann::json& json) 65 | { 66 | json[name] = nlohmann::json::object(); 67 | to_json(obj, json[name]); 68 | } 69 | #ifdef _ENABLE_XORM_ 70 | template 71 | static typename std::enable_if::type>::value && (!xmart::is_fundamention_type::type>::value && !xmart::is_date_type::type>::value)>::type to_json_v(T&& obj, std::string const& name, nlohmann::json& json) 72 | { 73 | json[name] = obj; 74 | } 75 | template 76 | static typename std::enable_if::type>::value && (xmart::is_fundamention_type::type>::value || xmart::is_date_type::type>::value)>::type to_json_v(T&& obj, std::string const& name, nlohmann::json& json) 77 | { 78 | if (!obj.is_null()) { 79 | json[name] = obj.value(); 80 | } 81 | else { 82 | json[name] = nullptr; 83 | } 84 | } 85 | #else 86 | template 87 | static typename std::enable_if::type>::value>::type to_json_v(T&& obj, std::string const& name, nlohmann::json& json) 88 | { 89 | json[name] = obj; 90 | } 91 | #endif 92 | template::type>::value>::type> 93 | static void to_json(T && obj, nlohmann::json & json) 94 | { 95 | each_auto_params_lambda_to_json_v lambda{ json }; 96 | reflector::each_object(std::forward(obj),lambda); 97 | //reflector::each_object(std::forward(obj), [&json](auto& t, auto& name, auto offset) { 98 | // to_json_v((t.*offset), name, json); 99 | //}); 100 | } 101 | template 102 | static typename std::enable_if::type>::value>::type to_object_v(T& t, U&& v) 103 | { 104 | to_object(t, std::forward(v)); 105 | } 106 | #ifdef _ENABLE_XORM_ 107 | template 108 | static typename std::enable_if::type>::value && (!xmart::is_fundamention_type::type>::value && !xmart::is_date_type::type>::value)>::type to_object_v(T& t, U&& v) 109 | { 110 | t = v.template get(); 111 | } 112 | 113 | template 114 | static typename std::enable_if::type>::value&& xmart::is_fundamention_type::type>::value && !xmart::is_date_type::type>::value>::type to_object_v(T& t, U&& v) 115 | { 116 | if (!v.is_null()) { 117 | t = v.template get(); 118 | } 119 | else { 120 | t.clear(); 121 | } 122 | } 123 | 124 | template 125 | static typename std::enable_if::type>::value && !xmart::is_fundamention_type::type>::value&& xmart::is_date_type::type>::value>::type to_object_v(T& t, U&& v) 126 | { 127 | if (!v.is_null()) { 128 | t = v.template get(); 129 | } 130 | else { 131 | t.clear(); 132 | } 133 | } 134 | #else 135 | template 136 | static typename std::enable_if::type>::value>::type to_object_v(T& t, U&& v) 137 | { 138 | t = v.template get(); 139 | } 140 | #endif 141 | 142 | template::type>::value>::type> 143 | static void to_object(T && t, nlohmann::json const& json) 144 | { 145 | each_auto_params_lambda_to_object_v lambda{ json }; 146 | reflector::each_object(std::forward(t), lambda); 147 | //reflector::each_object(std::forward(t), [&json](auto& t, auto& name, auto offset) { 148 | // to_object_v((t.*offset), json[name]); 149 | //}); 150 | } 151 | }; 152 | namespace serializer { 153 | template 154 | inline nlohmann::json to_json(T&& obj, nlohmann::json& json) 155 | { 156 | serialize_::to_json(std::forward(obj), json); 157 | return json; 158 | } 159 | template 160 | inline nlohmann::json to_json(T&& obj) 161 | { 162 | nlohmann::json root; 163 | serialize_::to_json(std::forward(obj), root); 164 | return root; 165 | } 166 | 167 | template 168 | inline typename std::remove_reference::type to_object(T&& t, nlohmann::json const& json) 169 | { 170 | serialize_::to_object(std::forward(t), json); 171 | return std::forward(t); 172 | } 173 | 174 | template 175 | inline typename std::remove_reference::type to_object(nlohmann::json const& json) 176 | { 177 | T t; 178 | serialize_::to_object(t, json); 179 | return t; 180 | } 181 | } 182 | } -------------------------------------------------------------------------------- /utils/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "serialize.hpp" 4 | namespace xmart { 5 | template 6 | typename std::enable_if::value || std::is_same::value, T>::type str_to_fundamention(nonstd::string_view str) { 7 | return std::atoi(str.data()); 8 | } 9 | 10 | template 11 | typename std::enable_if::value, T>::type str_to_fundamention(nonstd::string_view str) { 12 | return std::atoll(str.data()); 13 | } 14 | 15 | template 16 | typename std::enable_if::value || std::is_same::value, T>::type str_to_fundamention(nonstd::string_view str) { 17 | return std::atof(str.data()); 18 | } 19 | 20 | #ifdef _ENABLE_XORM_ 21 | template 22 | typename std::enable_if::value && (!std::is_same::value), typename T::value_type>::type mapping_query_value(nonstd::string_view str) { 23 | return str_to_fundamention(str); 24 | } 25 | 26 | template 27 | typename std::enable_if::value&& std::is_same::value, typename T::value_type>::type mapping_query_value(nonstd::string_view str) { 28 | return char(std::atoi(str.data()) ); 29 | } 30 | 31 | template 32 | typename std::enable_if::value, T>::type mapping_query_value(nonstd::string_view str) { 33 | return T{ std::string(str.data(),str.size()) }; 34 | } 35 | 36 | template 37 | typename std::enable_if::value, std::string>::type mapping_query_value(nonstd::string_view str) { 38 | return std::string(str.data(), str.size()); 39 | } 40 | 41 | 42 | #endif 43 | 44 | template 45 | struct auto_params_lambda_map_from_params { 46 | auto_params_lambda_map_from_params(Request& req_) :req(req_) { 47 | 48 | } 49 | template 50 | void operator()(T&& obj, U&& name, Y&& field) { 51 | (obj.*field) = mapping_query_value::type>(req.param(name)); 52 | } 53 | private: 54 | Request& req; 55 | }; 56 | 57 | template 58 | struct auto_params_lambda_map_from_query { 59 | auto_params_lambda_map_from_query(Request& req_) :req(req_) { 60 | 61 | } 62 | template 63 | void operator()(T&& obj, U&& name, Y&& field) { 64 | (obj.*field) = mapping_query_value::type>(req.query(name)); 65 | } 66 | private: 67 | Request& req; 68 | }; 69 | 70 | template 71 | typename std::enable_if::value, T>::type map_from_query(Request& req) { 72 | T tmp{}; 73 | auto_params_lambda_map_from_query lambda{ req }; 74 | reflector::each_object(tmp, lambda); 75 | return tmp; 76 | } 77 | 78 | template 79 | typename std::enable_if::value, T>::type map_from_params(Request& req) { 80 | T tmp{}; 81 | auto_params_lambda_map_from_params lambda{ req }; 82 | reflector::each_object(tmp, lambda); 83 | //reflector::each_object(tmp, [&req](auto&& obj, auto name, auto field) { 84 | // (obj.*field) = mapping_query_value::type>(req.param(name)); 85 | //}); 86 | return tmp; 87 | } 88 | 89 | template 90 | typename std::enable_if::value, T>::type map_from_json(nlohmann::json const& json ) { 91 | T tmp{}; 92 | serializer::to_object(tmp, json); 93 | return tmp; 94 | } 95 | 96 | template 97 | typename std::enable_if::type>::value, nlohmann::json>::type map_to_json(T&& obj) { 98 | return serializer::to_json(std::forward(obj)); 99 | } 100 | 101 | template 102 | typename std::enable_if::type>::value, nlohmann::json>::type list_to_json(std::vector& vec) { 103 | nlohmann::json list; 104 | for (auto& iter : vec) { 105 | auto node = map_to_json(iter); 106 | list.push_back(node); 107 | } 108 | return list; 109 | } 110 | 111 | template 112 | typename std::enable_if::type>::value, nlohmann::json>::type list_to_json(std::vector&& vec) { 113 | nlohmann::json list; 114 | for (auto& iter : vec) { 115 | auto node = map_to_json(iter); 116 | list.push_back(node); 117 | } 118 | return list; 119 | } 120 | } -------------------------------------------------------------------------------- /xmart.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "utils/utils.hpp" 4 | namespace xmart { 5 | using namespace xfinal; 6 | inline std::unique_ptr init_xmart(std::string const& configPath, bool& r, std::function error_cb = nullptr) { 7 | std::unique_ptr server_; 8 | json config_json; 9 | std::ifstream file(configPath); 10 | std::stringstream ss; 11 | ss << file.rdbuf(); 12 | auto config_str = ss.str(); 13 | if (config_str.empty()) { 14 | r = false; 15 | return server_; 16 | } 17 | else { 18 | try { 19 | config_json = json::parse(config_str); 20 | std::size_t thread_count = std::thread::hardware_concurrency(); 21 | auto number = config_json.at("http_thread").get(); 22 | if (number > 0) { 23 | thread_count = number; 24 | } 25 | server_ = std::unique_ptr(new http_server(thread_count)); 26 | if (error_cb == nullptr) { 27 | server_->on_error([](std::string const& message) { 28 | std::cout << message << "\n"; 29 | }); 30 | } 31 | else { 32 | server_->on_error(std::move(error_cb)); 33 | } 34 | auto port = config_json.at("http_port").get(); 35 | auto host = config_json.at("http_host").get(); 36 | server_->listen(host, port); 37 | auto read_timeout = config_json.at("http_read_timeout").get(); 38 | auto write_timeout = config_json.at("http_write_timeout").get(); 39 | auto keepalive_timeout = config_json.at("http_keepalive_timeout").get(); 40 | server_->set_wait_read_time((std::time_t)read_timeout); 41 | server_->set_wait_write_time((std::time_t)write_timeout); 42 | server_->set_keep_alive_wait_time(keepalive_timeout); 43 | #ifdef _ENABLE_XORM_ 44 | auto server_ptr = server_.get(); 45 | dao_message::get().set_error_callback([server_ptr](std::string const& message) { 46 | server_ptr->trigger_error(message); 47 | }); 48 | auto db_configs = config_json.at("db_configs"); 49 | for (auto&& iter : db_configs) { 50 | dataBaseConfig config{}; 51 | config.index_key = iter.at("db_index_key").get(); 52 | config.character_encoding = iter.at("db_character_encoding").get(); 53 | config.conn_number = iter.at("db_conn_number").get(); 54 | config.dbname = iter.at("db_name").get(); 55 | config.host = iter.at("db_host").get(); 56 | config.password = iter.at("db_pass").get(); 57 | config.port = iter.at("db_port").get(); 58 | config.reconnect_number = iter.at("db_reconnumber").get(); 59 | config.timeout = iter.at("db_timeout").get(); 60 | config.user = iter.at("db_user").get(); 61 | #ifdef XORM_ENABLE_MYSQL 62 | dao_t::init_conn_pool(config); 63 | #endif 64 | #ifdef XORM_ENABLE_SQLITE 65 | dao_t::init_conn_pool(config); 66 | #endif 67 | } 68 | #endif 69 | r = true; 70 | } 71 | catch (std::exception const& ec) { 72 | std::cout << ec.what() << "\n"; 73 | r = false; 74 | return server_; 75 | } 76 | return server_; 77 | } 78 | 79 | } 80 | 81 | } --------------------------------------------------------------------------------