001package io.jboot.web; 002 003import com.jfinal.aop.Interceptor; 004import com.jfinal.aop.InterceptorManager; 005import com.jfinal.config.Routes; 006import com.jfinal.core.*; 007import io.jboot.utils.ArrayUtil; 008import io.jboot.utils.ClassUtil; 009 010import java.lang.reflect.*; 011 012public class JbootActionMapping extends ActionMapping { 013 014 public JbootActionMapping(Routes routes) { 015 super(routes); 016 } 017 018 @Override 019 protected void buildActionMapping() { 020 mapping.clear(); 021 Class<?> dc; 022 InterceptorManager interMan = InterceptorManager.me(); 023 for (Routes routes : getRoutesList()) { 024 for (Routes.Route route : routes.getRouteItemList()) { 025 Class<? extends Controller> controllerClass = route.getControllerClass(); 026 Interceptor[] controllerInters = interMan.createControllerInterceptor(controllerClass); 027 028 boolean declaredMethods = !routes.getMappingSuperClass() || controllerClass.getSuperclass() == Controller.class; 029 030 Method[] methods = (declaredMethods ? controllerClass.getDeclaredMethods() : controllerClass.getMethods()); 031 for (Method method : methods) { 032 if (declaredMethods) { 033 if (!Modifier.isPublic(method.getModifiers())) 034 continue; 035 } else { 036 dc = method.getDeclaringClass(); 037 if (dc == Controller.class || dc == Object.class) 038 continue; 039 } 040 041 if (method.getAnnotation(NotAction.class) != null) { 042 continue; 043 } 044 045 Interceptor[] actionInters = interMan.buildControllerActionInterceptor(routes.getInterceptors(), controllerInters, controllerClass, method); 046 String controllerPath = route.getControllerPath(); 047 048 String methodName = method.getName(); 049 ActionKey ak = method.getAnnotation(ActionKey.class); 050 String actionKey; 051 if (ak != null) { 052 actionKey = ak.value().trim(); 053 if ("".equals(actionKey)) { 054 throw new IllegalArgumentException(controllerClass.getName() + "." + methodName + "(): The argument of ActionKey can not be blank."); 055 } 056 057 if (actionKey.startsWith(SLASH)) { 058 //actionKey = actionKey 059 } else if (actionKey.startsWith("./")) { 060 actionKey = controllerPath + actionKey.substring(1); 061 } else { 062 actionKey = SLASH + actionKey; 063 } 064// if (!actionKey.startsWith(SLASH)) { 065// actionKey = SLASH + actionKey; 066// } 067 } else if (methodName.equals("index")) { 068 actionKey = controllerPath; 069 } else { 070 actionKey = controllerPath.equals(SLASH) ? SLASH + methodName : controllerPath + SLASH + methodName; 071 } 072 073// Action action = new Action(controllerPath, actionKey, controllerClass, method, methodName, actionInters, route.getFinalViewPath(routes.getBaseViewPath())); 074// if (mapping.put(actionKey, action) != null) { 075// throw new RuntimeException(buildMsg(actionKey, controllerClass, method)); 076// } 077 078 Action newAction = new Action(controllerPath, actionKey, controllerClass, method, methodName, actionInters, route.getFinalViewPath(routes.getBaseViewPath())); 079 Action existAction = mapping.get(actionKey); 080 if (existAction == null) { 081 mapping.put(actionKey, newAction); 082 } else { 083 084 Type controllerType = controllerClass.getGenericSuperclass(); 085 Method existActionMethod = existAction.getMethod(); 086 087 // 不是泛型 088 if (!(controllerType instanceof ParameterizedType)) { 089 throw new RuntimeException(buildMsg(actionKey, method, existActionMethod)); 090 } 091 092 if (method.getParameterCount() == 0 093 || method.getParameterCount() != existActionMethod.getParameterCount() 094 || method.getDeclaringClass() != existActionMethod.getDeclaringClass()) { 095 throw new RuntimeException(buildMsg(actionKey, method, existActionMethod)); 096 } 097 098 Type[] argumentTypes = ((ParameterizedType) controllerType).getActualTypeArguments(); 099 100 Class<?>[] paraTypes = method.getParameterTypes(); 101 Class<?>[] existParaTypes = existActionMethod.getParameterTypes(); 102 103 for (int i = 0; i < paraTypes.length; i++) { 104 Class<?> newType = paraTypes[i]; 105 Class<?> existType = existParaTypes[i]; 106 if (newType == existType) { 107 continue; 108 } 109 // newType 是父类 110 else if (newType.isAssignableFrom(existType) && ArrayUtil.contains(argumentTypes, existType)) { 111 break; 112 } 113 // newType 是子类 114 else if (existType.isAssignableFrom(newType) && ArrayUtil.contains(argumentTypes, newType)) { 115 mapping.put(actionKey, newAction); 116 break; 117 } else { 118 throw new RuntimeException(buildMsg(actionKey, method, existActionMethod)); 119 } 120 } 121 122 } 123 } 124 } 125 } 126 routes.clear(); 127 128 // support url = controllerPath + urlParas with "/" of controllerPath 129 Action action = mapping.get("/"); 130 if (action != null) { 131 mapping.put("", action); 132 } 133 } 134 135 136 protected String buildMsg(String actionKey, Method method, Method existMethod) { 137 StringBuilder sb = new StringBuilder("The action \"") 138 .append(ClassUtil.buildMethodString(method)) 139 .append("\" can not be mapped, actionKey \"") 140 .append(actionKey) 141 .append("\" is already in used by: \"") 142 .append(ClassUtil.buildMethodString(existMethod)) 143 .append("\""); 144 145 String msg = sb.toString(); 146 System.err.println("\nException: " + msg); 147 return msg; 148 } 149 150 151}