Spring:MVC原理

1、处理流程和核心组件

1.1 处理流程

    Spring MVC大致的处理流程:

这里写图片描述

    流程简述:

  1. 用户发送请求至前端控制器DispatcherServlet;
  2. 前端控制器DispatcherServlet收到请求后调用处理器映射器HandlerMapping;
  3. 处理器映射器HandlerMapping根据请求的URL找到具体的处理器,生成处理器对象Handler及处理器拦截器HandlerIntercepter(如果有则生成),一并返回给前端控制器DispatcherServlet。
  4. 前端控制器DispatcherServlet通过处理器适配器HandlerAdapter调用处理器Controller。
  5. 执行处理器Handler(Controller);
  6. 处理器Controller执行完后返回ModelAndView;
  7. 处理器映射器HandlerAdapter将处理器Controller执行返回的结果ModelAndView返回给前端控制器DispatcherServlet;
  8. 前端控制器DispatcherServlet将ModelAndView传给视图解析器ViewResolver;
  9. 视图解析器ViewResolver解析后返回具体的视图View;
  10. 前端控制器DispatcherServlet对视图View进行渲染视图(即:将模型数据填充至视图中);
  11. 前端控制器DispatcherServlet响应用户。

1.2 核心组件概览

    以核心组件为主的简化流程图:

    核心组件:

  • DispatcherServlet:Spring MVC中的前端控制器(Front Controller),负责接收Request并将Request转发给对应的处理组件;
  • HandlerMapping:Spring MVC中完成URL到Controller映射的组件。DispatcherServlet接收Request,然后从HandlerMapping中根据URL查找处理Request的HandlerAdapter;
  • Controller:是Spring MVC中负责处理Request的组件,处理Request并返回ModelAndView对象;
  • ModelAndView:封装结果视图的组件。视图解析器解析ModelAndView并将视图返回给客户端。

2、主要组件

2.1 HandlerMapping

    HandlerMapping是用来查找处理器Handler的。Handler可以是类,也可以是方法,比如标注了RequestMapping的每个方法都可以看成一个Handler。Hanlder负责实际的请求处理,在请求到达之后,HandlerMapping的作用是找到请求相应的处理器Hanlder和Interceptor。

2.2 HandlerAdapter

    HandlerAdapter是一个适配器。因为Spring MVC中的Handler可以是任意形式的,但是把请求交给Servlet的时候,由于Servlet的方法结构都是doService(HttpServletRequest request, HttpServletResponse response)形式,要让固定的Servlet处理方法调用Handler来进行处理,这一步工作就是Handler要做的事情。

2.3 HandlerExceptionResolver

    HandlerExceptionResolver是用来处理Handler产生的异常情况的组件。组件根据异常设置ModelAndView,然后交给渲染方法进行渲染,渲染方法会将ModelAndView渲染成页面。

    需要注意的是,HandlerExceptionHandler只用于解析对请求做处理阶段的异常,不负责渲染阶段的异常。

2.4 ViewResolver

    ViewResolver是视图解析器。通常在Spring MVC的配置文件中,都会配上一个实现类来进行视图解析。这个组件主要的作用是将String类型的视图名称和LocaleView类型的视图,只有一个resolveViewName()方法,用于将Controller层返回的String类型的视图名viewName解析成View。

    View是用来渲染页面的,它会将程序返回的参数和数据填入模板中,生成HTML文件。ViewResolver在这个过程中主要做两件大事:

  1. 找到渲染所用的模板;
  2. 找到渲染所用的技术,即视图的类型,例如JSP,并填入参数。

2.5 RequestToViewNameTranslator

    RequestToViewNameTranslator组件的作用是从请求中获取ViewName。因为ViewResolver根据ViewName查找View,但是有的Handler处理完成之后,没有设置View,也没有设置ViewName,就需要通过这个组件来从请求中查找ViewName。

