ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Spring MVC组件源码分析

2019-08-01 11:58:17  阅读:184  来源: 互联网

标签:HttpServletRequest String Spring request 视图 public MVC null 源码


组件概览

HandlerMapping

根据 request 找到对应的处理器 Handler 和 Interceptors。内部只有一个方法

HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

HandlerAdapter

Handler 适配器,内部方法如下:

boolean supports(Object handler);//判断是否可以使用某个 Handler
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; //具体使用
long getLastModified(HttpServletRequest request, Object handler);//获取资源上一次修改的时间

HandlerExceptionResolver

根据异常设置 ModelAndView ,再交给 render 方法进行渲染。

ModelAndView resolveException(
            HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex)

ViewResolver

用来将 String 类型的视图名和 Locale 解析为 View 类型的视图。

View resolveViewName(String viewName, Locale locale) throws Exception;

它的一个实现类 BeanNameViewResolver,它重写 resolveViewName 方法如下:

public View resolveViewName(String viewName, Locale locale) throws BeansException {
        ApplicationContext context = getApplicationContext();
        //如果应用上下文没有找到视图,返回 null
        if (!context.containsBean(viewName)) {
            if (logger.isDebugEnabled()) {
                logger.debug("No matching bean found for view name '" + viewName + "'");
            }
            // Allow for ViewResolver chaining...
            return null;
        }
        //如果找到的视图类型不匹配,也返回 null
        if (!context.isTypeMatch(viewName, View.class)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Found matching bean for view name '" + viewName +
                        "' - to be ignored since it does not implement View");
            }
            // Since we're looking into the general ApplicationContext here,
            // let's accept this as a non-match and allow for chaining as well...
            return null;
        }
        //根据视图名称从 Spring 容器中查找 Bean,返回找到的 bean
        return context.getBean(viewName, View.class);
    }

RequestToViewNameTranslator

获取 request 中的视图名。接口里面也是只有一个方法:

String getViewName(HttpServletRequest request) throws Exception; //根据 request 查找视图名

LocaleResolver

用于从 request 解析出 Locale。

public interface LocaleResolver {
    //从 request 解析出 Locale
    Locale resolveLocale(HttpServletRequest request);
    //根据 request 设置  locale
    void setLocale(HttpServletRequest request, HttpServletResponse response, @Nullable Locale locale);
}

ThemeResolver

解析主题

public interface ThemeResolver {
    //通过给定的 request 查找主题名
    String resolveThemeName(HttpServletRequest request);
    //根据给定的 request 设置主题名
    void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}

在 RequestContext.java 文件中可以获取主题:

public String getThemeMessage(String code, String defaultMessage) {
        //获取主题的信息
        return getTheme().getMessageSource().getMessage(code, null, defaultMessage, this.locale);
    }

public Theme getTheme() {
        //判断主题是否为空
        if (this.theme == null) {
            // 通过 RequestContextUtils 获取 request 中的主题名
            this.theme = RequestContextUtils.getTheme(this.request);
            if (this.theme == null) {   //如果还是为空的话
                //那就是没有有效的主题解析器和主题
                this.theme = getFallbackTheme();
            }
        }
        return this.theme;
    }

RequestContextUtils.getTheme() 方法:

public static Theme getTheme(HttpServletRequest request) {
        ThemeResolver themeResolver = getThemeResolver(request);
        ThemeSource themeSource = getThemeSource(request);
        if (themeResolver != null && themeSource != null) {
            String themeName = themeResolver.resolveThemeName(request);
            return themeSource.getTheme(themeName);
        }
        else {
            return null;
        }
    }

MultipartResolver

用于处理上传请求,处理方法:将普通的 request 包装成 MultipartHttpServletRequest

public interface MultipartResolver {
    //根据 request 判断是否是上传请求
    boolean isMultipart(HttpServletRequest request);
    //将 request 包装成 MultipartHttpServletRequest
    MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;
    //清理上传过程中产生的临时资源
    void cleanupMultipart(MultipartHttpServletRequest request);
}

FlashMapManager

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

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

小结

介绍 Spring MVC 中九大组件的接口、作用、内部方法实现及作用进行了简单的介绍,详细的还需大家自己去看源码。

总结

Spring MVC 原理总结

本质是一个 Servlet,这个 Servlet 继承自 HttpServlet。Spring MVC 中提供了三个层次的 Servlet:HttpServletBean、FrameworkServlet 和 DispatcherServlet。他们相互继承, HttpServletBean 直接继承自 Java 的 HttpServlet。HttpServletBean 用于将 Servlet 中的 Servlet 中配置的参数设置到相应的属性中,FrameworkServlet 初始化了 Spring MVC 中所使用的 WebApplicationContext,具体处理请求的 9 大组件是在 DispatcherServlet 中初始化的,整个继承图如下:

Spring MVC组件源码分析

标签:HttpServletRequest,String,Spring,request,视图,public,MVC,null,源码
来源: https://blog.51cto.com/14230003/2425544

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有