mif adalah kerangka aplikasi web C++11 yang dirancang untuk pengembangan layanan mikro backend. Kerangka kerja ini menggunakan jenis informasi meta tambahan.
1.5.1
CATATAN: Cabang master dikembangkan secara aktif, gunakan rilis terbaru untuk penggunaan produksi.
Terakhir diuji pada gcc 13.2
Linux (Terakhir diuji di Ubuntu 23.10)
git clone https://github.com/tdv/mif.git
cd mif
./download_third_party.sh
mkdir build
cd build
cmake ..
make
make install
CATATAN: Di Ubuntu Anda mungkin harus menginstal beberapa paket tambahan: liblz4-dev, pkgconf, bison, flex
Anda dapat mencoba menggunakan CMAKE_INSTALL_PREFIX untuk memilih direktori instalasi
Setelah mif dibuat, Anda dapat membuat contoh
cd mif /examples/{sample_project}
mkdir build
cd build
cmake ..
make
CATATAN: Untuk mengembangkan aplikasi Anda, Anda dapat menggunakan templat aplikasi. Setelah mendownload proyek mif , ikuti langkah-langkahnya
cd mif /template
mkdir build
cd build
cmake ..
make
Setelah itu Anda dapat mengubah template ini untuk membuat aplikasi Anda sendiri. Selain itu, Anda dapat menggunakan contoh yang diberikan dari template. Contoh sudah selesai sepenuhnya dan memiliki skrip untuk membangunnya sendiri. Semuanya ada di folder _docs. Anda dapat menemukan dokumentasi rinci tentang contoh-contoh tersebut di wiki.
pelayan:
cd mif /exammples/{sample_project}/bin
./{sample_project}_server
Klien:
cd mif /exammples/{sample_project}/bin
./{sample_project}_client
Silakan gunakan --help untuk mendapatkan informasi lebih lanjut tentang menjalankan contoh
Kode sumber
Keterangan
Contoh ini menunjukkan cara kerja server gema HTTP sederhana. Server gema HTTP
// mif
# include < mif /application/http_server.h >
# include < mif /common/log.h >
# include < mif /net/http/constants.h >
class Application
: public mif ::Application::HttpServer
{
public:
using HttpServer::HttpServer;
private:
// mif .Application.HttpServer
virtual void Init ( mif ::Net::Http::ServerHandlers &handlers) override final
{
handlers[ " / " ] = [] ( mif ::Net::Http::IInputPack const &request,
mif ::Net::Http::IOutputPack &response)
{
auto data = request. GetData ();
mif _LOG (Info) << " Process request " " << request. GetPath () << request. GetQuery () << " "t Data: "
<< (data. empty () ? std::string{ " null " } : std::string{ std::begin (data), std::end (data)});
response. SetCode ( mif ::Net::Http::Code::Ok);
response. SetHeader ( mif ::Net::Http::Constants::Header::Connection::Value,
mif ::Net::Http::Constants::Value::Connection::Close::Value);
response. SetData ( std::move (data));
};
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
Tes
curl -iv -X POST " http://localhost:55555/ " -d ' Test data '
Kode sumber
Keterangan
Contoh ini menunjukkan kerja server HTTP dengan antarmuka ganda untuk memproses permintaan HTTP mentah dan mif RPC melalui HTTP. Selengkapnya dapat Anda lihat di bab "Layanan Web. Tambahan"
Kode sumber
Keterangan
Contoh "Hello World" mendemonstrasikan aplikasi klien-server dasar dengan marshaling RPC berbasis antarmuka dan komunikasi TCP dengan menggunakan boost.archives untuk serialisasi data
Langkah-langkah dasar untuk membangun aplikasi client-server dengan RPC
Antarmuka umum
// STD
# include < string >
// mif
# include < mif /service/iservice.h >
namespace Service
{
struct IHelloWorld
: public mif ::Service::Inherit< mif ::Service::IService>
{
virtual void AddWord (std::string const &word) = 0;
virtual std::string GetText () const = 0;
virtual void Clean () = 0;
};
} // namespace Service
Meta-informasi antarmuka umum
// STD
# include < string >
// mif
# include < mif /remote/ps.h >
// THIS
# include " common/interface/ihello_world.h "
namespace Service
{
namespace Meta
{
using namespace ::Service ;
mif _REMOTE_PS_BEGIN (IHelloWorld)
mif _REMOTE_METHOD (AddWord)
mif _REMOTE_METHOD (GetText)
mif _REMOTE_METHOD (Clean)
mif _REMOTE_PS_END ()
} // namespace Meta
} // namespace Service
mif _REMOTE_REGISTER_PS (Service::Meta::IHelloWorld)
Implementasi antarmuka server
...
// mif
# include < mif /service/creator.h >
// THIS
# include " common/id/service.h "
# include " common/interface/ihello_world.h "
namespace Service
{
namespace Detail
{
namespace
{
class HelloWorld
: public IHelloWorld
{
public:
...
private:
...
// IHelloWorld
virtual void AddWord (std::string const &word) override final
{
...
}
virtual std::string GetText () const override final
{
...
}
virtual void Clean () override final
{
...
}
};
} // namespace
} // namespace Detail
} // namespace Service
mif _SERVICE_CREATOR
(
::Service::Id::HelloWorld,
::Service::Detail::HelloWorld
)
Aplikasi pelayan
// mif
# include < mif /application/tcp_service.h >
// COMMON
# include " common/id/service.h "
# include " common/ps/ihello_world.h "
class Application
: public mif ::Application::TcpService
{
public:
using TcpService::TcpService;
private:
// mif .Application.TcpService
virtual void Init ( mif ::Service::FactoryPtr factory) override final
{
factory-> AddClass <Service::Id::HelloWorld>();
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
Aplikasi klien
// mif
# include < mif /application/tcp_service_client.h >
# include < mif /common/log.h >
// COMMON
# include " common/ps/ihello_world.h "
class Application
: public mif ::Application::TcpServiceClient
{
public:
using TcpServiceClient::TcpServiceClient;
private:
// mif .Application.TcpServiceClient
virtual void Init ( mif ::Service::IFactoryPtr factory) override final
{
auto service = factory-> Create <Service::IHelloWorld>( " HelloWorld " );
mif _LOG (Info) << " Add words. " ;
service-> AddWord ( " Hello " );
service-> AddWord ( " World " );
service-> AddWord ( " !!! " );
mif _LOG (Info) << " Result from server: " " << service-> GetText () << " " " ;
mif _LOG (Info) << " Clean. " ;
service-> Clean ();
mif _LOG (Info) << " Result from server: " " << service-> GetText () << " " " ;
}
};
int main ( int argc, char const **argv)
{
return mif ::Application::Run<Application>(argc, argv);
}
Kode sumber
Keterangan
Contoh ini sama dengan "Hello World". Perbedaannya terletak pada pemanggilan metode jarak jauh dengan struktur data yang ditentukan pengguna sebagai parameter dan mengembalikan nilai. Struktur proyek sama seperti pada contoh proyek sebelumnya, kami hanya menambahkan definisi struktur data yang ditentukan pengguna dan informasi meta.
Struktur data pengguna
// STD
# include < cstdint >
# include < map >
# include < string >
namespace Service
{
namespace Data
{
using ID = std::string;
struct Human
{
std::string name;
std::string lastName;
std:: uint32_t age = 0 ;
};
enum class Position
{
Unknown,
Developer,
Manager
};
struct Employee
: public Human
{
Position position = Position::Unknown;
};
using Employees = std::map<ID, Employee>;
} // namespace Data
} // namespace Service
Meta-informasi
// mif
# include < mif /reflection/reflect_type.h >
// THIS
# include " common/data/data.h "
namespace Service
{
namespace Data
{
namespace Meta
{
mif _REFLECT_BEGIN (Human)
mif _REFLECT_FIELD (name)
mif _REFLECT_FIELD (lastName)
mif _REFLECT_FIELD (age)
mif _REFLECT_END ()
mif _REFLECT_BEGIN (Position)
mif _REFLECT_FIELD (Unknown)
mif _REFLECT_FIELD (Developer)
mif _REFLECT_FIELD (Manager)
mif _REFLECT_END ()
mif _REFLECT_BEGIN (Employee, Human)
mif _REFLECT_FIELD (position)
mif _REFLECT_END ()
} // namespace Meta
} // namespace Data
} // namespace Service
mif _REGISTER_REFLECTED_TYPE (::Service::Data::Meta::Human)
mif _REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Position)
mif _REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Employee)
Kode sumber
Keterangan
Dibandingkan dengan contoh sebelumnya, contoh ini menambahkan warisan antarmuka. Dalam implementasinya Anda dapat menanyakan antarmuka yang berada di luar hierarki.
Kode sumber
Keterangan
Contoh "Pengunjung" menunjukkan mekanisme panggilan balik jarak jauh untuk metode antarmuka. Ini dapat digunakan sebagai titik awal untuk menerbitkan/berlangganan aplikasi berbasis.
Kode sumber
Keterangan
Contoh ini menunjukkan Json API (operasi CRUD) di server HTTP.
Tes
curl -i -X POST " http://localhost:55555/employee/create " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":200000.00} '
curl -i " http://localhost:55555/employee/read?id=1 "
curl -i " http://localhost:55555/employee/update?id=1 " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":220000.00} '
curl -i " http://localhost:55555/employee/list?limit=2&offset=0 "
curl -i " http://localhost:55555/employee/delete?id=1 "
Kode sumber
Keterangan
Contoh ini menunjukkan komunikasi antara dua layanan mikro (contohnya adalah versi http crud yang lebih kuat). Tes
./storage —config=storage.xml
./service --config=service.xml
curl -i -X POST " http://localhost:55555/employee/create " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":200000.00} '
curl -i " http://localhost:55555/employee/read?id=1 "
curl -i " http://localhost:55555/employee/update?id=1 " -d ' {"name":"Ivan", "lastName":"Ivanov","age":33,"email":"[email protected]","position":"Developer","rate":220000.00} '
curl -i " http://localhost:55555/employee/list?limit=2&offset=0 "
curl -i " http://localhost:55555/employee/delete?id=1 "
Kode sumber
Keterangan
Contoh ini menunjukkan mekanisme refleksi struktur data C++. Ini dapat digunakan sebagai titik awal untuk membangun aplikasi dengan serialisasi, ORM dan REST API.