This commit is contained in:
@@ -11,7 +11,9 @@ import com.wentch.redkale.net.Context;
|
||||
import com.wentch.redkale.util.AnyValue;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
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) {
|
||||
if (request.getRequestURI().startsWith(en.getKey())) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -180,12 +194,28 @@ public abstract class BasedHttpServlet extends HttpServlet {
|
||||
this.method = method;
|
||||
this.servlet = servlet;
|
||||
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() {
|
||||
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 int moduleid;
|
||||
@@ -198,4 +228,33 @@ public abstract class BasedHttpServlet extends HttpServlet {
|
||||
|
||||
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> {
|
||||
|
||||
/**
|
||||
* 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 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 Interceptor interceptor;
|
||||
//------------------------------------------------
|
||||
|
||||
private final DefaultAnyValue header = new DefaultAnyValue();
|
||||
|
||||
private final String[][] defaultAddHeaders;
|
||||
@@ -130,6 +142,7 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||
this.cookies = null;
|
||||
this.headsended = false;
|
||||
this.header.clear();
|
||||
this.interceptor = null;
|
||||
return super.recycle();
|
||||
}
|
||||
|
||||
@@ -142,6 +155,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||
return httpCodes.get(status);
|
||||
}
|
||||
|
||||
protected HttpRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
protected String getHttpCode(int status, String defValue) {
|
||||
String v = httpCodes.get(status);
|
||||
return v == null ? defValue : v;
|
||||
@@ -186,6 +203,9 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||
return;
|
||||
}
|
||||
if (context.getCharset() == null) {
|
||||
if (interceptor != null) {
|
||||
interceptor.invoke(this, new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(obj))});
|
||||
}
|
||||
final char[] chars = Utility.charArray(obj);
|
||||
this.contentLength = Utility.encodeUTF8Length(chars);
|
||||
final ByteBuffer headbuf = createHeader();
|
||||
@@ -198,6 +218,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||
}
|
||||
} else {
|
||||
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();
|
||||
final ByteBuffer headbuf = createHeader();
|
||||
headbuf.flip();
|
||||
@@ -247,6 +271,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||
|
||||
@Override
|
||||
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 (!this.headsended) {
|
||||
long len = 0;
|
||||
@@ -422,6 +450,10 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||
this.headsended = true;
|
||||
}
|
||||
|
||||
protected DefaultAnyValue duplicateHeader() {
|
||||
return this.header.duplicate();
|
||||
}
|
||||
|
||||
public void setHeader(String name, Object value) {
|
||||
this.header.setValue(name, String.valueOf(value));
|
||||
}
|
||||
@@ -454,6 +486,14 @@ public class HttpResponse<R extends HttpRequest> extends Response<R> {
|
||||
this.contentLength = contentLength;
|
||||
}
|
||||
|
||||
public Interceptor getInterceptor() {
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
public void setInterceptor(Interceptor interceptor) {
|
||||
this.interceptor = interceptor;
|
||||
}
|
||||
|
||||
protected final class TransferFileHandler implements CompletionHandler<Integer, ByteBuffer> {
|
||||
|
||||
private final AsynchronousFileChannel filechannel;
|
||||
|
||||
Reference in New Issue
Block a user