This commit is contained in:
Redkale
2022-06-20 11:08:23 +08:00
parent a1e6413704
commit 481cde05bf
17 changed files with 250 additions and 47 deletions

View File

@@ -1,27 +1,27 @@
<h1>项目介绍</h1>
<b>项目介绍</b>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redkale (中文名: 红菜苔,一种湖北特产蔬菜) 是基于Java 11全新的微服务框架 包含HTTP、WebSocket、TCP/UDP、数据序列化、数据缓存、依赖注入等功能。 本框架致力于简化集中式和微服务架构的开发,在增强开发敏捷性的同时保持高性能。
</p>
<strong>RedKale 有如下主要特点:</strong>
<ol>
<li>大量使用Java 8新特性接口默认值、Stream、Lambda、JDk8内置的ASM等</li>
<li>大量使用Java 8+新特性接口默认值、Stream、Lambda、内置的ASM、HttpClient等)</li>
<li>提供HTTP服务同时内置JSON功能与限时缓存功能</li>
<li>TCP层完全使用NIO并统一TCP与UDP的接口换</li>
<li>提供分布式与集中式部署的无缝切换</li>
<li>提供类似JPA功能包含数据缓存自动同步、分表分库与简洁的数据层操作接口</li>
<li>可以动态修改已依赖注入的资源</li>
</ol>
</ol>
<strong>Redkale 设计理念</strong>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作为一个全新的微服务框架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的默认实现。这其实包含了控制反转的思想让框架里的各个组件均可让开发者控制。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;与主流框架比功能上Redkale显得很简单这体现了Redkale的简易性而并非是不足从一个良好的设计习惯或架构上来看有些常用功能是不需要提供的如Redkale的HTTP服务不支持HTTPS和JSPHTTPS比HTTP多了一层加密解密这种密集型的计算不是Java的专长通常提供HTTP服务的架构不会将Java动态服务器放在最前端而是在前方会放nginx或apache除了负载均衡还能静动分离因此HTTPS的加解密应交给nginx这样的高性能服务器处理。Redkale再提供HTTPS服务就显得鸡肋。JSP其实算是一个落后的技术现在是一个多样化终端的时代终端不只局限于桌面程序和PC浏览器还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端这些都不是JSP能方便兼顾的而HTTP+JSON作为通用性接口可以避免重复开发模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选不会为了迎合主流而提供而是以良好的设计思想为指导。这是Redkale的主导思维。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作为一个全新的微服务框架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的默认实现。这其实包含了控制反转的思想让框架里的各个组件均可让开发者控制。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;与主流框架比功能上Redkale显得很简单这体现了Redkale的简易性而并非是不足从一个良好的设计习惯或架构上来看有些常用功能是不需要提供的如Redkale的HTTP服务不支持JSP, JSP其实算是一个落后的技术现在是一个多样化终端的时代终端不只局限于桌面程序和PC浏览器还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端这些都不是JSP能方便兼顾的而HTTP+JSON作为通用性接口可以避免重复开发模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选不会为了迎合主流而提供而是以良好的设计思想为指导。这是Redkale的主导思维。
</p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>详情请访问:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org' target='_blank'>https://redkale.org</a></h5>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>详情请访问:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org' target='_blank'>https://redkale.org</a></b>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>基本文档:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org/articles.html' target='_blank'>https://redkale.org/articles.html</a></h5>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>基本文档:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org/articles.html' target='_blank'>https://redkale.org/articles.html</a></b>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>欢迎加入Redkale QQ群: 527523235</h5>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>欢迎加入Redkale QQ群: 527523235</b>
&nbsp;

View File

@@ -15,10 +15,10 @@
<maven.compiler.target>11</maven.compiler.target>
<junit.version>5.7.0</junit.version>
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>3.0.0-M5</maven-failsafe-plugin.version>
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
<maven-compiler-plugin.version>3.9.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.0.0-M6</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>3.0.0-M6</maven-failsafe-plugin.version>
</properties>
<licenses>

View File

