ByteTreeNode

This commit is contained in:
redkale
2024-10-05 19:04:50 +08:00
parent d2b8ef4471
commit a0a12bc709
6 changed files with 49 additions and 22 deletions

View File

@@ -65,8 +65,8 @@ public class DeMemberInfo {
protected static class DeMemberNode extends ByteTreeNode<DeMember> { protected static class DeMemberNode extends ByteTreeNode<DeMember> {
@Override @Override
public void put(String key, DeMember value) { public ByteTreeNode<DeMember> put(String key, DeMember value) {
super.put(key, value); return super.put(key, value);
} }
} }
} }

View File

@@ -71,12 +71,12 @@ public class HttpContext extends Context {
random.setSeed(Math.abs(System.nanoTime())); random.setSeed(Math.abs(System.nanoTime()));
} }
ByteTreeNode<String> getUriPathNode() { UriPathNode getUriPathNode() {
return uriPathNode; return uriPathNode;
} }
void addUriPath(final String path) { void addUriPath(final String path, HttpServlet servlet) {
this.uriPathNode.put(path, path); this.uriPathNode.put(path, path, servlet);
byte[] bs = path.getBytes(StandardCharsets.UTF_8); byte[] bs = path.getBytes(StandardCharsets.UTF_8);
int index = bs.length >= uriPathCaches.length ? 0 : bs.length; int index = bs.length >= uriPathCaches.length ? 0 : bs.length;
Map<ByteArray, String> map = uriPathCaches[index]; Map<ByteArray, String> map = uriPathCaches[index];
@@ -260,18 +260,31 @@ public class HttpContext extends Context {
protected static class UriPathNode extends ByteTreeNode<String> { protected static class UriPathNode extends ByteTreeNode<String> {
public UriPathNode() { protected HttpServlet servlet;
protected UriPathNode() {
super(); super();
} }
@Override protected UriPathNode(ByteTreeNode<String> parent, int index) {
protected void put(String key, String value) { super(parent, index);
super.put(key, value); }
protected ByteTreeNode<String> put(String key, String value, HttpServlet servlet) {
UriPathNode n = (UriPathNode) super.put(key, value);
n.servlet = servlet;
return n;
} }
@Override @Override
protected String subNodeValue(ByteTreeNode<String> node, String key, int subLen) { protected ByteTreeNode<String> createNode(ByteTreeNode<String> parent, int index, String key, int subLen) {
return key.substring(0, subLen); UriPathNode n = new UriPathNode(parent, index);
n.value = key.substring(0, subLen);
return n;
}
public HttpServlet getServlet() {
return servlet;
} }
} }

View File

@@ -322,7 +322,9 @@ public class HttpDispatcherServlet
response.finish(100, response.getHttpCode(100)); response.finish(100, response.getHttpCode(100));
return; return;
} }
if (request.isWebSocket()) { if (request.pathServlet != null) {
servlet = request.pathServlet;
} else if (request.isWebSocket()) {
servlet = wsMappings.get(uri); servlet = wsMappings.get(uri);
if (servlet == null && this.regexWsArray != null) { if (servlet == null && this.regexWsArray != null) {
for (MappingEntry en : regexWsArray) { for (MappingEntry en : regexWsArray) {
@@ -510,7 +512,7 @@ public class HttpDispatcherServlet
getServlets().forEach(s -> { getServlets().forEach(s -> {
s.postStart(context, getServletConf(s)); s.postStart(context, getServletConf(s));
}); });
forEachMappingKey((k, s) -> context.addUriPath(k)); forEachMappingKey(context::addUriPath);
} }
public HttpServlet findServletByTopic(String topic) { public HttpServlet findServletByTopic(String topic) {

View File

@@ -20,6 +20,7 @@ import org.redkale.annotation.Comment;
import org.redkale.convert.*; import org.redkale.convert.*;
import org.redkale.convert.json.JsonConvert; import org.redkale.convert.json.JsonConvert;
import org.redkale.net.Request; import org.redkale.net.Request;
import org.redkale.net.http.HttpContext.UriPathNode;
import org.redkale.util.*; import org.redkale.util.*;
import static org.redkale.util.Utility.isEmpty; import static org.redkale.util.Utility.isEmpty;
import static org.redkale.util.Utility.isNotEmpty; import static org.redkale.util.Utility.isNotEmpty;
@@ -171,6 +172,8 @@ public class HttpRequest extends Request<HttpContext> {
protected String locale; protected String locale;
HttpServlet pathServlet;
// 主要给chunked和unzip用的 // 主要给chunked和unzip用的
private ByteArray array; private ByteArray array;
@@ -761,6 +764,7 @@ public class HttpRequest extends Request<HttpContext> {
if (qst >= 0) { // 带?参数 if (qst >= 0) { // 带?参数
if (pathNode != null) { if (pathNode != null) {
this.requestPath = pathNode.getValue(); this.requestPath = pathNode.getValue();
this.pathServlet = ((UriPathNode) pathNode).getServlet();
} else if (decodeable) { // 需要转义 } else if (decodeable) { // 需要转义
this.requestPath = toDecodeString(bytes, 0, qst, charset); this.requestPath = toDecodeString(bytes, 0, qst, charset);
} else { } else {
@@ -778,6 +782,7 @@ public class HttpRequest extends Request<HttpContext> {
} else { // 没有带?参数 } else { // 没有带?参数
if (pathNode != null) { if (pathNode != null) {
this.requestPath = pathNode.getValue(); this.requestPath = pathNode.getValue();
this.pathServlet = ((UriPathNode) pathNode).getServlet();
} else if (decodeable) { // 需要转义 } else if (decodeable) { // 需要转义
this.requestPath = toDecodeString(bytes, 0, bytes.length(), charset); this.requestPath = toDecodeString(bytes, 0, bytes.length(), charset);
} else { } else {
@@ -1303,6 +1308,7 @@ public class HttpRequest extends Request<HttpContext> {
this.respConvertType = null; this.respConvertType = null;
this.headers.clear(); this.headers.clear();
// 其他 // 其他
this.pathServlet = null;
this.newSessionid = null; this.newSessionid = null;
this.method = null; this.method = null;
this.getmethod = false; this.getmethod = false;

View File

@@ -27,7 +27,7 @@ public class ByteTreeNode<T> {
this(null, 0); this(null, 0);
} }
private ByteTreeNode(ByteTreeNode<T> parent, int index) { protected ByteTreeNode(ByteTreeNode<T> parent, int index) {
this.parent = parent; this.parent = parent;
if (index < 0 || index >= nodes.length) { if (index < 0 || index >= nodes.length) {
throw new RedkaleException(index + " is illegal"); throw new RedkaleException(index + " is illegal");
@@ -70,7 +70,7 @@ public class ByteTreeNode<T> {
return n.value; return n.value;
} }
protected void put(String key, T value) { protected ByteTreeNode<T> put(String key, T value) {
ByteTreeNode<T> n = this; ByteTreeNode<T> n = this;
int i = 0; int i = 0;
for (char ch : key.toCharArray()) { for (char ch : key.toCharArray()) {
@@ -80,17 +80,17 @@ public class ByteTreeNode<T> {
i++; i++;
ByteTreeNode<T> s = n.nodes[ch]; ByteTreeNode<T> s = n.nodes[ch];
if (s == null) { if (s == null) {
s = new ByteTreeNode(n, ch); s = createNode(n, ch, key, i);
s.value = subNodeValue(s, key, i);
n.nodes[ch] = s; n.nodes[ch] = s;
} }
n = s; n = s;
} }
n.value = value; n.value = value;
return n;
} }
protected T subNodeValue(ByteTreeNode<T> node, String key, int subLen) { protected ByteTreeNode<T> createNode(ByteTreeNode<T> parent, int index, String key, int subLen) {
return null; return new ByteTreeNode(parent, index);
} }
@Override @Override

View File

@@ -4,11 +4,13 @@
*/ */
package org.redkale.test.httpparser; package org.redkale.test.httpparser;
import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.redkale.net.http.HttpContext; import org.redkale.net.http.HttpContext;
import org.redkale.net.http.HttpRequest; import org.redkale.net.http.HttpRequest;
import org.redkale.net.http.HttpServlet;
/** /**
* *
@@ -116,11 +118,12 @@ public class HttpRequestTest {
httpConfig.sameHeader = true; httpConfig.sameHeader = true;
httpConfig.maxHeader = 16 * 1024; httpConfig.maxHeader = 16 * 1024;
httpConfig.maxBody = 64 * 1024; httpConfig.maxBody = 64 * 1024;
HttpServlet servlet = new HttpServlet();
HttpContext context = new HttpContext(httpConfig); HttpContext context = new HttpContext(httpConfig);
Method method = HttpContext.class.getDeclaredMethod("addUriPath", String.class); Method method = HttpContext.class.getDeclaredMethod("addUriPath", String.class, HttpServlet.class);
method.setAccessible(true); method.setAccessible(true);
method.invoke(context, "/test/sleep200"); method.invoke(context, "/test/sleep200", servlet);
method.invoke(context, "/test/aaa"); method.invoke(context, "/test/aaa", servlet);
HttpRequestX req = new HttpRequestX(context); HttpRequestX req = new HttpRequestX(context);
String text = "GET /test/azzzz HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n"; String text = "GET /test/azzzz HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n";
@@ -139,6 +142,9 @@ public class HttpRequestTest {
r1 = req.readHeader(ByteBuffer.wrap(text.getBytes()), 0); r1 = req.readHeader(ByteBuffer.wrap(text.getBytes()), 0);
Assertions.assertEquals(0, r1); Assertions.assertEquals(0, r1);
Assertions.assertEquals("/test/sleep200", req.getRequestPath()); Assertions.assertEquals("/test/sleep200", req.getRequestPath());
Field serField = HttpRequest.class.getDeclaredField("pathServlet");
serField.setAccessible(true);
Assertions.assertEquals(servlet, serField.get(req));
req = new HttpRequestX(context); req = new HttpRequestX(context);
text = "GET /test/sleep201 HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n"; text = "GET /test/sleep201 HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n";