SpringMVC工作流程

在这里插入图片描述

DispatcherServlet 为 SpringMVC 处理 servlet 的入口.

在 doService 方法中调用 doDispatcher 方法,也就是说业务逻辑主要是在 doDispatcher 中实现.

HandlerMapping 抽象了请求 URL 到请求处理器之间的映射. 当一个请求过来时,DispatcherServlet 会轮询 HandlerMapping 那个请求处理器能处理.

实际上处理请求的是 RequestMappingHandlerMapping 这个类.

HandlerExecutionChain 的字面意思就能够表达清了. 它的概念是 handler 执行的链式结构.

当执行 HandlerExecutionChain handler = hm.getHandler(request); 这段代码后,将调转到 AbstractHandlerMethodMapping.getHandlerInternal 方法.

lookupHandlerMethod 方法返回的是 HandlerMethod 对象. 这个的概念,我理解是类似于反射的机制,用于执行方法.

PS: SpringMVC 的 DispatcherServlet 的设计理念和 OFBiz 关于 Web MVC 的设计很相似,只不过的是 OFBiz 这块的设计是通过 XML 文件实现的,而 Spring MVC 是通过注解实现的. 后续有计划将 OFBiz 有关 XML 的解析替换成注解的方式,来简化工作量.

关于为啥要构造 HandlerExecutionChain 这个对象,是可以在执行实际方法之前,执行某些 HandlerInterceptor.

getHandler 方法会做两步:
1.获取实际的执行方法.
2.构造 HandlerExecutionChain.

经过上面的步骤,我们可以获得 HandlerExecutionChain 对象. 然后进一步的获取 HandlerAdapter 对象.

HandlerAdapter 是啥概念了?HandlerAdapter 是对上面 handler 对象的包装. 或者说 HandlerAdapter 是一个桥梁,承接处理和 ModelView.

然后预执行. 预执行的作用是:比如说我有拦截器,当不满足条件的时候可以跳过. 就不会执行实际的代码.
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

实际执行.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

承接代码执行和 ModelView.
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {

    return handleInternal(request, response, (HandlerMethod) handler);
}

实际执行(调用方法)
invocableMethod.invokeAndHandle(webRequest, mavContainer);

返回结果.
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

返回视图.
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

    modelFactory.updateModel(webRequest, mavContainer);
    if (mavContainer.isRequestHandled()) {
        return null;
    }
    ModelMap model = mavContainer.getModel();
    // ModelAndView: reference to view with name '/login.html'; model is {} 为调试信息.
    ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
    if (!mavContainer.isViewReference()) {
        mav.setView((View) mavContainer.getView());
    }
    if (model instanceof RedirectAttributes) {
        Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        if (request != null) {
            RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
        }
    }
    return mav;
}

处理视图.
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

渲染——感觉 Spring 关于 MVC 的处理逻辑和 OFBiz 非常像,后续在做进一步的验证.
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
View view;
String viewName = mv.getViewName();
if (viewName != null) {
// We need to resolve the view name.
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException(“Could not resolve view with name '” + mv.getViewName() +
“’ in servlet with name '” + getServletName() + “’”);
}
}

    try {
        if (mv.getStatus() != null) {
            response.setStatus(mv.getStatus().value());
        }
        view.render(mv.getModelInternal(), request, response);
    }
    catch (Exception ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
                    getServletName() + "'", ex);
        }
        throw ex;
    }
}

protected final void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

    if (this.exposeSpringMacroHelpers) {
        if (model.containsKey(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE)) {
            throw new ServletException(
                    "Cannot expose bind macro helper '" + SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE +
                    "' because of an existing model object of the same name");
        }
        // Expose RequestContext instance for Spring macros.
        model.put(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE,
                new RequestContext(request, response, getServletContext(), model));
    }

    applyContentType(response);

    renderMergedTemplateModel(model, request, response);
}

补充一点:

Controller 注解和 RequestMapping 注解在哪里被解析的?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值