原理初探 自动配置:
SpringBoot所有自动配置都是在启动的时候扫描并加载,spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,自动装配就会生效,然后就配置成功。
SpringBoot在启动的时候,从类路径下/META-INF/spring.factories 获取指定的值;
将这些自动配置的类导入容器。自动配置就会生效,帮我们进行自动配置
以前我们需要自动配置的东西,现在SpringBoot帮我们做了!
整个JavaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure这个包下
它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到Spring容器中。
容器中也会存在非常多的XXXXAutoConfituration的文件,就是这些类给容器中导入了这个场景需要的所有组件,并自动配置。
有了自动配置类,免去了我们手动编写配置类的过程。
自动装配原理:
SpringBoot启动会加载大量的自动装配类
我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要使用的组件存在其中,我们就不需要再手动配置了)
给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
xxxxAutoConfiguration:自动配置类;给容器中添加组件 xxxxProperties:封装配置文件中相关属性(可以通过properties配置文件中跳转到对应的源码)
SpringApplication 这个类主要做了以下四件事情:
推断应用的类型是普通的项目还是Web项目。
查找并加载所有可用初始化器,设置到initializers属性中。
找出所有的应用程序监听器,设置到listeners属性中。
推断并设置main方法的定义类,找到运行的主类。
@ConfigurationProperties 的作用 将配置文件中配置的每一个属性的值,映射到这个组件中。
告诉SpringBoot将苯类中的所有属性和配置文件中的相关配置进行绑定。
参数 prefix = "person"
: 将配置文件中的person下面的所有属性一一对应。
@ConfigurationProperties
使用松散绑定,比如yaml中
配置文件的位置 1 2 3 4 优先级1: file: ./config/ 项目根目录config下(注意不是Module下) 优先级2: file: ./ 项目根目录下(注意不是Module下) 优先级3: classpath: /config/ 优先级4: classpath: /
pom.xml
spring-boot-dependencies: 核心依赖在这个父工程中
启动器: 普通应用版本:
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter</artifactId > </dependency >
Web版本:
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency >
多环境配置 properties方式 properties文件可以通过实现多环境配置
application-dev.properties文件:
application-test.properties文件:
然后在application.properties文件中指定
1 2 spring.profiles.active =test
yaml方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 name: geekhall server: port: 8081 spring: profiles: active: prod --- server: port: 8082 spring: profiles: test --- server: port: 8083 spring: profiles: prod
JSR303校验 |Constraint | 详细信息 | |:—- |:—- | |@Null| 被注释的元素必须为 null| |@NotNull| 被注释的元素必须不为 null| |@AssertTrue| 被注释的元素必须为 true| |@AssertFalse| 被注释的元素必须为 false| |@Min(value)| 被注释的元素必须是一个数字,其值必须大于等于指定的最小值| |@Max(value)| 被注释的元素必须是一个数字,其值必须小于等于指定的最大值| |@DecimalMin(value)| 被注释的元素必须是一个数字,其值必须大于等于指定的最小值| |@DecimalMax(value) |被注释的元素必须是一个数字,其值必须小于等于指定的最大值| |@Size(max, min) |被注释的元素的大小必须在指定的范围内| |@Digits (integer, fraction) |被注释的元素必须是一个数字,其值必须在可接|受的范围内 |@Past |被注释的元素必须是一个过去的日期| |@Future| 被注释的元素必须是一个将来的日期| |@Pattern(value) |被注释的元素必须符合指定的正则表达式|
静态资源 1. 使用webjars 导入依赖
1 2 3 4 5 <dependency > <groupId > org.webjars</groupId > <artifactId > jquery</artifactId > <version > 3.6.0</version > </dependency >
导入后就可以在:http://localhost:8080/webjars/jquery/3.6.0/jquery.js
这里访问到jquery。/webjars/
目录对应了/META-INF/resources/webjars/
因为WebMvcAutoConfiguration.java
文件中:
1 addResourceHandler(registry, "/webjars/**" , "classpath:/META-INF/resources/webjars/" );
2. 使用默认位置
上面位置对应网站根目录: localhost:8080/
定制首页 SpringBoot默认首页为静态资源下的index.html favicon.ico文件放在上面静态资源文件的默认根目录下就可以了
Thymeleaf Thymeleaf模版引擎,只需要导入对应的依赖就可以了, 将Html页面放到templates目录下。
1 2 3 4 5 6 7 8 9 <dependency > <groupId > org.thymeleaf</groupId > <artifactId > thymeleaf-spring5</artifactId > </dependency > <dependency > <groupId > org.thymeleaf.extras</groupId > <artifactId > thymeleaf-extras-java8time</artifactId > </dependency >
Thymeleaf语法
Simple expressions:
Variable : ${…}
Selection Variable: *{…}
Message : #{…}
Link URL : @{…}
Fragment : ~{…}
国际化 resources目录下新建page.properties和page_zh_CN.properties,page_en_US.properties 可以在不同的properties文件中配置多语言支持
page_zh_CN.properties
page_en_US.properties
可以在IDEA的左下角的Resource Bundle中可视化编辑。
配置文件中指定目录:
1 spring.messages.basename =i18n.index
使用:
1 Index, <span th:text ="#{login.tip}" > </span >
SpringBoot Data 新建项目时添加jdbc和MySQL-Driver的支持。
配置数据源(application.yml):
1 2 3 4 5 6 7 8 9 spring: datasource: username: mybatis password: yy123456 url: jdbc:mysql://127.0.0.1:3316/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource
测试使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @SpringBootTest class Springboot05DataApplicationTests { @Autowired DataSource dataSource; @Test void contextLoads () throws SQLException { System.out.println(dataSource.getClass()); Connection connection = dataSource.getConnection(); System.out.println(connection); connection.close(); } }
SpringBoot 中有很多XXXXTemplate类,是SpringBoot已经配置好的模板Bean,拿来即用。
注意: SpringBoot在使用druid引入数据源之后,若使用了filters中有log4j,则需要在pom文件中加入log4j的依赖
1 2 3 4 5 <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.17</version > </dependency >
注意这里不能配置成下面的这个,否则会报ClassNotFoundException:
1 2 3 4 5 <dependency > <groupId > org.apache.logging.log4j</groupId > <artifactId > log4j</artifactId > <version > 2.14.1</version > </dependency >
SpringBoot整合MyBatis 使用MyBatis Spring Boot Stater
1 2 3 4 5 <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.2.0</version > </dependency >
导入包
配置文件
mybatis配置
编写Sql
service层调用dao层
controller调用service层
SpringSecurity & Shiro 解决安全(Security)、认证(Authentication)、授权(Authorization)问题,是Spring-AOP思想的应用, SpringSecurity是针对Spring项目的安全框架,也是SpringBoot底层安全模块默认的技术选型,可以实现强大的web安全控制,对于安全控制,我们仅仅需要引入spring-boot-starter-security模块,进行少量配置,即可实现强大的安全管理。
记住几个类:
WebSecurityConfigurerAdapter:自定义Security策略
AuthenticationManagerBuilder: 自定义认证策略
@EnableWebSecurity:开启WebSecurity模式
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { protected void configure (HttpSecurity http) throws Exception{ http.authorizeRequests() .antMatchers("/" ).permitAll() .antMatchers("/level1/**" ).hasRole("vip1" ) .antMatchers("/level2/**" ).hasRole("vip2" ) .antMatchers("/level3/**" ).hasRole("vip3" ); http.formLogin(); } @Override protected void configure (AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("moonwhite" ).password("123456" ).roles("vip2" ,"vip3" ) .and() .withUser("root" ).password("123456" ).roles("vip1" ,"vip2" ,"vip3" ) .and() .withUser("guest" ).password("123456" ).roles("vip1" ); } }
Swagger 简介 号称世界上最流行的API框架
RestFul API文档在线自动生成工具,API与定义同步更新
使用Swagger 导入依赖
1 2 3 4 5 <dependency > <groupId > io.springfox</groupId > <artifactId > springfox-boot-starter</artifactId > <version > 3.0.0</version > </dependency >
配置类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Configuration @EnableOpenApi public class SwaggerConfig { @Bean public Docket docket () { return new Docket (DocumentationType.OAS_30) .apiInfo(apiInfo()).enable(true ) .select() .apis(RequestHandlerSelectors.basePackage("cn.geekhall" )) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo () { return new ApiInfoBuilder () .title("Swagger-demo项目接口文档" ) .description("Swagger-demo项目描述" ) .contact(new Contact ("MoonWhite" , "作者URL" , "作者Email" )) .version("1.0" ) .build(); } }
Controller代码:
1 2 3 4 5 6 7 8 9 10 11 12 @Api(tags="用户管理") @RestController @RequestMapping("/user") public class UserController { @ApiOperation("使用ID获取用户") @GetMapping("/{id}") public User getUserById (@PathVariable("id") int id) throws Exception{ return new User (); } }
访问:http://localhost:8080/swagger-ui/index.html 即可看到生成的接口页面。
Spring整合Redis SpringData是和SpringBoot同级的Spring项目,在SpringBoot2.x之后,原来使用的jedis被替换成了lettuce
jedis : 采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全,使用jedis pool连接池!更像BIO模式
lettuce: 采用Netty,实例可以在多个线程中进行共享,不存在线程不安全的情况。可以减少线程数据了,更像NIO模式。
源码分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Configuration(proxyBeanMethods = false) @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) public class RedisAutoConfiguration { @Bean @ConditionalOnMissingBean(name = "redisTemplate") @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public RedisTemplate<Object, Object> redisTemplate (RedisConnectionFactory redisConnectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate <>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public StringRedisTemplate stringRedisTemplate (RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate (); template.setConnectionFactory(redisConnectionFactory); return template; } }
SpringBoot 所有的配置类和属性类,都有一个自动配置类 , 自动配置类都会绑定一个properties配置文件 如:RedisAutoConfiguration 和 RedisProperties
配置 导入依赖:
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-redis</artifactId > </dependency >
1 2 3 4 5 6 7 8 @Data @AllArgsConstructor @NoArgsConstructor @Component public class User implements Serializable { private String name; private int age; }
如果对象没有实现Serializable接口,会抛出SerializationFailedException异常。
1 2 3 4 5 6 7 8 9 10 @Test public void test () throws JsonProcessingException { User user = new User ("极客堂" , 3 ); redisTemplate.opsForValue().set("user" , user); Object user1 = redisTemplate.opsForValue().get("user" ); System.out.println(user1); }
微服务架构的4个核心问题
服务很多,客户端该怎么访问?
这么多服务,服务之间如何通信?
这么多服务,如何治理?
服务挂了怎么办?
解决方案:
Spring Cloud NetFlix : 一站式解决方案(2018年12月停止维护) API:api网关,zuul组件 通信:Feign — HttpClient : Http通信方式,同步,阻塞 服务注册发现: Eureka 熔断机制: Hystrix
Spring Cloud Alibaba : 一站式解决方案,更简单。
Dubbo + ZooKeeper : 半自动,需要整合别人的。 API: 没有,找第三方组件,或者自己实现 通信:Dubbo:高性能的基于Java的RPC通信框架 服务注册发现:ZooKeeper 熔断机制:没有,借助Hystrix
新概念:服务网格(Server Mesh)istio
常见面试题
什么是微服务?
微服务之间是如何独立通讯的?
SpringCloud和Dubbo有哪些区别?
SpringBoot和SpringCloud,请你谈谈对他们的理解
什么是服务熔断?什么是服务降级?
微服务的优缺点分别是什么?说下你在项目开发中遇到的坑。
你所知道的微服务技术栈有哪些?请列举一二
Nacos、Erueka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别。
微服务技术栈
微服务条目
落地技术
服务开发
SpringBoot,Spring,SpringMVC
服务配置与管理
Netflix公司的Archaius,阿里的Diamond等
服务注册与发现
Eureka、Consul、ZooKeeper、Nacos等
服务调用
Rest、RPC、gRPC
服务熔断器
Hystrix、Envoy等
负载均衡
Ribbon、Nginx等
服务接口调用(客户端调用服务的简化工具)
Feign等
消息队列
Kafka、RabbitMQ、ActiveMQ
服务配置中心管理
SpringCloudConfig、Chef等
服务路由(API网关)
Zuul等
服务监控
Zabbix、Nagios、Metrics、Specatator等
全链路追踪
Zipkin、Brave、Dapper等
服务部署
Docker、OpenStack、Kubernetes
数据流操作开发包
SpringCloudStream(封装与Redis、Rabbit、Kafka等发送接收消息)
时间消息总线
SpringCloudBus
spring.factories 在spring-boot项目中pom文件里面添加的依赖中的bean是如何注册到spring-boot项目的spring容器中的呢?
不难得出spring.factories文件是帮助spring-boot项目包以外的bean(即在pom文件中添加依赖中的bean)注册到spring-boot项目的spring容器的。
由于@ComponentScan注解只能扫描spring-boot项目包内的bean并注册到spring容器中,因此需要@EnableAutoConfiguration注解来注册项目包外的bean。
而spring.factories文件,则是用来记录项目包外需要注册的bean类名。