0%

https://docs.spring.io/spring-framework/docs/current/reference/html/index.html

Spring Framework 5.3.4 参考指南 (官方文档翻译)

主要模块包含内容
Overviewhistory, design philosophy, feedback, getting started.
CoreIoC Container, Events, Resources, i18n, Validation, Data Binding, Type Conversion, SpEL, AOP.
TestingMock Objects, TestContext Framework, Spring MVC Test, WebTestClient.
Data AccessTransactions, DAO Support, JDBC, R2DBC, O/R Mapping, XML Marshalling.
Web ServletSpring MVC, WebSocket, SockJS, STOMP Messaging.
Web ReactiveSpring WebFlux, WebClient, WebSocket, RSocket.
IntegrationRemoting, JMS, JCA, JMX, Email, Tasks, Scheduling, Caching.
LanguagesKotlin, Groovy, Dynamic Languages.

Rod Johnson, Juergen Hoeller, Keith Donald, Colin Sampaleanu, Rob Harrop, Thomas Risberg, Alef Arendsen, Darren Davison, Dmitriy Kopylenko, Mark Pollack, Thierry Templier, Erwin Vervaet, Portia Tung, Ben Hale, Adrian Colyer, John Lewis, Costin Leau, Mark Fisher, Sam Brannen, Ramnivas Laddad, Arjen Poutsma, Chris Beams, Tareq Abedrabbo, Andy Clement, Dave Syer, Oliver Gierke, Rossen Stoyanchev, Phillip Webb, Rob Winch, Brian Clozel, Stephane Nicoll, Sebastien Deleuze, Jay Bryant, Mark Paluch

Copyright © 2002 - 2021 Pivotal, Inc. All Rights Reserved.

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

概要

Spring帮助构建 Java 企业级应用变得更加简单。它提供了你在企业环境中使用Java语言开始时所需要的一切,包括支持 Groovy 和 Kotlin 作为JVM上的替代语言,以及可以根据应用程序的需要来灵活的创建各式各样的架构。

从 Spring Framework 5.1 版本开始,Spring 仅支持 JDK 8 及以上版本,并且提供对 JDK 11 LTS 开箱即用的支持。Java SE 8 update 60 版本是 Java 8 中能够支持的最小版本,但通常来说建议使用最新版本。

Spring 支持不同的应用场景。大型企业中,应用程序通常需要长时间运行在升级周期不受开发人员控制的 JDK 和服务器上。其他的可能是在嵌入式服务器中运行单个 jar,也可能是在云环境。另外可能还可以是不需要服务器的独立应用程序。

Spring 作为开源应用,其拥有一个大型且活跃的社区,由于这个社区能够经常提供基于各种实际情况的案例,所以 Spring 的茁壮成长也得益于该社区。

1. 为何称其为“Spring”

“Spring”这个术语在不同的环境下有着不同的含义。它常常被用来指代 Spring Framework 这个项目本身,同时这个项目也是 Spring 的开始。随着时间的推移,其他新的 Spring 项目都是基于 Spring Framework 构建的。大多数时候,人们称呼“Spring”时,更多的是表达 Spring 整个项目家族。本参考文档重点想介绍的也是 Spring Framework 这个基础应用。

Spring Framework 分为多个模块。构建应用时,可以根据情况自由选择。core container 模块是所有模块中最重要的,它包含了配置模型依赖注入机制。除此之外,Spring Framework 为不同的应用程序架构都提供了基础支持,包括消息队列、事务数据、持久化和web服务。也包含了基于 Servlet 的 SpringMVC,以及 Spring WebFlux 响应式web框架。

A note about modules: Spring’s framework jars allow for deployment to JDK 9’s module path ("Jigsaw"). For use in Jigsaw-enabled applications, the Spring Framework 5 jars come with "Automatic-Module-Name" manifest entries which define stable language-level module names ("spring.core", "spring.context" etc) independent from jar artifact names (the jars follow the same naming pattern with "-" instead of ".", e.g. "spring-core" and "spring-context"). Of course, Spring’s framework jars keep working fine on the classpath on both JDK 8 and 9+.

2. Spring 和 Spring Framework 的发家史

Spring于2003年为了解决 J2EE 规范的复杂性而诞生,尽管当时人们认为 Spring 是想与 JavaEE 进行竞争才出现的,但实际上 Spring 一直将自己视为 Java EE 的补充。Spring 编程模型并没有选择整个 JavaEE 平台规范,而是取其精华。例如:

Spring Framework 还支持依赖注入 (JSR 330) 和通用注解 (JSR 250) 规范,开发者可以选择通过这些规范来替换 Spring Framework 提供的 Spring 内置机制。

从 Spring Framework 5.0 开始,Spring 支持 Java EE 7 (e.g. Servlet 3.1+, JPA 2.1+) 以上的版本,同时在运行时提供基于 Java EE 8 (e.g. Servlet 4.0, JSON Binding API) 版本的新API的现有集成。这使得 Spring 完全兼容例如 Tomcat 8 和 9,WebSphere 9 和 JBoss EAP 7。

