SpringMVC 请求处理

来源:互联网 发布:b2b自动发布软件 编辑:程序博客网 时间:2024/06/02 00:25

转自http://blog.csdn.net/u012420654/article/details/52304594

基本概念

SpringMVC 通过 HandlerAdapterhandler 方法来调用请求处理函数。

在 DispatcherServlet 中根据请求路径利用 Handlermapping 找到对应的 handler 后,首先检查当前 Ioc 容器中所有可用的HandlerAdapter ,再利用 HandlerAdapter 中的 supports 方法找到可以使用的HandlerAdapter

首先来看它的继承关系:

这里写图片描述


内部构造

该接口内部定义了定义了三个方法。

public interface HandlerAdapter {    // 是否支持该 HandlerMethod     boolean supports(Object handler);    // 根据 HandlerMethod 取得 ModelAndView     ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)         throws Exception;    long getLastModified(HttpServletRequest request, Object handler);}

AbstractHandlerMethodAdapter

该类是 HandlerAdapter 接口的简单抽象类,实现了接口定义的方法。

但也并未做真正的实现,而是留给了子类。下面来看它的源码:

public final boolean supports(Object handler) {    return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));}public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response,     Object handler) throws Exception {    return handleInternal(request, response, (HandlerMethod) handler);}public final long getLastModified(HttpServletRequest request, Object handler) {    return getLastModifiedInternal(request, (HandlerMethod) handler);}

RequestMappingHandlerAdapter

该类继承了 AbstractHandlerMethodAdapter 类,真正意义上实现了 HandlerAdapter 接口定义的功能。


1.supportsInternal

默认返回 true,说明只要处理器是 HandlerMethod 类即可

protected boolean supportsInternal(HandlerMethod handlerMethod) {    return true;}

2.getLastModifiedInternal

默认返回 -1.

protected long getLastModifiedInternal(HttpServletRequest request,     HandlerMethod handlerMethod) {    return -1;}

3.handleInternal

该方法负责调用 HandlerMethod(处理器) ,并返回 ModelAndView 。

protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response,     HandlerMethod handlerMethod) throws Exception {    // 1.校验请求    // 检查是否支持当前 rqeuest 的 method 和 session    checkRequest(request);    // 2.判断控制器是否存在 @SessionAttributes 注解    if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {        // 2.1设置缓存        applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);    } else {        // 2.2准备响应        prepareResponse(response);    }    // 默认为 false,为 true 表示在同步块中执行 invokeHandlerMethod    if (this.synchronizeOnSession) {        HttpSession session = request.getSession(false);        if (session != null) {            Object mutex = WebUtils.getSessionMutex(session);            synchronized (mutex) {                return invokeHandlerMethod(request, response, handlerMethod);            }        }    }    // 关键 -> 3.处理器调用    return invokeHandlerMethod(request, response, handlerMethod);}

分析代码,该方法的具体过程如下:

  • 1.校验请求,即检查是否支持当前 rqeuest 的 method 和 session
  • 2.判断控制器是否存在 @SessionAttributes 注解,有则设置缓存,否则准备响应
  • 3.处理器调用,返回 ModelAndView 。

ModelMap

该类继承自 LinkedHashMap,说明它代表一组有序的映射集,用于保存数据。

它的签名如下:

public class ModelMap extends LinkedHashMap<String, Object> 

再来看它的构造函数:

public ModelMap(String attributeName, Object attributeValue) {    addAttribute(attributeName, attributeValue);}public ModelMap addAttribute(String attributeName, Object attributeValue) {    // 存储 <K,V>    put(attributeName, attributeValue);    return this;}

ModelAndView

该类内部保存了 ModelMap 和 View。

private Object view;private ModelMap model;public ModelAndView(String viewName, String modelName, Object modelObject) {    this.view = viewName;    addObject(modelName, modelObject);}public ModelAndView addObject(String attributeName, Object attributeValue) {    getModelMap().addAttribute(attributeName, attributeValue);    return this;}public ModelMap getModelMap() {    if (this.model == null) {        this.model = new ModelMap();    }    return this.model;}

ModelAndViewContainer

该类表示一个容器,不仅包含了 ModelMap 、View 还有其他相关内容。

观察它的成员变量可知:

private Object view;private final ModelMap defaultModel = new BindingAwareModelMap();private ModelMap redirectModel;private final SessionStatus sessionStatus = new SimpleSessionStatus();private boolean redirectModelScenario = false;private boolean ignoreDefaultModelOnRedirect = false;private boolean requestHandled = false;

ServletInvocableHandlerMethod

1.基本概念

该类实现了 HandlerMethod 类,具体继承关系如下:

这里写图片描述

下面来看它的构造函数:

public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) {    super(handlerMethod);    initResponseStatus();}

观察代码,该类的构造函数执行过程如下:

  • 调用父类,即 HandlerMethod 的构造函数 ,将 HandlerMethod 的成员变量赋值给自己的成员变量。

    protected HandlerMethod(HandlerMethod handlerMethod) {    this.bean = handlerMethod.bean;    this.beanFactory = handlerMethod.beanFactory;    this.beanType = handlerMethod.beanType;    this.method = handlerMethod.method;    this.bridgedMethod = handlerMethod.bridgedMethod;    this.parameters = handlerMethod.parameters;    this.resolvedFromHandlerMethod =         handlerMethod.resolvedFromHandlerMethod;}
  • 提取 @ResponseStatus 注解的相关内容赋值给自己的成员变量

    private void initResponseStatus() {    ResponseStatus annotation = getMethodAnnotation(ResponseStatus.class);    if (annotation != null) {        this.responseStatus = annotation.code();        this.responseReason = annotation.reason();    }}

2. invokeAndHandle

关键来看该类的 invokeAndHandle 方法, 它负责调用 HandlerMethod 中控制器的指定方法。

public void invokeAndHandle(ServletWebRequest webRequest,ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {    // 关键 -> 1.执行控制器指定方法    Object returnValue =         invokeForRequest(webRequest, mavContainer, providedArgs);    // 2.设置响应状态    setResponseStatus(webRequest);    // 3.判断请求是否处理完毕,根据返回值来判断。    if (returnValue == null) {        if (isRequestNotModified(webRequest) ||             hasResponseStatus() ||             mavContainer.isRequestHandled()) {            // 为 true ,表示方法调用完毕            mavContainer.setRequestHandled(true);            return;        }    }else if (StringUtils.hasText(this.responseReason)) {        mavContainer.setRequestHandled(true);        return;    }    // 存在返回值时,可能还需进行视图解析    mavContainer.setRequestHandled(false);    try {        // 处理返回值,在 MavContainer 中设置 ViewName        // 并判断其是不是【重定向请求】        this.returnValueHandlers.handleReturnValue(            returnValue,             getReturnValueType(returnValue),             mavContainer,             webRequest);    }catch (Exception ex) {        // 抛出异常...    }}

  • 执行控制器指定方法
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,    Object... providedArgs) throws Exception {    // 省略部分代码...    // 取得方法入参值    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);    // 利用反射执行该方法,并取得返回值    Object returnValue = doInvoke(args);    return returnValue;}protected Object doInvoke(Object... args) throws Exception {    // 设置方法的访问权限,BridgedMethod 表示控制器类的指定方法    ReflectionUtils.makeAccessible(getBridgedMethod());    try {        // 关键 -> 利用反射执行该方法,Bean 表示控制器类名称        return getBridgedMethod().invoke(getBean(), args);    }catch (IllegalArgumentException ex) {        // 抛出异常...    }catch (InvocationTargetException ex) {        // 抛出异常...    }}

处理器调用

接下里分析下 handleInternal 方法中的处理器调用

protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response,     HandlerMethod handlerMethod) throws Exception {    ServletWebRequest webRequest = new ServletWebRequest(request, response);    // 1.数据绑定    WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);    // 2.创建 ModelFactory     // 添加了 @ModelAttribute,@SessionAttributes 等注解内容    ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);    // 3.创建 ServletInvocableHandlerMethod,并绑定相关属性    ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);    invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);    invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);    invocableMethod.setDataBinderFactory(binderFactory);    invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);    // 4.创建 ModelAndViewContainer    ModelAndViewContainer mavContainer = new ModelAndViewContainer();    mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));    modelFactory.initModel(webRequest, mavContainer, invocableMethod);    mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);    // 省略部分源码...    // 5.调用控制器方法    invocableMethod.invokeAndHandle(webRequest, mavContainer);    // 6.返回 ModelAndView    return getModelAndView(mavContainer, modelFactory, webRequest);}

接着来看该类的 getModelAndView 方法:

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,ModelFactory modelFactory,     NativeWebRequest webRequest) throws Exception {    // 更新 Mdoel     modelFactory.updateModel(webRequest, mavContainer);    // 判断请求是否处理器完毕    if (mavContainer.isRequestHandled()) {        return null;    }    // 关键 -> 创建 ModelAndView    ModelMap model = mavContainer.getModel();    ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);    // 判断 view 是不是字符串    if (!mavContainer.isViewReference()) {        mav.setView((View) mavContainer.getView());    }    // 重定向相关    if (model instanceof RedirectAttributes) {        Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);        RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);    }    return mav;}

总结

下面来看 HandlerAdapter 的工作流程图:

这里写图片描述


原创粉丝点击