355 lines
11 KiB
Java
355 lines
11 KiB
Java
package cn.access.authority;
|
||
|
||
import java.io.IOException;
|
||
import java.io.PrintWriter;
|
||
import java.lang.annotation.Annotation;
|
||
import java.lang.reflect.InvocationTargetException;
|
||
import java.lang.reflect.Method;
|
||
import java.text.MessageFormat;
|
||
import java.util.Map;
|
||
import java.util.Set;
|
||
|
||
import javax.servlet.ServletContext;
|
||
import javax.servlet.ServletException;
|
||
import javax.servlet.http.HttpServletRequest;
|
||
import javax.servlet.http.HttpServletResponse;
|
||
import javax.ws.rs.HttpMethod;
|
||
import javax.ws.rs.QueryParam;
|
||
import javax.ws.rs.core.Context;
|
||
|
||
import apx.com.amarsoft.als.base.model.RspObject;
|
||
import cn.access.dispatcher.RestfullDispatcher;
|
||
import cn.bean.Org;
|
||
import cn.bean.User;
|
||
import cn.config.container.RequestContext;
|
||
import cn.config.mapping.URIMappingCache;
|
||
import cn.config.mapping.URIMappingKey;
|
||
import cn.config.mapping.URIMappingValue;
|
||
import cn.config.model.GlobalConfigure;
|
||
|
||
import com.alibaba.fastjson.JSON;
|
||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||
import com.amarsoft.are.ARE;
|
||
import com.amarsoft.are.jbo.JBOException;
|
||
import com.amarsoft.are.jbo.JBOFactory;
|
||
import com.amarsoft.are.log.Log;
|
||
import com.amarsoft.awe.util.Transaction;
|
||
import com.base.constant.RestfullConstant;
|
||
import com.base.helper.SessionHelper;
|
||
import com.base.helper.UserHelper;
|
||
import com.base.tool.URIMappingTool;
|
||
import com.base.util.RequestUtil;
|
||
import com.google.common.collect.Sets;
|
||
|
||
/**
|
||
* Restfull分发器实现类
|
||
*
|
||
* @author yangsong
|
||
* @date 2015年3月29日
|
||
*/
|
||
public class AnnotationRestfullDispatcherImpl implements RestfullDispatcher {
|
||
|
||
protected Log logger = ARE.getLog();
|
||
private Long sExpire;
|
||
|
||
/**
|
||
* 自动扫描路径设置
|
||
*/
|
||
public void init(ServletContext servletContext) {
|
||
URIMappingTool.scanPackageAndInitResfSetting(servletContext
|
||
.getInitParameter("RestfullScanPackage"));
|
||
}
|
||
|
||
public void doPost(HttpServletRequest req, HttpServletResponse rep)
|
||
throws ServletException, IOException {
|
||
doProcess(req, rep, HttpMethod.POST);
|
||
}
|
||
|
||
public void doDelete(HttpServletRequest req, HttpServletResponse rep)
|
||
throws ServletException, IOException {
|
||
doProcess(req, rep, HttpMethod.DELETE);
|
||
|
||
}
|
||
|
||
public void doPut(HttpServletRequest req, HttpServletResponse rep)
|
||
throws ServletException, IOException {
|
||
doProcess(req, rep, HttpMethod.PUT);
|
||
|
||
}
|
||
|
||
public void doGet(HttpServletRequest req, HttpServletResponse rep)
|
||
throws ServletException, IOException {
|
||
doProcess(req, rep, HttpMethod.GET);
|
||
}
|
||
|
||
protected void doProcess(HttpServletRequest req, HttpServletResponse rep,
|
||
String httpMethod) throws IOException {
|
||
RequestContext reqContext = new RequestContext();
|
||
RspObject<?> rsp = null;
|
||
PrintWriter out = rep.getWriter();
|
||
try {
|
||
setRequestContext(reqContext, req, rep);
|
||
rsp = callService(req, httpMethod, reqContext, rsp);
|
||
if (reqContext.jboTx != null)
|
||
reqContext.jboTx.commit();
|
||
if (reqContext.sqlca != null)
|
||
reqContext.sqlca.commit();
|
||
} catch (Throwable e) {
|
||
logger.error("error:", e);
|
||
if (reqContext.jboTx != null) {
|
||
try {
|
||
reqContext.jboTx.rollback();
|
||
} catch (JBOException e1) {
|
||
logger.error("tx rollback error", e1);
|
||
}
|
||
}
|
||
if (reqContext.sqlca != null) {
|
||
try {
|
||
reqContext.sqlca.rollback();
|
||
} catch (Exception e1) {
|
||
logger.error("sqlca rollback error", e1);
|
||
}
|
||
}
|
||
e = ((InvocationTargetException) e).getTargetException();
|
||
rsp = RspObject.build(e);
|
||
rsp.getHeader().setCode("500");
|
||
if (e.getMessage() != null) {
|
||
rsp.getHeader().setMessage(e.getMessage());
|
||
}
|
||
} finally {
|
||
if (reqContext.sqlca != null) {
|
||
try {
|
||
reqContext.sqlca.disConnect();
|
||
} catch (Exception e) {
|
||
logger.error("sqlca close error", e);
|
||
}
|
||
}
|
||
}
|
||
setResonse(rep, rsp, out);
|
||
}
|
||
|
||
protected void setRequestContext(RequestContext reqContext,
|
||
HttpServletRequest req, HttpServletResponse rep) throws Exception {
|
||
reqContext.req = req;
|
||
reqContext.rep = rep;
|
||
reqContext.curUser = lookupUser(req);
|
||
reqContext.jboTx = JBOFactory.createJBOTransaction();
|
||
reqContext.sqlca = Transaction
|
||
.createTransaction((String) RestfullConstant.baseProperty
|
||
.get("DATASOURCE".toLowerCase()));
|
||
}
|
||
|
||
protected RspObject<?> callService(HttpServletRequest req,
|
||
String httpMethod, RequestContext reqContext, RspObject<?> rsp)
|
||
throws Exception {
|
||
String uri = req.getPathInfo();
|
||
Map<String, Object> parameter = mapParameter(req);
|
||
URIMappingKey key = new URIMappingKey(uri, httpMethod);
|
||
URIMappingValue value = URIMappingCache.getInstance().get(key);
|
||
|
||
if (value == null) {
|
||
rsp = RspObject.build(new ServletException(MessageFormat.format(
|
||
"{0} {1} not found", key.getHttpMethod(), key.getUri())));
|
||
rsp.getHeader().setCode(
|
||
(String) RestfullConstant.baseProperty.get("CODE404"
|
||
.toLowerCase()));
|
||
} else {
|
||
logger.debug(httpMethod + " " + uri + " " + parameter + " "
|
||
+ value.getClazz().getName());
|
||
Class<?> clazz = value.getClazz();
|
||
Method method = value.getMethod();
|
||
Class<?> returnType = method.getReturnType();
|
||
Object repObject = null;
|
||
Object object = clazz.newInstance();
|
||
repObject = invokeMethod(object, method, reqContext);
|
||
|
||
// 没有返回值的,repObject直接设置为空
|
||
if (RestfullConstant.baseProperty.get("VOID".toLowerCase()).equals(
|
||
returnType.getName())) {
|
||
// rsp = null;
|
||
rsp = RspObject.build("");
|
||
} else if (repObject == null) {
|
||
rsp = RspObject.build("");
|
||
} else if (repObject instanceof RspObject) {
|
||
rsp = (RspObject<?>) repObject;
|
||
// app 附件下载
|
||
} else if (RestfullConstant.baseProperty
|
||
.get("APPATT".toLowerCase()).equals(
|
||
returnType.getSimpleName())) {
|
||
rsp = null;
|
||
} else {
|
||
rsp = RspObject.build(repObject);
|
||
}
|
||
// 修改到期
|
||
sExpire = SessionHelper.edit(reqContext.jboTx, req);
|
||
}
|
||
|
||
return rsp;
|
||
}
|
||
|
||
//
|
||
protected Object invokeMethod(Object object, Method method,
|
||
RequestContext reqContext) throws IllegalAccessException,
|
||
IllegalArgumentException, InvocationTargetException {
|
||
// 取所有的参数类型以及参数注解,构建传入参数对象数组
|
||
Class<?>[] argTypes = method.getParameterTypes();
|
||
Annotation[][] annotations = method.getParameterAnnotations();
|
||
Object[] argValues = new Object[annotations.length];
|
||
|
||
for (int i = 0; i < annotations.length; i++) {
|
||
int length = annotations[i].length;
|
||
argValues[i] = null;
|
||
String typeName = argTypes[i].getName();
|
||
if (length == 0) {// 如果为0,则表示没有为该参数添加注释
|
||
if (isBaseNumberType(typeName)) {
|
||
argValues[i] = (short) 0;// 基础数据类型不能为null,要给个默认值0
|
||
} else {
|
||
continue;
|
||
}
|
||
}
|
||
;
|
||
|
||
for (int k = 0; k < length; k++) {
|
||
Annotation annotation = annotations[i][k];
|
||
argValues[i] = injectWithAnnotation(object, annotation,
|
||
reqContext, typeName);
|
||
}
|
||
}
|
||
// System.out.println("arg:"+Arrays.asList(argValues));
|
||
return method.invoke(object, argValues);
|
||
}
|
||
|
||
protected boolean isBaseNumberType(String typeName) {
|
||
Set<String> numberTypeSet = Sets.newHashSet();
|
||
numberTypeSet.add("byte");
|
||
numberTypeSet.add("short");
|
||
numberTypeSet.add("int");
|
||
numberTypeSet.add("long");
|
||
numberTypeSet.add("float");
|
||
numberTypeSet.add("double");
|
||
return numberTypeSet.contains(typeName);
|
||
}
|
||
|
||
/**
|
||
* 从request中传入的参数始终都是String类型的,需要强制转换为Java方法上相应的方法
|
||
*
|
||
* @param value
|
||
* @param argType
|
||
* @return
|
||
*/
|
||
protected Object convertArgValue(String value, String argType) {
|
||
if ("int".equals(argType)) {
|
||
return Integer.valueOf(value);
|
||
} else if ("java.lang.Integer".equals(argType)) {
|
||
return Integer.valueOf(value);
|
||
} else if ("java.lang.Double".equals(argType)) {
|
||
return Double.valueOf(value);
|
||
} else if ("double".equals(argType)) {
|
||
return Double.valueOf(value);
|
||
} else if ("java.lang.String".equals(argType)) {
|
||
return value;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 根据注解,放入参数
|
||
*
|
||
* @param instance
|
||
* @param annotation
|
||
* @param req
|
||
* @param rep
|
||
* @param typeName
|
||
* @return
|
||
*/
|
||
protected Object injectWithAnnotation(Object instance,
|
||
Annotation annotation, RequestContext reqContext, String typeName) {
|
||
// 从Request中取出参数
|
||
if (annotation instanceof QueryParam) {
|
||
QueryParam anoQp = (QueryParam) annotation;
|
||
String paraName = anoQp.value();
|
||
String paraValue = reqContext.getReq().getParameter(paraName);
|
||
if (paraValue == null)
|
||
return null;
|
||
return convertArgValue(paraValue, typeName);
|
||
} else if (annotation instanceof Context) {
|
||
if (" javax.servlet.ServletRequest".equals(typeName)) {
|
||
return reqContext.req;
|
||
} else if ("javax.servlet.http.HttpServletRequest".equals(typeName)) {
|
||
return reqContext.req;
|
||
} else if ("javax.servlet.ServletResponse".equals(typeName)) {
|
||
return reqContext.rep;
|
||
} else if ("javax.servlet.http.HttpServletResponse"
|
||
.equals(typeName)) {
|
||
return reqContext.rep;
|
||
} else if ("com.amarsoft.ams.base.User".equals(typeName)) { // 用户对象
|
||
return reqContext.curUser;
|
||
} else if ("cn.bean.User".equals(typeName)) { // 用户对象
|
||
return reqContext.curUser;
|
||
}else if ("com.amarsoft.awe.util.Transaction".equals(typeName)) { // Sqlca对象
|
||
return reqContext.sqlca;
|
||
} else if ("com.amarsoft.are.jbo.JBOTransaction".equals(typeName)) { // JBO事务
|
||
return reqContext.jboTx;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 从上下文环境中取当前用户
|
||
*
|
||
* @return
|
||
*/
|
||
protected User lookupUser(HttpServletRequest request) {
|
||
|
||
String sUserId = (String) request.getSession().getAttribute(
|
||
(String) RestfullConstant.sessionProperty.get("USERID"
|
||
.toLowerCase()));
|
||
if (sUserId == null || sUserId.length() < 1)
|
||
return null;
|
||
Map<String, Object> userMap = UserHelper.getUser(sUserId);
|
||
if (userMap == null)
|
||
return null;
|
||
User user = new User();
|
||
user.setUserId(userMap.get("USERID".toLowerCase()) == null ? ""
|
||
: userMap.get("USERID".toLowerCase()).toString());
|
||
user.setStatus(userMap.get("STATUS".toLowerCase()) == null ? ""
|
||
: userMap.get("STATUS".toLowerCase()).toString());
|
||
user.setUserName(userMap.get("USERNAME".toLowerCase()) == null ? ""
|
||
: userMap.get("USERNAME".toLowerCase()).toString());
|
||
Org org = new Org(userMap.get("".toLowerCase()) == null ? "" : userMap
|
||
.get("".toLowerCase()).toString());
|
||
user.setOrg(org);
|
||
return user;
|
||
}
|
||
|
||
protected void setResonse(HttpServletResponse rep, RspObject<?> rsp,
|
||
PrintWriter out) {
|
||
if (rsp != null) {
|
||
// 设置响应头
|
||
rep.setHeader("Cache-Control", "no-cache");
|
||
rep.setHeader("Pragma", "no-cache");
|
||
// rep.setDateHeader("Expires", 0);
|
||
rep.setDateHeader("Expires", sExpire);
|
||
rep.addHeader("Access-Control-Allow-Origin", "*");
|
||
rep.addHeader("Allow", "GET, POST, DELETE, PUT,OPTIONS");
|
||
rep.addHeader("Access-Control-Allow-Methods",
|
||
"GET, POST, DELETE, PUT");
|
||
rep.addHeader("Access-Control-Allow-Headers", "Content-Type");
|
||
rep.setContentType("application/json; charset="
|
||
+ GlobalConfigure.getInstance().getProperty("encoding"));
|
||
String jsonString = JSON.toJSONStringWithDateFormat(rsp,
|
||
"yyyy/MM/dd HH:mm:ss.SSS",
|
||
SerializerFeature.WriteMapNullValue,
|
||
SerializerFeature.PrettyFormat,
|
||
SerializerFeature.WriteNonStringKeyAsString,
|
||
SerializerFeature.SortField);
|
||
out.println(jsonString);
|
||
}
|
||
}
|
||
|
||
protected Map<String, Object> mapParameter(HttpServletRequest req) {
|
||
return RequestUtil.convertRequestToMap(req);
|
||
}
|
||
}
|