SpringBoot简化了Spring配置文件,无需再使用SpringMVC,只需要引入相关的starter即可。本文是Spring第二讲:SpringBoot 原理及应用
1、定义
2、Springboot的特点?
3、SpringBoot注解大全:
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元注解,只是使用了不同的条件。
核心功能:
java配置:java Config提供了配置spring ioc容器的纯java方法,有助于避免使用xml配置,优点在于
日志管理(slf4j日志抽象层+logback日志实现层)
1、首先引入maven文件
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
SpringBoot提供了spring-boot-start-test启动器,该启动器提供了常见的单元测试库:
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
@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
@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
@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);
}
}
如何理解starter
开发技巧:
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接口
Springboot自身的缓存在ConcurrentMap<>中,在实际开发中我们使用缓存中间件
几个重要的概念
@Cacheable/@CachePut的区别:前者先调缓存,后者先更新方法,在把结果存在缓存中,两者可以结合使用(@caching),注意:要保证取缓存的key和存缓存的key是一致的
几个属性:
redis数据类型 去看数据库部分
springboot redis保存数据:1、以jdk底层序列化方式 默认 2、json格式的序列化器,底层是jackson2的jar包
kafka/activeMQ/RabbitMQ 以rabbitMQ为例,端口号5672(客户端访问)/15672(访问管理页面) 引入的依赖项springboot-starter-activemq
MQ的作用:异步处理/应用解耦/流量削峰(秒杀)
JMS:java消息服务 ActiveMQ(队列类型有queue/topic)AMQP:高级消息队列协议 rabbitMQ(交换器类型有direct/fanout/topic)
异步任务 @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、配置中心配置项
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、 代码编写
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
解决办法:
4.2、在job任务接口实现类中,如果需要获取spring context,可以使用工具类
4.3、启动报错:
Caused by: java.lang.NoSuchMethodError: com.google.gson.stream.JsonWriter.jsonValue(Ljava/lang/String;)Lcom/google/gson/stream/
解决方法:
4.4、问题反馈
5、ElasticJob 原理分析
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版本)
shiro或security 注解@EnableWebSecurity 引入依赖:spring-boot-starter-security ,配置类必须扩展WebSecurityConfigurerAdapter并覆盖其方法。
1、Spring security与apache shiro的对比?
在分布式系统中国,国内常用zookeeper+dubbo组合(我们公司的分布式框架组合),而springboot推荐使用全栈的Spring(springboot+springcloud)
在开发中修改了一个java文件后想看到效果不得不重启应用,希望能在不重启应用的情况下,程序可以自动部署(该模块在生产环境中被禁用)
Spring Loaded/JRebel/springboot Devtools
作用:帮助我们访问生产环境中正在运行的应用程序的当前状态,监视器模块公开了一组可直接作为HTTP URL访问的REST端点来检查状态 .beans 容器中所有bean的信息;autconfig所有自动配置信息 auditevents审计信息 configprops 所有配置属性 dump线程状态信息 env当前环境信息 health应用健康状态; info当前应用信息 metrics应用的各项指标 mappings应用@RequestMapping映射路径 shutdown关闭当前应用 trace追踪信息
1、依赖注入 Spring:构造器注入xml文件 springboot:@Bean(value)+java配置
2、包扫描 spring:< context:component-scan> springboot:@ComponentScan(value)
1. 加载位置与顺序
SpringBoot启动会扫描以下位置的application.properties/yml文件作为spring boot的默认配置文件:
file:./config/ file: 指当前项目根目录
file:./
classpath:/config/ classpath: 指当前项目的resources目录
classpath:/
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置的内容,并形成互补配置;当然,我们也可以通过spring.config.location来改变默认配置