Spring第二讲:SpringBoot 原理及应用

SpringBoot简化了Spring配置文件,无需再使用SpringMVC,只需要引入相关的starter即可。本文是Spring第二讲:SpringBoot 原理及应用

文章目录

      • 1、Springboot是什么
      • 2、Springboot原理(**@Conditonal是核心**)
      • 3、Springboot的整合技术
      • 4、SpringBoot 单元测试
      • 5、Springboot自定义starter
      • 6、Springboot与Redis缓存
      • 7 Springboot与消息中间件
      • 8 Springboot与任务 20210307补
      • 9、Springboot与ElasticSearch
      • 10 Springboot与安全
      • 11、Springboot与分布式
      • 12、Springboot与热部署
      • 13、Springboot与监控管理Actuator
      • 14、Springboot与Spring比较?
      • 15、Springboot配置加载优先级?

1、Springboot是什么

1、定义

  • 简化了Spring配置文件,使用默认开发配置来实现快速开发,无需再使用springMVC,只需要引入相关的starter即可

2、Springboot的特点?

  • 约定优于配置:SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml (application.yaml)进行配置(yaml文件更加结构化,比json占用字符少)
  • 通过整合通用实践,更加自动、智能的依赖管理等,Spring Boot提供了各种典型应用领域的快速开发基础,所以它是以应用为中心的框架集合(如:内嵌servlet容器)
  • 通过起步依赖和自动配置简化开发;可以对Spring的配置进行简化

3、SpringBoot注解大全:

  • @ComponentScan指定了扫描指定基本包下的类;
  • @SpringbootConfiguration标注该类是Spring的一个配置类
  • @EnableAutoConfiguration是SpringBoot自动配置功能开启的注解

2、Springboot原理(@Conditonal是核心

Springboot原理:几个重要的事件回调机制,配置在META_INF/spring.factories ApplicationContextInitializer/SprigApplicationRunListener

Springboot启动会加载大量的自动配置类;我们看需要的功能有没有Springboot默认写好的自动配置类;再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件有,我们就不需要再来配置);给容器中自动配置类添加组件时,会从properties类中获取某些属性,我们就可以在配置文件中指定这些属性的值。

运作原理:从@SpringbootApplication注解开始,这是一个组合注解,核心功能时@EnableAutoConfiguration注解提供的;
@EnableAutoConfiguration关键的@Import导入的类有EnableAutoConfigurationImportSelector使用springFactoriesloader.loadFactoryNames方法扫描具有META-INF/spring.factories文件的jar包,里面声明了哪些自动配置。

核心注解:打开任意一个AutoConfiguration文件,一般都有下面的条件注解,例如autoconfigure.condition包下条件注解
@ConditionalOnBean:容器中有指定的Bean的条件下 @ConditionalOnClass:当类路径下有指定的类的条件下 @ConditionalOnExpression 基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件 @ConditionalONMissingBean:容器中没有指定Bean的情况下 @ConditionalOnWebApplication:当前项目是web项目的条件下 等
这些注解组合了@Conditional元注解,只是使用了不同的条件。

核心功能:

  • 1、独立运行的Spring项目,springboot可以以jar包形式独立运行,运行项目只需通过java -jar xx.jar来运行
  • 2、内嵌Servlet容器,可以内嵌Tomcat/jetty,我们无需以war包形式部署项目
  • 3、提供starter简化Maven配置:springboot提供一系列的starter pom来简化Maven的依赖加载,例如导入springboot-starter-web时,自动会导入所有相关依赖包
  • 4、自动配置Spring:Springboot会根据类路径中的jar包、类,为jar包里的类自动配置Bean,这样会极大减少我们需要的配置,也可以自定义自动配置
  • 5、准生产的应用监控:springboot提供基于http/ssh/telnet对运行时的项目进行监控
  • 6、无代码生成和xml配置:通过spring4.x提供的条件注解,使用java配置+注解配置组合,不再需要任何xml配置即可实现Spring所有配置

