This commit is contained in:
Redkale
2017-05-13 10:50:52 +08:00
parent 0be3d8a4fa
commit a5756c0b4d
8 changed files with 73 additions and 58 deletions

View File

@@ -134,13 +134,13 @@
<!-- <!--
REST的核心配置项 REST的核心配置项
当Server为HTTP协议时, rest节点才有效。存在[rest]节点则Server启动时会加载REST服务, 节点可以多个 当Server为HTTP协议时, rest节点才有效。存在[rest]节点则Server启动时会加载REST服务, 节点可以多个
base: REST服务的BaseServlet必须是 org.redkale.net.http.RestServlet 的子类,该属性值默认值为 org.redkale.net.http.RestServlet base: REST服务的BaseServlet必须是 org.redkale.net.http.HttpServlet 的子类,且子类必须标记@HttpUserType
autoload默认值"true" 默认值. 加载当前server所能使用的Servce对象; autoload默认值"true" 默认值. 加载当前server所能使用的Servce对象;
mustsign默认值"true" 是否只加载标记为RestService的Service类默认只加载标记RestService且ignore=false的Service mustsign默认值"true" 是否只加载标记为RestService的Service类默认只加载标记RestService且ignore=false的Service
includes当autoload="true" 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开 includes当autoload="true" 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
excludes当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开 excludes当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
--> -->
<rest base="org.redkale.net.http.DefaultRestServlet" mustsign="true" autoload="true" includes="" excludes=""> <rest base="org.redkale.net.http.HttpServlet" mustsign="true" autoload="true" includes="" excludes="">
<!-- <!--
value: Service类名列出的表示必须被加载的Service对象 value: Service类名列出的表示必须被加载的Service对象
ignore: 是否忽略设置为true则不会加载该Service对象默认值为false ignore: 是否忽略设置为true则不会加载该Service对象默认值为false

View File

