springmvc迁移springboot之路2

1、常规springmvc的流程

1.1springmvc的启动过程

首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;

其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;

再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。

1.2spring mvc工作流程图

Spring工作流程描述

springmvc迁移springboot之路2_第1张图片

1.用户向服务器发送请求,请求被Spring前端控制Servelt DispatcherServlet捕获;

2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

3. DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)

4.提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息

数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

数据根式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等;

数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中;

5.  Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象;

6.根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet;

7. ViewResolver结合Model和View,来渲染视图

8.将渲染结果返回给客户端。

2springboot搭建

2.1选取ide工具

下图是spring官网提供的ide工具

springmvc迁移springboot之路2_第2张图片

要创建springboot项目可以下载spring官网提供的sts这款IDE,自动集成了创建boot项目所需的插件,当然对使用eclipse的开发者也可以安装对应系统的插件进行构建boot项目。

2.2创建项目

File> New > Spring Starter Project

springmvc迁移springboot之路2_第3张图片
springmvc迁移springboot之路2_第4张图片

Next> Finish

项目创建完成:

springmvc迁移springboot之路2_第5张图片

可以看出,项目源码就一个Java类,在pom.xml中有spring-boot-starter-web的依赖。

SpringBootSampleApplication.java

packageorg.springboot.sample;

importorg.springframework.boot.SpringApplication;

importorg.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

publicclass SpringBootSampleApplication {

public static void main(String[] args) {

SpringApplication.run(SpringBootSampleApplication.class,args);

}

}

pom.xml


4.0.0

org.springboot.sample

spring-boot-sample

0.0.1-SNAPSHOT

jar

spring-boot-sample

Spring Boot Sample WebApplication

org.springframework.boot

spring-boot-starter-parent

1.3.1.RELEASE


UTF-8

1.8

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-maven-plugin

这样就完成了项目的创建,下面我们创建一个HelloController.java定义3个方法

packageorg.springboot.sample.controller;

importjava.util.ArrayList;

importjava.util.HashMap;

importjava.util.List;

importjava.util.Map;

importorg.springframework.web.bind.annotation.RequestMapping;

importorg.springframework.web.bind.annotation.RequestParam;

importorg.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping("/hello")

publicclass HelloController {

@RequestMapping

public String hello() {

return "Hello Spring-Boot";

}

@RequestMapping("/info")

public Map getInfo(@RequestParamString name) {

Map map = newHashMap<>();

map.put("name", name);

return map;

}

@RequestMapping("/list")

public List>getList() {

List> list= new ArrayList<>();

Map map = null;

for (int i = 1; i <= 5; i++) {

map = new HashMap<>();

map.put("name", "Shanhy-"+ i);

list.add(map);

}

return list;

}

}

然后现在可以直接运行SpringBootSampleApplication的main方法,和执行普通java程序一样。

然后可以看到spring-boot内置server容器(默认为Tomcat),这一切spring-boot都帮我们做好了。

控制台输出内容Started SpringBootSampleApplication in 7.358 seconds (JVM running

for 9.154)表示服务已经启动。

在浏览器输入我们3个请求便可看到结果。http://localhost:8080/hello

输出:HelloSpring-Boothttp://localhost:8080/hello/info?name=shanhy

输出:{“name”:”shanhy”}http://localhost:8080/hello/list

输出:[{“name”:”Shanhy-1”},{“name”:”Shanhy-2”},{“name”:”Shanhy-3”},{“name”:”Shanhy-4”},{“name”:”Shanhy-5”}]

通过我们的Hello实例,相信大家一目了然,可谓spring-boot创建一个项目如此简单,完全可以在几分钟内将服务启动。spring-boot抛弃繁琐的配置,让开发人员更专注与业务逻辑的实现。后面几篇文章将会对spring-boot的多个方面通过实例的方式呈现给大家。

3springboot的运行原理

系统启动类视图如下:

springmvc迁移springboot之路2_第6张图片

可以发现启动类有个@SpringBootApplication注解,这是一个组合注解,结构如下图:

