From 909b81357349e836c320d94b7fdfed5e29ff9b10 Mon Sep 17 00:00:00 2001 From: redkale Date: Sun, 13 Oct 2024 09:29:23 +0800 Subject: [PATCH] =?UTF-8?q?finishJson=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redkale/convert/json/JsonBytesWriter.java | 6 +- .../redkale/convert/json/JsonDynEncoder.java | 3 + .../org/redkale/convert/json/JsonReader.java | 6 +- .../org/redkale/convert/json/JsonWriter.java | 6 ++ .../convert/pb/ProtobufBytesWriter.java | 3 +- src/main/java/org/redkale/net/Context.java | 5 ++ src/main/java/org/redkale/net/Response.java | 26 ++++-- .../org/redkale/net/http/HttpRequest.java | 4 + .../org/redkale/net/http/HttpResponse.java | 79 ++++++++++++++----- 9 files changed, 102 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/redkale/convert/json/JsonBytesWriter.java b/src/main/java/org/redkale/convert/json/JsonBytesWriter.java index e0a47e996..6820d528e 100644 --- a/src/main/java/org/redkale/convert/json/JsonBytesWriter.java +++ b/src/main/java/org/redkale/convert/json/JsonBytesWriter.java @@ -49,7 +49,7 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple { } public JsonBytesWriter(int size) { - this.content = new byte[size > 1024 ? size : 1024]; + this.content = new byte[size > DEFAULT_SIZE ? size : DEFAULT_SIZE]; } public JsonBytesWriter(ByteArray array) { @@ -425,10 +425,6 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple { return copy; } - public int count() { - return this.count; - } - @Override public void writeString(String value) { writeString(true, value); diff --git a/src/main/java/org/redkale/convert/json/JsonDynEncoder.java b/src/main/java/org/redkale/convert/json/JsonDynEncoder.java index 0862849b1..635f8304a 100644 --- a/src/main/java/org/redkale/convert/json/JsonDynEncoder.java +++ b/src/main/java/org/redkale/convert/json/JsonDynEncoder.java @@ -158,6 +158,9 @@ public abstract class JsonDynEncoder extends ObjectEncoder { if (onlyShotIntLongLatin1MoreFieldObjectFlag && membersSize < 2) { onlyShotIntLongLatin1MoreFieldObjectFlag = false; // 字段个数必须大于1 } + onlyTwoIntFieldObjectFlag = false; // 废弃此特性 + onlyOneLatin1FieldObjectFlag = false; // 废弃此特性 + onlyShotIntLongLatin1MoreFieldObjectFlag = false; // 废弃此特性 { // 构造函数 mv = (cw.visitMethod( ACC_PUBLIC, "", "(" + jsonfactoryDesc + typeDesc + objEncoderDesc + ")V", null, null)); diff --git a/src/main/java/org/redkale/convert/json/JsonReader.java b/src/main/java/org/redkale/convert/json/JsonReader.java index 64da69e68..68789a1cc 100644 --- a/src/main/java/org/redkale/convert/json/JsonReader.java +++ b/src/main/java/org/redkale/convert/json/JsonReader.java @@ -75,7 +75,7 @@ public class JsonReader extends Reader { this.limit = -1; this.text = null; if (this.array != null) { - if (this.array.content.length > CharArray.DEFAULT_SIZE * 200) { + if (this.array.content.length > JsonWriter.DEFAULT_SIZE * 200) { this.array = null; } else { this.array.clear(); @@ -1096,11 +1096,9 @@ public class JsonReader extends Reader { protected static class CharArray { - private static final int DEFAULT_SIZE = 1024; - private int count; - private char[] content = new char[DEFAULT_SIZE]; + private char[] content = new char[JsonWriter.DEFAULT_SIZE]; private char[] expand(int len) { int newcount = count + len; diff --git a/src/main/java/org/redkale/convert/json/JsonWriter.java b/src/main/java/org/redkale/convert/json/JsonWriter.java index 2cbb719dd..bbb515a78 100644 --- a/src/main/java/org/redkale/convert/json/JsonWriter.java +++ b/src/main/java/org/redkale/convert/json/JsonWriter.java @@ -96,24 +96,30 @@ public abstract class JsonWriter extends Writer { public abstract void writeFieldLatin1Value(final byte[] fieldBytes, final char[] fieldChars, final String value); @ClassDepends + @Deprecated(since = "2.8.0") public abstract void writeLastFieldShortValue(final byte[] fieldBytes, final char[] fieldChars, final short value); @ClassDepends + @Deprecated(since = "2.8.0") public abstract void writeLastFieldIntValue(final byte[] fieldBytes, final char[] fieldChars, final int value); @ClassDepends + @Deprecated(since = "2.8.0") public abstract void writeLastFieldLongValue(final byte[] fieldBytes, final char[] fieldChars, final long value); @ClassDepends + @Deprecated(since = "2.8.0") public abstract void writeLastFieldLatin1Value(final byte[] fieldBytes, final char[] fieldChars, String value); // firstFieldBytes 必须带{开头 @ClassDepends + @Deprecated(since = "2.8.0") public abstract void writeObjectByOnlyOneLatin1FieldValue( final byte[] firstFieldBytes, final char[] firstFieldChars, final String value); // firstFieldBytes 必须带{开头, lastFieldBytes必须,开头 @ClassDepends + @Deprecated(since = "2.8.0") public abstract void writeObjectByOnlyTwoIntFieldValue( final byte[] firstFieldBytes, final char[] firstFieldChars, diff --git a/src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java b/src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java index 6f4135610..27ebded94 100644 --- a/src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java +++ b/src/main/java/org/redkale/convert/pb/ProtobufBytesWriter.java @@ -13,10 +13,11 @@ import org.redkale.util.ByteArray; import org.redkale.util.ByteTuple; /** + * * * @author zhangjx */ -public class ProtobufBytesWriter extends ProtobufWriter { +public class ProtobufBytesWriter extends ProtobufWriter { // 存在child情况因此不能实现ByteTuple private static final int RESET_MAX_SIZE = DEFAULT_SIZE << 4; diff --git a/src/main/java/org/redkale/net/Context.java b/src/main/java/org/redkale/net/Context.java index 278901416..850790029 100644 --- a/src/main/java/org/redkale/net/Context.java +++ b/src/main/java/org/redkale/net/Context.java @@ -6,6 +6,7 @@ package org.redkale.net; import java.net.InetSocketAddress; +import java.nio.ByteBuffer; import java.nio.charset.*; import java.util.concurrent.ExecutorService; import java.util.logging.*; @@ -184,6 +185,10 @@ public class Context { this.serverAddress = addr; } + public ByteBuffer createByteBuffer() { + return ByteBuffer.allocateDirect(getBufferCapacity()); + } + public ResourceFactory getResourceFactory() { return resourceFactory; } diff --git a/src/main/java/org/redkale/net/Response.java b/src/main/java/org/redkale/net/Response.java index febaecdc2..acfba6f3a 100644 --- a/src/main/java/org/redkale/net/Response.java +++ b/src/main/java/org/redkale/net/Response.java @@ -103,7 +103,11 @@ public abstract class Response> { public void completed(final Integer result, final ByteBuffer[] attachments) { if (attachments != null) { for (ByteBuffer attachment : attachments) { - channel.offerWriteBuffer(attachment); + if (attachment != writeBuffer) { + channel.offerWriteBuffer(attachment); + } else { + attachment.clear(); + } } } completeInIOThread(false); @@ -113,7 +117,11 @@ public abstract class Response> { public void failed(Throwable exc, final ByteBuffer[] attachments) { if (attachments != null) { for (ByteBuffer attachment : attachments) { - channel.offerWriteBuffer(attachment); + if (attachment != writeBuffer) { + channel.offerWriteBuffer(attachment); + } else { + attachment.clear(); + } } } completeInIOThread(true); @@ -124,9 +132,12 @@ public abstract class Response> { this.context = context; this.request = request; this.thread = WorkThread.currentWorkThread(); - this.writeBuffer = context != null ? ByteBuffer.allocateDirect(context.getBufferCapacity()) : null; - this.workExecutor = - context == null || context.workExecutor == null ? ForkJoinPool.commonPool() : context.workExecutor; + this.writeBuffer = context.createByteBuffer(); + this.workExecutor = context.workExecutor == null ? ForkJoinPool.commonPool() : context.workExecutor; + } + + protected ByteBuffer writeBuffer() { + return writeBuffer; } protected AsyncConnection removeChannel() { @@ -157,6 +168,7 @@ public abstract class Response> { } channel = null; } + this.writeBuffer.clear(); this.responseSupplier = null; this.responseConsumer = null; this.recycleListener = null; @@ -364,6 +376,10 @@ public abstract class Response> { } } + protected void writeInIOThread(ByteBuffer buffer) { + this.channel.writeInIOThread(buffer, buffer, finishBufferIOThreadHandler); + } + public final void finish(final byte[] bs) { finish(false, bs, 0, bs.length); } diff --git a/src/main/java/org/redkale/net/http/HttpRequest.java b/src/main/java/org/redkale/net/http/HttpRequest.java index b3a9a4861..7da46d6ab 100644 --- a/src/main/java/org/redkale/net/http/HttpRequest.java +++ b/src/main/java/org/redkale/net/http/HttpRequest.java @@ -291,6 +291,10 @@ public class HttpRequest extends Request { return req; } + protected int pipelineIndex() { + return pipelineIndex; + } + protected boolean isWebSocket() { return maybews && getmethod && "Upgrade".equalsIgnoreCase(getHeader("Connection")); } diff --git a/src/main/java/org/redkale/net/http/HttpResponse.java b/src/main/java/org/redkale/net/http/HttpResponse.java index 960a7e96d..6effcdd22 100644 --- a/src/main/java/org/redkale/net/http/HttpResponse.java +++ b/src/main/java/org/redkale/net/http/HttpResponse.java @@ -201,6 +201,10 @@ public class HttpResponse extends Response { private final JsonBytesWriter jsonWriter = new JsonBytesWriter(); + private final Consumer headerArrayConsumer; + + private final Consumer headerBufferConsumer; + @SuppressWarnings("Convert2Lambda") protected final ConvertBytesHandler convertHandler = new ConvertBytesHandler() { @Override @@ -231,6 +235,8 @@ public class HttpResponse extends Response { this.jsonLiveContentLengthArray = config == null ? null : config.jsonLiveContentLengthArray; this.jsonCloseContentLengthArray = config == null ? null : config.jsonCloseContentLengthArray; this.contentType = this.plainContentType; + this.headerArrayConsumer = headerArray::put; + this.headerBufferConsumer = writeBuffer()::put; } @Override @@ -425,7 +431,33 @@ public class HttpResponse extends Response { * @param obj 输出对象 */ public final void finishJson(final Type type, final Object obj) { - finishJson((Convert) null, type, obj); + if (sendHandler == null + && cacheHandler == null + && headerBufferConsumer != null + && request.pipelineIndex() <= 0 + && !this.channel.hasPipelineData() + && request.getRespConvert() == jsonRootConvert + && this.header.getStringEntrys().length == 0) { + this.contentType = this.jsonContentType; + if (this.recycleListener != null) { + this.output = obj; + } + JsonBytesWriter writer = jsonWriter; + jsonRootConvert.convertTo(writer.clear(), type, obj); + this.contentLength = writer.length(); + createHeader(headerBufferConsumer); // 写进writeBuffer + + ByteBuffer buffer = writeBuffer(); + if (buffer.capacity() >= contentLength) { + buffer.put(writer.content(), 0, writer.length()); + buffer.flip(); + writeInIOThread(buffer); + } else { + finish(this.jsonContentType, writer); + } + } else { + finishJson((Convert) null, type, obj); + } } /** @@ -1069,6 +1101,12 @@ public class HttpResponse extends Response { // Header大小 protected void createHeader() { + createHeader(headerArrayConsumer); + this.headWritedSize = headerArray.length(); + } + + // Header大小 + protected void createHeader(Consumer writer) { if (this.status == 200 && !this.respHeadContainsConnection && !this.request.isWebSocket() @@ -1088,47 +1126,47 @@ public class HttpResponse extends Response { lengthArray = this.plainCloseContentLengthArray; } } - headerArray.put(lengthArray[(int) this.contentLength]); + writer.accept(lengthArray[(int) this.contentLength]); } else { if (this.status == 200 && !this.respHeadContainsConnection && !this.request.isWebSocket()) { if (this.request.isKeepAlive()) { - headerArray.put(status200_server_live_Bytes); + writer.accept(status200_server_live_Bytes); } else { - headerArray.put(status200_server_close_Bytes); + writer.accept(status200_server_close_Bytes); } } else { if (this.status == 200) { - headerArray.put(status200Bytes); + writer.accept(status200Bytes); } else { - headerArray.put(("HTTP/1.1 " + this.status + " " + httpCodes.get(this.status) + "\r\n").getBytes()); + writer.accept(("HTTP/1.1 " + this.status + " " + httpCodes.get(this.status) + "\r\n").getBytes()); } - headerArray.put(serverNameBytes); + writer.accept(serverNameBytes); if (!this.respHeadContainsConnection) { byte[] bs = this.request.isKeepAlive() ? connectAliveBytes : connectCloseBytes; if (bs.length > 0) { - headerArray.put(bs); + writer.accept(bs); } } } if (!this.request.isWebSocket()) { if (this.contentType == this.jsonContentType) { - headerArray.put(this.jsonContentTypeBytes); + writer.accept(this.jsonContentTypeBytes); } else if (this.contentType == null || this.contentType == this.plainContentType) { - headerArray.put(this.plainContentTypeBytes); + writer.accept(this.plainContentTypeBytes); } else { - headerArray.put(("Content-Type: " + this.contentType + "\r\n").getBytes()); + writer.accept(("Content-Type: " + this.contentType + "\r\n").getBytes()); } } if (this.contentLength >= 0) { if (this.contentLength < contentLengthArray.length) { - headerArray.put(contentLengthArray[(int) this.contentLength]); + writer.accept(contentLengthArray[(int) this.contentLength]); } else { - headerArray.put(("Content-Length: " + this.contentLength + "\r\n").getBytes()); + writer.accept(("Content-Length: " + this.contentLength + "\r\n").getBytes()); } } } if (dateSupplier != null) { - headerArray.put(dateSupplier.get()); + writer.accept(dateSupplier.get()); } if (this.defaultAddHeaders != null) { @@ -1166,7 +1204,7 @@ public class HttpResponse extends Response { } } for (Entry en : this.header.getStringEntrys()) { - headerArray.put((en.name + ": " + en.getValue() + "\r\n").getBytes()); + writer.accept((en.name + ": " + en.getValue() + "\r\n").getBytes()); } if (request.newSessionid != null) { String domain = defaultCookie == null ? null : defaultCookie.getDomain(); @@ -1180,12 +1218,12 @@ public class HttpResponse extends Response { // path = "/"; // } if (request.newSessionid.isEmpty()) { - headerArray.put(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=; " + domain + writer.accept(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=; " + domain + "Path=/; Max-Age=0; HttpOnly\r\n") .getBytes()); } else { - headerArray.put(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=" + request.newSessionid + "; " - + domain + "Path=/; HttpOnly\r\n") + writer.accept(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=" + request.newSessionid + "; " + domain + + "Path=/; HttpOnly\r\n") .getBytes()); } } @@ -1202,11 +1240,10 @@ public class HttpResponse extends Response { cookie.setPath(defaultCookie.getPath()); } } - headerArray.put(("Set-Cookie: " + cookieString(cookie) + "\r\n").getBytes()); + writer.accept(("Set-Cookie: " + cookieString(cookie) + "\r\n").getBytes()); } } - headerArray.put(LINE); - this.headWritedSize = headerArray.length(); + writer.accept(LINE); } private CharSequence cookieString(HttpCookie cookie) {