• 新版网站前后台即将上线,2019年将致力于提高文章质量,加大原创力度,打造一个更加舒适的阅读体验!
  • 极客文库小编@勤劳的小蚂蚁,为您推荐每日资讯,欢迎关注!
  • 新版网站前后台即将上线,2019年将致力于提高文章质量,加大原创力度,打造一个更加舒适的阅读体验!
  • 如果有任何体验不佳的地方,欢迎向客服反馈!

教你理清SpringBoot与SpringMVC的关系

 spring boot 就是一个大框架里面包含了许许多多的东西,其中 spring 就是最核心的内容之一,当然就包含 spring mvc。spring mvc 是只是 spring 处理 web 层请求的一个模块。因此他们的关系大概就是这样:spring mvc  < spring <springboot。

理清 SpringBoot 与 SpringMVC 的关系

Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa 等等。但他们的基础都是 Spring 的 ioc 和 aop ioc 提供了依赖注入的容器 aop ,解决了面向横切面的编程,然后在此两者的基础上实现了其他延伸产品的高级功能。
Spring MVC 是基于 Servlet 的一个 MVC 框架 主要解决 WEB 开发的问题,因为 Spring 的配置非常复杂,各种 XML、 JavaConfig、hin 处理起来比较繁琐。
于是为了简化开发者的使用,从而创造性地推出了 Spring boot,约定优于配置,简化了 spring 的配置流程。
说得更简便一些:Spring 最初利用“工厂模式”(DI)和“代理模式”(AOP)解耦应用组件。
大家觉得挺好用,于是按照这种模式搞了一个 MVC 框架(一些用 Spring 解耦的组件),用开发 web 应用( SpringMVC )。
然后有发现每次开发都写很多样板代码,为了简化工作流程,于是开发出了一些“懒人整合包”(starter),这套就是 Spring Boot。
Spring MVC 的功能 Spring MVC 提供了一种轻度耦合的方式来开发 web 应用。Spring MVC 是 Spring 的一个模块,式一个 web 框架。
通过 Dispatcher Servlet, ModelAndView 和 View Resolver,开发 web 应用变得很容易。解决的问题领域是网站应用程序或者服务开发——URL 路由、Session、模板引擎、静态 Web 资源等等。
Spring Boot 的功能 Spring Boot 实现了自动配置,降低了项目搭建的复杂度。
众所周知 Spring 框架需要进行大量的配置,Spring Boot 引入自动配置的概念,让项目设置变得很容易。
Spring Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。
同时它集成了大量常用的第三方库配置(例如 Jackson, JDBC, Mongo, Redis, Mail 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box),大部分的 Spring Boot 应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。Spring Boot 只是承载者,辅助你简化项目搭建过程的。如果承载的是 WEB 项目,使用 Spring MVC 作为 MVC 框架,那么工作流程和你上面描述的是完全一样的,因为这部分工作是 Spring MVC 做的而不是 Spring Boot。对使用者来说,换用 Spring Boot 以后,项目初始化方法变了,配置文件变了,另外就是不需要单独安装 Tomcat 这类容器服务器了,maven 打出 jar 包直接跑起来就是个网站,但你最核心的业务逻辑实现与业务流程实现没有任何变化。
所以,用最简练的语言概括就是:
Spring 是一个“引擎”;
Spring MVC 是基于 Spring 的一个 MVC 框架 ;
Spring Boot 是基于 Spring4 的条件注册的一套快速开发整合包。

Spring MVC 自动配置

Spring Boot 为 Spring MVC 提供的 auto-configuration 适用于大多数应用,并在 Spring 默认功能上添加了以下特性:
  1. 引入 ContentNegotiatingViewResolver 和 BeanNameViewResolver beans。
  2. 对静态资源的支持,包括对 WebJars 的支持。
  3. 自动注册 Converter,GenericConverter,Formatter beans。
  4. 对 HttpMessageConverters 的支持。
  5. 自动注册 MessageCodeResolver。
  6. 对静态 index.html 的支持。
  7. 对自定义 Favicon 的支持。
  8. 自动使用 ConfigurableWebBindingInitializer bean。
