8.Spring MVC重要组件概述

       这里说的组件指的是DispatcherServlet中直接初始化的那9个组件;

HandlerMapping

       HandlerMapping的作用是根据request找到相应的处理器Handler和Interceptors;

       HandlerMapping接口里面只有一个方法,方法的实现非常灵活,只要使用Request返回HandlerExecutionChain即可;

       你可以把HandlerExecutionChain看做是Handler+Interceptors;

HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

       HandlerMapping需要注册到Spring MVC的容器里面才可以使用,注册也很简单,只需要在配置文件里面配置一个Bean就可以了,Spring MVC会按照类型将它注册到HandlerMapping中;


       可能有多个HandlerMapping可以处理同个url,可以用order标注优先级,order越小越先使用;

       查找Handler是按顺序遍历所有的HandlerMapping,当找到一个HandlerMapping后立即停止查找并返回;

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping hm : this.handlerMappings) {
				......
				HandlerExecutionChain handler = hm.getHandler(request);
				if (handler != null) {
					return handler;    //立即返回
				}
			}
		}
		return null;
}

HandlerAdapter

       可以理解为使用Handler的人;它里面共有三个方法,

       supports(Object handler)判断是否可以使用某个Handler;

       handler方法是用来具体使用Handler干活的;

       getLastModified是获取资源的Last-Modified,Last-Modified是资源最后一次修改的时间;

public interface HandlerAdapter {
    boolean supports(Object handler);   //注意:是Object类型
    ModeAndView handle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception;
    long getLastModified(HttpServletRequest request,Object handler); 
}

      之所以要使用HandlerAdapter是因为Spring MVC中并没有对Handler做任何限制,Handler可以以任意合理的方式来实现,可以是个类,也可以是个方法,还可以是别的合理的形式;从supports方法的参数是Object类型就可以看出这一点;

//这是Spring MVC自带的HandlerAdapter
public class SimpleControllerHandlerAdapter implements HandlerAdapter {

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof Controller);   //实现了Controller接口的Handler
	}

	@Override
	@Nullable
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
                //直接调用handleRequest方法
		return ((Controller) handler).handleRequest(request, response);
	}

	@Override
	public long getLastModified(HttpServletRequest request, Object handler) {
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}
}

       选择使用哪个HandlerAdapter的过程在getHandlerAdapter方法中,它的逻辑是遍历所有的Adapter,然后检查哪个可以处理当前的Handler,找到第一个可以处理Handler的Adapter后就停止查找并将其返回;既然查找,那肯定有个顺序,这顺序也是通过Order属性来设置的;

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
      if (this.handlerAdapters != null) {
		for (HandlerAdapter ha : this.handlerAdapters) {
			......
			if (ha.supports(handler)) {
				return ha;
			}
		}
       }
       throw new ServletException("No adapter for handler [" + handler +
			"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

      HandlerAdapter需要注册到Spring MVC的容器里,注册方法和HandlerMapping一样,只要配置一个Bean就可以了;Handler是从HandlerMapping里返回的;

HandlerExceptionResolver

       处理异常,根据异常设置ModelAndView,之后再交给render方法进行渲染;render只负责将ModelAndView渲染成页面,具体ModelAndView从哪里来的不重要;

        从doDispatcher的分析可以知道,HandlerExceptionResolver只是用于解析对请求做处理的过程中产生的异常,而渲染环节产生的异常不归它管,现在我们知道原因了:它是在render之前工作的,先解析出ModelAndView之后render才去渲染,当然它就不能处理render过程中的异常了;

public interface HandlerExceptionResolver {
        //异常--> ModelAndView
	@Nullable
	ModelAndView resolveException(
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);

}

       具体实现上,维护一个异常为key,View为value的Map,解析的时候直接从Map里获取View就可以了,如果在Map里没有相应的异常可以返回默认的View;我们可以在这个View上显示一些关于错误的细节;

ViewResolver

       ViewResolver将String类型的视图名和Locale解析为View;

public interface ViewResolver {
        //视图名和Locale,不过一般情况下,只需要根据视图名找到对应的视图,然后渲染就行了
        //locale,是用来达到,不同地区使用不同的View,一般用不到
	@Nullable
	View resolveViewName(String viewName, Locale locale) throws Exception;

}

ViewResolver的使用需要注册到Spring MVC的容器中,默认使用的是org.spring.framework.web.servlet.view.InternalResourceViewResolver;

RequestToViewNameTranslator

       ViewResolver是根据ViewName查找View,但有的Handler处理完成之后并没有设置View也没有设置viewName,这时就需要从request中获取viewName,而如何从request中获取ViewName就是RequestToViewNameTranslator要做的事情;

public interface RequestToViewNameTranslator {
     String getViewName(HttpServletRequest request) throws Exception;
}


FlashMapManager

          FlashMap主要用在redirect中传递参数,而FlashMapManager是用来管理FlashMap的;

public interface FlashMapManager {
        //恢复参数,并将恢复过额度和超时的参数从FlashMap中删除
	@Nullable
	FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
	//将参数保存起来
	void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}

          默认实现是SessionFlashMapManager,它是将参数保存到session中;


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值