c++ 后台小练习--基于Vue的在线记事本
目录
效果
前端代码
后端代码
效果
前端使用vue3,后端使用Rester,
数据库采用cpp_redist实现的连接池。
前后端主要有获取事项,增加事项,删除事项几个简单的功能。完整的前端项目地址note_book地址
注意处理OPTIONS方法,重点注意allow这几个字段。
前端功能还可以继续增加,比如注册和登录。
为不同的用户存储各自的数据。
数据库连接池还可以进一步优化,考虑动态增加连接数量。
对于js, var self=this, 函数也是一个对象,也有this指针
对于log,程序关闭并不会将日志写完,只会强行kill后台线程。
因此在析构函数中join 后台日志写线程,并写完当前线程。
前端代码
<!--
* @Author: hjhj111 2268716068@qq.com
* @Date: 2022-08-30 12:15:37
* @LastEditors: hjhj111 2268716068@qq.com
* @LastEditTime: 2022-08-31 10:55:45
* @FilePath: \note_book\src\components\HelloWorld.vue
* @Description: 这是一个简单基于vue的在线备忘录,结合c++网络库Rester,内存数据库redis使用
-->
<template>
<div>
<h1>数据服务器地址: {{ address }}</h1>
<ol style="list-style-type:none">
<li v-for="note in notes" :key="note.text">
<h2>{{note.text}}</h2>
<button @click="deleteNote(note)">完成待办</button>
</li>
</ol>
<!-- <form action={{this.adress}} method="post"> -->
<input type="text" id="form" placeholder="添加待办……">
<input type="submit" value="确认添加" @click="addNote">
<!-- </form> -->
</div>
</template>
<script>
//import { setgroups } from 'process';
import axios from 'axios'
export default {
name: 'NoteBook',
data(){
return{
notes:[
{text:"hhhh"},
{text:"jjjjj"}
],
Address: this.address
}
},
props: {
address:{default: "no url for data"},
},
created(){
this.getNotes()
console.log(this.notes)
},
methods:{
getNotes: function(){
console.log(this.address)
var self=this//修改父对象,函数也是对象
axios.get(this.address).then(function(res){
console.log(res.data)
self.notes=res.data
console.log(self.notes)
}
).catch((err)=>{
console.log(err)
})
},
addNote: function(){
var self=this
console.log(document.getElementById("form").value)
axios({
method:"Post",
url:self.address,
headers:{
'Content-Type': 'text/plain'//application/json
},
data:{text:document.getElementById("form").value}
//data:"{\"text\":\"更加发奋建安费\"}"
}).then(function(res){
if(res.status==201){
//update
self.getNotes();
alert("添加完成");
}
else{
alert("添加失败");
}
})
},
deleteNote: function(note){
var self=this
axios({
method:"Delete",
url:self.address,
data:note
}).then(function(res){
if(res.status==201){
//update
self.getNotes()
alert("删除成功")
}
else{
alert("删除失败")
}
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
后端代码
#include<iostream>
#include<string>
#include <signal.h>
#include"rester.h"
//#define MYTEST
shared_ptr<Rester> server_ptr;
void SigFunc(int sig)
{
printf("sigfunc %d\n",sig);
server_ptr->running_=false;
signal(SIGINT,SIG_DFL);
}
int main(int argc, char *argv[])
{
#ifdef MYTEST
fclose(stdout);
#endif
Config config;
config.Update();
cout<<config;
server_ptr=make_shared<Rester>(config);
//close_log > 0 for close log
if(!Log::get_instance()->init("log",0,8192,5000000,1000))
{
return 4;
}
printf("log inited\n");
auto& connection_pool=ConnectionPool::GetInstance();//auto can not carry & itself
Router note_book("/notes");//default router
auto on_get= [&connection_pool](RequestPtr request_ptr,ResponsePtr response_ptr)
{
//auto client =ConnectToRedis();
auto client=connection_pool.GetClient();
ClientHelper client_helper(connection_pool,client);//for automatic return client
// if(client== nullptr)
// {
// client =ConnectToRedis();
// }
cpp_redis::reply reply1;
// client->get("notes_list", [&reply1](cpp_redis::reply& reply) {
// reply1=reply;
// std::cout << "get from redis: " << reply.as_string() << std::endl;
// });
auto notes_size=client->llen("notes_list");
client->sync_commit();
auto si=notes_size.get().as_integer()-1;
std::cout<<si<<std::endl;
client->lrange("notes_list",0,si,[&reply1](cpp_redis::reply& reply){
if(reply.ok())
{
reply1=reply;
std::cout << "get from redis: " << reply.is_array() << std::endl;
}
else
{
cout<<"error: "<<reply1.error()<<endl;
}
});
client->sync_commit();
string ret;
auto arr=reply1.as_array();
ret+="[";
for(int i=0;i<arr.size();i++)
{
auto& re=arr[i];
auto re_str=re.as_string();
ret+=re_str;
if(i==arr.size()-1)
{
continue;
}
ret+=",";
}
ret+="]";
printf("list from redis: %s\n",ret.c_str());
//client->shutdown();
response_ptr->SetStatusCode(200);
response_ptr->SetHeader("Content-Type", "application/json"); //application/x-zip-compressed
response_ptr->SetHeader("Connection", "keep-alive");
response_ptr->SetHeader("Access-Control-Allow-Origin","*");
response_ptr->SetHeader("Allow","GET,POST,DELETE");
response_ptr->PrintResponse();
// char *buf2 = nullptr;
// int length = ReadFileAll("notes.json", buf2);
// response_ptr->SetData(buf2, length);
int length=-1;
length=ret.length();
auto buf2=ret.c_str();
response_ptr->SetData(buf2, length);
response_ptr->CombineResponse();
printf("read file all %s body_length: %d, response_length: %d \n", response_ptr->HeadersStr().c_str(),length,response_ptr->ResponseLen());
};
note_book.SetGet(on_get);
auto on_post=[&connection_pool](RequestPtr request_ptr,ResponsePtr response_ptr)
{
// auto client =ConnectToRedis();
auto client=connection_pool.GetClient();
ClientHelper client_helper(connection_pool,client);//for automatic return client
cpp_redis::reply reply1;
cout<<"body: "<<(*request_ptr)["body"]<<(*request_ptr)["body"].size()<<endl;
client->lpush("notes_list",vector<string>{(*request_ptr)["body"]},[response_ptr](cpp_redis::reply& reply){
if(reply.ok())
{
response_ptr->SetStatusCode(201);
response_ptr->SetHeader("Content-Type", "application/json"); //application/x-zip-compressed
response_ptr->SetHeader("Access-Control-Allow-Origin","*");
response_ptr->PrintResponse();
response_ptr->CombineResponse();
}
else
{
response_ptr->SetStatusCode(406);
response_ptr->SetHeader("Content-Type", "application/json"); //application/x-zip-compressed
response_ptr->SetHeader("Access-Control-Allow-Origin","*");
response_ptr->PrintResponse();
response_ptr->CombineResponse();
}
});
client->sync_commit();
//printf("%s\n",reply1.as_string().c_str());
//client->shutdown();
};
note_book.SetPost(on_post);
auto on_options=[](RequestPtr request_ptr,ResponsePtr response_ptr)
{
response_ptr->SetStatusCode(200);
response_ptr->SetHeader("Content-Type", "application/json"); //application/x-zip-compressed
response_ptr->SetHeader("Access-Control-Allow-Origin","*");
response_ptr->SetHeader("Access-Control-Allow-Headers","*");
response_ptr->SetHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS,DELETE");
response_ptr->PrintResponse();
response_ptr->CombineResponse();
};
note_book.SetOptions(on_options);
auto on_delete=[&connection_pool](RequestPtr request_ptr,ResponsePtr response_ptr)
{
// auto client =ConnectToRedis();
auto client=connection_pool.GetClient();
ClientHelper client_helper(connection_pool,client);//for automatic return client
cpp_redis::reply reply1;
cout<<"body: "<<(*request_ptr)["body"]<<(*request_ptr)["body"].size()<<endl;
client->lrem("notes_list",0,(*request_ptr)["body"],[response_ptr](cpp_redis::reply& reply){
if(reply.ok())
{
cout<<"delete ok"<<endl;
response_ptr->SetStatusCode(201);
response_ptr->SetHeader("Content-Type", "application/json"); //application/x-zip-compressed
response_ptr->SetHeader("Access-Control-Allow-Origin","*");
response_ptr->PrintResponse();
response_ptr->CombineResponse();
}
else
{
cout<<"delete error"<<endl;
response_ptr->SetStatusCode(406);
response_ptr->SetHeader("Content-Type", "application/json"); //application/x-zip-compressed
response_ptr->SetHeader("Access-Control-Allow-Origin","*");
response_ptr->PrintResponse();
response_ptr->CombineResponse();
}
});
client->sync_commit();
};
note_book.SetDelete(on_delete);
auto on_close=[](ConnectionPtr conn)
{
struct in_addr tmp;
tmp.s_addr=conn->ip_;
auto str_ip=inet_ntoa(tmp);
LOG_INFO("connection closed:%s: %d",str_ip,conn->port_);
//cout<<"close loginfo"<<endl;
};
note_book.SetClose(on_close);
server_ptr->AddWorker(note_book);
signal(SIGINT,SigFunc);
server_ptr->Init();
return 0;
}