2.6 LocaleResolver

    ViewResolver的resolveViewName()方法需要两个参数,一个是视图名,另一个就是Locale。

    LocaleResolver用于从请求中解析出Locale,比如在中国,Locale就是zh-CN,用来表示一个区域。

2.7 ThemeResolver

    ThemeResolver是用来解析主题的组件。主题就是样式、图片以及它们形成的显示效果的集合。Spring MVC的一套主题对应一个properties文件,里面存放着与当前主题相关的所有资源,如图片、CSS样式等。

    创建主题只需要准备好资源,然后创建一个“主题名.properties”并将资源设置进去,放在classpath下,之后就可以在页面中使用了。

    Spring MVC中与主题名有关的类:

  • ThemeResolver:负责从请求中解析出主题名;
  • ThemeSource:负责根据主题名找到具体的主题;
  • Theme:主题的抽象,可以通过Theme来获取主题和具体的资源。

2.8 MultipartResolver

    MultipartResolver用于处理上传请求,通过将普通请求包装成MultiHttpServletRequest,使普通请求拥有文件上传的功能。MultiHttpServletRequest可以通过getFile()方法直接获得文件。如果上传多个文件,还可以调用getFileMap()方法得到Map<FileName, File>这种结构。

2.9 FlashMapManager

    FlashMapManager就是用来管理FlashMap的。

    FlashMap用于重定向时的参数传递,比如在处理用户订单时,为了避免重复提交,可以处理完post请求后重定向到一个get请求,这个get请求可以用来显示订单详情之类的信息。这个页面上要显示的订单的信息,可以通过FlashMap来传递。只需要在重定向前将要传递的数据写入到请求的属性OUTPUT_FLASH_MAP_ATTRIBUTE中,这样在重定向之后的Handler中Spring就会自动将其设置到Model中,在显示订单信息的页面上就可以直接从Model中获得数据。

3、处理流程详解

    Spring MVC的处理过程可以分为三步:

  1. ApplicationContext初始化时用Map保存所有URL和Controller类的对应关系;
  2. 根据请求URL找到对应的Controller,并从Controller中找到处理请求的方法;
  3. 将Request参数绑定到方法的形参上,执行方法处理请求,并返回结果视图。

3.1 初始化阶段

    在DispatcherServlet中调用父类HttpServletBean的init()方法,执行初始化。初始化要做的事情:

  1. 初始化IoC容器:调用refresh()方法初始化IoC容器;
  2. 初始化组件:初始化IoC容器之后,又会调用onRefresh()方法,执行九大组件的初始化;
  3. 建立URL和Controller的映射关系:通过HandlerMapping的子类AbstractDetectingUrlHandlerMapping实现的initApplicationContext()方法实现。方法中会遍历所有的Bean,遍历所有的Controller上的URL和方法上的URL,并存储为Map<String [] urls, String beanName>的映射关系。

3.2 运行阶段

    运行调用是由请求触发的,所以入口为DispatcherServlet的核心方法doService(),doService()的核心是由doDispatch()实现的。任务执行流程:

  1. 检查是否是文件上传的请求;
  2. 取得处理当前请求的Controller,实际上取到的是封装了Handler(Controller)和Interceptor的HandlerExecutionChain对象;
  3. 将请求参数映射成Controller中相应方法的入参;
  4. 根据Handler实例获取HandlerAdapter实例;
  5. 通过HandlerAdapter实例调用相应的Handler,并返回结果视图对象;
  6. 结果视图对象处理,并返回处理结果。

    对于将请求参数映射成Controller中相应方法的入参,Spring MVC提供了两种参数绑定的方式:

  1. 通过注解进行绑定:@RequestParam("paramName");
  2. 通过参数名进行绑定。

    由于Java反射只提供了获取方法参数类型的方法,而并没有提供获取参数名的方法,所以Spring MVC使用asm框架读取字节码,来获取方法的参数名。个人建议使用通过参数进行绑定的方式,这样可以省去asm框架读取字节码的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值