java配置:java Config提供了配置spring ioc容器的纯java方法,有助于避免使用xml配置,优点在于

  • 1、面向对象的配置,用户能充分利用java中的面向对象功能,一个配置类可以继承另一个,重写它的@Bean方法
  • 2、较少或消除xml配置
  • 3、类型安全和重构友好:javaConfig提供了一种类型安全的方法来配置Spring容器,由于java5对泛型的支持,现在可以按类型而不是按名称检索bean,不需要任何强制转换或基于字符串的查找

3、Springboot的整合技术

日志管理(slf4j日志抽象层+logback日志实现层)

  • 整合Mybatis时,可以在application.properties中配置mybatis.mapper-locations指定要加载的映射文件
  • 整合Junit时,需要在测试类上添加@RunWith(SpringRunner.class)
  • 整合SpringData JPA时,需要添加SpringData JPA的起步依赖spring-boot-starter-data-jpa
  • 整合JPA可以实现分页和排序,将可分页的org.springframework.data.domain.Pageable传递给存储库方法

4、SpringBoot 单元测试

1、首先引入maven文件

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-testartifactId>
    <scope>testscope>
dependency>

SpringBoot提供了spring-boot-start-test启动器,该启动器提供了常见的单元测试库:

  • JUnit: 一个Java语言的单元测试框架
  • Spring Test & Spring Boot Test:为Spring Boot应用提供集成测试和工具支持
  • AssertJ:支持流式断言的Java测试框架
  • Hamcrest:一个匹配器库
  • Mockito:一个java mock框架
  • JSONassert:一个针对JSON的断言库
  • JsonPath:JSON XPath库

2、常用注解

  • @RunWith(SpringRunner.class)
    JUnit运行使用Spring的测试支持。SpringRunner是SpringJUnit4ClassRunner的新名字

  • @SpringBootTest
    该注解为SpringApplication创建上下文并支持Spring Boot特性,其webEnvironment提供如下配置:Mock-加载WebApplicationContext并提供Mock Servlet环境,嵌入的Servlet容器不会被启动。RANDOM_PORT-加载一个EmbeddedWebApplicationContext并提供一个真实的servlet环境。嵌入的Servlet容器将被启动并在一个随机端口上监听。DEFINED_PORT-加载一个EmbeddedWebApplicationContext并提供一个真实的servlet环境。嵌入的Servlet容器将被启动并在一个默认的端口上监听(application.properties配置端口或者默认端口8080)。NONE- 使用SpringApplication加载一个ApplicationContext,但是不提供任何的servlet环境。

  • @MockBean
    在你的ApplicationContext里为一个bean定义一个Mockito mock。

  • @SpyBean
    定制化Mock某些方法。使用@SpyBean除了被打过桩的函数,其它的函数都将真实返回。

  • @WebMvcTest
    该注解被限制为一个单一的controller,需要利用@MockBean去Mock合作者(如service)。

3、测试Controller

  • 在测试Controller时需要进行隔离测试,这个时候需要Mock Service层的服务
@RunWith(SpringRunner.class)
@WebMvcTest(ScoreController.class)
public class ScoreControllerTestNew {
    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private ICalculateService calculateService;
    @MockBean
    private IModelMonitorService modelMonitorService;
    @MockBean
    private IScoreConfigService scoreConfigService;
    @MockBean
    private IModelProductService modelProductService;
    @Before   初始化工作
    public void setUp(){
    }
    @Test
    public void testScore() throws Exception {
        given(this.modelProductService.get(anyLong())).willReturn(null);
        String jsonStr = "{\"data\":{\"debit_account_balance_code\":40,\"credit_consume_count\":1,\"debit_start_age\":1,\"debit_consume_sum_code\":2,\"age\":38},\"modelProductId\":5}";
        RequestBuilder requestBuilder = null;
        requestBuilder = post("/scoreApi/score").contentType(MediaType.APPLICATION_JSON).content(jsonStr);
        this.mockMvc.perform(requestBuilder).andExpect(status().isOk()).andExpect(MockMvcResultMatchers.content().string("{}"));
    }
}

