很多时候,为什么感觉一本书很难啃,俩字,抽象,所谓的抽象,不过是自己对这些概念不甚理解,本来程序 软件设计的东西就是从现实里抽取的,大不了我们还原到里面就是。
在这里,我拿去饭店吃饭做比,当http这个客人受到前台的接待,前台会根据你的请求将房间号的包间给你,你过去,这个包间就是一个servlet,然后通过菜单点菜,菜单就是servlet里方法的注解,映射了每道菜制作的过程,无须对展示层展示,只需要客人看到最终的菜肴即可,这样也就达到了隔离安全的效果,餐桌就是一个模板,每个不同的请求返回的结果可以在这个模板里集中展示,modelandview与view解析器也派上用场了。
再仔细的分解这个过程,当http受接待的时候,会受到这个饭店的配置限制吧,也就是你的web.xml就要设置为此饭店,也就是容器了,当你进入饭店的时候,拦截处理,往往会确认一下你是否预定等一些事宜,这里拿Struts2的dispatcher来说明,通过对这些请求进行预处理,这里是PrepareOperations的对象来处理的,其实其也就是个代理对象,正儿八经实现的还是dispatcher本身,由其进行转发处理,这里就别贴源码了,可以自己打开ide自己追着看,想想前台服务员是不是可以各种换,然后其执行的任务是不是始终都一样,通过对客人提供的信息进行处理封装,就像房间号和你放在一个Map中一样,同样,也可以在这里看到Struts和XWork融合的地方,就是dispatcher的serviceAction方法可以看到这里是是Dispatcher对象的核心逻辑调度方法,起到了中转站的作用
* @since 2.3.17 */ public void serviceAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException { Map<String, Object> extraContext = createContextMap(request, response, mapping); // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); boolean nullStack = stack == null; if (nullStack) { ActionContext ctx = ActionContext.getContext(); if (ctx != null) { stack = ctx.getValueStack(); } } if (stack != null) { extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack)); } String timerKey = "Handling request from Dispatcher"; try { UtilTimerStack.push(timerKey); String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod(); ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, extraContext, true, false); request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack()); // if the ActionMapping says to go straight to a result, do it! if (mapping.getResult() != null) { Result result = mapping.getResult(); result.execute(proxy.getInvocation()); } else { proxy.execute(); } // If there was a previous value stack then set it back onto the request if (!nullStack) { request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); } } catch (ConfigurationException e) { logConfigurationException(request, e); sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e); } catch (Exception e) { if (handleException || devMode) { sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e); } else { throw new ServletException(e); } } finally { UtilTimerStack.pop(timerKey); } }
同样,我们也会看到里面有几个cleanup的方法,在客人吃完饭,需要清理残局的时候,又要麻烦dispatcher这个调度器了,拿到框架里就是对这个事件的生命周期里框架元素的清理(总会有不少残余的存在)。
同样,对于我们这拨人去饭店吃饭这个流程,中间所设计的各个小事件,比如点菜,一些突发事件的特别服务等会在大伙入门登记的那一刻起已经绑在一条线程上了,对于框架里 也就是ThreadLocal,当我们付完款离开的时候,那个账单也就没多大用了,留个日志就可以撇过一边了,程序里就是销毁。
再分析,当我们点菜之后,菜单交给服务员,服务员交给后厨,后厨做完饭菜给服务员,服务员上菜,其实这里面就涉及了一个责任链的模式,关于菜单,还涉及到一个模式,就是构造模式,饭店根据季节和自己的优势来设计菜单,然后由厨子来实现,而客人呢只需要点菜就可以了。
当我们消费多少之后,往往饭店会打折或者送东西,这就是涉及到了一个策略的模式,一个接口下有不同的策略实现,减100还是更大力度等等
有时候我们会遇到很奇葩的事情,就是一个菜品,就比如一盘黄瓜,往往会有一个特别高大上的名字,然后一个名字就把这盘黄瓜的身价给提升了,看看装饰模式是多么值钱。。。
看到了吧,一个菜单都有这么多的学问,在这里这个层面的注解包含房间号 菜名,类注解假如写房间号,方法只写菜名就成,否则每道菜都得加房间号,具体就按照自己的想法来就成
可见一个框架的实现其实也就那些东西,各种离不开ThreadLocal模式 装饰模式 策略模式 构造模式 责任链模式 调度器等,源码来源于生活,读源码的时候多多联系实际,理解好了,敲嘛,也就那回事儿了
下一篇,就总结下注解就成