Spring Boot、Spring MVC、Spring对比

Spring Boot、Spring MVC、Spring中都有spring这个单词,让我们来看看你应该在哪儿、何时使用这些工具。

在本文,你将鸟瞰Spring、Spring MVC和Spring Boot,了解它们都处理哪些问题,它们最佳应用场景。你将认识到最重要的一点是,它们不是在同一个领域内竞争,它们都在各自的领域很出色地处理问题。

1.Spring框架处理的核心问题是什么?

好好想想,Spring框架处理的是什么问题?其实,Spring框架最核心的特性就是依赖注入(DI,Dependency Injection)。在所有的Spring模块中,最核心的部分都是依赖注入或者叫控制反转(IOC,Inversion of Control)。

为什么依赖注入和控制反转如此重要?因为,通过正确地使用依赖注入和控制反转,我们可以开发出松耦合的应用程序,然后松耦合的应用程序可以很容易地进行单元测试。
让我们来考虑一个小例子:

1.没有依赖注入的例子

考虑下面的例子:WelcomeController依赖WelcomeService去获得欢迎信息(welcome message),WelcomeController要怎么去获取WelcomeService实例呢?

@RestController
public class WelcomeController {
    private WelcomeService service = new WelcomeService();
    @RequestMapping("/welcome")
    public String welcome() {
        return service.retrieveWelcomeMessage();
    }
}

上面的方式,通过WelcomeService service = new WelcomeService();,WelcomeController创建了一个WelcomeService实例,但是它们被紧紧耦合了。例如,如果我想要对WelcomeController进行单元测试,并且mock WelcomeService,我要怎么让WelcomeController使用mock对象呢?不容易!

2.有依赖注入的例子

有依赖注入的世界简单多了,让Spring框架来做艰苦的工作。我们只需要使用两个简单的注解:@Component@Autowired

  • 使用@Component,我们是在告诉Spring框架:嘿,这是个需要你管理的bean。
  • 使用@Autowired,我们是在告诉Spring框架:嘿,给我找到一个最匹配这儿的类型自动装配进来。

在下面的例子中,Spring框架将为WelcomeService创建一个bean,并且自动注入到WelcomeController中。
在单元测试中,我可以要求Spring框架给WelcomeController自动装配一个WelcomeService的mock对象。(Spring Boot通过@MockBean注解让这件事情更容易,不过那又是另外一码事了。)


@Component
public class WelcomeService {
    //Bla Bla Bla
}
@RestController
public class WelcomeController {
    @Autowired
    private WelcomeService service;
    @RequestMapping("/welcome")
    public String welcome() {
        return service.retrieveWelcomeMessage();
    }
}

2.Spring框架还处理什么问题?

问题1:重复代码、样板代码

Spring止步于依赖注入了?不,它在依赖注入的概念上构建了很多其它的Spring模块:

  • Spring JDBC
  • Spring MVC
  • Spring AOP
  • Spring ORM
  • Spring JMS
  • Spring Test

考虑一下Spring JMS和Spring JDBC。这些模块引入了什么新功能么?并没有!我们可以通过J2EE或者Java EE来完成这些所有工作。那么,这些模块引入了什么?它们引入简单的抽象(simple abstractions)。这些抽象的目的是:

  • 减少样板代码/重复代码
  • 推崇解耦合/更易于单元测试

例如,和传统的JDBC和JMS比起来,你只需要写非常少的代码来使用JDBCTemplate或者JMSTemplate。

问题2:和其它框架更好地集成

Spring框架的伟大之处在于,它没有尝试去解决已经解决的问题。它所做的是,集成一些优秀框架:

  • 集成Hibernate来做ORM
  • 集成iBatis(MyBatis)来做对象映射
  • 集成JUnit和Mockito来做单元测试

3.Spring MVC框架主要解决什么问题?

Spring MVC框架为开发web应用提供了解耦合方式。通过简单的概念,如Dispatcher Servlet、ModelAndView和View Resolver,它使得开发web应用变得很简单。

4.我们为什么还需要Spring Boot呢?

基于Spring的应用有很多配置。当我们使用Spring MVC的时候,我们需要配置组件扫描component scan、请求分发器dispatcher servlet、一个视图解析器view resolver、web jars(用于存放静态资源)等其它事情。

  <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
  </bean>
  <mvc:resources mapping="/webjars/**" location="/webjars/"/>

下面的代码片段展示了web应用中配置dispatcher servlet的典型方式:


    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/todo-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