4、测试Service

  • 测试Service和测试Controller类似,同样采用隔离法
@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceTest {
    @MockBean
    private ModelMonitorMapper modelMonitorMapper;
    @Autowired
    private IModelMonitorService modelServiceServiceImpl;
    @Test
    public void testModelServiceServiceImpl(){
        given(modelMonitorMapper.insert(anyObject())).willReturn(0);
        int n =  modelServiceServiceImpl.insert(new ModelMonitor());
        assertThat(n).isEqualTo(0);
    }
}

5、测试Dao

  • 测试的时候为了防止引入脏数据使用注解@Transactional和@Rollback在测试完成后进行回滚。
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class ScoreControllerTestNew {
    @Autowired
    private ModelMonitorMapper modelMonitorMapper;
    @Test
    @Rollback
    public void testDao() throws Exception {
        ModelMonitor modelMonitor = new ModelMonitor();
        modelMonitor.setModelProductId(Long.parseLong("5"));
        modelMonitor.setLogit(21.144779999999997);
        modelMonitor.setDerivedVariables("{\"debit_account_balance_code\":1.0,\"credit_consume_count\":1.0,\"debit_start_age\":1.0,\"debit_consume_sum_code\":1.0,\"age\":1.0}");
        modelMonitor.setScore("300");
        modelMonitor.setSrcData("{\"data\":{\"debit_account_balance_code\":40,\"credit_consume_count\":1,\"debit_start_age\":1,\"debit_consume_sum_code\":2,\"age\":38},\"modelProductId\":5}");
        int n = modelMonitorMapper.insert(modelMonitor);
        assertThat(n).as("检查数据是否成功插入").isEqualTo(0);
    }
}

5、Springboot自定义starter

如何理解starter

  • 使用Spring+SpringMVC框架进行开发时,如果需要引入MyBatis框架,那么需要在xml中定义需要的bean对象,这个过程很明显是很麻烦的,如果需要引入额外的组件,那么也需要进行复杂的配置,因此在SpringBoot中引入了starter
  • starter是一个jar包,写一个@Configuration 配置类,将这些bean定义在其中,然后再starter包的META_INF/spring.factories 中写入配置类,那么SpringBoot程序在启动时就会按照约定来加载该配置类
  • 开发人员只需要将相应的starter包依赖进应用中,进行相关的属性配置,就可以进行代码开发,而不需要单独进行bean对象的配置。

开发技巧:

  • 1、模板引擎页面修改后要实时生效则禁用模板引擎的缓存,页面修改完成Ctrl+f9,重新编译

  • 2、F5重新提交的问题:拦截器进行登录检查

  • 3、jdk1.8.0_131/maven3.3.9/idea2017.2.2/springboot1.5.19 springboot不支持jsp,默认使用模板引擎(freemarker/thymeleaf),得注意版本间适配的问题,以免发生错误

    Springboot Rest风格的注解:原来@RequestMapping;现在:@PostMapping增加/@GetMapping查询/@PutMapping修改/@DeleteMapping删除;spring4.2之后:使用@RestController代替@ResponseBody+@Controller
    可以启动springMVC的自动配置@EnableWebMvc,对于浏览器返回modelAndview,对于客户端,返回json数据

springboot配置嵌入式servlet容器(tomcat/jetty长连接/Undertow不支持jsp):嵌入式的tomcat只能执行jar项目,由IOC容器带动嵌入式tomcat,若是使用外置tomcat,则可以运行war项目,此时,pom.xml文件server-tomcat的scope设置为provided
Docker容器技术,用于管理框架的自动配置,不需要重复配置
Springboot整合jdbc/mybatis/spribgdataJPA:jdbc的连接池tomcat.jdbc.pool.DataSource ,数据源使用Druid连接池更常见(可以查看SQL监控,web应用统计,jdbc执行数时间);mybatis配置ConfigurationCustomizer
开启驼峰命名法,使用MapperScan注解批量扫描Mapper接口