@@ -174,7 +174,7 @@ public class NodeHttpServer extends NodeServer {
if (!autoload && !includeValues.contains(stypename)) return; if (!autoload && !includeValues.contains(stypename)) return;
if (!restFilter.accept(stypename)) return; if (!restFilter.accept(stypename)) return;
RestServlet servlet = httpServer.addRestServlet(name, stype, service, baseServletClass, prefix, (AnyValue) null); HttpServlet servlet = httpServer.addRestServlet(name, stype, service, baseServletClass, prefix, (AnyValue) null);
resourceFactory.inject(servlet, NodeHttpServer.this); resourceFactory.inject(servlet, NodeHttpServer.this);
if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet); if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
if (ss != null) { if (ss != null) {

View File

@@ -68,6 +68,8 @@ public class HttpRequest extends Request<HttpContext> {
protected int actionid; protected int actionid;
protected Object currentUser;
private final String remoteAddrHeader; private final String remoteAddrHeader;
Object attachment; //供 HttpBaseServlet传递Entry使用 Object attachment; //供 HttpBaseServlet传递Entry使用
@@ -240,6 +242,33 @@ public class HttpRequest extends Request<HttpContext> {
return super.removeProperty(name); return super.removeProperty(name);
} }
/**
* 设置当前用户信息, 通常在HttpServlet.authenticate方法里设置currentUser <br>
* 数据类型由&#64;HttpUserType指定
*
* @param <T> 泛型
* @param user 用户信息
*
* @return HttpRequest
*/
public <T> HttpRequest currentUser(T user) {
this.currentUser = user;
return this;
}
/**
* 获取当前用户信息, 通常在HttpServlet.authenticate方法里设置currentUser <br>
* 数据类型由&#64;HttpUserType指定
*
* @param <T> &#64;HttpUserType指定的用户信息类型
*
* @return 用户信息
*/
@SuppressWarnings("unchecked")
public <T> T currentUser() {
return (T) this.currentUser;
}
/** /**
* 获取模块ID来自&#64;HttpServlet.moduleid() * 获取模块ID来自&#64;HttpServlet.moduleid()
* *
@@ -403,6 +432,7 @@ public class HttpRequest extends Request<HttpContext> {
this.bodyparsed = false; this.bodyparsed = false;
this.moduleid = 0; this.moduleid = 0;
this.actionid = 0; this.actionid = 0;
this.currentUser = null;
this.attachment = null; this.attachment = null;

View File

@@ -102,7 +102,7 @@ public final class HttpServer extends Server<String, HttpContext, HttpRequest, H
* *
* @return RestServlet * @return RestServlet
*/ */
public <S extends Service, T extends RestServlet> RestServlet addRestServlet(String name, Class<S> serviceType, S service, Class<T> baseServletClass, String prefix) { public <S extends Service, T extends HttpServlet> T addRestServlet(String name, Class<S> serviceType, S service, Class<T> baseServletClass, String prefix) {
return addRestServlet(name, serviceType, service, baseServletClass, prefix, null); return addRestServlet(name, serviceType, service, baseServletClass, prefix, null);
} }
@@ -120,16 +120,16 @@ public final class HttpServer extends Server<String, HttpContext, HttpRequest, H
* *
* @return RestServlet * @return RestServlet
*/ */
public <S extends Service, T extends RestServlet> RestServlet addRestServlet( public <S extends Service, T extends HttpServlet> T addRestServlet(
final String name, Class<S> serviceType, final S service, final Class<T> baseServletClass, final String prefix, AnyValue conf) { final String name, Class<S> serviceType, final S service, final Class<T> baseServletClass, final String prefix, AnyValue conf) {
RestServlet servlet = null; T servlet = null;
for (final HttpServlet item : ((HttpPrepareServlet) this.prepare).getServlets()) { for (final HttpServlet item : ((HttpPrepareServlet) this.prepare).getServlets()) {
if (!(item instanceof RestServlet)) continue; if (!(item instanceof HttpServlet)) continue;
if (item.getClass().getAnnotation(Rest.RestDynamic.class) == null) continue; if (item.getClass().getAnnotation(Rest.RestDynamic.class) == null) continue;
try { try {
Field field = item.getClass().getDeclaredField(Rest.REST_SERVICE_FIELD_NAME); Field field = item.getClass().getDeclaredField(Rest.REST_SERVICE_FIELD_NAME);
if (serviceType.equals(field.getType())) { if (serviceType.equals(field.getType())) {
servlet = (RestServlet) item; servlet = (T) item;
break; break;
} }
} catch (NoSuchFieldException | SecurityException e) { } catch (NoSuchFieldException | SecurityException e) {

View File

@@ -0,0 +1,28 @@
/*
* 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 org.redkale.net.http;
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 配合 HttpServlet 使用。
* 用于指定HttpRequest.currentUser的数据类型。
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({TYPE})
@Retention(RUNTIME)
public @interface HttpUserType {
Class value();
}

View File

@@ -104,9 +104,9 @@ public final class Rest {
return (!controller.name().isEmpty()) ? controller.name() : serviceType.getSimpleName().replaceAll("Service.*$", "").toLowerCase(); return (!controller.name().isEmpty()) ? controller.name() : serviceType.getSimpleName().replaceAll("Service.*$", "").toLowerCase();
} }
static <T extends RestServlet> T createRestServlet(final Class<T> baseServletClass, final Class<? extends Service> serviceType) { static <T extends HttpServlet> T createRestServlet(final Class<T> baseServletClass, final Class<? extends Service> serviceType) {
if (baseServletClass == null || serviceType == null) return null; if (baseServletClass == null || serviceType == null) return null;
if (!RestServlet.class.isAssignableFrom(baseServletClass)) return null; if (!HttpServlet.class.isAssignableFrom(baseServletClass)) return null;
int mod = baseServletClass.getModifiers(); int mod = baseServletClass.getModifiers();
if (!java.lang.reflect.Modifier.isPublic(mod)) return null; if (!java.lang.reflect.Modifier.isPublic(mod)) return null;
if (java.lang.reflect.Modifier.isAbstract(mod)) return null; if (java.lang.reflect.Modifier.isAbstract(mod)) return null;
@@ -115,7 +115,6 @@ public final class Rest {
final String webServletDesc = Type.getDescriptor(WebServlet.class); final String webServletDesc = Type.getDescriptor(WebServlet.class);
final String reqDesc = Type.getDescriptor(HttpRequest.class); final String reqDesc = Type.getDescriptor(HttpRequest.class);
final String respDesc = Type.getDescriptor(HttpResponse.class); final String respDesc = Type.getDescriptor(HttpResponse.class);
final String contextDesc = Type.getDescriptor(HttpContext.class);
final String retDesc = Type.getDescriptor(RetResult.class); final String retDesc = Type.getDescriptor(RetResult.class);
final String futureDesc = Type.getDescriptor(CompletableFuture.class); final String futureDesc = Type.getDescriptor(CompletableFuture.class);
final String flipperDesc = Type.getDescriptor(Flipper.class); final String flipperDesc = Type.getDescriptor(Flipper.class);
@@ -130,24 +129,18 @@ public final class Rest {
final String reqInternalName = Type.getInternalName(HttpRequest.class); final String reqInternalName = Type.getInternalName(HttpRequest.class);
final String respInternalName = Type.getInternalName(HttpResponse.class); final String respInternalName = Type.getInternalName(HttpResponse.class);
final String contextInternalName = Type.getInternalName(HttpContext.class);
final String attrInternalName = Type.getInternalName(org.redkale.util.Attribute.class); final String attrInternalName = Type.getInternalName(org.redkale.util.Attribute.class);
final String retInternalName = Type.getInternalName(RetResult.class); final String retInternalName = Type.getInternalName(RetResult.class);
final String serviceTypeInternalName = Type.getInternalName(serviceType); final String serviceTypeInternalName = Type.getInternalName(serviceType);
final Class userType = getSuperUserType(baseServletClass); HttpUserType hut = baseServletClass.getAnnotation(HttpUserType.class);
final Class userType = hut == null ? Object.class : hut.value();
final String supDynName = baseServletClass.getName().replace('.', '/'); final String supDynName = baseServletClass.getName().replace('.', '/');
final RestService controller = serviceType.getAnnotation(RestService.class); final RestService controller = serviceType.getAnnotation(RestService.class);
if (controller != null && controller.ignore()) return null; //标记为ignore=true不创建Servlet if (controller != null && controller.ignore()) return null; //标记为ignore=true不创建Servlet
ClassLoader loader = Sncp.class.getClassLoader(); ClassLoader loader = Sncp.class.getClassLoader();
String newDynName = serviceTypeInternalName.substring(0, serviceTypeInternalName.lastIndexOf('/') + 1) + "_Dyn" + serviceType.getSimpleName().replaceAll("Service.*$", "") + "RestServlet"; String newDynName = serviceTypeInternalName.substring(0, serviceTypeInternalName.lastIndexOf('/') + 1) + "_Dyn" + serviceType.getSimpleName().replaceAll("Service.*$", "") + "RestServlet";
Method currentUserMethod = null;
try {
currentUserMethod = baseServletClass.getDeclaredMethod("currentUser", HttpRequest.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
final String defmodulename = getWebModuleName(serviceType); final String defmodulename = getWebModuleName(serviceType);
for (char ch : defmodulename.toCharArray()) { for (char ch : defmodulename.toCharArray()) {
@@ -656,9 +649,9 @@ public final class Rest {
throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)"); throw new RuntimeException(method + " only " + RestParam.class.getSimpleName() + "(#) to Type(primitive class or String)");
} }
} else if ("&".equals(pname) && ptype == userType) { //当前用户对象的类名 } else if ("&".equals(pname) && ptype == userType) { //当前用户对象的类名
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "currentUser", Type.getMethodDescriptor(currentUserMethod), false); mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "currentUser", "()Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(userType));
mv.visitVarInsn(ASTORE, maxLocals); mv.visitVarInsn(ASTORE, maxLocals);
varInsns.add(new int[]{ALOAD, maxLocals}); varInsns.add(new int[]{ALOAD, maxLocals});
} else if (ptype == boolean.class) { } else if (ptype == boolean.class) {
@@ -1055,19 +1048,6 @@ public final class Rest {
} }
} }
private static Class getSuperUserType(Class servletClass) {
java.lang.reflect.Type type = servletClass.getGenericSuperclass();
if (type instanceof Class) return getSuperUserType((Class) type);
if (type instanceof java.lang.reflect.ParameterizedType) {
java.lang.reflect.ParameterizedType pt = (java.lang.reflect.ParameterizedType) type;
if (pt.getRawType() == RestServlet.class) {
java.lang.reflect.Type usert = pt.getActualTypeArguments()[0];
if (usert instanceof Class) return (Class) usert;
}
}
return null;
}
private static class MappingEntry { private static class MappingEntry {
private static final RestMapping DEFAULT__MAPPING; private static final RestMapping DEFAULT__MAPPING;

View File

@@ -17,7 +17,7 @@ import java.io.*;
* @param <T> 当前用户对象类型 * @param <T> 当前用户对象类型
*/ */
@Deprecated @Deprecated
public class RestHttpServlet<T> extends RestServlet<T> { public class RestHttpServlet<T> extends HttpServlet {
protected T currentUser(HttpRequest req) throws IOException { protected T currentUser(HttpRequest req) throws IOException {
return null; return null;

View File

@@ -1,23 +0,0 @@
/*
* 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 org.redkale.net.http;
import java.io.*;
/**
*
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 当前用户对象类型
*/
public class RestServlet<T> extends HttpServlet {
protected T currentUser(HttpRequest req) throws IOException {
return null;
}
}