完善文档
This commit is contained in:
@@ -6,17 +6,17 @@
|
|||||||
  Redkale (中文名: 红菜苔,一种湖北特产蔬菜) 是基于Java 11全新的微服务框架, 包含HTTP、WebSocket、TCP/UDP、数据序列化、数据缓存、依赖注入等功能。 本框架致力于简化集中式和微服务架构的开发,在增强开发敏捷性的同时保持高性能。
|
  Redkale (中文名: 红菜苔,一种湖北特产蔬菜) 是基于Java 11全新的微服务框架, 包含HTTP、WebSocket、TCP/UDP、数据序列化、数据缓存、依赖注入等功能。 本框架致力于简化集中式和微服务架构的开发,在增强开发敏捷性的同时保持高性能。
|
||||||
|
|
||||||
主要特点::
|
主要特点::
|
||||||
* 大量使用Java 8+新特性(接口默认值、Stream、Lambda、内置的ASM、HttpClient等)
|
* 提供了动态依赖注入和动态字节码生成类功能
|
||||||
* 提供HTTP服务,同时内置JSON功能与限时缓存功能
|
* 提供HTTP服务,同时内置JSON功能与限时缓存功能
|
||||||
* TCP层完全使用NIO,并统一TCP与UDP的接口换
|
* TCP层完全使用NIO,并统一TCP与UDP的接口换
|
||||||
* 提供分布式与集中式部署的无缝切换
|
* 提供分布式与集中式部署的无缝切换
|
||||||
* 提供类似JPA功能,包含数据缓存自动同步、分表分库与简洁的数据层操作接口
|
* 提供类似JPA功能,包含数据缓存自动同步、分表分库与简洁的数据层操作接口
|
||||||
* 可以动态修改已依赖注入的资源
|
* 提供了MQ消息消费与生产简洁化API
|
||||||
|
|
||||||
## 开发文档
|
## 开发文档
|
||||||
* [快速入门](docs/quick-start.md)
|
* [快速入门](docs/quick-start.md)
|
||||||
* [Service组件](docs/service.md)
|
* [Service组件](docs/service.md)
|
||||||
* [Json序列化](docs/convert-json.md)
|
* [序列化](docs/convert.md)
|
||||||
* [DB数据源组件](docs/datasource.md)
|
* [DB数据源组件](docs/datasource.md)
|
||||||
* [Cache数据源组件](docs/cachesource.md)
|
* [Cache数据源组件](docs/cachesource.md)
|
||||||
* [WebSocket](docs/websocket.md)
|
* [WebSocket](docs/websocket.md)
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
* [FAQ](docs/faq.md)
|
* [FAQ](docs/faq.md)
|
||||||
|
|
||||||
## 设计理念
|
## 设计理念
|
||||||
  作为一个全新的微服务框架,Redkale在接口定义上使用了Java 8以上版本的大量新特性,接口有默认实现、接口带静态方法、重复注解等特性,同时在设计上与主流框架有很大不同。Redkale是按组件形式设计的,而非以容器为主,几乎每个子包都是能提供独立功能的组件。如Tomcat是按容器设计的,所有web资源/配置由Tomcat控制,开发者很能难控制到Tomcat内部,而Redkale的HTTP服务只是个组件,开发者既可以自己启动和配置HttpServer,也可以把Redkale当成容器通过Redkale进程来初始化服务。Spring的Ioc容器也是如此,Redkale提供的依赖注入仅通过ResouceFactory一个类来控制,非常轻量,并且可动态更改已注入的资源。Spring提倡控制反转思想,而自身的容器却让开发者很难控制。Redkale是一个既能以组件形式也能以容器形式存在的框架。从整体上看,Redkale的架构分两层:接口和默认实现。开发者若想替换掉Redkale内置的HTTP服务而使用符合JavaEE规范的HttpServlet, 可以采用自定义协议基于JSR 340(Servlet 3.1)来实现自己的HTTP服务;若想使用Hibernate作为数据库操作,可以写一个自己的DataSource实现类;JSON的序列化和反序列化也可以使用第三方的实现;Memcached或Redis也可以作为另一个CacheSource的实现替换Redkale的默认实现。这其实包含了控制反转的思想,让框架里的各个组件均可让开发者控制。
