胡诌Spring MVC

Struts一样,Spring MVC框架中同样分为前端控制器和后端控制器,其可以用如下图简单描述,Spring MVC的前端控制器DispatcherServlet负责初始化所需的资源和处理整个请求的工作流程(Struts中为ActionServlet),接收并处理符合一定规则http请求,例如 /springmvc/*等(在web.xml文件中配置),同时将http请求负责给后端控制器,目前默认后端控制器主要有Controller HttpRequestHandlerThrowawayController,其中以Controller为主。

 

 

Spring MVC的处理过程大致如下:

 

http请求---à根据handlerMappings解析url---à找到最精确匹配的mappedHandlerHandlerExecutionChain类型,该类型其实是封装了Handler和拦截器)-à执行拦截器的preHandle方法--à获得HandlerAdapter,并通过Adapter模式调用Handlerhandlerhandle方法(此处非常关键,其实就是执行Controller),并返回ModelAndView对象---à执行拦截器的postHandle方法--à渲染试图--à渲染拦截器的afterCompletion方法。

 

在此至少能学到做框架设计四个非常重要的方

1、      Framework其实我们也可以写---------规范了处理流程,提供常用的功能实现

一个技术架构之所以成为框架,我个人认为首先应该明确整个处理的工作流程,也就是定下规则,当然这里需要用到大量的接口编程,使得以后的程序员可以扩展,更重要的是,以后具体实现功能可以不一样(例如同样是渲染到视图上,有的是采用jsp,有的采用freemarker等),当然框架要定义自己默认的一些实现(例如Spring MVCController就提供了很多现成的实现,包括UrlFilenameViewController MultiActionController等,当然实际的项目中,我们要写更多自己的Controller实现)。

2、  代码可以更优雅---------设计模式

一个好的框架,尤其是Spring这样优秀的框架,里面用到了大量的设计模式(对于设计模式,可能对于初学者有点怵头,其实我个人认为设计模式就是处理一类事情的思路,当然这些需要经过适当的抽象和精炼,所以设计模式在我们没有接触编程语言之前就会了一些,有些人就习惯把事情搞复杂  ^_^),在此简单介绍一种Adapter模式(当然上面的第一点,我们又可以认为用到了模板设计模式),

上面的过程已经定义了我们用Spring MVC处理一件事情的流程,但是具体做什么事情是由我们的业务系统解决的。还一句话说,具体做什么,需要我们程序员根据系统的需要自己来处理(在此不涉及DAOBO层),在Spring MVC中更多是写自己的Controller(就像Struts中的Action),

还是简单介绍一下Adapter,我们举一个不太精准的例子,假如我的某电器只接受的是38V的电压,而我们常用的是220V的民用电,如何才能在220V的电压上用我38V的电器? 非常简单,找一个变压器,这就用到了Adapter设计模式,如果我已经有两个现成功能的对象,但不想改变继承关系,我们需要做一个适配器(Spring MVC在此用到了HandlerAdapter适配器)。

我们先看下面两个接口,Controller是我们自己要实现的接口

public interface Controller {

         ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;

 

}

 

HandlerAdapter

public interface HandlerAdapter {

         boolean supports(Object handler);

         ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

         long getLastModified(HttpServletRequest request, Object handler);

}

如果我们想办法让执行handle方法的时候去调用Controller中的handleRequest方法,一切搞定。

Spring MVC默认为为我们提供了三种HandlerAdapter实现,分别为org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,

org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,

org.springframework.web.servlet.mvc.throwaway.ThrowawayControllerHandlerAdapte

(在DispatcherServlet.properties中配置)

以我们系统中常用的Controller为例:

public class SimpleControllerHandlerAdapter implements HandlerAdapter {

         public boolean supports(Object handler) {

                   return (handler instanceof Controller);

         }

         public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)

                            throws Exception {

                   return ((Controller) handler).handleRequest(request, response);

         }

         public long getLastModified(HttpServletRequest request, Object handler) {

                   if (handler instanceof LastModified) {

                            return ((LastModified) handler).getLastModified(request);

                   }

                   return -1L;

         }

 

}

经过上面的描述,我们只要去实现Controller接口(更多的时候,我们继承AbstractController抽象类更合适,在第三点介绍),剩下的DispatcherServlet都帮我们搞定了。

3、  我的地盘我做主-----------开放-封闭原则

我们在来看一下Controller接口

public interface Controller {

         ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;

}

所有的类,只要实现handleRequest方法即可,可在描述第二点的时候,我推荐继承AbstractController抽象类,那么我们研究一下AbstractController,很奇怪的是我们看到

handleRequest方法被final所修饰,意味着我们的子类没有办法来覆写该方法,好像和上面说的有一些矛盾。

public final ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)

           throws Exception {

       checkAndPrepare(request, response, this instanceof LastModified);

       if (this.synchronizeOnSession) {

           HttpSession session = request.getSession(false);

           if (session != null) {

              Object mutex = WebUtils.getSessionMutex(session);

              synchronized (mutex) {

                  return handleRequestInternal(request, response);

              }

           }

       }

       return handleRequestInternal(request, response);

    }

其实AbstractController已经偷梁换柱了,给我们提供了如下的抽象方法

protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)

        throws Exception;

回过头来仔细想想,同样都是处理HTTP请求,如果我们要设置HTTP缓存时间?设置允许请求的方法(常用的GETPOST)?是否要在我们每个Controller子类中来设置?Spring MVC在此良苦用心,在AbstractController中都为我们处理好了。一方面在handleRequest中规定了处理流程,使得以后的程序员(尤其是不知道内情的程序员)不能更改,我们把它叫封闭原则,另一方面我们给以后的程序员提供了扩展的地方,在这里就是覆写handleRequestInternal方法。当然在此如果还不清楚的话,我们举一个通俗的例子:如果要做一盘醋溜白菜,为了更可口一点,我们知道最后要勾点芡,如果是一个不会做菜的人,一刚开始就放勾好的芡,那就坏了,换句话说,如果做一件事的业务逻辑非常重要,撒开手交给别人做,可能就出问题,如果我们把业务逻辑规定好,出错的概率就小多了,在这里封闭就体现必须在将勾芡放在最后一步,扩展体现在你可以用圆白菜,也可以用大白菜,业务需要(或者个人喜好)由你自己决定。

4、  术业有专攻,做你自己擅长的

“不重复发明轮子”这句话对我影响比较深,一方面说明不重复投资,另一方面其实也说明术业有专攻,在这一点Spring发挥到了极致,到处用成熟的框架,例如封装Hibernate、封装Quartz等,这些框架本身很成熟,Spring团队没有必要重新搞一套,除非是吃饱了撑的。在这里我要说明的是Spring MVC中将返回什么内容和怎么显示返回的内容两者分开,前者是业务逻辑决定的,后者是纯视图技术(可以用jspPDFexcel等),Spring MVC抽象出一个View接口,专门用于视图显示。

public interface View {

    String getContentType();

   void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception;

 

}

Spring MVC除了抛出一个View规范之外,还有非常多的默认实现,包括JstlViewTilesViewXsltViewImageViewAbstractPdfViewAbstractExcelView等,让我们熟悉不同视图技术的工程师对Spring MVC折服之余,也让我们以后写代码、做项目多了几分从容。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值