`
ganqing1234
  • 浏览: 171687 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

公司源码分析之contoller架构spring

阅读更多

公司采用的是spring的mvc架构,但是做了很多改动。spring mvc架构本身提供了几种从url映射contrller的方法。常用的如:SimpleUrlHandlerMapping等。公司的mvc架构在SimpleUrlHandlerMapping基础上做了一层封装。前台不论什么url都会映射到同一个contrller上,然后通过java反射机制来调用具体的处理方法,然后返回相应的ModelAndView。

genericController中的关键代码如下:

protected ModelAndView _handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

        request.setCharacterEncoding("UTF-8");

        String methodName = this.methodNameResolver.getHandlerMethodName(request);

        String moduleName = (String) request.getAttribute(BaseUtils.PARAMNAME + "0");

        ModelAndView mav = controllerProcess.invoke(moduleName, methodName, request, response);

        return mav;
    }

 其中methodName为函数名,modelName为模块类名。例如一个请求是以/console.login.do结尾,methodName就为login,moduleName为console,这样根据Java反射机制就会去调用ConsoleController.java里面的login方法来处理这个请求。这个处理过程很复杂,公司的代码写的很乱,很多函数现在都已不使用。

 

首先有一个properties文件保存modelName到具体controller的映射关系。

appservice=com.wiscom.ccs.web.controller.AppserviceController
reader=com.wiscom.ccs.web.controller.ReaderController
vote=com.wiscom.ccs.web.controller.VoteController
csh=com.wiscom.ccs.web.controller.CSHDateController

  程序中得到这样的关系放到map中。然后

private void loadBeanHandlersFromProperties() {
        //从propertyies文件得到映射关系
        Map map = getPropertiesFromConfigs(this.controllerConfigFiles);
        //得到key的迭代器
        Iterator it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            String cname = (String) map.get(key);
            log.info("load web handler:" + key + "=" + cname);
            try {
                Class clazz = Class.forName(cname);
                BeanHandler bh = new BeanHandler();
                bh.setClassz(clazz);
                try {
                   // 实例化
                    Object obj = BeanUtils.instantiateClass(clazz);
                    bh.setValue(obj);
                    this.beanHandlerMap.put(key, obj);
                } catch (Throwable e) {
                    log.error("create '" + clazz.getName() + "' error!");
                    log.error(e.getMessage(), e);
                    continue;
                }
                //结果保存在map中
                beanHandlers.add(bh);
            } catch (ClassNotFoundException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

  然后根据得到的modelName从map中得到相应的object。然后来查找methodName:

...
Method[] methods = obj.getClass().getMethods();

        for (int i = 0; i < methods.length; i++) {
            Method _method = methods[i];
            // log.debug("methods:" + _method.getName());
            Class returnType = _method.getReturnType();
            // log.debug("return class:" + returnType);
            if (ModelAndView.class.equals(returnType) || Map.class.equals(returnType)
                    || ModelAndMethod.class.equals(returnType)) {
                // 找到方法
                if (_method.getName().equals(methodName)) {
                    method = _method;
                    break;
                }
            }
        }
...

  然后得到params并执行,拿参数这段很长:

            List params = new ArrayList();
            Class[] classes = method.getParameterTypes();
            int paramLen = classes.length;
            BindException be = null;
            for (int i = 0; i < paramLen; i++) {
                // 一般参数类型都是下面几种主要的
                if (classes[i].equals(HttpServletRequest.class)) {
                    params.add(request);
                } else if (classes[i].equals(HttpServletResponse.class)) {
                    params.add(response);
                } else if (classes[i].equals(HttpSession.class)) {
                    params.add(getHttpSession(request, response));
                } else if (classes[i].equals(WebInput.class)) {
                    params.add(new WebInput(request));
                } else if (classes[i].equals(FileWebInput.class)) {
                    params.add(new FileWebInput(request));
                } else if (classes[i].equals(WebOutput.class)) {
                    params.add(new WebOutput(request, response));
                } else if (classes[i].equals(ApplicationContext.class)) {
                    params.add(this.getApplicationContext());
                } else {
                    // 其他类型去spring context里拿
                    Object resultObject = null;
                    if (beanParameterHandlers != null && beanParameterHandlers.size() > 0) {
                        Iterator it = beanParameterHandlers.iterator();
                        while (it.hasNext()) {
                            BeanHandler bh = (BeanHandler) it.next();
                            if (classes[i].equals(bh.getClassz())) {
                                if (bh.getName() != null) {
                                    String bname = bh.getName();
                                    resultObject = this.getApplicationContext().getBean(bname);
                                } else {
                                    resultObject = bh.getValue();
                                }
                                if (resultObject instanceof BeanHandlerFactory) {
                                    try {
                                        resultObject = ((BeanHandlerFactory) resultObject).getValue(request, response);
                                    } catch (ModelAndViewDefiningException e) {
                                        return e.getModelAndView();
                                    } catch (Throwable ex) {
                                        log.error(ex.getMessage(), ex);
                                        return handleException(request, response, ex);
                                    }
                                }
                                break;
                            }

                        }
                    }

                    if (resultObject != null) {
                        params.add(resultObject);
                    } else {
                        // 还没有就直接实例化生成, 这里的是需要绑定的command类                        
                        Object command = newCommandObject(classes[i]);
                        try {
                            bind(request, command);
                            params.add(command);
                        } catch (BindException _be) {
                            be = _be;
                            params.add(null);
                        }
                    }
                }
            }

            if (be != null) {
                if (classes[paramLen - 1].equals(BindException.class)) {
                    params.add(be);
                } else {
                    throw new ServletRequestBindingException("Errors binding onto object '" + be.getObjectName() + "'",
                            be);
                }
            }
            // 执行
            Object returnValue = method.invoke(obj, params.toArray(new Object[params.size()]));
 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics