mirror of
https://github.com/oatpp/oatpp.git
synced 2025-04-06 18:40:24 +08:00
Update 1.2.0.md
This commit is contained in:
parent
26154e039c
commit
2214f095b5
@ -0,0 +1,169 @@
|
||||
# Oat++ 1.2.0
|
||||
|
||||
Feel free to ask questions - [Chat on Gitter](https://gitter.im/oatpp-framework/Lobby)
|
||||
|
||||
Contents:
|
||||
|
||||
- [Continuous Multipart Streaming](#continuous-multipart-streaming)
|
||||
- [Changes In ConnectionProvider Interface](#changes-in-connectionprovider-interface)
|
||||
- [Object-Mapping - Type Interpretations](#type-interpretations)
|
||||
- [The new Oat++ ORM](#orm)
|
||||
|
||||
## Continuous Multipart Streaming
|
||||
|
||||
Now it's possible to continuously stream multipart data to the client.
|
||||
For example, you can implement `multipart/x-mixed-replace` video stream.
|
||||
|
||||
Both Simple-APIs and Async-APIs available.
|
||||
|
||||
```cpp
|
||||
using namespace oatpp::web::mime::multipart;
|
||||
|
||||
class MPStream : public Multipart {
|
||||
public:
|
||||
|
||||
MPStream()
|
||||
: Multipart(generateRandomBoundary())
|
||||
{}
|
||||
|
||||
std::shared_ptr<Part> readNextPart(async::Action& action /* For Simple-API action is ignored */) override {
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1)); // For Simple-API you may sleep just like that
|
||||
|
||||
oatpp::String frameData = "<frame-binary-jpeg-data>" // frame data. One jpeg image.
|
||||
|
||||
auto part = std::make_shared<Part>();
|
||||
part->putHeader(Header::CONTENT_TYPE, "image/jpeg");
|
||||
part->setDataInfo(std::make_shared<oatpp::data::stream::BufferInputStream>(frameData));
|
||||
|
||||
return part;
|
||||
|
||||
}
|
||||
|
||||
void writeNextPart(const std::shared_ptr<Part>& part, async::Action& action) override {
|
||||
throw std::runtime_error("No writes here!!!");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ENDPOINT("GET", "multipart-stream", multipartStream) {
|
||||
auto multipart = std::make_shared<MPStream>();
|
||||
auto body = std::make_shared<oatpp::web::protocol::http::outgoing::MultipartBody>(
|
||||
multipart,
|
||||
"multipart/x-mixed-replace",
|
||||
true /* flush parts */
|
||||
);
|
||||
return OutgoingResponse::createShared(Status::CODE_200, body);
|
||||
}
|
||||
```
|
||||
|
||||
## Changes In ConnectionProvider Interface
|
||||
|
||||
Both `oatpp::network::ServerConnectionProvider` and `oatpp::network::ClientConnectionProvider`
|
||||
are now subclasses of a general `oatpp::provider::Provider<data::stream::IOStream>` class.
|
||||
|
||||
Renamed methods:
|
||||
|
||||
- `getConnection()` --> `get()`
|
||||
- `getConnectionAsync()` --> `getAsync()`
|
||||
- `invalidateConnection()` --> `invalidate()`
|
||||
|
||||
This was done to unify providers' APIs and to have same API for all resource providers and resource pools.
|
||||
Connection Providers and Connection Pools of the new ORM database adaptors are implemented based on the same functionality.
|
||||
|
||||
## Type Interpretations
|
||||
|
||||
To simplify the integration of custom types with oatpp Object-Mapping framework the the "Type Interpretation" feature was introduced.
|
||||
|
||||
Let's say you have some struct that is not part of oatpp object-mapping framework.
|
||||
|
||||
```cpp
|
||||
struct VPoint {
|
||||
v_int32 x;
|
||||
v_int32 y;
|
||||
v_int32 z;
|
||||
};
|
||||
```
|
||||
|
||||
To integrate it with oatpp object-mapping you can do the following:
|
||||
|
||||
```cpp
|
||||
namespace __class {
|
||||
class PointClass;
|
||||
}
|
||||
|
||||
/* Declare ObjectWrapper for your type */
|
||||
/* Mapping-Enabled Point */
|
||||
typedef oatpp::data::mapping::type::Primitive<VPoint, __class::PointClass> Point;
|
||||
|
||||
namespace __class {
|
||||
|
||||
/**
|
||||
* Type info
|
||||
*/
|
||||
class PointClass {
|
||||
private:
|
||||
|
||||
/**
|
||||
* Type interpretation
|
||||
*/
|
||||
class Inter : public oatpp::Type::Interpretation<Point, oatpp::UnorderedFields<oatpp::Int32>> {
|
||||
public:
|
||||
|
||||
oatpp::UnorderedFields<oatpp::Int32> interpret(const Point& value) const override {
|
||||
return {{"x", value->x}, {"y", value->y}, {"z", value->z}};
|
||||
}
|
||||
|
||||
Point reproduce(const oatpp::UnorderedFields<oatpp::Int32> map) const override {
|
||||
return Point({map["x"], map["y"], map["z"]});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
static const oatpp::ClassId CLASS_ID;
|
||||
|
||||
static oatpp::Type* getType(){
|
||||
static Type type(
|
||||
CLASS_ID, nullptr, nullptr, nullptr, nullptr,
|
||||
{
|
||||
{"my-types", new Inter()} //<-- Add type interpretation
|
||||
}
|
||||
);
|
||||
return &type;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const oatpp::ClassId PointClass::CLASS_ID("my-types::Point");
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Now the "Point" struct can be serialized/deserialized with object mappers.
|
||||
|
||||
```cpp
|
||||
oatpp::parser::json::mapping::ObjectMapper mapper;
|
||||
|
||||
{
|
||||
auto config = mapper.getSerializer()->getConfig();
|
||||
config->enableInterpretations = {"my-types"}; // Enable "my-types" for serializer
|
||||
}
|
||||
|
||||
{
|
||||
auto config = mapper.getDeserializer()->getConfig();
|
||||
config->enableInterpretations = {"my-types"}; // Enable "my-types" for deserializer
|
||||
}
|
||||
|
||||
Point point ({1, 2, 3}); // Create mapping-enabled Point
|
||||
|
||||
auto json = mapper.writeToString(point); // Serialize Point
|
||||
auto pointClone = mapper.readFromString<Point>(json); // Deserialize Point
|
||||
```
|
||||
|
||||
## ORM
|
||||
|
||||
The main feature of the `1.2.0` release is the new ORM Framework.
|
||||
For details see - [Object-Relational Mapping (ORM) framework](https://oatpp.io/docs/components/orm/)
|
||||
|
Loading…
x
Reference in New Issue
Block a user