随着时间的推移,Java EE 在应用开发中担任的角色开始变化。在 Java EE 和 Spring 早期,创建应用程序是为了部署到应用服务器上。现如今,在 Spring Boot 的帮助下,应用程序可以通过devops和cloud-friendly的方式被创建,Servlet 容器被嵌入其中,且仅需一点点修改。从 Spring Framework 5.0 开始,一个 WebFlux 应用甚至不直接使用 Servlet API,也可以在没有 Servlet 容器(例如Netty)的上运行。

随着 Spring 的持续创新和发展。除了 Spring Framework,还有诞生了其他项目,如 Spring Boot, Spring Security, Spring Data, Spring Cloud, Spring Batch 等。请务必记住,每个项目都有其自己的源代码存储库,问题跟踪程序和发布节奏。有关 Spring 项目的完整列表,请参见 spring.io/projects

设计理念

在学习框架时,最重要的不仅是知道它的原理,而且还要知道它遵循什么原则。以下是 Spring 框架的指导原则:

  • 提供各种级别的选择。Spring 允许你尽可能的退出设计决策。例如,你可以通过配置文件来切换持久化的提供者,而无需修改你的代码。对于许多其他基础架构问题以及与第三方API的集成也是如此。
  • 接受不同的想法。Spring 拥抱灵活,对事情应该如何做并不固执己见,他亦不同的视角支持各种应用需求。
  • 保持健壮的向后兼容性。由于 Spring 在发展过程中管理得当,以至于版本之间几乎很少有重大变化。Spring 仔细的挑选 JDK 版本和第三方库,以帮助那些依赖于 Spring 的应用程序。
  • 着重API设计。Spring团队投入了大量的心思和时间来构建使用简便的API,以确保这些API可以跨越多个版本及很多年。
  • 为代码质量设置高标准。Spring Framework非常强调有意义、最新、准确的 javadoc,也是少数代码结构干净且包之间没有循环依赖的项目。

反馈和贡献

对于如何提问、分析、调试问题,我们建议使用 Stack Overflow。单击 此处 来获取使用 Stack Overflow 的建议。如果你确定 Spring Framework 中存在问题或者提出一个feature,请使用 GitHub Issues

如果你有一个解决方案或修复建议,你可以提交一个pull请求在Github上。但请记住,对于一些琐碎的问题外,我们希望能够将 issue 中留下你的问题记录,以便于进行讨论或在未来当作参考。

有关更多详细信息,请参考CONTRIBUTING

快速上手

如果你刚刚开始上手 Spring,你可能想开始通过创建一个基于 Spring Boot 的应用程序来使用 Spring Framework。Spring Boot 提供了一种快速的方式来创建一个基于 Spring 可用于生产环境的应用程序。它基于 Spring 框架,采用约定优于配置的方式,旨在使您尽快启动并运行。

您可以使用 start.spring.io 生成一个基础项目,或者遵循 "Getting Started" guides 中的 Getting Started Building a RESTful Web Service。这些指南不仅易于理解,而且非常注重任务,并且大多数都是基于 Spring Boot 的。它们还涵盖了 Spring 家族中的其他项目,您在解决特定问题时可能要考虑这些项目。

核心内容

测试

Data Access

参考文档的这一部分涉及数据访问以及数据访问层与业务或服务层之间的交互。详细介绍了 Spring 的全面事务管理支持,然后全面介绍了 Spring 框架与之集成的各种数据访问框架和技术。

Transaction Management

完善的事务支持是使用 Spring Framework 的理由之一。 Spring Framework 为事务管理提供了一致的抽象,具有以下优点:

  • 跨不同事务 API 的一致编程模型,例如 Java 事务 API (JTA)、JDBC、Hibernate 和 Java Persistence API (JPA)。
  • 支持声明式事务管理。
  • 比复杂的事务 API(例如 JTA)更简单的用于程序化事务管理的 API。
  • 与 Spring 的数据访问抽象的完美集成。

以下部分描述了 Spring Framework 的事务特性和技术:

本章还讨论了最佳实践、应用服务器集成和常见问题的解决方案。

Web Servlet

DispatcherServlet

Web MVC Config

应用程序可以声明所需的在 Special Bean Types 中列出的基础bean来处理请求。DispatcherServlet 会检查每个特殊bbean的 WebApplicationContext。如果没有匹配的bean类型,它会使用{spring-framework-main-code}/spring-springmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties[DispatcherServlet.properties]中列出默认类型。

在大多数情况下,MVC Config 是最好的起点。它在 Java 或 XML 中声明了所需的 bean,并提供了一个更高级别的配置回调 API 来自定义它。

✏️ Spring Boot 依赖于 MVC Java 配置来配置 Spring MVC,并提供了许多额外方便的选项。

Servlet Config

在 Servlet 3.0+ 环境中,您可以选择以编程方式配置 Servlet 容器作为替代方案或与 web.xml 文件结合使用。

以下示例注册一个 DispatcherServlet

import org.springframework.web.WebApplicationInitializer;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

WebApplicationInitializer 是 Spring MVC 提供的一个接口,可确保检测到您的实现并自动用于初始化任何 Servlet 3 容器。AbstractDispatcherServletInitializer 是实现了 WebApplicationInitializer 接口的抽象基类,可以通过覆盖其方法来指定 servlet 映射和 DispatcherServlet 配置的位置,使得注册 DispatcherServlet 变得更加容易。

