package org.theonefx.wcframework.mvc.wcweb; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Collection; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpSession; import org.theonefx.wcframework.core.ClassWrapper; import org.theonefx.wcframework.core.InitializableBean; import org.theonefx.wcframework.ioc.val.GenericTypeResolver; import org.theonefx.wcframework.ioc.val.MethodParameter; import org.theonefx.wcframework.mvc.MVCConfig; import org.theonefx.wcframework.mvc.annotation.BodyType; import org.theonefx.wcframework.mvc.annotation.Param; import org.theonefx.wcframework.mvc.annotation.ParamSource; import org.theonefx.wcframework.mvc.annotation.ParamType; import org.theonefx.wcframework.mvc.annotation.ResponseBody; import org.theonefx.wcframework.mvc.exception.CannotEnsureTranslateException; import org.theonefx.wcframework.mvc.exception.ParamTranslateException; import org.theonefx.wcframework.mvc.wcweb.translate.ArgsTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.ArrayParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.BeanParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.CollectionParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.DefaultParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.EnumParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.FileTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.JavaBeanParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.MapParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.ParamTranslatSupport; import org.theonefx.wcframework.mvc.wcweb.translate.ParamTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.RequestTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.ResponseTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.ServletContextTranslater; import org.theonefx.wcframework.mvc.wcweb.translate.SessionTranslater; import org.theonefx.wcframework.utils.StringUtils; /** * @File : ActionInvoker.java * @ClassName : ActionInvoker * @Author : TheoneFx * @Date : 2012-4-21 下午09:21:58 * @Version : v1.0 * @Description : Action调用器,用于调用action,返回view */ public class ActionInvoker implements Comparable<ActionInvoker>, InitializableBean, Action { private String nameSpace; private PathMatcher matcher; private String beanId; private Method method; private View[] views; private String encoding = null; private String name; private ParamTranslater[] translaters; private BodyType bodyType; /** * Action类的包装器 */ private ClassWrapper<?> classWrapper; public String getBeanId() { return beanId; } public void setBeanId(String beanId) { this.beanId = beanId; } public Method getMethod() { return method; } public String getEncoding() { return encoding; } public void setEncoding(String encoding) { this.encoding = encoding; } public void setMethod(Method method) { this.method = method; } public View[] getViews() { return views; } public void setViews(View[] views) { this.views = views; } public ActionInvoker(PathMatcher matcher) { this.matcher = matcher; } public PathMatcher getMatcher() { return matcher; } public void setNameSpace(String namespace) { this.nameSpace = namespace; } @Override public String getNamespace() { return nameSpace; } @Override public String getName() { return name; } @Override public int compareTo(ActionInvoker o) { return matcher.getLevel() - o.getMatcher().getLevel(); } @Override public BodyType getBodyType() { return bodyType; } public void setBodyType(BodyType bodyType) { this.bodyType = bodyType; } @Override public Object execute(ActionInvocationContext ctx) throws Exception { // 获得action的bean对象 Object bean = ctx.getWebApplicationContext().getBean(beanId); if (StringUtils.isBlank(encoding)) { encoding = MVCConfig.defaultEncoding; } // action方法调用的返回值 Object ret = null; if (translaters == null || translaters.length == 0) { ret = method.invoke(bean); } else { // 自动转换params Object[] params = new Object[translaters.length]; for (int i = 0; i < params.length; i++) { ParamTranslater translater = translaters[i]; params[i] = translater.translate(ctx); } ret = method.invoke(bean, params); } return ret; } @Override public void initialize() throws Exception { ResponseBody responseBody = method.getAnnotation(ResponseBody.class); if (responseBody != null) { BodyType type = responseBody.type(); if (type != null) { bodyType = type; } } // 生成参数转换器 Annotation[][] annoss = method.getParameterAnnotations(); Class<?>[] types = method.getParameterTypes(); if (types.length == 0) { // 没有参数 } else if (types.length == 1 && annoss.length == 0) { // 唯一参数,无注解 translaters = new ParamTranslater[1]; MethodParameter methodParam = new MethodParameter(method, 0); Class<?> type = GenericTypeResolver.resolveParameterType(methodParam, classWrapper.getWrapperedClass()); ParamTranslatSupport paramTranslat = getTranslaterFromType(type); paramTranslat.setSources(new ParamSource[] { ParamSource.REQUEST }); paramTranslat.setAction(this); translaters[0] = paramTranslat; try { translaters[0].initialize(); } catch (Exception e) { throw new ParamTranslateException("创建转换器出错:Method=" + method.getName() + " paramType=" + type.getName() + " paramName=" + name); } } else { // 有参数情况下的处理 // 创建转换器数组,大小和参数数量一致 translaters = new ParamTranslater[types.length]; // 循环处理每一个参数 for (int i = 0; i < annoss.length; i++) { ParamTranslatSupport translater = null; // 这是参数的真实类型 MethodParameter methodParam = new MethodParameter(method, i); Class<?> type = GenericTypeResolver.resolveParameterType(methodParam, classWrapper.getWrapperedClass()); // 这是某个参数的注解数组 Annotation[] annos = annoss[i]; // 属性名 String name = null; boolean xss = false; ParamSource[] sources = null; // 循环查找某个参数的注解,看看有没有@Param注解,如果找不到就在下面的if中处理了 for (Annotation anno : annos) { ParamType paramType = null; if (anno instanceof Param) { Param p = (Param) anno; paramType = p.type(); name = p.value(); xss = p.XSS(); sources = p.source(); } else { continue; } switch (paramType) { case AUTO: translater = getTranslaterFromType(type); break; case GENERIC: translater = new DefaultParamTranslater(); break; case BEAN: translater = new JavaBeanParamTranslater(); break; case REF: translater = new BeanParamTranslater(); break; case FILE: if (!UploadFile.class.isAssignableFrom(type)) { throw new CannotEnsureTranslateException("FILE型的参数必须是一个org.theonefx.wcframework.mvc.wcweb.UploadFile"); } translater = new FileTranslater(); break; default: throw new CannotEnsureTranslateException("怎么可能?没有指定的参数转换器?我把整个枚举都检查了啊。。。。"); } // 找到一个合适的就退出annotation的遍历 break; } if(sources == null){ sources = new ParamSource[] { ParamSource.REQUEST }; } // 如果没有找到对应的@Param注解,那么就看是不是 if (translater == null) { translater = getTranslaterFromType(type); } translater.setXss(xss); translater.setSources(sources); translater.setName(name); translater.setParamType(type); translater.setMethodParam(methodParam); translater.setAction(this); translaters[i] = translater; try { translaters[i].initialize(); } catch (Exception e) { throw new ParamTranslateException("创建转换器出错:Method=" + method.getName() + " paramType=" + type.getName() + " paramName=" + name); } } } } public ParamTranslatSupport getTranslaterFromType(Class<?> type) { ParamTranslatSupport translater = null; if (type.isPrimitive() || type == String.class || type == Integer.class || type == Short.class || type == Byte.class || type == Long.class || type == Boolean.class || type == Character.class || type == Float.class || type == Double.class) { translater = new DefaultParamTranslater(); } else if (Collection.class.isAssignableFrom(type)) { translater = new CollectionParamTranslater(); } else if (Map.class.isAssignableFrom(type)) { translater = new MapParamTranslater(); } else if (type.isEnum()) { translater = new EnumParamTranslater(); } else if (ServletRequest.class.isAssignableFrom(type)) { translater = new RequestTranslater(); } else if (HttpSession.class.isAssignableFrom(type)) { translater = new SessionTranslater(); } else if (ServletResponse.class.isAssignableFrom(type)) { translater = new ResponseTranslater(); } else if (ServletContext.class.isAssignableFrom(type)) { translater = new ServletContextTranslater(); } else if (ArgsHolder.class.isAssignableFrom(type)) { translater = new ArgsTranslater(); } else if (UploadFile.class.isAssignableFrom(type) || (type.isArray() && UploadFile.class.isAssignableFrom(type.getComponentType()))) { translater = new FileTranslater(); } else if (type.isArray()) { translater = new ArrayParamTranslater(); } else { translater = new JavaBeanParamTranslater(); } return translater; } public void setClassWrapper(ClassWrapper<?> wrapper) { this.classWrapper = wrapper; } }