当我们使用Hibernate/JPA的时候,我们需要配置一个数据源datasource,一个实体类管理工厂(entity manager factory),一个事务管理器(transaction manager):

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="${db.driver}" />
        <property name="jdbcUrl" value="${db.url}" />
        <property name="user" value="${db.username}" />
        <property name="password" value="${db.password}" />
    </bean>
    <jdbc:initialize-database data-source="dataSource">
        <jdbc:script location="classpath:config/schema.sql" />
        <jdbc:script location="classpath:config/data.sql" />
    </jdbc:initialize-database>
    <bean
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        id="entityManagerFactory">
        <property name="persistenceUnitName" value="hsql_pu" />
        <property name="dataSource" ref="dataSource" />
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>

问题#1.Spring Boot自动配置:我们可以从不同的角度思考么?

Spring Boot提供了一种新的思考方式:我们可以引入更多的智慧嘛?当spring mvc的jar被添加进入应用,我们不能自动配置一些bean嘛?

  • 如果Hibernate jar在classpath下,怎么自动配置一个DataSource?
  • 如果Spring MVC jar在classpath下,怎么自动配置一个DispatcherServlet?

还应该提供一种可以覆盖自动配置的方式。

Spring Boot通过查看
a)classpath下的可用的框架
b)应用已有的配置
来提供一些需要为集成了这些框架的应用提供一些基础配置,也叫做Auto Configuration(自动配置)。

问题#2.Spring Boot起步工程:建立在众所周知的模式上

比如我们需要开发一个web应用。
首先,我们需要明确我们想使用什么框架,使用哪个版本的框架,怎么将它们连接在一起。
所有的web应用都有类似的需求。下面列举了一些在Spring MVC中会使用到的依赖:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>4.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.2.Final</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

这些依赖包括Spring MVC,Jackson Databind,Hibernate-Validator和Log4j。当开发Spring MVC应用的时候,我们需要选择这些框架的兼容版本。

下面是Spring Boot官方文档关于starters(起步依赖)的描述:

Starters是一系列可以在应用中很方便地使用的依赖描述。你可以获得你需要的所有Spring及其相关的技术的一站式服务,不需要去寻找、拷贝别的工程的依赖。例如,如果你想使用Spring和JPA来做数据访问,只需要在项目中引入spring-boot-starter-data-jpa依赖即可。

让我们看看一个起步依赖的例子:Spring Boot Starter Web。
如果你想要开发一个web应用,或者一个需要暴露restful服务的应用,Spring Boot Starter Web可以拿来用用。我们可以通过使用Spring Initializer来快速创建一个使用了Spring Boot Starter Web的工程。

Spring Boot Starter Web依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

然后你可以在你的应用的依赖中看到:

Spring Boot、Spring MVC、Spring对比
依赖可以被分类为:

  • Spring: core, beans, context, aop
  • Web MVC: (Spring MVC)
  • Jackson: for JSON Binding
  • Validation: Hibernate Validator, Validation API
  • Embedded Servlet Container: Tomcat
  • Logging: logback, slf4j

任何典型的web应用都将使用这些依赖。Spring Boot Starter Web提前把它们打包好了。作为一个开发者,你不用再担心它们之间会有版本冲突了。

Spring Boot Starter项目可选列表:

从Spring Boot Starter Web项目中可以看到,starter工程让我们开发特定类型的应用更快速。还有如下的starter工程可供选择:

  • spring-boot-starter-web-services: SOAP Web Services
  • spring-boot-starter-web: Web and RESTful applications
  • spring-boot-starter-test: Unit testing and Integration Testing
  • spring-boot-starter-jdbc: Traditional JDBC
  • spring-boot-starter-hateoas: Add HATEOAS features to your services
  • spring-boot-starter-security: Authentication and Authorization using Spring Security
  • spring-boot-starter-data-jpa: Spring Data JPA with Hibernate
  • spring-boot-starter-cache: Enabling Spring Framework’s caching support
  • spring-boot-starter-data-rest: Expose Simple REST Services using Spring Data REST

Spring Boot的其它目标

还有一些技术性的starter:

  • spring-boot-starter-actuator: 开箱即用的高级特性,用于监控和追踪你的应用。
  • spring-boot-starter-undertow, spring-boot-starter-jetty, spring-boot-starter-tomcat: 让你选择自己特定的内嵌Servlet容器。
  • spring-boot-starter-logging: 用于使用logback记录日志。
  • spring-boot-starter-log4j2: 用于使用Log4j2记录日志。

原文链接:https://dzone.com/articles/spring-boot-vs-spring-mvc-vs-spring-how-do-they-compare