SpringBoot2基础入门
一、Spring与SpringBoot
Springboot官网:https://spring.io/projects/spring-boot
1.Spring的能力
2.Spring的生态
覆盖了:web开发、数据访问、安全控制、分布式、消息服务、移动开发、批处理......
3.Spring5重大升级
响应式编程
内部源码设计:基于Java8的一些新特性,如:接口默认实现。重新设计源码架构。
4.为什么用SpringBoot
能快速创建出生产级别的Spring应用
5.SpringBoot优点
-
Create stand-alone Spring applications
-
创建独立Spring应用
-
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
-
内嵌web服务器
-
Provide opinionated 'starter' dependencies to simplify your build configuration
-
自动starter依赖,简化构建配置
-
Automatically configure Spring and 3rd party libraries whenever possible
-
自动配置Spring以及第三方功能
-
Provide production-ready features such as metrics, health checks, and externalized configuration
-
提供生产级别的监控、健康检查及外部化配置
-
Absolutely no code generation and no requirement for XML configuration
-
无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架
5.SpringBoot缺点
- 人称版本帝,迭代快,需要时刻关注变化
- 封装太深,内部原理复杂,不容易精通
6.时代背景
6.1微服务
-
微服务是一种架构风格
-
一个应用拆分为一组小型服务
-
每个服务运行在自己的进程内,也就是可独立部署和升级
-
服务之间使用轻量级HTTP交互
-
服务围绕业务功能拆分
-
可以由全自动部署机制独立部署
-
去中心化,服务自治。服务可以使用不同的语言、不同的存储技术
6.2分布式
分布式的困难:
-
远程调用
-
服务发现
-
负载均衡
-
服务容错
-
配置管理
-
服务监控
-
链路追踪
-
日志管理
-
任务调度
分布式的解决
- SpringBoot + SpringCloud
6.3云原生
原生应用如何上云。 Cloud Native
上云的困难:
-
服务自愈
-
弹性伸缩
-
服务隔离
-
自动化部署
-
灰度发布
-
流量治理
7.如何学习SpringBoot
1.官网文档架构
2.查看版本特性
https://github.com/spring-projects/spring-boot/wiki#release-notes
二、SpringBoot2入门
1.系统要求
- Java8
- Maven3.3+
- IDEA(社区版貌似也可以)
2.Maven设置
Seeing.xml
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
3.HelloWorld
3.1、需求:
浏览发送/hello请求,响应 Hello,Spring Boot 2
3.2、创建Maven工程
3.3、导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
3.4、创建主程序
/**
* 主程序类
* @SpringBootApplication:这是一个SpringBoot应用
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
}
3.4、编写业务
@RestController
public class HelloController {
@RequestMapping("/hello")
public String handle01(){
return "Hello, Spring Boot 2!";
}
}
3.5、测试
直接运行main方法
运行成功后在浏览器输入:localhost:8080/hello
页面出现Hello, Spring Boot 2!即成功
3.6、简化配置
在resourses文件下创建配置文件:application.properties 添加如下
server.port=8888
重新运行Main方法,浏览器输入localhost:8080/hello发现页面找不到
原因是已经修改了默认的端口号
输入:localhost:8888/hello即可
3.7、简化部署
在pom.xml文件添加
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
将项目打成jar包,直接在目标服务器上运行即可
java -jar 包名
三、了解自动配置原理
1.SpringBoot特点
1.1、依赖管理
- 父项目做依赖管理
依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制
- 开发导入starter场景启动器
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
-
无需关注版本号,自动版本仲裁
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
-
可以修改默认版本号
1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
<properties>
<mysql.version>5.1.43</mysql.version>
</properties>
1.2、自动配置
-
自动配好Tomcat
-
引入Tomcat依赖。
-
配置Tomcat
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.3.4.RELEASE</version> <scope>compile</scope> </dependency>
-
- 自动配置MVC
- 引入SpringMVC全套组件
- 自动配好SpringMVC常用组件(功能)
-
自动配好Web常见功能,如:字符编码问题
SpringBoot帮我们配置好了所有web开发的常见场景
-
默认的包结构
- 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
-
无需以前的包扫描配置
-
想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.yka")或者@ComponentScan 指定扫描路径
@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.yka.boot")
- 各种配置拥有默认值
- 默认配置最终都是映射到某个类上,如:MultipartProperties
- 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
-
按需加载所有自动配置项
-
非常多的starter
-
引入了哪些场景这个场景的自动配置才会开启
-
SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
-
2.容器功能
2.1组件添加
2.1.1、@Configuration
Full模式与Lite模式
Full模式和Lite模式是针对spring配置而言的,和xml配置无关。
何时为Lite模式:
1.类上有@Component注解
2.类上有@ComponentScan注解
3.类上有@Import注解
4.类上有@ImportResource注解
5.类上没有任何注解,但是类中存在@Bean方法
6.类上有@Configuration(proxyBeanMethods = false)注解
Lite总结:运行时不用生成CGLIB子类,提高运行性能,降低启动时间,可以作为普通类使用。但是不能声明@Bean之间的依赖
何时为Full模式:
1.标注有@Configuration或者@Configuration(proxyBeanMethods = true)的类被称为Full模式的配置类。
Full模式总结:单例模式能有效避免Lite模式下的错误。性能没有Lite模式好
最佳实践
- 配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
Configuration使用示例:
package com.yka.boot.config;
/**
* 1.配置类里面使用的@Bean标注的方法上给容器注册组件,默认也是单实例的;
* 2.配置类本身也是组件
* 3.proxyBeanMethods:代理bean的方法
* Full(@Configuration (proxyBeanMethods = true) [保证每个@Bean方法被调用多少次返回的组件都是单实例的]
* Lite(@Configuration (proxyBeanMethods = true) [每个@Bean方法被调用多少次返回的组件都是新创建的]
* 组件依赖必须使用Full模式默认。其他默认是否Lite模式
* */
@Configuration (proxyBeanMethods = false) //告诉Spring这是一个配置类 == 配置文件
//1.开启Car的配置绑定功能
//2.把这个组件自动导入容器中
public class MyConfig {
/**
* FULL:外部无论对配置类中的组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
* */
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型 返回的值就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖类Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom2")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
测试代码:
package com.yka.boot;
/**
* 主程序类
* @SpringBootApplication: 这是一个SpringBoot应用
* */
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//1.返回ioc容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器内的组件
String[] names = run.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);
}
//3.从容器中获取组件
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:"+(tom01 == tom02));
//4、com.yka.boot.config.MyConfig$$EnhancerBySpringCGLIB$$8a4ba04f@57f64f5e
MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);
//如果@Configuration (proxyBeanMethods = true) /代理对象调用方法SringBoot总会这个组件是否在容器中有
//保持组件单实例
User user = bean.user01();
User user1 = bean.user01();
System.out.println((user == user1));
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:"+(user01.getPet() == tom));
}
}
2.1.2、@Bean、@Component、@Controller、@Service、@Repository
2.1.3、@ComponentScan、@Import
//@Import({User.class, DBHelper.class})
//给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
2.1.4、@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
条件装配示例:
package com.yka.boot.config;
//条件装配
//@ConditionalOnBean(name = "tom") 容器中有tom才进行装配
@ConditionalOnMissingBean(name = "tom") //容器中没有tom才进行装配
@Configuration (proxyBeanMethods = false) //告诉Spring这是一个配置类 == 配置文件
public class MyConfig {
/**
* 外部无论对配置类中的组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
* */
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型 返回的值就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖类Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom2")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
测试代码:
package com.yka.boot;
import ch.qos.logback.core.db.DBHelper;
import com.yka.boot.bean.Pet;
import com.yka.boot.bean.User;
import com.yka.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
import org.springframework.cache.interceptor.CacheAspectSupport;
import org.springframework.context.ConfigurableApplicationContext;
/**
* 主程序类
* @SpringBootApplication: 这是一个SpringBoot应用
* */
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//1.返回ioc容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器内的组件
String[] names = run.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);
}
boolean tom = run.containsBean("tom");
System.out.println("容器中Tom组件:"+tom);
boolean user01 = run.containsBean("user01");
System.out.println("容器中user01组件:"+user01);
boolean tom2 = run.containsBean("tom2");
System.out.println("容器中tom2组件:"+tom2);
}
}
2.2、原生配置文件引入
2.2.1、@ImportResource
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "haha" class="com.yka.boot.bean.User">
<property name="name" value="zhansan"></property>
<property name="age" value="18"></property>
</bean>
<bean id = "hehe" class="com.yka.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>
示例:
package com.yka.boot.config;
@ImportResource("classpath:beans.xml")
public class MyConfig {
/**
* 外部无论对配置类中的组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
* */
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型 返回的值就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖类Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom2")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
测试代码:
package com.yka.boot;
/**
* 主程序类
* @SpringBootApplication: 这是一个SpringBoot应用
* */
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
//1.返回ioc容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器内的组件
String[] names = run.getBeanDefinitionNames();
for(String name : names){
System.out.println(name);
}
boolean hehe = run.containsBean("hehe");
boolean haha = run.containsBean("haha");
System.out.println("容器中hehe组件:"+hehe);
System.out.println("容器中haha组件:"+haha);
}
}
2.3、配置绑定
2.3.1@ConfigurationProperties
/**
* 只有在容器中的组件,才会拥有SpringBoot提供的强大功能
*/
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
}
2.3.2、@EnableConfigurationProperties + @ConfigurationProperties
2.3.3、@Component + @ConfigurationProperties
@EnableConfigurationProperties(Car.class)
//1、开启Car配置绑定功能
//2、把这个Car这个组件自动注册到容器中
public class MyConfig {
}
3.自动配置原理入门
3.1、引导加载自动配置类
3.1.1、@SpringBootConfiguration
@Configuration。代表当前是一个配置类
3.1.2、@ComponentScan
指定扫描哪些,Spring注解;
3.1.3、@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
-
@AutoConfigurationPackage 自动配置包 指定了默认的包规则
-
@Import(AutoConfigurationImportSelector.class)
3.2、按需开启自动配置项
3.3、修改默认配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
//给容器中加入了文件上传解析器;
SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先(约定大于配置),主要体现在@ConditionalOnMissingBean,如果没有存在这个bean,那么springboot就会自动帮你配置
总结:
-
SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
-
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
-
生效的配置类就会给容器中装配很多组件
-
只要容器中有这些组件,相当于这些功能就有了
-
定制化配置
-
用户直接自己@Bean替换底层的组件
-
用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties
三、开发小技巧
1.Lombok
介绍:简化JavaBean开发,不用费时费力生成get。set、toString方法。使用注解在编译的时候自动生成
-
idea安装lombok插件
-
添加依赖
-
修改xml文件,添加
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
测试代码:
package com.yka.boot.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* 宠物
* **/
@ToString
@Data
@NoArgsConstructor //无参构造器
@AllArgsConstructor //有参构造器
public class Pet {
private String name;
}
简化日志开发:
package com.yka.boot.controller;
import com.yka.boot.bean.Car;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
//@ResponseBody
//@Controller
@Slf4j
@RestController
public class HelloController {
@Autowired
Car car;
@RequestMapping("/car")
public Car car(){
return car;
}
@RequestMapping("/hello")
public String handle01(@RequestParam("name") String name){
log.info("请求进来了。。。。。");
return "Hello,Spring Boot2 " + "你好" + name;
}
}
2.Spring Initailizr(项目初始化向导:只有收费版idea支持)
新建项目:
下一步:选择需要开发的场景