@@ -732,7 +732,10 @@ public final class Application {
if (key.startsWith("redkale.datasource[") || key.startsWith("redkale.cachesource[")) {
sourceProperties.put(key, value);
} else if (key.startsWith("system.property.")) {
System.setProperty(key.substring("system.property.".length()), value);
String propName = key.substring("system.property.".length());
if (System.getProperty(propName) == null) { //命令行传参数优先级高
System.setProperty(propName, value);
}
} else if (key.startsWith("mimetype.property.")) {
MimeType.add(key.substring("mimetype.property.".length()), value);
} else if (key.startsWith("property.")) {

View File

@@ -50,6 +50,7 @@ public class LoggingFileHandler extends LoggingBaseHandler {
public LoggingConsoleHandler() {
super();
setFormatter(new LoggingFormater());
configure();
}

View File

@@ -42,6 +42,13 @@ public abstract class Convert<R extends Reader, W extends Writer> {
return writer;
}
protected <S extends W> S fieldFunc(S writer, BiFunction<Object, Object, Object> mapFieldFunc, BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
writer.mapFieldFunc = mapFieldFunc;
writer.objFieldFunc = objFieldFunc;
writer.objExtFunc = objExtFunc;
return writer;
}
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc);
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc);

View File

@@ -61,6 +61,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
private final Set<Class> skipIgnores = new HashSet();
final Set<String> ignoreMapColumns = new HashSet();
//key:需要屏蔽的字段value排除的字段名
private final ConcurrentHashMap<Class, Set<String>> ignoreAlls = new ConcurrentHashMap();
@@ -707,7 +709,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
if (set == null) {
ignoreAlls.put(type, new HashSet<>(Arrays.asList(excludeColumns)));
} else {
set.addAll(Arrays.asList(excludeColumns));
synchronized (set) {
set.addAll(Arrays.asList(excludeColumns));
}
}
}
@@ -716,17 +720,47 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
if (set == null) {
ignoreAlls.put(type, new HashSet<>(excludeColumns));
} else {
set.addAll(new ArrayList(excludeColumns));
synchronized (set) {
set.addAll(new ArrayList(excludeColumns));
}
}
}
public final void register(final Class type, boolean ignore, String... columns) {
if (type == Map.class) {
synchronized (ignoreMapColumns) {
if (ignore) {
for (String column : columns) {
ignoreMapColumns.add(column);
}
} else {
for (String column : columns) {
ignoreMapColumns.remove(column);
}
}
}
return;
}
for (String column : columns) {
register(type, column, new ConvertColumnEntry(column, ignore));
}
}
public final void register(final Class type, boolean ignore, Collection<String> columns) {
if (type == Map.class) {
synchronized (ignoreMapColumns) {
if (ignore) {
for (String column : columns) {
ignoreMapColumns.add(column);
}
} else {
for (String column : columns) {
ignoreMapColumns.remove(column);
}
}
}
return;
}
for (String column : columns) {
register(type, column, new ConvertColumnEntry(column, ignore));
}

View File

@@ -7,7 +7,8 @@ package org.redkale.convert;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.*;
import java.util.function.BiFunction;
/**
* Map的序列化操作类
@@ -32,6 +33,8 @@ public class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
protected final Object lock = new Object();
protected final Set<String> ignoreMapColumns;
public MapEncoder(final ConvertFactory factory, final Type type) {
this.type = type;
try {
@@ -43,6 +46,9 @@ public class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
this.keyEncoder = factory.getAnyEncoder();
this.valueEncoder = factory.getAnyEncoder();
}
synchronized (factory.ignoreMapColumns) {
this.ignoreMapColumns = factory.ignoreMapColumns.isEmpty() ? null : new HashSet<>(factory.ignoreMapColumns);
}
} finally {
inited = true;
synchronized (lock) {
@@ -74,11 +80,15 @@ public class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
}
}
}
Set<String> ignoreColumns = this.ignoreMapColumns;
BiFunction<K, V, V> mapFieldFunc = (BiFunction) out.mapFieldFunc;
if (out.writeMapB(values.size(), (Encodeable) keyEncoder, (Encodeable) valueEncoder, value) < 0) {
boolean first = true;
for (Map.Entry<K, V> en : values.entrySet()) {
if (ignoreColumns != null && ignoreColumns.contains(en.getKey())) continue;
V v = mapFieldFunc == null ? en.getValue() : mapFieldFunc.apply(en.getKey(), en.getValue());
if (!first) out.writeArrayMark();
writeMemberValue(out, member, en.getKey(), en.getValue(), first);
writeMemberValue(out, member, en.getKey(), v, first);
if (first) first = false;
}
}

View File

@@ -25,6 +25,9 @@ public abstract class Writer {
//convertTo时是否以指定Type的ObjectEncoder进行处理
protected Type specify;
//对某个key值进行动态处理仅供MapEncoder使用
protected BiFunction<Object, Object, Object> mapFieldFunc;
//对某个字段值进行动态处理
protected BiFunction<Attribute, Object, Object> objFieldFunc;

View File

@@ -58,16 +58,25 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
}
@Override
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc) {
return newConvert(fieldFunc, null);
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc) {
return newConvert(objFieldFunc, null);
}
@Override
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc, Function<Object, ConvertField[]> objExtFunc) {
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
return new JsonConvert(getFactory(), tiny) {
@Override
protected <S extends JsonWriter> S configWrite(S writer) {
return fieldFunc(writer, fieldFunc, objExtFunc);
return fieldFunc(writer, objFieldFunc, objExtFunc);
}
};
}
public JsonConvert newConvert(BiFunction<Object, Object, Object> mapFieldFunc, final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
return new JsonConvert(getFactory(), tiny) {
@Override
protected <S extends JsonWriter> S configWrite(S writer) {
return fieldFunc(writer, mapFieldFunc, objFieldFunc, objExtFunc);
}
};
}

View File

@@ -34,8 +34,10 @@ public class HttpMessageRequest extends HttpRequest {
return this;
}
public void setRequestURI(String uri) {
@Override
public HttpMessageRequest setRequestURI(String uri) {
this.requestURI = uri;
return this;
}
@Override

View File

@@ -62,6 +62,7 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
Set<S> newservlets = new HashSet<>(servlets);
newservlets.remove(servlet);
this.servlets = newservlets;
doAfterRemove(servlet);
}
}
@@ -95,8 +96,9 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
synchronized (lock2) {
if (mappings.containsKey(key)) {
Map<K, S> newmappings = new HashMap<>(mappings);
newmappings.remove(key);
S s = newmappings.remove(key);
this.mappings = newmappings;
doAfterRemove(s);
}
}
}
@@ -112,9 +114,13 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
}
for (K key : keys) newmappings.remove(key);
this.mappings = newmappings;
doAfterRemove(servlet);
}
}
protected void doAfterRemove(S servlet) {
}
protected S mappingServlet(K key) {
return mappings.get(key);
}

View File

@@ -57,6 +57,19 @@ public abstract class Request<C extends Context> {
this.jsonConvert = context.getJsonConvert();
}
protected Request(Request<C> request) {
this.context = request.context;
this.bsonConvert = request.bsonConvert;
this.jsonConvert = request.jsonConvert;
this.createTime = request.createTime;
this.keepAlive = request.keepAlive;
this.pipelineIndex = request.pipelineIndex;
this.pipelineCount = request.pipelineCount;
this.pipelineOver = request.pipelineOver;
this.hashid = request.hashid;
this.channel = request.channel;
}
protected Request copyHeader() {
return null;
}

View File

@@ -21,4 +21,24 @@ public abstract class HttpFilter extends Filter<HttpContext, HttpRequest, HttpRe
//Server执行start后运行此方法
public void postStart(HttpContext context, AnyValue config) {
}
protected void setMethod(HttpRequest request, String method) {
request.setMethod(method);
}
protected void setRequestURI(HttpRequest request, String requestURI) {
request.setRequestURI(requestURI);
}
protected void setRemoteAddr(HttpRequest request, String remoteAddr) {
request.setRemoteAddr(remoteAddr);
}
protected void setParameter(HttpRequest request, String name, String value) {
request.setParameter(name, value);
}
protected void setHeader(HttpRequest request, String name, String value) {
request.setHeader(name, value);
}
}

View File

@@ -50,6 +50,8 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
private BiPredicate<String, String>[] forbidURIPredicates; //禁用的URL的Predicate, 必须与 forbidURIMaps 保持一致
private HttpServlet lastRunServlet;
private List<HttpServlet> removeHttpServlet(final Predicate<MappingEntry> predicateEntry, final Predicate<Map.Entry<String, WebSocketServlet>> predicateFilter) {
List<HttpServlet> servlets = new ArrayList<>();
synchronized (allMapStrings) {
@@ -91,6 +93,7 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
allMapStrings.remove(key);
}
}
this.lastRunServlet = null;
}
return servlets;
}
@@ -365,7 +368,7 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
} else if (mappingpath != null && !mappingpath.isEmpty()) {
if (servlet._actionmap != null && servlet._actionmap.containsKey(mappingpath)) {
//context.addRequestURINode(mappingpath);
putMapping(mappingpath, new HttpServlet.HttpActionServlet(servlet._actionmap.get(mappingpath), servlet));
putMapping(mappingpath, new HttpServlet.HttpActionServlet(servlet._actionmap.get(mappingpath), servlet, mappingpath));
} else {
putMapping(mappingpath, servlet);
}
@@ -434,6 +437,22 @@ public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, Http
return predicate == null ? servletStream() : servletStream().filter(predicate);
}
@Override
protected HttpServlet mappingServlet(String key) {
HttpServlet last = this.lastRunServlet;
if (last != null && last._actionSimpleMappingUrl != null && last._actionSimpleMappingUrl.equalsIgnoreCase(key)) {
return last;
}
HttpServlet s = super.mappingServlet(key);
this.lastRunServlet = s;
return s;
}
@Override
protected void doAfterRemove(HttpServlet servlet) {
this.lastRunServlet = null;
}
@Override
public void destroy(HttpContext context, AnyValue config) {
super.destroy(context, config); //必须要执行

View File

@@ -840,6 +840,32 @@ public class HttpRequest extends Request<HttpContext> {
}
}
protected HttpRequest setMethod(String method) {
this.method = method;
this.getmethod = "GET".equalsIgnoreCase(method);
return this;
}
protected HttpRequest setRequestURI(String requestURI) {
this.requestURI = requestURI;
return this;
}
protected HttpRequest setRemoteAddr(String remoteAddr) {
this.remoteAddr = remoteAddr;
return this;
}
protected HttpRequest setParameter(String name, String value) {
this.params.put(name, value);
return this;
}
protected HttpRequest setHeader(String name, String value) {
this.headers.put(name, value);
return this;
}
protected static String toDecodeString(ByteArray array, int offset, int len, final Charset charset) {
byte[] content = array.content();
int start = offset;
@@ -2471,14 +2497,14 @@ public class HttpRequest extends Request<HttpContext> {
}
/**
* 获取翻页对象 同 getFlipper("flipper", needcreate, 0);
* 获取翻页对象 同 getFlipper("flipper", autoCreate, 0);
*
* @param needcreate 无参数时是否创建新Flipper对象
* @param autoCreate 无参数时是否创建新Flipper对象
*
* @return Flipper翻页对象
*/
public org.redkale.source.Flipper getFlipper(boolean needcreate) {
return getFlipper(needcreate, 0);
public org.redkale.source.Flipper getFlipper(boolean autoCreate) {
return getFlipper(autoCreate, 0);
}
/**
@@ -2493,44 +2519,46 @@ public class HttpRequest extends Request<HttpContext> {
}
/**
* 获取翻页对象 同 getFlipper("flipper", needcreate, maxLimit)
* 获取翻页对象 同 getFlipper("flipper", autoCreate, maxLimit)
*
* @param needcreate 无参数时是否创建新Flipper对象
* @param autoCreate 无参数时是否创建新Flipper对象
* @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT
*
* @return Flipper翻页对象
*/
public org.redkale.source.Flipper getFlipper(boolean needcreate, int maxLimit) {
return getFlipper("flipper", needcreate, maxLimit);
public org.redkale.source.Flipper getFlipper(boolean autoCreate, int maxLimit) {
return getFlipper("flipper", autoCreate, maxLimit);
}
/**
* 获取翻页对象 https://redkale.org/pipes/users/list/offset:0/limit:20/sort:createtime%20ASC <br>
* https://redkale.org/pipes/users/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'} <br>
* 以上两种接口都可以获取到翻页对象
* 获取翻页对象 https://redkale.org/pipes/users/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'} <br>
*
*
* @param name Flipper对象的参数名默认为 "flipper"
* @param needcreate 无参数时是否创建新Flipper对象
* @param autoCreate 无参数时是否创建新Flipper对象
* @param maxLimit 最大行数, 小于1则值为Flipper.DEFAULT_LIMIT
*
* @return Flipper翻页对象
*/
public org.redkale.source.Flipper getFlipper(String name, boolean needcreate, int maxLimit) {
public org.redkale.source.Flipper getFlipper(String name, boolean autoCreate, int maxLimit) {
org.redkale.source.Flipper flipper = getJsonParameter(org.redkale.source.Flipper.class, name);
if (flipper == null) {
if (maxLimit < 1) maxLimit = org.redkale.source.Flipper.DEFAULT_LIMIT;
int limit = getRequstURIPath("limit:", 0);
int offset = getRequstURIPath("offset:", 0);
String sort = getRequstURIPath("sort:", "");
if (limit > 0) {
if (limit > maxLimit) limit = maxLimit;
flipper = new org.redkale.source.Flipper(limit, offset, sort);
}
// if (maxLimit < 1) maxLimit = org.redkale.source.Flipper.DEFAULT_LIMIT;
// String limitstr = getParameter("limit");
// if (limitstr != null && !limitstr.isEmpty()) {
// String offsetstr = getParameter("offset");
// if (offsetstr != null && !offsetstr.isEmpty()) {
// int limit = Integer.parseInt(limitstr);
// int offset = Integer.parseInt(offsetstr);
// String sort = getParameter("sort");
// if (limit > maxLimit) limit = maxLimit;
// flipper = new org.redkale.source.Flipper(limit, offset, sort);
// }
// }
} else if (flipper.getLimit() < 1 || (maxLimit > 0 && flipper.getLimit() > maxLimit)) {
flipper.setLimit(maxLimit);
}
if (flipper != null || !needcreate) return flipper;
if (flipper != null || !autoCreate) return flipper;
if (maxLimit < 1) maxLimit = org.redkale.source.Flipper.DEFAULT_LIMIT;
return new org.redkale.source.Flipper(maxLimit);
}

View File

@@ -33,6 +33,8 @@ public class HttpServlet extends Servlet<HttpContext, HttpRequest, HttpResponse>
public static final int RET_METHOD_ERROR = 1200_0002;
String _actionSimpleMappingUrl; //只给HttpActionServlet使用_actionSimpleMappingUrl不能包含正则表达式比如 /json /createRecord, 不能是 /user/**
String _prefix = ""; //当前HttpServlet的path前缀
String _reqtopic; //根据RestService+MQ生成的值 @since 2.5.0
@@ -454,9 +456,12 @@ public class HttpServlet extends Servlet<HttpContext, HttpRequest, HttpResponse>
final HttpServlet servlet;
public HttpActionServlet(ActionEntry actionEntry, HttpServlet servlet) {
public HttpActionServlet(ActionEntry actionEntry, HttpServlet servlet, String actionSimpleMappingUrl) {
this.action = actionEntry;
this.servlet = servlet;
if (actionSimpleMappingUrl != null && !Utility.contains(actionSimpleMappingUrl, '*', '{', '[', '(', '|', '^', '$', '+', '?', '\\')) {
this._actionSimpleMappingUrl = actionSimpleMappingUrl;
}
}
@Override

View File

@@ -0,0 +1,43 @@
/*
*/
package org.redkale.test.convert;
import java.util.*;
import org.junit.jupiter.api.*;
import org.redkale.convert.json.*;
/**
*
* @author zhangjx
*/
public class MapIgnoreColumnTest {
private boolean main;
public static void main(String[] args) throws Throwable {
MapIgnoreColumnTest test = new MapIgnoreColumnTest();
test.main = true;
test.run();
}
@Test
public void run() throws Exception {
Map<String, Object> map = new LinkedHashMap<>();
map.put("aaa", "123");
map.put("bbb", List.of(1, 2));
System.out.println(JsonConvert.root().convertTo(map));
JsonFactory factory = JsonFactory.create();
factory.register(Map.class, true, "aaa");
JsonConvert convert = factory.getConvert();
String rs = "{\"bbb\":[1,2]}";
if (!main) Assertions.assertEquals(rs, convert.convertTo(map));
System.out.println(convert.convertTo(map));
JsonConvert convert2 = JsonConvert.root().newConvert((k, v) -> {
if ("bbb".equals(k)) return null;
return v;
}, null, null);
if (!main) Assertions.assertEquals("{\"aaa\":\"123\",\"bbb\":null}", convert2.convertTo(map));
System.out.println(convert2.convertTo(map));
}
}