如果保留 Spring Boot MVC 特性,你只需添加其他的 MVC 配置(拦截器,格式化处理器,视图控制器等)。你可以添加自己的 WebMvcConfigurerAdapter 类型的@Configuration 类,而不需要注解@EnableWebMvc。如果希望使用自定义的 RequestMappingHandlerMapping,RequestMappingHandlerAdapter,或 ExceptionHandlerExceptionResolver,你可以声明一个 WebMvcRegistrationsAdapter 实例提供这些组件。
如果想全面控制 Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc 注解。

HttpMessageConverters

Spring MVC 使用 HttpMessageConverter 接口转换 HTTP 请求和响应,合适的默认配置可以开箱即用,例如对象自动转换为 JSON(使用 Jackson 库)或 XML(如果 Jackson XML 扩展可用,否则使用 JAXB),字符串默认使用 UTF-8 编码。
可以使用 Spring Boot 的 HttpMessageConverters 类添加或自定义转换类:
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration
publicclassMyConfiguration{

   @Bean
   public HttpMessageConverters customConverters(){
       HttpMessageConverter<?> additional = …
       HttpMessageConverter<?> another = …
       returnnew HttpMessageConverters(additional, another);
   }

}

上下文中出现的所有 HttpMessageConverter bean 都将添加到 converters 列表,你可以通过这种方式覆盖默认的转换器列表(converters)。

自定义 JSON 序列化器和反序列化器

如果使用 Jackson 序列化,反序列化 JSON 数据,你可能想编写自己的 JsonSerializer 和 JsonDeserializer 类。自定义序列化器(serializers)通常通过 Module 注册到 Jackson,但 Spring Boot 提供了@JsonComponent 注解这一替代方式,它能轻松的将序列化器注册为 Spring Beans。

MessageCodesResolver

Spring MVC 有一个实现策略,用于从绑定的 errors 产生用来渲染错误信息的错误码:MessageCodesResolver。Spring Boot 会自动为你创建该实现,只要设置 spring.mvc.message-codes-resolver.format 属性为 PREFIX_ERROR_CODE 或 POSTFIX_ERROR_CODE(具体查看 DefaultMessageCodesResolver.Format 枚举值)。

静态内容

