This commit is contained in:
kamhung
2015-11-27 11:29:34 +08:00
parent 43bcbc8a49
commit fd06646e1d
3 changed files with 125 additions and 1 deletions

View File

@@ -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;
}
}
}

View 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;
}

View File

@@ -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;