6、Springboot与Redis缓存

Springboot自身的缓存在ConcurrentMap<>中,在实际开发中我们使用缓存中间件
几个重要的概念

  • Cache:缓存接口,定义缓存操作,实现类有redisCache、EhCacheCache、ConcurrentMapCache等
  • CacheManager:缓存管理器,管理各种缓存组件(cache)
  • @Cacheable:主要针对方法配置,能够根据方法的请求对其结果进行缓存
  • @CacheEvict:清空缓存
  • @CachePut:保证方法被调用,又希望结果被缓存
  • @EnableCaching:开启基于注解的缓存
  • keyGenerator:缓存数据时key生成策略
  • serialize:缓存数据时value序列化策略

@Cacheable/@CachePut的区别:前者先调缓存,后者先更新方法,在把结果存在缓存中,两者可以结合使用(@caching),注意:要保证取缓存的key和存缓存的key是一致的
几个属性:

  • cacheNames/value:指定缓存组件的名字;
  • key:缓存数据使用的key,可以用它来指定,默认是使用方法参数的值 1-方法的返回值编写SpEL, #id 参数id的值
  • keyGenerater:key的生成器,可以自己指定key的生成器的组件id
  • key/keyGenerator:二选一使用
  • cacheManager:指定符合条件的情况下才缓存; condition=“#id>0”
  • unless:否定缓存,当unless指定的条件为true,方法的返回值就不会被缓存,可以获取到结果进行判断
  • sync:是否使用异步模式

redis数据类型 去看数据库部分
springboot redis保存数据:1、以jdk底层序列化方式 默认 2、json格式的序列化器,底层是jackson2的jar包

7 Springboot与消息中间件

kafka/activeMQ/RabbitMQ 以rabbitMQ为例,端口号5672(客户端访问)/15672(访问管理页面) 引入的依赖项springboot-starter-activemq
MQ的作用:异步处理/应用解耦/流量削峰(秒杀)
JMS:java消息服务 ActiveMQ(队列类型有queue/topic)AMQP:高级消息队列协议 rabbitMQ(交换器类型有direct/fanout/topic)

  • 我们公司整合的是阿里云提供的RocketMQ

8 Springboot与任务 20210307补

异步任务 @Async注解 开启@EnableAsync
定时任务 @EnableScheduling @Scheduled
邮件任务 pop3 smtp
同类产品 quartz

接入ElasticJob
1、引入配置

<dependency>
	<groupId>cn.gov.zcy.bootgroupId>
	<artifactId>spring-boot-starter-elasticjobartifactId>
	<version>3.0.2-RELEASEversion>
dependency>

2、配置中心配置项

  • spring-boot-starter-elasticjob 支持多个定时任务的配置,如上所示,显而易见elasticjobs 是一个数组。
  • namespace 请使用默认值,不需要动
  • jobName 给你的定时任务请个英文名吧
  • cron cron表达式,不必详说
  • shardingCount 分片数量
  • jobType ,job类型,0- 简单任务,1-数据流任务(熟悉tbshecuPle就不陌生了),2-脚本任务
  • itemParams, 任务项,自定义项
  • classFullName,自定义的类,完全限定名
  • streamingProcess 使用默认值,数据流任务使用
  • scriptCmdLine 脚本任务使用
  • dataSource 很简单不必详说
  • needLog: false 这一项一定要设为false,实际中发现开启了数据库日志功能后,对数据库造成的压力很大,而且记录的数据基本没有什么价值 以上的配置中如:zk、数据源请使用项目中通用的配置即可
