This commit is contained in:
@@ -11,7 +11,9 @@ import com.wentch.redkale.net.Context;
|
|||||||
import com.wentch.redkale.util.AnyValue;
|
import com.wentch.redkale.util.AnyValue;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.nio.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
import jdk.internal.org.objectweb.asm.*;
|
import jdk.internal.org.objectweb.asm.*;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
@@ -33,7 +35,19 @@ public abstract class BasedHttpServlet extends HttpServlet {
|
|||||||
for (Map.Entry<String, Entry> en : actions) {
|
for (Map.Entry<String, Entry> en : actions) {
|
||||||
if (request.getRequestURI().startsWith(en.getKey())) {
|
if (request.getRequestURI().startsWith(en.getKey())) {
|
||||||
Entry entry = en.getValue();
|
Entry entry = en.getValue();
|
||||||
if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) entry.servlet.execute(request, response);
|
if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) {
|
||||||
|
if (entry.cachetimeout > 0) {//有缓存设置
|
||||||
|
CacheEntry ce = entry.cache.get(request.getRequestURI());
|
||||||
|
if (ce != null && ce.time + entry.cachetimeout > System.currentTimeMillis()) { //缓存有效
|
||||||
|
response.setStatus(ce.status);
|
||||||
|
response.setContentType(ce.contentType);
|
||||||
|
response.finish(ce.getBuffers());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.setInterceptor(entry.cacheInterceptor);
|
||||||
|
}
|
||||||
|
entry.servlet.execute(request, response);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,12 +194,28 @@ public abstract class BasedHttpServlet extends HttpServlet {
|
|||||||
this.method = method;
|
this.method = method;
|
||||||
this.servlet = servlet;
|
this.servlet = servlet;
|
||||||
this.ignore = typeIgnore || method.getAnnotation(AuthIgnore.class) != null;
|
this.ignore = typeIgnore || method.getAnnotation(AuthIgnore.class) != null;
|
||||||
|
HttpCacheable hc = method.getAnnotation(HttpCacheable.class);
|
||||||
|
this.cachetimeout = hc == null ? 0 : hc.timeout() * 1000;
|
||||||
|
this.cache = cachetimeout > 0 ? new ConcurrentHashMap() : null;
|
||||||
|
this.cacheInterceptor = cachetimeout > 0 ? (HttpResponse response, ByteBuffer[] buffers) -> {
|
||||||
|
int status = response.getStatus();
|
||||||
|
if (status != 200) return null;
|
||||||
|
CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), buffers);
|
||||||
|
cache.put(response.getRequest().getRequestURI(), ce);
|
||||||
|
return ce.getBuffers();
|
||||||
|
} : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNeedCheck() {
|
public boolean isNeedCheck() {
|
||||||
return this.moduleid != 0 || this.actionid != 0;
|
return this.moduleid != 0 || this.actionid != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final HttpResponse.Interceptor cacheInterceptor;
|
||||||
|
|
||||||
|
public final ConcurrentHashMap<String, CacheEntry> cache;
|
||||||
|
|
||||||
|
public final int cachetimeout;
|
||||||
|
|
||||||
public final boolean ignore;
|
public final boolean ignore;
|
||||||
|
|
||||||
public final int moduleid;
|
public final int moduleid;
|
||||||
@@ -198,4 +228,33 @@ public abstract class BasedHttpServlet extends HttpServlet {
|
|||||||
|
|
||||||
public final HttpServlet servlet;
|
public final HttpServlet servlet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class CacheEntry {
|
||||||
|
|
||||||
|
public final long time = System.currentTimeMillis();
|
||||||
|
|
||||||
|
private final ByteBuffer[] buffers;
|
||||||
|
|
||||||
|
private final int status;
|
||||||
|
|
||||||
|
private final String contentType;
|
||||||
|
|
||||||
|
public CacheEntry(int status, String contentType, ByteBuffer[] bufs) {
|
||||||
|
this.status = status;
|
||||||
|
this.contentType = contentType;
|
||||||
|
final ByteBuffer[] newBuffers = new ByteBuffer[bufs.length];
|
||||||
|
for (int i = 0; i < newBuffers.length; i++) {
|
||||||
|
newBuffers[i] = bufs[i].duplicate().asReadOnlyBuffer();
|
||||||
|
}
|
||||||
|
this.buffers = newBuffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer[] getBuffers() {
|
||||||
|
final ByteBuffer[] newBuffers = new ByteBuffer[buffers.length];
|
||||||
|
for (int i = 0; i < newBuffers.length; i++) {
|
||||||
|
newBuffers[i] = buffers[i].duplicate();
|
||||||
|
}
|
||||||
|
return newBuffers;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/com/wentch/redkale/net/http/HttpCacheable.java
Normal file
25
src/com/wentch/redkale/net/http/HttpCacheable.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package com.wentch.redkale.net.http;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface HttpCacheable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时的秒数
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int timeout() default 15;
|
||||||
|
}
|
||||||
@@ -26,6 +26,15 @@ import java.util.concurrent.atomic.*;
|
|||||||
*/
|
*/
|
||||||
public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HttpResponse.finish 方法内调用
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static interface Interceptor {
|
||||||
|
|
||||||
|
public ByteBuffer[] invoke(final HttpResponse response, final ByteBuffer[] buffers);
|
||||||
|
}
|
||||||
|
|
||||||
private static final ByteBuffer buffer304 = ByteBuffer.wrap("HTTP/1.1 304 Not Modified\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
private static final ByteBuffer buffer304 = ByteBuffer.wrap("HTTP/1.1 304 Not Modified\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
||||||
|
|
||||||
private static final ByteBuffer buffer404 = ByteBuffer.wrap("HTTP/1.1 404 Not Found\r\nContent-Length:0\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
private static final ByteBuffer buffer404 = ByteBuffer.wrap("HTTP/1.1 404 Not Found\r\nContent-Length:0\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
||||||
@@ -98,6 +107,9 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
|
|
||||||
private boolean headsended = false;
|
private boolean headsended = false;
|
||||||
|
|
||||||
|
private Interceptor interceptor;
|
||||||
|
//------------------------------------------------
|
||||||
|
|
||||||
private final DefaultAnyValue header = new DefaultAnyValue();
|
private final DefaultAnyValue header = new DefaultAnyValue();
|
||||||
|
|
||||||
private final String[][] defaultAddHeaders;
|
private final String[][] defaultAddHeaders;
|
||||||
@@ -130,6 +142,7 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
this.cookies = null;
|
this.cookies = null;
|
||||||
this.headsended = false;
|
this.headsended = false;
|
||||||
this.header.clear();
|
this.header.clear();
|
||||||
|
this.interceptor = null;
|
||||||
return super.recycle();
|
return super.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +155,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
return httpCodes.get(status);
|
return httpCodes.get(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected HttpRequest getRequest() {
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getHttpCode(int status, String defValue) {
|
protected String getHttpCode(int status, String defValue) {
|
||||||
String v = httpCodes.get(status);
|
String v = httpCodes.get(status);
|
||||||
return v == null ? defValue : v;
|
return v == null ? defValue : v;
|
||||||
@@ -186,6 +203,9 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (context.getCharset() == null) {
|
if (context.getCharset() == null) {
|
||||||
|
if (interceptor != null) {
|
||||||
|
interceptor.invoke(this, new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(obj))});
|
||||||
|
}
|
||||||
final char[] chars = Utility.charArray(obj);
|
final char[] chars = Utility.charArray(obj);
|
||||||
this.contentLength = Utility.encodeUTF8Length(chars);
|
this.contentLength = Utility.encodeUTF8Length(chars);
|
||||||
final ByteBuffer headbuf = createHeader();
|
final ByteBuffer headbuf = createHeader();
|
||||||
@@ -198,6 +218,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ByteBuffer buffer = context.getCharset().encode(obj);
|
ByteBuffer buffer = context.getCharset().encode(obj);
|
||||||
|
if (interceptor != null) {
|
||||||
|
ByteBuffer[] bufs = interceptor.invoke(this, new ByteBuffer[]{buffer});
|
||||||
|
if (bufs != null) buffer = bufs[0];
|
||||||
|
}
|
||||||
this.contentLength = buffer.remaining();
|
this.contentLength = buffer.remaining();
|
||||||
final ByteBuffer headbuf = createHeader();
|
final ByteBuffer headbuf = createHeader();
|
||||||
headbuf.flip();
|
headbuf.flip();
|
||||||
@@ -247,6 +271,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finish(boolean kill, ByteBuffer... buffers) {
|
public void finish(boolean kill, ByteBuffer... buffers) {
|
||||||
|
if (interceptor != null) {
|
||||||
|
ByteBuffer[] bufs = interceptor.invoke(this, buffers);
|
||||||
|
if (bufs != null) buffers = bufs;
|
||||||
|
}
|
||||||
if (kill) refuseAlive();
|
if (kill) refuseAlive();
|
||||||
if (!this.headsended) {
|
if (!this.headsended) {
|
||||||
long len = 0;
|
long len = 0;
|
||||||
@@ -422,6 +450,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
this.headsended = true;
|
this.headsended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected DefaultAnyValue duplicateHeader() {
|
||||||
|
return this.header.duplicate();
|
||||||
|
}
|
||||||
|
|
||||||
public void setHeader(String name, Object value) {
|
public void setHeader(String name, Object value) {
|
||||||
this.header.setValue(name, String.valueOf(value));
|
this.header.setValue(name, String.valueOf(value));
|
||||||
}
|
}
|
||||||
@@ -454,6 +486,14 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
|||||||
this.contentLength = contentLength;
|
this.contentLength = contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Interceptor getInterceptor() {
|
||||||
|
return interceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInterceptor(Interceptor interceptor) {
|
||||||
|
this.interceptor = interceptor;
|
||||||
|
}
|
||||||
|
|
||||||
protected final class TransferFileHandler implements CompletionHandler<Integer, ByteBuffer> {
|
protected final class TransferFileHandler implements CompletionHandler<Integer, ByteBuffer> {
|
||||||
|
|
||||||
private final AsynchronousFileChannel filechannel;
|
private final AsynchronousFileChannel filechannel;
|
||||||
|
|||||||
Reference in New Issue
Block a user