默认情况下,Spring Boot 从 classpath 下的/static(/public,/resources 或/META-INF/resources)文件夹,或从 ServletContext 根目录提供静态内容。这是通过 Spring MVC 的 ResourceHttpRequestHandler 实现的,你可以自定义 WebMvcConfigurerAdapter 并覆写 addResourceHandlers 方法来改变该行为(加载静态文件)。
在单机 web 应用中,容器会启动默认的 servlet,并用它加载 ServletContext 根目录下的内容以响应那些 Spring 不处理的请求。大多数情况下这都不会发生(除非你修改默认的 MVC 配置),因为 Spring 总能够通过 DispatcherServlet 处理这些请求。
你可以设置 spring.resources.staticLocations 属性自定义静态资源的位置(配置一系列目录位置代替默认的值),如果你这样做,默认的欢迎页面将从自定义位置加载,所以只要这些路径中的任何地方有一个 index.html,它都会成为应用的主页。
此外,除了上述标准的静态资源位置,有个例外情况是 Webjars 内容。任何在/webjars/**路径下的资源都将从 jar 文件中提供,只要它们以 Webjars 的格式打包。
注 如果你的应用将被打包成 jar,那就不要使用 src/main/webapp 文件夹。尽管该文件夹是通常的标准格式,但它仅在打包成 war 的情况下起作用,在打包成 jar 时,多数构建工具都会默认忽略它。
Spring Boot 也支持 Spring MVC 提供的高级资源处理特性,可用于清除缓存的静态资源或对 WebJar 使用版本无感知的 URLs。
如果想使用针对 WebJars 版本无感知的 URLs(version agnostic),只需要添加 webjars-locator 依赖,然后声明你的 Webjar。以 jQuery 为例,”/webjars/jquery/dist/jquery.min.js”实际为”/webjars/jquery/x.y.z/dist/jquery.min.js”,x.y.z 为 Webjar 的版本。
注 如果使用 JBoss,你需要声明 webjars-locator-jboss-vfs 依赖而不是 webjars-locator,否则所有的 Webjars 将解析为 404。
以下的配置为所有的静态资源提供一种缓存清除(cache busting)方案,实际上是将内容 hash 添加到 URLs 中,比如<link href=”/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/>:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
注 实现该功能的是 ResourceUrlEncodingFilter,它在模板运行期会重写资源链接,Thymeleaf,Velocity 和 FreeMarker 会自动配置该 filter,JSP 需要手动配置。其他模板引擎还没自动支持,不过你可以使用 ResourceUrlProvider 自定义模块宏或帮助类。
当使用比如 JavaScript 模块加载器动态加载资源时,重命名文件是不行的,这也是提供其他策略并能结合使用的原因。下面是一个”fixed”策略,在 URL 中添加一个静态 version 字符串而不需要改变文件名:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/lib/
spring.resources.chain.strategy.fixed.version=v12
使用以上策略,JavaScript 模块加载器加载”/js/lib/”下的文件时会使用一个固定的版本策略”/v12/js/lib/mymodule.js”,其他资源仍旧使用内容 hash 的方式<link href=”/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/>。查看 ResourceProperties 获取更多支持的选项。

欢迎页面

Spring Boot 支持静态和模板欢迎页面。它首先 index.html 在配置的静态内容位置中查找 文件。如果找不到,则会查找 index 模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。、

自定义 Favicon

Spring Boot favicon.ico 在配置的静态内容位置和类路径的根目录(按此顺序)中查找 a 。如果存在这样的文件,它会自动用作应用程序的图标。

路径匹配和内容协商

Spring MVC 可以通过查看请求路径并将它匹配到应用程序中定义的映射(例如@GetMapping Controller 方法上的注释),将传入的 HTTP 请求映射到处理程序。
Spring Boot 选择默认禁用后缀模式匹配,这意味着请求”GET /projects/spring-boot.json”不会匹配 @GetMapping(“/projects/spring-boot”)映射。这被认为是 Spring MVC 应用程序的 最佳实践。此功能在过去对于没有发送正确的“Accept”请求标头的 HTTP 客户端来说非常有用; 我们需要确保将正确的内容类型发送到客户端。如今,内容协商更可靠。
还有其他一些方法可以处理不一致地发送适当的“接受”请求标头的 HTTP 客户端。我们可以使用查询参数来确保类似的请求”GET /projects/spring-boot?format=json” 将映射到@GetMapping(“/projects/spring-boot”)以下内容,而不是使用后缀匹配:
spring.mvc.contentnegotiation.favor-parameter = true

#我们可以更改参数名称,默认为“格式”:
#spring.mvc.contentnegotiation.parameter-name = myparam

#我们还可以通过以下方式注册其他文件扩展名/媒体类型:
spring.mvc.contentnegotiation.media-types.markdown = text / markdown
如果您了解注意事项并仍然希望应用程序使用后缀模式匹配,则需要进行以下配置:
spring.mvc.contentnegotiation.favor-path-extension = true

#您也可以将该功能限制为已知扩展
#spring.mvc.pathmatch.use-registered-suffix-pattern = true

#我们还可以通过以下方式注册其他文件扩展名/媒体类型:
#spring.mvc.contentnegotiation.media-types.adoc = text / asciidoc

ConfigurableWebBindingInitializer

Spring MVC 使用 WebBindingInitializer 为每个特殊的请求初始化相应的 WebDataBinder,如果你创建自己的 ConfigurableWebBindingInitializer @Bean,Spring Boot 会自动配置 Spring MVC 使用它。

模板引擎

正如 REST web 服务,你也可以使用 Spring MVC 提供动态 HTML 内容。Spring MVC 支持各种各样的模板技术,包括 Velocity, FreeMarker 和 JSPs,很多其他的模板引擎也提供它们自己的 Spring MVC 集成。
Spring Boot 为以下的模板引擎提供自动配置支持:
  1. FreeMarker
  2. Groovy
  3. Thymeleaf
  4. Velocity(1.4 已不再支持)
  5. Mustache
注:由于在内嵌 servlet 容器中使用 JSPs 存在一些已知的限制,所以建议尽量不使用它们。
使用以上引擎中的任何一种,并采用默认配置,则模块会从 src/main/resources/templates 自动加载。
注:IntelliJ IDEA 根据你运行应用的方式会对 classpath 进行不同的排序。在 IDE 里通过 main 方法运行应用,跟从 Maven,或 Gradle,或打包好的 jar 中运行相比会导致不同的顺序,这可能导致 Spring Boot 不能从 classpath 下成功地找到模板。如果遇到这个问题,你可以在 IDE 里重新对 classpath 进行排序,将模块的类和资源放到第一位。或者,你可以配置模块的前缀为 classpath*:/templates/,这样会查找 classpath 下的所有模板目录。

错误处理

Spring Boot 默认提供一个/error 映射用来以合适的方式处理所有的错误,并将它注册为 servlet 容器中全局的 错误页面。对于机器客户端(相对于浏览器而言,浏览器偏重于人的行为),它会产生一个具有详细错误,HTTP 状态,异常信息的 JSON 响应。对于浏览器客户端,它会产生一个白色标签样式(whitelabel)的错误视图,该视图将以 HTML 格式显示同样的数据(可以添加一个解析为’error’的 View 来自定义它)。为了完全替换默认的行为,你可以实现 ErrorController,并注册一个该类型的 bean 定义,或简单地添加一个 ErrorAttributes 类型的 bean 以使用现存的机制,只是替换显示的内容。
注 BasicErrorController 可以作为自定义 ErrorController 的基类,如果你想添加对新 context type 的处理(默认处理 text/html),这会很有帮助。你只需要继承 BasicErrorController,添加一个 public 方法,并注解带有 produces 属性的@RequestMapping,然后创建该新类型的 bean。
你也可以定义一个@ControllerAdvice 去自定义某个特殊 controller 或 exception 类型的 JSON 文档:
@ControllerAdvice(basePackageClasses = FooController.class)
publicclassFooControllerAdviceextendsResponseEntityExceptionHandler{

   @ExceptionHandler(YourException.class)
   @ResponseBody
   ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
       HttpStatus status = getStatus(request);
       returnnew ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
   }

   private HttpStatus getStatus(HttpServletRequest request){
       Integer statusCode = (Integer) request.getAttribute(“javax.servlet.error.status_code”);
       if (statusCode == null) {
           return HttpStatus.INTERNAL_SERVER_ERROR;
       }
       return HttpStatus.valueOf(statusCode);
   }

}

在以上示例中,如果跟 FooController 相同 package 的某个 controller 抛出 YourException,一个 CustomerErrorType 类型的 POJO 的 json 展示将代替 ErrorAttributes 展示。
自定义错误页面
如果想为某个给定的状态码展示一个自定义的 HTML 错误页面,你需要将文件添加到/error 文件夹下。错误页面既可以是静态 HTML(比如,任何静态资源文件夹下添加的),也可以是使用模板构建的,文件名必须是明确的状态码或一系列标签。
例如,映射 404 到一个静态 HTML 文件,你的目录结构可能如下:
src/
+- main/
    +- java/
    |   + <source code>
    +- resources/
        +- public/
            +- error/
            |   +- 404.html
            +- <other public assets>
使用 FreeMarker 模板映射所有 5xx 错误,你需要如下的目录结构:
src/
+- main/
    +- java/
    |   + <sourcecode>
    +- resources/
        +- templates/
            +- error/
            |   +- 5xx.ftl
            +- <othertemplates>
对于更复杂的映射,你可以添加实现 ErrorViewResolver 接口的 beans:
publicclassMyErrorViewResolverimplementsErrorViewResolver{

   @Override
   public ModelAndView resolveErrorView(HttpServletRequest request,
           HttpStatus status, Map<String, Object> model){
       // Use the request or status to optionally return a ModelAndView
       return
   }

}

你也可以使用 Spring MVC 特性,比如@ExceptionHandler 方法和@ControllerAdvice,ErrorController 将处理所有未处理的异常。
映射 Spring MVC 以外的错误页面
对于不使用 Spring MVC 的应用,你可以通过 ErrorPageRegistrar 接口直接注册 ErrorPages。该抽象直接工作于底层内嵌 servlet 容器,即使你没有 Spring MVC 的 DispatcherServlet,它们仍旧可以工作。
@Bean
public ErrorPageRegistrar errorPageRegistrar(){
   returnnew MyErrorPageRegistrar();
}

// …

privatestaticclassMyErrorPageRegistrarimplementsErrorPageRegistrar{

   @Override
   publicvoidregisterErrorPages(ErrorPageRegistry registry){
       registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, “/400”));
   }

}
注.如果你注册一个 ErrorPage,该页面需要被一个 Filter 处理(在一些非 Spring web 框架中很常见,比如 Jersey,Wicket),那么该 Filter 需要明确注册为一个 ERROR 分发器(dispatcher),例如:
@Bean
public FilterRegistrationBean myFilter(){
   FilterRegistrationBean registration = new FilterRegistrationBean();
   registration.setFilter(new MyFilter());
   …
   registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
   return registration;

}

(默认的 FilterRegistrationBean 不包含 ERROR dispatcher 类型)。
WebSphere 应用服务器的错误处理
当部署到一个 servlet 容器时,Spring Boot 通过它的错误页面过滤器将带有错误状态的请求转发到恰当的错误页面。request 只有在 response 还没提交时才能转发(forwarded)到正确的错误页面,而 WebSphere 应用服务器 8.0 及后续版本默认情况会在 servlet 方法成功执行后提交 response,你需要设置 com.ibm.ws.webcontainer.invokeFlushAfterService 属性为 false 来关闭该行为。

Spring HATEOAS

如果正在开发基于超媒体的 RESTful API,你可能需要 Spring HATEOAS,而 Spring Boot 会为其提供自动配置,这在大多数应用中都运作良好。 自动配置取代了@EnableHypermediaSupport,只需注册一定数量的 beans 就能轻松构建基于超媒体的应用,这些 beans 包括 LinkDiscoverers(客户端支持),ObjectMapper(用于将响应编排为想要的形式)。ObjectMapper 可以根据 spring.jackson.*属性或 Jackson2ObjectMapperBuilder bean 进行自定义。
通过注解@EnableHypermediaSupport,你可以控制 Spring HATEOAS 的配置,但这会禁用上述 ObjectMapper 的自定义功能。

CORS 支持

跨域资源共享(CORS)是一个大多数浏览器都实现了的 W3C 标准,它允许你以灵活的方式指定跨域请求如何被授权,而不是采用那些不安全,性能低的方式,比如 IFRAME 或 JSONP。
从 4.2 版本开始,Spring MVC 对 CORS 提供开箱即用的支持。不用添加任何特殊配置,只需要在 Spring Boot 应用的 controller 方法上注解@CrossOrigin,并添加 CORS 配置。通过注册一个自定义 addCorsMappings(CorsRegistry)方法的 WebMvcConfigurer bean 可以指定全局 CORS 配置:
@Configuration
publicclassMyConfiguration{

   @Bean
   public WebMvcConfigurer corsConfigurer(){
       returnnew WebMvcConfigurerAdapter() {
           @Override
           publicvoidaddCorsMappings(CorsRegistry registry){
               registry.addMapping(“/api/**”);
           }
       };
   }
}

    丨极客文库, 版权所有丨如未注明 , 均为原创丨
    本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
    转载请注明原文链接:教你理清 SpringBoot 与 SpringMVC 的关系
    喜欢 (0)
    [247507792@qq.com]
    分享 (0)
    勤劳的小蚂蚁
    关于作者:
    温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

    欢迎 注册账号 登录 发表评论!

    • 精品技术教程
    • 编程资源分享
    • 问答交流社区
    • 极客文库知识库

    客服QQ


    QQ:2248886839


    工作时间:09:00-23:00