|
  作为一个全新的微服务框架,Redkale在接口定义上使用了默认实现、接口带静态方法、重复注解等特性,同时在设计上与主流框架有很大不同。Redkale是按组件形式设计的,而非以容器为主,几乎每个子包都是能提供独立功能的组件。如Tomcat是按容器设计的,所有web资源/配置由Tomcat控制,开发者很能难控制到Tomcat内部,而Redkale的HTTP服务只是个组件,开发者既可以自己启动和配置HttpServer,也可以把Redkale当成容器通过Redkale进程来初始化服务。Spring的Ioc容器也是如此,Redkale提供的依赖注入仅通过ResouceFactory一个类来控制,非常轻量,并且可动态更改已注入的资源。Spring提倡控制反转思想,而自身的容器却让开发者很难控制。Redkale是一个既能以组件形式也能以容器形式存在的框架。从整体上看,Redkale的架构分两层:接口和默认实现。开发者若想替换掉Redkale内置的HTTP服务而使用符合JavaEE规范的HttpServlet, 可以采用自定义协议基于JSR 340(Servlet 3.1)来实现自己的HTTP服务;若想使用Hibernate作为数据库操作,可以写一个自己的DataSource实现类;JSON的序列化和反序列化也可以使用第三方的实现;Memcached或Redis也可以作为另一个CacheSource的实现替换Redkale的默认实现。这其实包含了控制反转的思想,让框架里的各个组件均可让开发者控制。
|
||||||
  与主流框架比,功能上Redkale显得很简单,这体现了Redkale的简易性,而并非是不足,从一个良好的设计习惯或架构上来看,有些常用功能是不需要提供的,如Redkale的HTTP服务不支持JSP, JSP其实算是一个落后的技术,现在是一个多样化终端的时代,终端不只局限于桌面程序和PC浏览器,还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端,这些都不是JSP能方便兼顾的,而HTTP+JSON作为通用性接口可以避免重复开发,模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选,不会为了迎合主流而提供,而是以良好的设计思想为指导。这是Redkale的主导思维。
|
  与主流框架比,功能上Redkale显得很简单,这体现了Redkale的简易性,而并非是不足,从一个良好的设计习惯或架构上来看,有些常用功能是不需要提供的,如Redkale的HTTP服务不支持JSP, JSP其实算是一个落后的技术,现在是一个多样化终端的时代,终端不只局限于桌面程序和PC浏览器,还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端,这些都不是JSP能方便兼顾的,而HTTP+JSON作为通用性接口可以避免重复开发,模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选,不会为了迎合主流而提供,而是以良好的设计思想为指导。这是Redkale的主导思维。
|
||||||
|
|
||||||
   <b>详情请访问:  <a href='https://redkale.org' target='_blank'>https://redkale.org</a></b>
|
   <b>详情请访问:  <a href='https://redkale.org' target='_blank'>https://redkale.org</a></b>
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Json序列化
|
|
||||||
文档完善中……
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
文档完善中……
|
|
||||||
397
docs/convert.md
397
docs/convert.md
@@ -1,2 +1,395 @@
|
|||||||
# Json序列化
|
# 序列化
|
||||||
文档完善中……
|
  Convert提供Java对象的序列化与反序列化功能。支持JSON(JavaScript Object Notation)、BSON(Binary Stream Object Notation)、PROTOBUF三种格式化。 三种格式使用方式完全一样,其性能都大幅度超过其他JSON框架。同时JSON内置于HTTP服务中,BSON也是SNCP协议数据序列化的基础。
