【小家Spring】Spring MVC容器启动时,web九大组件初始化详解(Spring MVC的运行机制)(中)

简介: 【小家Spring】Spring MVC容器启动时,web九大组件初始化详解(Spring MVC的运行机制)(中)

HandlerAdapter


因为SpringMVC中的Handler可以是任意的形式,只要能处理请求就ok,但是Servlet需要的处理方法的结构却是固定的,都是以request和response为参数的方法。如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就是HandlerAdapter要做的事情。


Handler是用来干活的工具;HandlerMapping用于根据需要干的活找到相应的工具;HandlerAdapter是使用工具干活的人


public interface HandlerAdapter {
  //当前 HandlerAdapter 是否支持这个 Handler
  boolean supports(Object handler);
  //调用handle处理这个请求,然后返回ModelAndView 对象
  @Nullable
  ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
  long getLastModified(HttpServletRequest request, Object handler);
}


因为它和HandlerMapping联系紧密,因此且听下文分解


HandlerAdapter可以有多个


HandlerExceptionResolver


其它组件都是用来干活的。在干活的过程中难免会出现问题,出问题后怎么办呢?这就需要有一个专门的角色对异常情况进行处理,在SpringMVC中就是HandlerExceptionResolver。具体来说,此组件的作用是根据异常设置ModelAndView,之后再交给render方法进行渲染。


以前我们可以用web.xml的<error-page>标签来捕获状态码500 400的异常,但是这个已经out了,现在全局的异常都可以交给HandlerExceptionResolver去捕获处理

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


这个接口捕获的是所有异常,而官方推荐的是使用@ExceptionHandler注解去捕获固定的异常


这个类建议交给Spring子容器管理(我们可以多实现),因为它就像一个特殊的controller


关于这块Spring MVC的全局异常的处理的一些技巧(比如页面、get、post、ajax等),请关注后面博文

RequestToViewNameTranslator


Spring MVC是通过ViewName来找到对应的视图的,而此接口的作用就是从request中获取viewName。

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


它只有一个实现,默认实现:DefaultRequestToViewNameTranslator:


  @Override
  public String getViewName(HttpServletRequest request) {
    String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
    return (this.prefix + transformPath(lookupPath) + this.suffix);
  }
  @Nullable
  protected String transformPath(String lookupPath) {
    String path = lookupPath;
    if (this.stripLeadingSlash && path.startsWith(SLASH)) {
      path = path.substring(1);
    }
    if (this.stripTrailingSlash && path.endsWith(SLASH)) {
      path = path.substring(0, path.length() - 1);
    }
    if (this.stripExtension) {
      path = StringUtils.stripFilenameExtension(path);
    }
    if (!SLASH.equals(this.separator)) {
      path = StringUtils.replace(path, SLASH, this.separator);
    }
    return path;
  }


主要实现就是调用UrlPathHelper的getLookupPathForRequest的方法获取一个looup路径。transformPath方法主要是对获取的路径字符串再做个简单处理罢了。

所以核心是UrlPathHelper的getLookupPathForRequest的实现:

(解析路径这块,这里就不做太多的解释了,自己读读源码,相对来说比较简单)

ViewResolver


ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。View是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html(也可能是其它类型)文件。这里就有两个关键问题:使用哪个模板?用什么技术(规则)填入参数?这其实是ViewResolver主要要做的工作


ViewResolver需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成。


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


image.png

1.AbstractCachingViewResolver 基于缓存的抽象视图解析器


2.UrlBasedViewResolver 实现了缓存 提供了prefix suffix拼接的url视图解析器。


3.InternalResourceViewResolver 基于url 的内部资源视图解析器。


4.XmlViewResolver 基于xml的缓存视图解析器


5.BeanNameViewResolver beanName来自容器,并且不支持缓存。


6.ResourceBundleViewResolver 这个有点复杂


7.reeMarkerViewResolver、VolocityViewResolver 都基于url 但会解析成特定的view

实现类也非常的多,在Spring MVC里是一个非常非常重要的概念(比如什么时候返回页面,什么时候返回json呢?),因此后面会有专门的文章进行深入解读


ViewResolverComposite简单来说就是使用简单的List来保存你配置使用的视图解析器。


ViewResolvers可以有多个

FlashMapManager


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

public interface FlashMapManager {
    @Nullable
    FlashMap retrieveAndUpdate(HttpServletRequest var1, HttpServletResponse var2);
    void saveOutputFlashMap(FlashMap var1, HttpServletRequest var2, HttpServletResponse var3);
}


image.png


可以看出结构图非常简单,抽象类采用模板模式定义整个流程,具体实现类用SessionFlashMapManager通过模板方法提供了具体操作FlashMap的功能。

功能说明:


  • 实际的Session中保存的FlashMap是List类型,也就是说一个Session可以保存多个FlashMap,一个FlashMap保存着一套Redirect转发所传递的参数
  • FlashMap继承自HashMap,除了用于HashMap的功能和设置有效期,还可以保存Redirect后的目标路径和通过url传递的参数,这两项内容主要用来从Session保存的多个FlashMap中查找当前的FalshMap


具体请持续关注吧,后面再详说


至此,SpringMVC中的9大组件也就简单地概述了一遍。通过对此9大组件的宏观认识,对分析SpringMVC的设计、原理与实现都会有很大的帮助作用。


onRefresh(wac) / initStrategies(wac)详解

这可以说是DisparcherServlet初始化时的核心逻辑


initMultipartResolver

  private void initMultipartResolver(ApplicationContext context) {
    try {
      this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
    } catch (NoSuchBeanDefinitionException ex) {
      this.multipartResolver = null;
    }
  }


这个很简单,若我们向容器里配置了此Bean就有,否则默认是不支持文件上传的

备注:注意配置此些配型Bean的名称,都是有固定值的,请必须保证一样,否则你的配置将不生效。下同

相关文章
|
7月前
|
缓存 安全 Java
《深入理解Spring》过滤器(Filter)——Web请求的第一道防线
Servlet过滤器是Java Web核心组件,可在请求进入容器时进行预处理与响应后处理,适用于日志、认证、安全、跨域等全局性功能,具有比Spring拦截器更早的执行时机和更广的覆盖范围。
|
7月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
7月前
|
监控 Linux 调度
【赵渝强老师】Docker容器的资源管理机制
本文介绍了Linux CGroup技术及其在Docker资源管理中的应用。通过实例演示了如何利用CGroup限制应用程序的CPU、内存和I/O带宽使用,实现系统资源的精细化控制,帮助理解Docker底层资源限制机制。
685 6
|
8月前
|
存储 安全 Java
如何在 Spring Web 应用程序中使用 @SessionScope 和 @RequestScope
Spring框架中的`@SessionScope`和`@RequestScope`注解用于管理Web应用中的状态。`@SessionScope`绑定HTTP会话生命周期,适用于用户特定数据,如购物车;`@RequestScope`限定于单个请求,适合无状态、线程安全的操作,如日志记录。合理选择作用域能提升应用性能与可维护性。
334 1
|
9月前
|
存储 NoSQL Java
探索Spring Boot的函数式Web应用开发
通过这种方式,开发者能以声明式和函数式的编程习惯,构建高效、易测试、并发友好的Web应用,同时也能以较小的学习曲线迅速上手,因为这些概念与Spring Framework其他部分保持一致性。在设计和编码过程中,保持代码的简洁性和高内聚性,有助于维持项目的可管理性,也便于其他开发者阅读和理解。
244 0
|
10月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
697 0
|
10月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
298 0
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
872 29
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
1012 7
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
1022 7
Spring Boot 入门:简化 Java Web 开发的强大工具