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 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 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 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 mapParameter(HttpServletRequest req) { return RequestUtil.convertRequestToMap(req); } }