|
||||||
|
## 基本API
|
||||||
|
  JSON序列化其操作类主要是JsonConvert,配置类主要是JsonFactory、ConvertColumn。JsonFactory采用同ClassLoader类似的双亲委托方式设计。
|
||||||
|
JsonConvert 序列化encode方法:
|
||||||
|
```java
|
||||||
|
public String convertTo(Object value);
|
||||||
|
|
||||||
|
public String convertTo(Type type, Object value);
|
||||||
|
|
||||||
|
public void convertTo(OutputStream out, Object value);
|
||||||
|
|
||||||
|
public void convertTo(OutputStream out, Type type, Object value);
|
||||||
|
|
||||||
|
public ByteBuffer[] convertTo(Supplier<ByteBuffer> supplier, Object value);
|
||||||
|
|
||||||
|
public ByteBuffer[] convertTo(Supplier<ByteBuffer> supplier, Type type, Object value);
|
||||||
|
|
||||||
|
public void convertTo(JsonWriter writer, Object value);
|
||||||
|
|
||||||
|
public void convertTo(JsonWriter writer, Type type, Object value);
|
||||||
|
```
|
||||||
|
JsonConvert 反序列化decode方法:
|
||||||
|
```java
|
||||||
|
public <T> T convertFrom(Type type, String text);
|
||||||
|
|
||||||
|
public <T> T convertFrom(Type type, char[] text);
|
||||||
|
|
||||||
|
public <T> T convertFrom(Type type, char[] text, int start, int len);
|
||||||
|
|
||||||
|
public <T> T convertFrom(Type type, InputStream in);
|
||||||
|
|
||||||
|
public <T> T convertFrom(Type type, ByteBuffer... buffers);
|
||||||
|
|
||||||
|
public <T> T convertFrom(Type type, JsonReader reader);
|
||||||
|
```
|
||||||
|
## Json基本用法
|
||||||
|
```java
|
||||||
|
@Data
|
||||||
|
public class UserRecord {
|
||||||
|
|
||||||
|
private int userid;
|
||||||
|
|
||||||
|
private String username = "";
|
||||||
|
|
||||||
|
private String password = "";
|
||||||
|
|
||||||
|
public UserRecord() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
UserRecord user = new UserRecord();
|
||||||
|
user.setUserid(100);
|
||||||
|
user.setUsername("redkalename");
|
||||||
|
user.setPassword("123456");
|
||||||
|
final JsonConvert convert = JsonConvert.root();
|
||||||
|
String json = convert.convertTo(user);
|
||||||
|
System.out.println(json); //应该是 {"password":"123456","userid":100,"username":"redkalename"}
|
||||||
|
UserRecord user2 = convert.convertFrom(UserRecord.class, json);
|
||||||
|
System.out.println(convert.convertTo(user2)); //应该也是 {"password":"123456","userid":100,"username":"redkalename"}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以下功能是为了屏蔽password字段。
|
||||||
|
* 等价于 public String getPassword() 加上 @ConvertColumn :
|
||||||
|
*
|
||||||
|
* @ConvertColumn(ignore = true, type = ConvertType.JSON)
|
||||||
|
* public String getPassword() {
|
||||||
|
* return password;
|
||||||
|
* }
|
||||||
|
**/
|
||||||
|
final JsonFactory childFactory = JsonFactory.root().createChild();
|
||||||
|
childFactory.register(UserRecord.class, true, "password"); //屏蔽掉password字段使其不输出
|
||||||
|
childFactory.reloadCoder(UserRecord.class); //重新加载Coder使之覆盖父Factory的配置
|
||||||
|
final JsonConvert childConvert = childFactory.getConvert();
|
||||||
|
json = childConvert.convertTo(user);
|
||||||
|
System.out.println(json); //应该是 {"userid":100,"username":"redkalename"}
|
||||||
|
user2 = childConvert.convertFrom(UserRecord.class, json);
|
||||||
|
System.out.println(childConvert.convertTo(user2)); //应该也是 {"userid":100,"username":"redkalename"}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
  在Redkale里存在默认的JsonConvert、BsonConvert、ProtobufConvert对象。 只需在所有Service、Servlet中增加依赖注入资源。
|
||||||
|
```java
|
||||||
|
public class XXXService implements Service {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private JsonConvert jsonConvert;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BsonConvert bsonConvert;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProtobufConvert protobufConvert;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class XXXServlet extends HttpServlet {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private JsonConvert jsonConvert;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BsonConvert bsonConvert;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProtobufConvert protobufConvert;
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
   同一类型数据通过设置新的JsonFactory可以有不同的输出。
|
||||||
|
```java
|
||||||
|
public class UserSimpleInfo {
|
||||||
|
|
||||||
|
private int userid;
|
||||||
|
|
||||||
|
private String username = "";
|
||||||
|
|
||||||
|
@ConvertColumn(ignore = true, type = ConvertType.JSON)
|
||||||
|
private long regtime; //注册时间
|
||||||
|
|
||||||
|
@ConvertColumn(ignore = true, type = ConvertType.JSON)
|
||||||
|
private String regaddr = ""; //注册IP
|
||||||
|
|
||||||
|
/** 以下省略getter setter方法 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class UserInfoServlet extends HttpBaseServlet {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserSerice service;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private JsonFactory jsonRootFactory;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private JsonConvert detailConvert;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(HttpContext context, AnyValue config) {
|
||||||
|
final JsonFactory childFactory = jsonRootFactory.createChild();
|
||||||
|
childFactory.register(UserSimpleInfo.class, false, "regtime", "regaddr"); //允许输出注册时间与注册地址
|
||||||
|
childFactory.reloadCoder(UserSimpleInfo.class); //重新加载Coder使之覆盖父Factory的配置
|
||||||
|
this.detailConvert = childFactory.getConvert();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取他人基本信息
|
||||||
|
@HttpMapping(url = "/user/info/")
|
||||||
|
public void info(HttpRequest req, HttpResponse resp) throws IOException {
|
||||||
|
int userid = Integer.parseInt(req.getRequstURILastPath());
|
||||||
|
UserSimpleInfo user = service.findUserInfo(userid);
|
||||||
|
resp.finishJson(user); // 不包含用户的注册时间和注册地址字段信息
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取用户自己的信息
|
||||||
|
@HttpMapping(url = "/user/myinfo")
|
||||||
|
public void mydetail(HttpRequest req, HttpResponse resp) throws IOException {
|
||||||
|
int userid = req.currentUser().getUserid(); //获取当前用户ID
|
||||||
|
UserSimpleInfo user = service.findUserInfo(userid);
|
||||||
|
resp.finishJson(detailConvert, user); // 包含用户的注册时间和注册地址字段信息
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
  Convert 支持带参数构造函数。
|
||||||
|
1. public 带参数的构造函数加上 @ConstructorParameters 注解:
|
||||||
|
```java
|
||||||
|
public class UserRecord {
|
||||||
|
|
||||||
|
private int userid;
|
||||||
|
|
||||||
|
private String username = "";
|
||||||
|
|
||||||
|
private String password = "";
|
||||||
|
|
||||||
|
@ConstructorParameters({"userid", "username", "password"})
|
||||||
|
public UserRecord(int userid, String username, String password) {
|
||||||
|
this.userid = userid;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserid() {
|
||||||
|
return userid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
2. 自定义Creator:
|
||||||
|
```java
|
||||||
|
public class UserRecord {
|
||||||
|
|
||||||
|
private int userid;
|
||||||
|
|
||||||
|
private String username = "";
|
||||||
|
|
||||||
|
private String password = "";
|
||||||
|
|
||||||
|
UserRecord(int userid, String username, String password) {
|
||||||
|
this.userid = userid;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserid() {
|
||||||
|
return userid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义Creator方法。
|
||||||
|
* 1) 方法名可以随意。
|
||||||
|
* 2) 方法必须是static。
|
||||||
|
* 3)方法的参数必须为空。
|
||||||
|
* 4)方法的返回类型必须是Creator。
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static Creator<UserRecord> creator() {
|
||||||
|
return new Creator<UserRecord>() {
|
||||||
|
@Override
|
||||||
|
@ConstructorParameters({"userid", "username", "password"}) //带参数的构造函数必须有ConstructorParameters注解
|
||||||
|
public UserRecord create(Object... params) {
|
||||||
|
return new UserRecord((params[0] == null ? 0 : (Integer) params[0]), (String) params[1], (String) params[2]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
  通常JavaBean类默认有个public空参数的构造函数,因此大部分情况下不要自定义Creator,其实只要不是private的空参数构造函数Convert都能自动支持(其他的框架都仅支持public的构造函数),只有仅含private的构造函数才需要自定义Creator。带参数的构造函数就需要标记@ConstructorParameters,常见于Immutable Object。
|
||||||
|
|
||||||
|
## 自定义
|
||||||
|
  Convert 支持自定义Decode、Encode。
|
||||||
|
1. 通过ConvertFactory显式的注册:
|
||||||
|
```java
|
||||||
|
public class FileSimpleCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, File> {
|
||||||
|
|
||||||
|
public static final FileSimpleCoder instance = new FileSimpleCoder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convertTo(W out, File value) {
|
||||||
|
out.writeString(value == null ? null : value.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File convertFrom(R in) {
|
||||||
|
String path = in.readString();
|
||||||
|
return path == null ? null : new File(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonFactory.root().register(File.class, FileSimpleCoder.instance);
|
||||||
|
|
||||||
|
BsonFactory.root().register(File.class, FileSimpleCoder.instance);
|
||||||
|
```
|
||||||
|
2. 通过JavaBean类自定义静态方法自动加载:
|
||||||
|
```java
|
||||||
|
public class InnerCoderEntity {
|
||||||
|
|
||||||
|
private final String val;
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
private InnerCoderEntity(int id, String value) {
|
||||||
|
this.id = id;
|
||||||
|
this.val = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InnerCoderEntity create(int id, String value) {
|
||||||
|
return new InnerCoderEntity(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 该方法提供给Convert组件自动加载。
|
||||||
|
* 1) 方法名可以随意。
|
||||||
|
* 2) 方法必须是static
|
||||||
|
* 3)方法的参数有且只能有一个, 且必须是org.redkale.convert.ConvertFactory或子类。
|
||||||
|
* —3.1) 参数类型为org.redkale.convert.ConvertFactory 表示适合JSON和BSON。
|
||||||
|
* —3.2) 参数类型为org.redkale.convert.json.JsonFactory 表示仅适合JSON。
|
||||||
|
* —3.3) 参数类型为org.redkale.convert.bson.BsonFactory 表示仅适合BSON。
|
||||||
|
* 4)方法的返回类型必须是org.redkale.convert.Decodeable/org.redkale.convert.Encodeable/org.redkale.convert.SimpledCoder
|
||||||
|
* 若返回类型不是org.redkale.convert.SimpledCoder, 就必须提供两个方法: 一个返回Decodeable 一个返回 Encodeable。
|
||||||
|
*
|
||||||
|
* @param factory
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static SimpledCoder<Reader, Writer, InnerCoderEntity> createConvertCoder(final org.redkale.convert.ConvertFactory factory) {
|
||||||
|
return new SimpledCoder<Reader, Writer, InnerCoderEntity>() {
|
||||||
|
|
||||||
|
//必须与EnMember[] 顺序一致
|
||||||
|
private final DeMember[] deMembers = new DeMember[]{
|
||||||
|
DeMember.create(factory, InnerCoderEntity.class, "id"),
|
||||||
|
DeMember.create(factory, InnerCoderEntity.class, "val")};
|
||||||
|
|
||||||
|
//必须与DeMember[] 顺序一致
|
||||||
|
private final EnMember[] enMembers = new EnMember[]{
|
||||||
|
EnMember.create(factory, InnerCoderEntity.class, "id"),
|
||||||
|
EnMember.create(factory, InnerCoderEntity.class, "val")};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convertTo(Writer out, InnerCoderEntity value) {
|
||||||
|
if (value == null) {
|
||||||
|
out.writeObjectNull(InnerCoderEntity.class);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.writeObjectB(value);
|
||||||
|
for (EnMember member : enMembers) {
|
||||||
|
out.writeObjectField(member, value);
|
||||||
|
}
|
||||||
|
out.writeObjectE(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InnerCoderEntity convertFrom(Reader in) {
|
||||||
|
if (in.readObjectB(InnerCoderEntity.class) == null) return null;
|
||||||
|
int index = 0;
|
||||||
|
final Object[] params = new Object[deMembers.length];
|
||||||
|
while (in.hasNext()) {
|
||||||
|
DeMember member = in.readFieldName(deMembers); //读取字段名
|
||||||
|
in.readBlank(); //读取字段名与字段值之间的间隔符,JSON则是跳过冒号:
|
||||||
|
if (member == null) {
|
||||||
|
in.skipValue(); //跳过不存在的字段的值, 一般不会发生
|
||||||
|
} else {
|
||||||
|
params[index++] = member.read(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.readObjectE(InnerCoderEntity.class);
|
||||||
|
return InnerCoderEntity.create(params[0] == null ? 0 : (Integer) params[0], (String) params[1]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVal() {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JsonConvert.root().convertTo(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bson数据格式
|
||||||
|
  BSON类似Java自带的Serializable, 其格式如下:
|
||||||
|
|
||||||
|
    1). 基本数据类型: 直接转换成byte[]
|
||||||
|
|
||||||
|
    2). SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
|
||||||
|
|
||||||
|
    3). String: length(4 bytes) + byte[](utf8);
|
||||||
|
|
||||||
|
    4). 数组: length(4 bytes) + byte[]...
|
||||||
|
|
||||||
|
    5). Object:
|
||||||
|
|
||||||
|
      1. realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名)
|
||||||
|
|
||||||
|
      2. 空字符串(SmallString)
|
||||||
|
|
||||||
|
      3. SIGN_OBJECTB 标记位,值固定为0xBB (short)
|
||||||
|
|
||||||
|
      4. 循环字段值:
|
||||||
|
|
||||||
|
        4.1 SIGN_HASNEXT 标记位,值固定为1 (byte)
|
||||||
|
|
||||||
|
        4.2 字段类型; 1-9为基本类型&字符串; 101-109为基本类型&字符串的数组; 127为Object
|
||||||
|
|
||||||
|
        4.3 字段名 (SmallString)
|
||||||
|
|
||||||
|
        4.4 字段的值Object
|
||||||
|
|
||||||
|
      5. SIGN_NONEXT 标记位,值固定为0 (byte)
|
||||||
|
|
||||||
|
       6. SIGN_OBJECTE 标记位,值固定为0xEE (short)
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# 数据源
|
|
||||||
文档完善中……
|
|
||||||
@@ -5,14 +5,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于类名的别名, 该值必须是全局唯一 <br>
|
* 用于类名的别名, 该值必须是全局唯一 <br>
|
||||||
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。 <br>
|
||||||
|
* 关联方法: {@link org.redkale.convert.Reader#readClassName()} 和 {@link org.redkale.convert.Writer#writeClassName(java.lang.String) } 。
|
||||||
*
|
*
|
||||||
* <p>详情见: https://redkale.org
|
* <p>详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user