+ Redkale 入门教程 11 -- SNCP分布式部署
+
+
+
+ Redkale 入门教程 10 -- WebSocket
+
+
+
+ Redkale 入门教程 09 -- 文件上传下载
+
+
+
+ Redkale 入门教程 08 -- HttpServlet
+
+
+
+ Redkale 入门教程 07 -- Convert
+
+
+
+ Redkale 入门教程 06 -- DataSource 分库分表
+
+
+
+ Redkale 入门教程 05 -- DataSource 增删改查
+
+
+
+ Redkale 入门教程 04 -- CacheSource缓存数据源
+
+
+
-
+ Redkale 入门教程 03 -- 用户鉴权
+
+
+
+ Redkale 入门教程 02 -- DataSource 连接
+
+
+
+ Redkale 入门教程 01 -- Hello Word!
+
+
+
Redkale 技术详解 03 -- Convert高性能序列化
diff --git a/course01_hello.html b/course01_hello.html
new file mode 100644
index 000000000..527f76033
--- /dev/null
+++ b/course01_hello.html
@@ -0,0 +1,111 @@
+
+
+
Redkale 入门教程 01 -- Hello Word!
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 02 -- DataSource 连接
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 03 -- 用户鉴权
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 04 -- CacheSource缓存数据源
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 05 -- DataSource 增删改查
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 06 -- DataSource 分库分表
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 07 -- Convert
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 08 -- HttpServlet
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 09 -- 文件上传下载
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 10 -- WebSocket
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +Redkale 入门教程 11 -- SNCP分布式部署
+ +
+ Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。
+
ClassLoader类加载
+
+ 双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
+ ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
+
Redkale 双亲委托
++ ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。 +
+public final <E> Encodeable<W, E> findEncoder(final Type type) {
+ Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
+ if (rs != null) return rs;
+ return this.parent == null ? null : this.parent.findEncoder(type);
+}+ 当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。 +
+public final <E> Encodeable<W, E> loadEncoder(final Type type) {
+ Encodeable<W, E> encoder = findEncoder(type);
+ if (encoder != null) return encoder;
+ if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
+ Class clazz;
+ if (type instanceof ParameterizedType) {
+ final ParameterizedType pts = (ParameterizedType) type;
+ clazz = (Class) (pts).getRawType();
+ } else if (type instanceof TypeVariable) {
+ TypeVariable tv = (TypeVariable) type;
+ Type t = Object.class;
+ if (tv.getBounds().length == 1) {
+ t = tv.getBounds()[0];
+ }
+ if (!(t instanceof Class)) t = Object.class;
+ clazz = (Class) t;
+ } else if (type instanceof Class) {
+ clazz = (Class) type;
+ } else {
+ throw new ConvertException("not support the type (" + type + ")");
+ }
+ encoder = findEncoder(clazz);
+ if (encoder != null) return encoder;
+ return createEncoder(type, clazz);
+}+ 大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 Convert基本用法 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。 +
++ Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。 +
+public NodeServer(Application application, Server server) {
+ this.application = application;
+ this.resourceFactory = application.getResourceFactory().createChild();
+ this.server = server;
+ this.logger = Logger.getLogger(this.getClass().getSimpleName());
+}+ 双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。 +
++
+ 转载请注明出处:https://redkale.org/article_parents.html +
+ + + +支付插件介绍
- -敬请期待……
-
REST插件介绍
-- org.redkalex.rest 是基于HTTP服务的REST插件,提供了很简单的REST服务接口方便开发。REST根据加载的Service组件自动生成对应的HttpServlet。其接口比Spring Boot之类的REST服务框架要简化得多,不需要进行注解配置也可以按REST服务加载。 -
- -快速上手
-
- 为了让REST生效,必须配置 application.xml 中 HTTP 的 <server> 节点的interceptor属性值为 org.redkalex.rest.RestNodeInterceptor 。
- 同时必须在<server> 节点 里增加 <rest> 子节点。配置介绍如下:
-
<application port="5001">
-
- <resources>
- <!-- ... -->
- </resources>
- <!--
- interceptor: 值必须要是 org.redkalex.rest.RestNodeInterceptor,且只能配置在protocol="HTTP"的server节点上,REST服务才会生效。
- -->
- <server protocol="HTTP" port="6060" interceptor="org.redkalex.rest.RestNodeInterceptor">
- <!--
- REST的核心配置项
- base: REST服务的BaseServlet,必须是 org.redkale.net.http.HttpServlet 的子类,且子类必须标记@HttpUserType。
- autoload:默认值"true" 默认值. 加载当前server所能使用的Servce对象;
- mustsign:默认值"true" 是否只加载标记为RestController的Service类,默认加载所有可用Service
- includes:当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
- excludes:当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
- -->
- <rest base="org.redkalex.test.rest.SimpleRestServlet" mustsign="true" autoload="true" includes="" excludes="">
- <!--
- value: Service类名,列出的表示必须被加载的Service对象。
- -->
- <service value="com.xxx.XXXXService"/>
- </rest>
- <!-- 其他配置... -->
- </server>
-</application>
-
- 通常配置都需要编写一个 org.redkale.net.http.HttpServlet 子类,主要用于获取当前用户信息和鉴权,且必须指定具体的User对象类。开发者的实现类可以参考 redkale-demo 中的BaseServlet类,以下是一个简单的范例:
-
public class SimpleRestServlet extends HttpServlet<UserInfo> {
-
- protected static final RetResult RET_UNLOGIN = RetCodes.retResult(RetCodes.RET_USER_UNLOGIN);
-
- protected static final RetResult RET_AUTHILLEGAL = RetCodes.retResult(RetCodes.RET_USER_AUTH_ILLEGAL);
-
- @Resource
- private UserService userService;
-
- //获取当前用户信息
- @Override
- protected UserInfo currentUser(HttpRequest req) throws IOException {
- String sessionid = req.getSessionid(false);
- if (sessionid == null || sessionid.isEmpty()) return null;
- return userService.current(sessionid);
- }
-
- //普通鉴权
- @Override
- public boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException {
- UserInfo info = currentUser(request);
- if (info == null) {
- response.finishJson(RET_UNLOGIN);
- return false;
- } else if (!info.checkAuth(module, actionid)) {
- response.finishJson(RET_AUTHILLEGAL);
- return false;
- }
- return true;
- }
-
-}
-
- 编写完 org.redkalex.rest.RestServlet 子类后就需要对Service进行设置,设置需要三大注解:@RestController、@RestMapping、@RestParam。
-
@RestController :
-
/**
- * 只能依附在Service类上,value默认为Service的类名去掉Service字样的字符串 (如HelloService,的默认路径为 hello)。
- */
-@Target({TYPE})
-public @interface RestController {
-
- boolean ignore() default false; //是否屏蔽该类的转换
-
- String value() default ""; //模块名, 只能是模板名,不能含特殊字符
-
- boolean repair() default true; //同@WebServlet的repair属性
-
- int module() default 0; //模块ID值,鉴权时用到
-
-}
-
-
@RestMapping :
-
/**
- * 只能依附在Service实现类的public方法上
- * value默认为"/" + Service的类名去掉Service及后面字样的小写字符串 (如HelloService,的默认路径为/hello)。
- */
-@Target({METHOD})
-public @interface RestMapping {
-
- boolean ignore() default false; //是否屏蔽该方法的转换
-
- //请求的方法名, 不能含特殊字符
- //默认为方法名的小写(若方法名以createXXX、updateXXX、deleteXXX、queryXXX、findXXX且XXXService为Service的类名将只截取XXX之前)
- String name() default "";
-
- boolean authignore() default true; //是否跳过鉴权,默认跳过
-
- int actionid() default 0; //操作ID值,鉴权时用到
-
- String contentType() default ""; //设置Response的ContentType 默认值为 text/plain; charset=utf-8
-
- String jsvar() default ""; //以application/javascript输出对象是指明js的对象名,该值存在时则忽略contentType()的值
-}
-
-
@RestParam :
-
/**
- * 只能依附在Service类的方法的参数上
- */
-@Target({PARAMETER})
-public @interface RestParam {
-
- String value(); //参数名
-
- /**
- * 参数是否从header取, 默认使用 request.getJsonParameter, 设置为true则使用 request.getJsonHeader 取值
- *
- * @return 是否从header取
- */
- boolean header() default false;
-}
-
- REST的设置方式有两大种: 一种是采用默认REST注解,一种是显式的设置。
- 第一种方式需要开发者对Service中的方法命名需要遵循一定规则, 如下范例,模块为Hello,Service类命名为HelloService,增删改查的方法采用createHello、deleteHello、updateHello、queryHello或其他xxxHello命名。REST插件加载任何没有标记@RestController、@RestMapping、@RestParam 的Service将按照一定规则生成默认值:
- 1、@RestController.value() 默认值为Service类名的小写化并去掉service及后面字样, 视为模块名
- 2、@RestMapping.name() 默认值为Service的方法名小写化并去掉模块名字样
- 3、@RestParam.value() 如果方法名以find、delete开头且方法的参数只有一个且参数类型是基本数据类型或String,则默认值为"#";若使用Java 8中带上 -parameters 编译项的新特性,默认值为参数名, 若没使用新特性则采用bean、bean2、bean3...的命名规则。
-
/**
- * 类说明:
- * Flipper : Source组件中的翻页对象, 只要Service方法中的参数类与该类相同,则不需要设定 @RestParam
- * UserInfo :当前用户类, 只要Service方法中的参数类与该类相同,则不需要设定 @RestParam
- * HelloEntity: Hello模块的实体类
- * HelloBean: Hellow模块实现FilterBean的过滤Bean类
- *
- */
-@RestController(value = "hello", module = 0, repair = true, ignore = false)
-public class HelloService implements Service {
-
- @Resource
- private DataSource source;
-
- //增加记录
- @RestMapping(name = "create", authignore = true)
- public RetResult<HelloEntity> createHello(UserInfo info, @RestParam("bean") HelloEntity entity) { //通过 /hello/create?bean={...} 增加对象
- entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
- entity.setCreatetime(System.currentTimeMillis());
- source.insert(entity);
- return new RetResult<>(entity);
- }
-
- //删除记录
- @RestMapping(name = "delete", authignore = true)
- public void deleteHello(@RestParam("#") int id) { //通过 /hello/delete/1234 删除对象
- source.delete(HelloEntity.class, id);
- }
-
- //修改记录
- @RestMapping(name = "update", authignore = true)
- public void updateHello(@RestParam("bean") HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
- entity.setUpdatetime(System.currentTimeMillis());
- source.update(entity);
- }
-
- //查询列表
- @RestMapping(name = "query", authignore = true)
- public Sheet<HelloEntity> queryHello(@RestParam("bean") HelloBean bean, Flipper flipper) { //通过 /hello/query/offset:0/limit:20?bean={...} 查询列表
- return source.querySheet(HelloEntity.class, flipper, bean);
- }
-
- //查询单个
- @RestMapping(name = "find", authignore = true)
- public HelloEntity findHello(@RestParam("#") int id) { //通过 /hello/find/1234 查询对象
- return source.find(HelloEntity.class, id);
- }
-}
-
- 根据默认命名规则可以看出,以上范例生成的RestServlet与去掉所有@RestController、@RestMapping、@RestParam后的Service生成的是完全相同的。 REST插件根据Service会动态生成HttpServlet,以上范例生成的HttpServlet如下:
-
@WebServlet(value = {"/hello/*"}, repair = true)
-public class _DynHelloRestServlet extends SimpleRestServlet {
-
- @Resource
- private HelloService _service;
-
- @AuthIgnore
- @HttpMapping(url = "/hello/create")
- public void create(HttpRequest req, HttpResponse resp) throws IOException {
- HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
- UserInfo user = currentUser(req);
- RetResult<HelloEntity> result = _service.createHello(user, bean);
- resp.finishJson(result);
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/delete/")
- public void delete(HttpRequest req, HttpResponse resp) throws IOException {
- int id = Integer.parseInt(req.getRequstURILastPath());
- _service.deleteHello(id);
- resp.finishJson(RetResult.success());
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/update")
- public void update(HttpRequest req, HttpResponse resp) throws IOException {
- HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
- _service.updateHello(bean);
- resp.finishJson(RetResult.success());
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/query")
- public void query(HttpRequest req, HttpResponse resp) throws IOException {
- HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
- Flipper flipper = req.getFlipper();
- Sheet<HelloEntity> result = _service.queryHello(bean, flipper);
- resp.finishJson(result);
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/find/")
- public void find(HttpRequest req, HttpResponse resp) throws IOException {
- int id = Integer.parseInt(req.getRequstURILastPath());
- HelloEntity bean = _service.findHello(id);
- resp.finishJson(bean);
- }
-}
-
- REST的第二种设置方式是显式的设置, 看如下范例:
-
/**
- * 类说明:
- * Flipper : Source组件中的翻页对象
- * UserInfo :当前用户类
- * HelloEntity: Hello模块的实体类
- * HelloBean: Hellow模块实现FilterBean的过滤Bean类
- *
- */
-public class HelloService implements Service {
-
- @Resource
- private DataSource source;
-
- //增加记录
- public RetResult<HelloEntity> createHello(UserInfo info, HelloEntity entity) {
- entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
- entity.setCreatetime(System.currentTimeMillis());
- source.insert(entity);
- return new RetResult<>(entity);
- }
-
- //删除记录
- public void deleteHello(int id) { //通过 /hello/delete/1234 删除对象
- source.delete(HelloEntity.class, id);
- }
-
- //修改记录
- public void updateHello(HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
- entity.setUpdatetime(System.currentTimeMillis());
- source.update(entity);
- }
-
- //修改记录
- @RestMapping(name = "partupdate")
- public void updateHello(HelloEntity entity, @RestParam("cols") String[] columns) { //通过 /hello/update?bean={...} 修改对象
- entity.setUpdatetime(System.currentTimeMillis());
- source.updateColumn(entity, columns);
- }
-
- //查询Sheet列表
- public Sheet<HelloEntity> queryHello(HelloBean bean, Flipper flipper) { //通过 /hello/query/offset:0/limit:20?bean={...} 查询Sheet列表
- return source.querySheet(HelloEntity.class, flipper, bean);
- }
-
- //查询List列表
- @RestMapping(name = "list")
- public List<HelloEntity> queryHello(HelloBean bean) { //通过 /hello/list?bean={...} 查询List列表
- return source.queryList(HelloEntity.class, bean);
- }
-
- //查询单个
- @RestMapping(name = "find")
- public HelloEntity findHello(@RestParam("#") int id) { //通过 /hello/find/1234 查询对象
- return source.find(HelloEntity.class, id);
- }
-}
-
- 转换为RestServlet如下:
-
@WebServlet(value = {"/hello/*"}, repair = true)
-public class _DynHelloRestServlet extends SimpleRestServlet {
-
- @Resource
- private HelloService _service;
-
- @AuthIgnore
- @HttpMapping(url = "/hello/create")
- public void create(HttpRequest req, HttpResponse resp) throws IOException {
- HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
- UserInfo user = currentUser(req);
- RetResult<HelloEntity> result = _service.createHello(user, bean);
- resp.finishJson(result);
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/delete/")
- public void delete(HttpRequest req, HttpResponse resp) throws IOException {
- int id = Integer.parseInt(req.getRequstURILastPath());
- _service.deleteHello(id);
- resp.finishJson(RetResult.success());
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/update")
- public void update(HttpRequest req, HttpResponse resp) throws IOException {
- HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
- _service.updateHello(bean);
- resp.finishJson(RetResult.success());
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/partupdate")
- public void partupdate(HttpRequest req, HttpResponse resp) throws IOException {
- HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
- String[] cols = req.getJsonParameter(String[].class, "cols");
- _service.updateHello(bean, cols);
- resp.finishJson(RetResult.success());
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/query")
- public void query(HttpRequest req, HttpResponse resp) throws IOException {
- HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
- Flipper flipper = req.getFlipper();
- Sheet<HelloEntity> result = _service.queryHello(bean, flipper);
- resp.finishJson(result);
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/list")
- public void list(HttpRequest req, HttpResponse resp) throws IOException {
- HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
- List<HelloEntity> result = _service.queryHello(bean);
- resp.finishJson(result);
- }
-
- @AuthIgnore
- @HttpMapping(url = "/hello/find/")
- public void find(HttpRequest req, HttpResponse resp) throws IOException {
- int id = Integer.parseInt(req.getRequstURILastPath());
- HelloEntity bean = _service.findHello(id);
- resp.finishJson(bean);
- }
-}
-
- REST插件让开发者省去了编写HttpServlet过程,让开发更加敏捷。
-