springmvc迁移springboot之路2_第7张图片

@SpringBootApplication注解的功能主要由@ EnableAutoCongiguration、@componentScan组成。

@EnableAutoCongiguration负责启动自动配置功能,在main方法中的SpringApplication启动的方法中,如下图:

springmvc迁移springboot之路2_第8张图片
springmvc迁移springboot之路2_第9张图片

在SpringApplication启动时,依据@ EnableAutoCongiguration设定的自动配置功能,有一部分功能是去扫描maven内所有jar包下的spring.factories文件,构建成一个配置文件链表,如果系统有引用,则根据条件注解去初始化bean,例如:

springmvc迁移springboot之路2_第10张图片

@componentScan负责扫描启动类所在package下子package的所有需要实例化的bean的IOC,比如@controller、@service、@Component、@Configuration、@bean等。

boot提供了默认的配置文件:application.xml,集成了各类starter服务的配置属性定制化,简单举几个例子:

日志配置

springmvc迁移springboot之路2_第11张图片

web服务器配置

springmvc迁移springboot之路2_第12张图片

模板配置

springmvc迁移springboot之路2_第13张图片

http编码、json和微服务配置

springmvc迁移springboot之路2_第14张图片

mvc交互配置

springmvc迁移springboot之路2_第15张图片

认证配置

springmvc迁移springboot之路2_第16张图片

还有spring.data.*和spring.datasource.*的异构数据源的配置等等,具体详情参考

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/

4springmvc迁移springboot

4.1零配置

常规springmvc的整体结构如下图:


springmvc迁移springboot之路2_第17张图片

springboot的整体结构如下图:


springmvc迁移springboot之路2_第18张图片

综合对比,springmvc要迁移springboot,首当其中的就是springboot是如何去XML(web.xml和applicationcontext.xml)的。

去web.xml:依赖内置web服务器启动初始化应用的上下文;

去applicationcontext.xml:依赖java注解和条件注解技术,使用自动配置功能实现。

4.2web.xml

对于一些springboot

application.xml中没有的服务,有三种解决方式:

1、自定义starter pom

2、原始方式自己编写服务

3、原始引用XML

对于springboot服务不好用,想进行变更的,boot设计中为它的任何一个服务都提供了可扩展性的方式进行变更,比如如何解决web.xml内配置的filter、Listener、Interceptor等,可通过注解方式(比如@Component、@Configuration)自行扩展对应的服务。

5样例

5.1pom文件配置


springmvc迁移springboot之路2_第19张图片
springmvc迁移springboot之路2_第20张图片
springmvc迁移springboot之路2_第21张图片

5.2application.xml配置

环境分流配置

springmvc迁移springboot之路2_第22张图片

开启shutdown功能

springmvc迁移springboot之路2_第23张图片

配置内容

springmvc迁移springboot之路2_第24张图片

5.3平滑升级


springmvc迁移springboot之路2_第25张图片

6总结

使用springboot,首选需要判断boot是否提供了服务,boot有一些服务是自动配置加载的,有一些服务是需要enable*打开才能用的,比如定时@EnableScheduling、异步@EnableAsync服务等,如果boot目前还无法定制某项目的个性化服务,可自行扩展,扩展方式参考4.2小节描述内容。

对于jar包版本一致性问题也是同理,先判断boot是否提供了对应的jar服务,决定是否需要自行扩展。

springboot可以导出jar包也可以导出war包,war包基本依赖外部应用服务器,可以利用外部应用服务器的shutdown功能平滑升级。但jar包形式依赖linux sh脚本的运行,基本都会使用kill去暴力杀线程,这是会影响线上业务的,所以为了保证线上线程不会突然崩溃影响业务,sringboot也考虑了这一点,在监控Actuator中提供了优雅的shutdown功能,只要我们在sh脚本中访问线上服务的shutdown地址,即可优雅的关闭线上服务,平滑升级了。

你可能感兴趣的:(springmvc迁移springboot之路2)