SpringMVC源代码学习(四)九大组件上

以下内容基于书:《看透SpringMVC-源代码分析与实践》基本照搬。。。用于自己查阅备忘。

1. HandlerMapping

在dispatcherServlet,doDispatch方法中有调用getHandler,代码如下:
其中List< HandlerMapping> handlerMappings是dispatcherServlet的内部变量。
那该方法的内容就是遍历handlerMappings,获得符合条件的HandlerMapping,调用其getHandler方法,返回获得的HandlerExecutionChain

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

HandlerMapping是一个接口,内部只有一个方法和诺干变量,它的作用是根据request找到对应的Handler。方法如下:
HandlerExecutionChain getHandler(HttpSevletRequest request) throws Exception
接下来看看一个该方法的实现,SimpleControllerHandlerAdapter,代码如下:

    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Object handler = getHandlerInternal(request);
        if (handler == null) {
            handler = getDefaultHandler();
        }
        if (handler == null) {
            return null;
        }
        // Bean name or resolved handler?
        if (handler instanceof String) {
            String handlerName = (String) handler;
            handler = getApplicationContext().getBean(handlerName);
        }

        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        if (CorsUtils.isCorsRequest(request)) {
            CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
            CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
            CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
            executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
        }
        return executionChain;
    }

另外一个要讨论的就是顺序问题,不同hander负责映射的条件可能有重复的,这时候就需要定义不同的HandlerMapping执行的顺序,这里的顺序可以通过实现Order接口,通过Order属性定义。order越小越先使用。如:

<bean class="com.excelib.TudouHandlerMapping"
    p:order="1"/>
<bean class="com.excelib.TudoupianHandlerMapping"
    p:order="0"/>

2.HandlerAdapter