elasticjobs:
-
zk: ${zookeeper.cluster}
namespace: zcy-elastic-job-${zcy.env.label}
jobName: test-case-1 
cron: 0/2 * * * * ? 
shardingCount: 4
jobType: 0
itemParams: 0=Beijing,1=Shanghai,2=Guangzhou  
classFullName: com.MySimpleJob
streamingProcess: false
needLog: false
overwrite: true
scriptCmdLine:

3、 代码编写

  • 如果是简单任务,请实现 com.dangdang.ddframe.job.api.simple.SimpleJob 接口
  • 如果使用数据流任务,请实现 com.dangdang.ddframe.job.api.dataflow.DataflowJob 接口
  • 如果是脚本任务,请实现 com.dangdang.ddframe.job.api.script.ScriptJob

4、问题排查

4.1、遇到错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘cn.gov.zcy.elasticjob.config.ElasticJobConfig’: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: org/apache/curator/connection/ConnectionHandlingPolicy

解决办法:

  • 检查直接依赖、间接依赖,将curator-framework、curator-client、curator-recipes 三个jar版本都改为 2.10.0 即可

4.2、在job任务接口实现类中,如果需要获取spring context,可以使用工具类

  • SpringContext.getBean(“xxxxx”)

4.3、启动报错:

Caused by: java.lang.NoSuchMethodError: com.google.gson.stream.JsonWriter.jsonValue(Ljava/lang/String;)Lcom/google/gson/stream/

解决方法:

  • 将gson 升级到2. 6.1

4.4、问题反馈

  • 如果本地启动时,没有找到apollo中配置的ElasticJob配置项,程序启动会报错

5、ElasticJob 原理分析

9、Springboot与ElasticSearch

elasticsearch初始会使用2G的堆空间,可通过docker run -e ES_java-_OPTS="-Xms 256m -Xmx 256m" -d -p 9200:9200 -p 9300:9300 --name ES01 镜像名 来启动
版本适配的问题:可以升级springboot版本1.5.19(不推荐),可以降ES的版本(使用2.4.6版本)

10 Springboot与安全

shiro或security 注解@EnableWebSecurity 引入依赖:spring-boot-starter-security ,配置类必须扩展WebSecurityConfigurerAdapter并覆盖其方法。
1、Spring security与apache shiro的对比?

11、Springboot与分布式

在分布式系统中国,国内常用zookeeper+dubbo组合(我们公司的分布式框架组合),而springboot推荐使用全栈的Spring(springboot+springcloud)

12、Springboot与热部署

在开发中修改了一个java文件后想看到效果不得不重启应用,希望能在不重启应用的情况下,程序可以自动部署(该模块在生产环境中被禁用)
Spring Loaded/JRebel/springboot Devtools

13、Springboot与监控管理Actuator

作用:帮助我们访问生产环境中正在运行的应用程序的当前状态,监视器模块公开了一组可直接作为HTTP URL访问的REST端点来检查状态 .beans 容器中所有bean的信息;autconfig所有自动配置信息 auditevents审计信息 configprops 所有配置属性 dump线程状态信息 env当前环境信息 health应用健康状态; info当前应用信息 metrics应用的各项指标 mappings应用@RequestMapping映射路径 shutdown关闭当前应用 trace追踪信息

14、Springboot与Spring比较?

1、依赖注入 Spring:构造器注入xml文件 springboot:@Bean(value)+java配置
2、包扫描 spring:< context:component-scan> springboot:@ComponentScan(value)

15、Springboot配置加载优先级?

1. 加载位置与顺序
SpringBoot启动会扫描以下位置的application.properties/yml文件作为spring boot的默认配置文件:

file:./config/    file: 指当前项目根目录
file:./
classpath:/config/    classpath: 指当前项目的resources目录
classpath:/

以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置的内容,并形成互补配置;当然,我们也可以通过spring.config.location来改变默认配置
在这里插入图片描述

  • 注意:maven打包是不能把src外面的两个application.properties文件打到jar包里的

你可能感兴趣的:(深入理解Spring生态,SpringBoot,原理及应用,Spring)