1.4 传统Spring MVC和Spring Boot的对比
在传统的Spring MVC项目开发中,开发一个简易的Spring MVC项目,需要配置DispatcherServlet,也需要配置Spring IoC的容器。你可以选择使用web.xml的配置来实现,当然,如果你使用的是Servlet 3.1规范,也可以继承由Spring MVC提供的AbstractAnnotationConfigDispatcherServletInitializer来配置Spring MVC项目。这里先给出可以运行的代码示例,即使你还不熟悉Spring MVC也没有关系,这里只是为了说明开发比较烦琐而已,后面将详谈Spring MVC的开发原理。
假设你已经导入需要的Spring和Spring MVC相关的依赖包到工程中,那么就可以开始配置DispatcherServlet了。例如,代码清单1-1就是通过继承AbstractAnnotationConfigDispatcherServletInitializer的方式来配置Spring MVC的DispatcherServlet的。
代码清单1-1 配置Spring MVC
package com.springboot.springmvc.conf; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { // Spring IoC容器配置 @Override protected Class<?>[] getRootConfigClasses() { // 可以返回Spring的Java配置文件数组 return new Class<?>[] {}; } // DispatcherServlet的URI映射关系配置 @Override protected Class<?>[] getServletConfigClasses() { // 可以返回Spring的Java配置文件数组 return new Class<?>[] { WebConfig.class }; } // DispatcherServlet拦截请求匹配 @Override protected String[] getServletMappings() { return new String[] { "*.do" }; } }
注意代码中加粗的地方。这里引入了一个Java配置文件—— WebConfig.java,它的主要作用是配置Spring MVC的核心类DispatcherServlet的上下文,如代码清单1-2所示。
代码清单1-2 配置DispatcherServlet的上下文
package com.springboot.springmvc.conf; import java.util.ArrayList; import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.http.MediaType; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration // 定义Spring MVC扫描的包 @ComponentScan(value="com.*", includeFilters = {@Filter(type = FilterType.ANNOTATION, value = Controller.class)}) // 启动Spring MVC配置 @EnableWebMvc public class WebConfig { /*** * 通过注解@Bean初始化视图解析器 * * @return ViewResolver视图解析器 */ @Bean(name = "internalResourceViewResolver") public ViewResolver initViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/jsp/"); viewResolver.setSuffix(".jsp"); return viewResolver; } /** * 初始化RequestMappingHandlerAdapter,并加载HTTP的JSON转换器 * * @return RequestMappingHandlerAdapter 对象 */ @Bean(name = "requestMappingHandlerAdapter") public HandlerAdapter initRequestMappingHandlerAdapter() { // 创建RequestMappingHandlerAdapter适配器 RequestMappingHandlerAdapter rmhd = new RequestMappingHandlerAdapter(); // HTTP JSON转换器 MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); // MappingJackson2HttpMessageConverter接收JSON类型消息的转换 mediaType = MediaType.APPLICATION_JSON_UTF8; List<MediaType> mediaTypes = new ArrayList<MediaType>(); mediaTypes.add(mediaType); // 加入转换器的支持类型 jsonConverter.setSupportedMediaTypes(mediaTypes); // 给适配器加入JSON转换器 rmhd.getMessageConverters().add(jsonConverter); return rmhd; } }
通过上面的代码,配置完成Spring MVC的开发环境后,才可以开发Spring MVC控制器Controller,这样就可以开发一个简单的控制器(Controller),如代码清单1-3所示。
代码清单1-3 开发Spring MVC控制器
package com.springboot.springmvc.controller; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class TestController { @RequestMapping("/test") @ResponseBody public Map<String, String> test() { Map<String, String> map = new HashMap<String, String>(); map.put("key", "value"); return map; } }
这样就完成了一个传统Spring MVC的开发,但是你还需要第三方服务器,如Tomcat、WebLogic等服务器去部署你的工程。在启动服务器后,再打开浏览器,输入对应的URL,如项目名称为SpringMVC则输入http://localhost:8080/SpringMVC/test.do,就可以得到图1-1所示的页面。
图1-1 测试传统的Spring MVC项目
从上面来看,传统的Spring MVC开发需要配置的内容还是比较多的,而且对设计人员要求较高。开发完成后,开发者还需要找到对应的服务器去运行,如Tomcat或者Jetty等,这样既要进行开发,又要进行配置和部署,工作量还是不少的。
而使用Spring Boot开发后,你就会发现原来一切可以那么简单。不过在入门阶段暂时不需要讨论太多的细节问题,这是未来需要讨论的问题,所以这里只展示它是如何简单而已。首先我们在IDE中创建一个Maven工程,并把其名称定义为Chapter1,这样就可以看到一个Maven配置文件pom.xml,将其内容修改为如代码清单1-4所示。
代码清单1-4 配置Spring Boot依赖环境
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>springboot</groupId> <artifactId>chapter1</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>chapter1 Maven Webapp</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- Spring Boot Starter依赖引入 --> <!-- AOP包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- Web开发包,将载入Spring MVC所需要的包,且内嵌tomcat --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--加载测试依赖包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- 引入插件 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
从加粗的代码中可以看到Maven的配置文件引入了多个Spring Boot的starter,Spring Boot会根据Maven配置的starter去寻找对应的依赖,将对应的jar包加载到工程中,而且它还会把绑定的服务器也加载到工程中,这些都不需要你再进行处理。正如Spring Boot承诺的那样,绑定服务器,并且实现Spring的尽可能的配置,采用约定优于配置的原则。这里我们只需要开发一个类就可以运行Spring Boot的应用了,为此新建类——Chapter1Main,如代码清单1-5所示。
代码清单1-5 开发Spring Boot应用
package com.springboot.chapter1; import java.util.HashMap; import java.util.Map; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller // 启用Spring Boot自动装配 @EnableAutoConfiguration public class Chapter1Main { @RequestMapping("/test") @ResponseBody public Map<String, String> test() { Map<String, String> map = new HashMap<String, String>(); map.put("key", "value"); return map; } public static void main(String[] args) throws Exception { SpringApplication.run(Chapter1Main.class, args); } }
好了,这个入门实例已经完结了。如果你没有接触过Spring Boot那么你会十分惊讶,这样就配置完成Spring MVC的内容了吗?我可以回答你:“是的,已经完成了,现在完全可以使用Java Application的形式去运行类Chapter1Main。”下面是Spring Boot的运行日志:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.0.RELEASE) 2018-03-01 22:21:55.843 INFO 16324 --- [ main] com.springboot.chapter1.Chapter1Main : Starting Chapter1Main on AFOIF-703271542 with PID 16324 (G:\springboot\v2\chapter1\target\classes started by Administrator in G:\springboot\v2\chapter1) ...... 2018-03-01 22:21:57.270 INFO 16324 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/test]}" onto public java.util.Map<java.lang.String, java.lang.String> com.springboot.chapter1.Chapter1Main.test() ...... 2018-03-01 22:21:57.270 INFO 16324 --- [ main] com.springboot.chapter1.Chapter1Main : Started Chapter1Main in 1.845 seconds (JVM running for 2.143)
从日志中可以看到,Tomcat已经启动,并且将我们开发的Chapter1Main作为Spring MVC的控制器加载进来了,也将对应的路径(/test)映射到开发的test方法上。因此,接下来就可以进行测试了。打开浏览器,在地址栏输入http://localhost:8080/test,可以看到如图1-2所示的结果。
图1-2 Spring Boot运行结果
与传统的Spring MVC是不是很不一样呢?从上面的对比可以看出,Spring Boot 允许直接进行开发,这就是它的优势。在传统所需要配置的地方,Spring Boot都进行了约定,也就是你可以直接以Spring Boot约定的方式进行开发和运行你的项目。当你需要修改配置的时候,它也提供了一些快速配置的约定,犹如它所承诺的那样,尽可能地配置好Spring项目和绑定对应的服务器,使得开发人员的配置更少,更加直接地开发项目。对于那些微服务而言,更喜欢的就是这样能够快速搭建环境的项目,而Spring Boot提供了这种可能性,同时Spring Boot还提供了监控的功能,随着云技术的到来,微服务成了市场的热点,于是代表Java微服务时代的Spring Boot微服务开发的时代已经到来,结合Spring Cloud后它还能很方便地构建分布式系统开发,满足大部分无能力单独开发分布式架构的企业所需,所以这无疑是激动人心的技术。后面的章节让我们走进Spring Boot开发的森林中。