在dispatcherServlet通过如下方法获得HandlerAdapter,其中List< HandlerAdapter> handlerAdapters是dispatcherServlet的成员变量,可以看到它的逻辑是遍历所有的Adapter,然后检查哪个可以处理当前的Handler,找到第一个可以处理Handler的Adapter后停止查找,返回。这里的顺序同样是通过Order属性设置的。

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        for (HandlerAdapter ha : this.handlerAdapters) {
            if (logger.isTraceEnabled()) {
                logger.trace("Testing handler adapter [" + ha + "]");
            }
            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的角色是使用工具(handler)的人。因为handler是Object类型,需要HandlerAdapter使用它来完成一定格式要求的任务。
它是一个接口,代码如下:

    public interface HandlerAdapter {   
        boolean supports(Object handler);   
        ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
       long getLastModified(HttpServletRequest request, Object handler);

接下来看一个spring自己实现的示例,代码如下:

public class SimpleControllerHandlerAdapter implements HandlerAdapter {

    @Override
    public boolean supports(Object handler) {
        return (handler instanceof Controller);
    }

    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        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;
    }

}

可以看到这个Adapter比较简单,它要求handler实现了Controller接口,方法的实现是通过处理器的handleRequest方法。

3. HandlerExceptionResolver

HandlerExceptionResolver是SpringMVC中专门负责处理异常的类。它负责:
根据异常设置ModelAndView
之后交给render方法进行渲染。render只负责将Model渲染成页面。具体ModelAndView的来源render并不关心。

public interface HandlerExceptionResolver {
    ModelAndView resolveException(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

}

它的结构很简单,只有一个方法,只需要从异常解析出ModelAndView就可以了。具体实现可以维护一个异常为Key、View为value的Map,解析时直接从Map里获取View。

4.ViewResolver

ViewResolver用来将String类型的视图名(也叫逻辑视图)和Locale解析为View类型的视图,ViewResolver接口也很简单,代码如下

public interface ViewResolver {
    View resolveViewName(String viewName, Locale locale) throws Exception;

}

这里可以看到参数是viewName和locale,不过一般我们只要根据视图名找到视图,然后渲染就可以,如果需要国际化支持也只要将显示的内容或者主题使用国际化支持。
View是用来渲染页面的,也就是将程序返回的参数填入模板中,生成html或其他格式的文件。所以说它会解决两个问题:
1. 填入哪个模板?
2. 如何填入?
它会找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交给不同的视图自己完成。
我们最常用的UrlBasedViewResolver系列的解析器都是针对单一视图类型进行解析的。比如InternalResourceViewResolver只针对jsp类型的视图,FreeMarkerViewResolver只针对FreeMarker,VelocityViewResolver只针对Velocity。而ResourceBundleViewResolver、XmlViewResolver、BeanNameViewResolver等解析器可以同时解析多种类型的视图。
ResourceBundleViewResolver使用properties配置文件来进行配置解析的文件类和url、XmlViewResolver使用xml配置。BeanNameViewResolver是根据ViewName从ApplicationContext容器中查找相应的bean做View的,它比较简单,源码如下:

public class BeanNameViewResolver extends WebApplicationObjectSupport implements ViewResolver, Ordered {
    private int order = Integer.MAX_VALUE;  // default: same as non-Ordered
    public void setOrder(int order) {
        this.order = order;
    }
    @Override
    public int getOrder() {
        return this.order;
    }
    @Override
    public View resolveViewName(String viewName, Locale locale) throws BeansException {
        ApplicationContext context = getApplicationContext();
        if (!context.containsBean(viewName)) {
            if (logger.isDebugEnabled()) {
                logger.debug("No matching bean found for view name '" + viewName + "'");
            }
            // Allow for ViewResolver chaining...
            return 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;
        }
        return context.getBean(viewName, View.class);
    }

}

可以看出原理就是根据viewName从spring容器中查找Bean,if(找不到||不是view类型) return null; else return context.getBean(viewName, View.class);
ViewResolver的使用需要注册到Spring MVC容器中,默认使用的是org.springframework.web.servlet.view.InternalResourceViewResolver。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
狂神springmvc代码指的是由李仁密老师在其视频教程中讲解的一套完整的Spring MVC项目代码,该代码涵盖了Spring MVC框架的各个功能模块,以及常用的Web开发技术和工具,具有实用性和参考价值。下面从代码结构、特点、使用和拓展等方面进行详述。 代码结构: 狂神springmvc代码采用Maven作为项目管理工具,以标准的MVC架构模式设计,目录结构清晰,分为java和resources两个目录。 Java目录下分为controller、dao、entity、service和util等包,各自对应了Spring MVC框架中Controller、Dao、Entity、Service和常用的工具类,这些包下又分别包含了相应的类和接口。Resources目录下主要是Spring MVC框架的配置文件,包含了web.xml、spring.xml、mybatis.xml等等,其中spring.xml是整个应用程序的核心配置文件,配置了包括数据源、transaction manager、各种bean和拦截器在内的所有Spring MVC组件。 特点: 1. 视频教程详细:狂神springmvc代码是通过李仁密老师的视频教程带领学生逐步完成的,在代码编写方面考虑较为全面和严谨。 2. 适用性强:狂神springmvc代码包含了Spring MVC框架的基本功能和高级特性,支持Restful结构,便于实现独立的业务模块。 3. 良好的开放性:代码分层清晰,各层之间耦合度低,便于后期的升级和扩展。 4. 数据持久化采用mybatis:狂神springmvc代码采用了mybatis框架作为持久化层,支持动态sql语句和对象映射,具有较好的可维护性和可扩展性。 5. 模块化设计:狂神springmvc代码实现了模块化设计,便于分组和管理,结构紧凑。 使用: 使用狂神springmvc代码需要使用Maven作为项目管理工具,以及Java、Spring、mybatis等开发框架,需要对这些工具和框架有一定的了解和掌握。在代码使用过程中,可以根据实际的需求进行自定义修改和调整,便于实现个性化的业务需求。 拓展: 狂神springmvc代码为学习者提供了一种全面学习Spring MVC框架的方式,开发者可以根据自己的需求对代码进行维护和拓展。如果需要调整和扩展功能,可以在原代码基础上进行二次开发,例如增加更多的业务模块、改进用户体验、优化性能等等。总而言之,狂神springmvc代码是一套具有实战价值和参考价值的完整的Spring MVC项目代码,适合需要学习或使用Spring MVC框架的开发人员。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值