///* // * Copyright im.longkai@gmail.com // * // * Licensed under the Apache License, Version 2.0 (the "License"); // * you may not use this file except in compliance with the License. // * You may obtain a copy of the License at // * // * http://www.apache.org/licenses/LICENSE-2.0 // * // * Unless required by applicable law or agreed to in writing, software // * distributed under the License is distributed on an "AS IS" BASIS, // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * See the License for the specific language governing permissions and // * limitations under the License. // */ //package common; // //import java.io.IOException; //import java.lang.annotation.Annotation; //import java.lang.reflect.Array; //import java.lang.reflect.Field; //import java.lang.reflect.InvocationTargetException; //import java.lang.reflect.Method; //import java.util.ArrayList; //import java.util.Date; //import java.util.HashMap; //import java.util.HashSet; //import java.util.List; //import java.util.Map; //import java.util.Set; // //import javax.servlet.ServletException; //import javax.servlet.http.HttpServletRequest; //import javax.servlet.http.HttpServletResponse; //import javax.servlet.http.HttpSession; // //import org.jaxen.javabean.JavaBeanXPath; //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; //import org.springframework.web.context.WebApplicationContext; // //import cn.newgxu.bbs.common.util.Util; //import cn.newgxu.ng.core.mvc.annotation.MVCExceptionpHandler; //import cn.newgxu.ng.core.mvc.annotation.MVCHandler; //import cn.newgxu.ng.core.mvc.annotation.MVCMapping; //import cn.newgxu.ng.core.mvc.annotation.MVCParamMapping; //import cn.newgxu.ng.util.StringUtils; //import cn.newgxu.ng.util.WrapperUtils; // ///** // * mvc处理,实际上了spring的bean获得controller。 // * 动态注入参数的时候采用了类似枚举的做法,可以试试下面的那个方法 // * @see java.lang.Class#isAssignableFrom(Class) // * @author longkai // * @since 2013-2-27 // * @version 1.0 // */ //public class MVCProcess { // // private static final Logger L = LoggerFactory // .getLogger(MVCProcess.class); // // /** 处理方法与处理器类名称的映射 */ // private static Map<String, String> handlers; // /** 请求路径与处理器方法的映射 */ // private static Map<String, String> mappedMethods; // /** 处理方法与该方法参数的映射 */ // private static Map<String, Class<?>[]> params; // /** 处理方法的参数 */ // private static Map<String, MVCParamMapping[]> mappedParams; // /** 处理器类与该类所包含异常处理器的映射 */ // private static Map<String, Method[]> exceptionHandlers; // // private static WebApplicationContext context; // // static { // handlers = new HashMap<String, String>(); // mappedMethods = new HashMap<String, String>(); // params = new HashMap<String, Class<?>[]>(); // mappedParams = new HashMap<String, MVCParamMapping[]>(); // exceptionHandlers = new HashMap<String, Method[]>(); // getContext(); // init(); // } // // private static WebApplicationContext getContext() { // if (context == null) { // context = Util.getWebApplicationContext(); // } // return context; // } // // public static void init() { // L.info("控制器初始化!"); // Map<String, Object> ajaxBeans = getContext().getBeansWithAnnotation(MVCHandler.class); // for (String handler : ajaxBeans.keySet()) { // Object obj = ajaxBeans.get(handler); // Method[] methods = obj.getClass().getMethods(); //// 用来暂存异常处理器的索引 // List<Integer> index = null; // for (int i = 0; i < methods.length; i++) { // if (methods[i].isAnnotationPresent(MVCMapping.class)) { // MVCMapping mapping = methods[i].getAnnotation(MVCMapping.class); // String[] paths = mapping.value(); // // for (int j = 0; j < paths.length; j++) { // mappedMethods.put(paths[j], methods[i].getName()); // handlers.put(paths[j], handler); // } // params.put(handler + "." + methods[i].getName(), methods[i].getParameterTypes()); // //// 请求参数注解映射 // Annotation[][] parameterAnnotations = methods[i].getParameterAnnotations(); // MVCParamMapping[] paramMappings = new MVCParamMapping[methods[i].getParameterTypes().length]; // for (int j = 0; j < parameterAnnotations.length; j++) { // for (int k = 0; k < parameterAnnotations[j].length; k++) { // if (parameterAnnotations[j][k].annotationType().equals(MVCParamMapping.class)) { // paramMappings[j] = (MVCParamMapping) parameterAnnotations[j][k]; // } // } // } // mappedParams.put(handler + "." + methods[i].getName(), paramMappings); // // L.info("请求参数映射 方法:{} 映射:{}", methods[i].getName(), paramMappings); // L.info("path:{}, handled by {}' s {} method", paths, // handler, methods[i].getName()); // } //// 暂存异常处理器索引 // if (methods[i].isAnnotationPresent(MVCExceptionpHandler.class)) { // if (index == null) { // index = new ArrayList<Integer>(); // } // index.add(i); // } // } //// 注册异常处理器 // if (index != null) { // Method[] exceptionHanlers = new Method[index.size()]; // for (int i = 0; i < index.size(); i++) { // exceptionHanlers[i] = methods[index.get(i)]; // L.info("控制器:{} 注册异常处理器:{}", handler, methods[i].getName()); // } // exceptionHandlers.put(handler, exceptionHanlers); // } // } // L.info("控制器初始化完成!"); // } // // public static void process(HttpServletRequest request, // HttpServletResponse response) throws ServletException, IOException { // String path = request.getRequestURI(); // // L.info("ajax 请求映射:{} ", path); // // if (mappedMethods.containsKey(path)) { // // 准备启动mvc // Model model = null; // View view = null; // Object controller = null; // // String methodName = mappedMethods.get(path); // String beanName = handlers.get(path); // Class<?>[] paramTypes = params.get(beanName + "." + methodName); // MVCParamMapping[] paramMappings = mappedParams.get(beanName + "." + methodName); // // L.info("控制器名称: {}", beanName); // L.info("方法名:{}", methodName); // // L.info("注入方法参数类型{}", paramTypes); // // controller = context.getBean(beanName); // Object[] injectedParams = new Object[paramTypes.length]; // Map<String, String[]> requestParams = request.getParameterMap(); //// 用set是因为不想在系统注入参数时出现重复注入。 // Set<String> tmpParams = null; // if (paramTypes.length > 0) { // tmpParams = new HashSet<String>(); // } // // for (int j = 0; j < paramTypes.length; j++) { // // TODO: can we inject super class in the future if needed? // L.info("正在注入第{}个参数", j + 1); // L.debug("暂存map:{}", tmpParams); // Class<?> tmpParamType = paramTypes[j]; // if (tmpParamType.equals(HttpServletRequest.class)) { // injectedParams[j] = request; // } else if (tmpParamType.equals(HttpServletResponse.class)) { // injectedParams[j] = response; // } else if (tmpParamType.equals(HttpSession.class)) { // injectedParams[j] = request.getSession(); // } else if (tmpParamType.equals(Model.class)) { //// 注入模型 // model = new Model(request); // injectedParams[j] = model; // } else if (tmpParamType.equals(View.class)) { //// 注入视图 // view = new View(); // injectedParams[j] = view; // } else if (tmpParamType.isPrimitive() || WrapperUtils.isWrapper(tmpParamType) || tmpParamType.equals(Date.class) || tmpParamType.equals(String.class)) { //// 如果是基本类型极其包装器类型 // if (paramMappings[j] != null) { //// if (!paramMappings[j].required()) { //// throw new RuntimeException("@MvcParaming required 已经被废弃!"); //// } // injectedParams[j] = StringUtils.parse(tmpParamType, requestParams.get(paramMappings[j].value())[0]); // L.info("请求参数绑定 key:{}, value: {}", paramMappings[j].value(), injectedParams[j]); // } else { //// 在参数类型不相同的时候可用 // for (String key : requestParams.keySet()) { // Object tmp = null; // if (!tmpParams.contains(key)) { //// 如果暂存set中没有这个的话 // tmp = StringUtils.parse(tmpParamType, requestParams.get(key)[0]); // } // if (tmp != null) { // injectedParams[j] = tmp; // tmpParams.add(key); // break; // } // } // L.warn("系统绑定参数 type: {}, vlaue: {}", tmpParamType.getName(), injectedParams[j]); // } // } else { //// 注入自定义参数 // Class<?> paramType = tmpParamType; // Field[] fields = paramType.getDeclaredFields(); //// Map<String, String[]> requestParams = request.getParameterMap(); // Object obj = null; // try { // obj = paramType.newInstance(); // } catch (InstantiationException e) { // e.printStackTrace(); // } catch (IllegalAccessException e) { // e.printStackTrace(); // } // for (int i = 0; i < fields.length; i++) { // Object field = null; // Object[] arrayField = null; // String fieldName = fields[i].getName(); // if (requestParams.containsKey(fieldName)) { // Class<?> fieldType = fields[i].getType(); // String[] values = requestParams.get(fieldName); //// paramType.getMethod("set" + fields[i].getName(), fieldType).invoke(obj, requestParams.get(fields[i].getName())); // Class<?> arrayType = fieldType.getComponentType(); // if (arrayType == null) { //// 不是数组类型 // field = StringUtils.parse(fieldType, values[0]); // } else { //// 数组类型 // L.debug("数组类型:{},长度:{}", arrayType, values.length); // arrayField = (Object[]) Array.newInstance(arrayType, values.length); // for (int k = 0; k < values.length; k++) { // L.debug("数组参数{}:{}", k, values[k]); // arrayField[k] = StringUtils.parse(arrayType, values[k]); // } // L.debug("array field:{}, field length:{}", arrayField, arrayField.length); // } //// 这里,暂时没有考虑集合类型的注入。so,TODO,collections inject(注意集合类型的初始化)... //// setter... // String setter = StringUtils.setter(fieldName); // L.debug("setter:{}, valuetype: {}, value: {},arrayValue:{}", setter, fieldType, field, arrayField); // try { // Method method = paramType.getMethod(setter, fieldType); // if (arrayField != null) { //// method.invoke(obj, arrayField); //// 不知道为什么,直接调用setter方法对于数组的字段老是抛出type mismatch 或者wrong arg number的异常,不得已用此法。。。 // fields[i].setAccessible(true); // fields[i].set(obj, arrayField); // fields[i].setAccessible(false); // } else { // method.invoke(obj, field); // } // } catch (IllegalArgumentException e) { // e.printStackTrace(); // } catch (SecurityException e) { // e.printStackTrace(); // } catch (IllegalAccessException e) { // e.printStackTrace(); // } catch (InvocationTargetException e) { // e.printStackTrace(); // } catch (NoSuchMethodException e) { // e.printStackTrace(); // } // } // } // injectedParams[j] = obj; // } // } // // Method method = null; // Object result = null; // // invoke it... // try { // method = controller.getClass() // .getMethod(methodName, paramTypes); // result = method.invoke(controller, injectedParams); // } catch (InvocationTargetException e) { //// 处理异常-。-,注意,是捕捉底层调用方法抛出的异常! // Method[] exps = exceptionHandlers.get(beanName); // for (int k = 0; k < exps.length; k++) { // MVCExceptionpHandler mh = exps[k].getAnnotation(MVCExceptionpHandler.class); // Class<?>[] exceptions = mh.value(); // for (int l = 0; l < exceptions.length; l++) { // if (exceptions[l].isAssignableFrom(e.getCause().getClass())) { // try { // exps[k].invoke(controller, e.getCause()); // response.getWriter().write("error"); //// TODO: 给异常返回视图 // return; // } catch (Throwable t) { //// 这时再遇上异常,没办法了-/-,交给全局异常处理。 // globalExceptionHandler(response, t); // } // } // } // } // } catch (Exception e) { //// 其余的索性都一并扔这里了。 // e.printStackTrace(); // } // Class<?> returnType = method.getReturnType(); // if (returnType.equals(String.class)) { // // string, 那视图就是一般的请求(非ajax),返回值代表viewname // if (view == null) { // view = new View(); // } // view.setViewName(result.toString()); // } else if (returnType.equals(View.class)) { // // 直接返回view // view = (View) result; // } else if (returnType.equals(ModelAndView.class)) { // // 返回模型和视图 // ModelAndView mav = (ModelAndView) result; // model = mav.getModel(); // view = mav.getView(); // } else { // L.warn("没有检测到预设的返回类型!"); // // 结束它。 // return; // } // // // 注入模型 // if (model != null) { // if (!model.isInjected()) { // Map<String, Object> map = model.toMap(); // for (String key : map.keySet()) { // request.setAttribute(key, map.get(key)); // } // } // } // // L.info("返回视图:{}", view); // switch (view.getType()) { // // case FREEMARKER: // // request.getRequestDispatcher(view.getViewName()).forward(request, // // response); // // break; // case JSON: // case AJAX: // response.getWriter().write(view.getContent()); // break; // case HTML: // case REDIRECT: // response.sendRedirect(view.getViewName()); // break; // default: // request.getRequestDispatcher(view.getViewName()).forward( // request, response); // break; // } // // // finish it, stop here... // L.info("请求:{} 处理结束...", path); // } else { // throw new RuntimeException("NOT FOUND ACTION!"); // } // // } // //// TODO: 全局异常处理器 // // private static void globalExceptionHandler(HttpServletResponse response, Throwable t) throws IOException { // L.error("系统抛出异常!{}", t); // response.sendRedirect(""); // } // //}