推荐使用基于Java代码的配置方式,示例如下:

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { MyWebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

如果你想使用基于XML的配置方式,你可以直接继承 AbstractDispatcherServletInitializer,示例如下:

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
        return cxt;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

AbstractDispatcherServletInitializer 还提供了一种方便的方法来添加 Filter 实例并使它们自动映射到 DispatcherServlet,示例如下:

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    // ...

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
            new HiddenHttpMethodFilter(),
            new CharacterEncodingFilter()
        };
    }
}

每个过滤器都根据其具体类型添加了一个默认名称,并自动映射到 DispatcherServlet

AbstractDispatcherServletInitializerisAsyncSupported 受保护方法提供了一个单一的地方来启用对 DispatcherServlet 和映射到它的所有过滤器的异步支持。默认情况下,此标志设置为 true。

最后,如果您需要进一步自定义 DispatcherServlet 本身,您可以覆盖 createDispatcherServlet 方法。

Processing

DispatcherServlet处理请求的过程如下:

  1. 找到一个WebApplicationContext用于作为一个属性绑定到请求中,以便于在处理过程中控制器和其他元素能够使用到。(默认绑定在DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE中)

  2. 将本地化解析器绑定到请求中,如果不需要可以忽略

  3. 将主题解析器绑定到请求中,让视图等元素决定使用哪个主题,如果不需要而已忽略

  4. 如果你指定了一个multipart file解析器,则会解析请求的multiparts。若能在请求中找到,则会将该请求包装为MultipartHttpServletRequest,以便于处理过程中其他元素进一步处理。有关multipart处理器,请参阅Multipart Resolver

  5. 查找匹配的处理器。如果找到,则执行与处理器(预处理器,后置处理器、控制器)相关联的执行链以准备用于渲染模型。或者,对于带有注解的controller,可以直接响应(在HandlerAdapter)而不是返回视图。

  6. 如果返回的是模型,则将渲染视图。否则不会渲染视图(可能由于预处理器或后置处理器拦截了请求,或处于安全原因),因为请求已经得到合理响应。

可以通过在WebApplicationContext中声明HandlerExceptionResolver beans来解决请求处理过程中抛出的异常。这些异常解析器允许自定义逻辑来解决异常。有关更多详细信息,请参阅Exceptions

Spring DispatcherServlet 还支持返回last-modification-date,如 Servlet API 指定的那样。确定特定请求的最后修改日期的过程很简单:DispatcherServlet 查找适当的处理程序映射并测试找到的处理程序是否实现了LastModified 接口。如果是,则将LastModified接口的long getLastModified(request)方法的值返回给客户端。

您可以通过将Servlet初始化参数(init-param元素)添加到web.xml 文件中的 Servlet 声明来自定义各个DispatcherServlet 实例。下表列出了支持的参数:

Table 1. DispatcherServlet initialization parameters

ParameterExplanation
contextClass实现 ConfigurableWebApplicationContext 的类,由这个 Servlet 实例化和本地配置。默认情况下,使用 XmlWebApplicationContext
contextConfigLocation传递给上下文实例(由contextClass 指定)以指示可以找到上下文的位置的字符串。该字符串可能包含多个字符串(使用逗号作为分隔符)以支持多个上下文。在 bean 定义两次的多个上下文位置的情况下,最新的位置优先。
namespaceWebApplicationContext 的命名空间。默认为 [servlet-name]-servlet
throwExceptionIfNoHandlerFound当找不到一个对应请求的处理器是,将抛出NoHandlerFoundException。该异常可以使用HandlerExceptionResolver 捕获(例如,通过使用被标记了@ExceptionHandler的控制器方法)并像其他任何方法一样处理。
默认情况下,这设置为false,在这种情况下 DispatcherServlet 将响应状态设置为 404 (NOT_FOUND) 而不引发异常。
请注意,如果还配置了默认servlet处理器,则未解析的请求始终转发到默认 servlet,并且永远不会引发 404。

Path Matching

ServletAPI会将一个完整的请求路径解析为requestURI,并且进一步分解出contextPathservletPath以及pathInfo。其中具体的值取决于Servlet的映射方式。SpringMVC将通过这些值确定用于映射handler的lookup pathlookup pathDispatcherServlet自身映射中的路径,不包括contextPathservletMapping前缀(如果存在)。

由于servletPathpathInfo会被解码,使得无法直接与requestURI进行比较,如果想要获取lookup path,则需要对requestURI进行解码。由于原本请求路径中可能包含编码的保留字符,使得解码操作将存在破坏原本请求路径的可能,产生安全隐患。

该问题可通过升级到5.3或更高的版本来解决,从5.3版本开始,将使用PathPattern来替代PathMatcher。其通过将路径分段解析,每次仅处理一个分段的解码操作,这样保证了不会存在改变路径结构的风险。PathPattern也支持使用servletPath前缀映射,不过需要保证其中不包含需要编码的字符。

Web Reactive

集成

其他语言