【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】
创建一个全新的Maven 工程模块
直接创建
OK, 一个全新的Maven 工程
【添加坐标】
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<version>2.7.4version>
dependency>
dependencies>
OK
【实体类】
package com.dingjiaxiong.bean;
/**
* ClassName: Cat
* date: 2022/10/25 13:03
*
* @author DingJiaxiong
*/
public class Cat {
}
package com.dingjiaxiong.bean;
/**
* ClassName: Mouse
* date: 2022/10/25 13:03
*
* @author DingJiaxiong
*/
public class Mouse {
}
【运行类】
package com.dingjiaxiong;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* ClassName: App
* date: 2022/10/25 13:03
*
* @author DingJiaxiong
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App.class);
}
}
OK, 基本环境就准备好了
来一个业务层【拍猫和老鼠的动画片】
package com.dingjiaxiong.bean;
import org.springframework.stereotype.Component;
/**
* ClassName: CartoonCatAndMouse
* date: 2022/10/25 13:06
*
* @author DingJiaxiong
*/
@Component
public class CartoonCatAndMouse {
private Cat cat;
private Mouse mouse;
public void play(){
System.out.println("3岁的tom和4岁的jerry打起来了");
}
}
OK, 在运行程序中获取这个bean
package com.dingjiaxiong;
import com.dingjiaxiong.bean.CartoonCatAndMouse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* ClassName: App
* date: 2022/10/25 13:03
*
* @author DingJiaxiong
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App.class);
CartoonCatAndMouse bean = context.getBean(CartoonCatAndMouse.class);
bean.play();
}
}
OK,直接运行
没啥问题,现在就是一个调用打印
现在的问题就是这句打印的数据都是一个字符串写死的,所以要换
先导一个lombok
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.24version>
dependency>
修改实体类
package com.dingjiaxiong.bean;
import lombok.Data;
/**
* ClassName: Cat
* date: 2022/10/25 13:03
*
* @author DingJiaxiong
*/
@Data
public class Cat {
private String name;
private Integer age;
}
package com.dingjiaxiong.bean;
import lombok.Data;
/**
* ClassName: Mouse
* date: 2022/10/25 13:03
*
* @author DingJiaxiong
*/
@Data
public class Mouse {
private String name;
private Integer age;
}
OK,现在属性都有了
修改业务代码
package com.dingjiaxiong.bean;
import org.springframework.stereotype.Component;
/**
* ClassName: CartoonCatAndMouse
* date: 2022/10/25 13:06
*
* @author DingJiaxiong
*/
@Component
public class CartoonCatAndMouse {
private Cat cat;
private Mouse mouse;
public CartoonCatAndMouse() {
cat = new Cat();
cat.setName("tom");
cat.setAge(3);
mouse = new Mouse();
mouse.setName("jerry");
mouse.setAge(4);
}
public void play(){
System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
}
}
OK,直接运行
这样就不是写死的数据了而且实现相同的效果
现在问题就是,当前这样子写,如果想正常运行
这些数据必须得告诉程序,但是如果有一天猫或者老鼠出意外了,导致咱们必须从外部修改这些“演员”,怎么做?
先来一个配置文件
cartoon:
cat:
name: tom
age: 3
mouse:
name: jerry
age: 4
在业务中读取值
package com.dingjiaxiong.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* ClassName: CartoonCatAndMouse
* date: 2022/10/25 13:06
*
* @author DingJiaxiong
*/
@Component
@Data
@ConfigurationProperties(prefix = "cartoon")
public class CartoonCatAndMouse {
private Cat cat;
private Mouse mouse;
public void play(){
System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
}
}
直接运行
可以看到, 这样子数据也上来了
修改一下配置文件
OK, 数据也正常替换了
但是如果我压根儿不给老鼠的数据
没给就导致业务中的mouse 没有初始化,然后又直接使用,就这样儿了
而且现在的问题是
现在这个类已经绑死了 yml 中的数据,如果yml 不提供数据,这个类就没法儿用了【这好像也不太行,有解决办法吗?】
答案是当然的
先来一个全新的类
package com.dingjiaxiong.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* ClassName: CartoonProperties
* date: 2022/10/25 13:27
*
* @author DingJiaxiong
*/
@Component
@Data
@ConfigurationProperties(prefix = "cartoon")
public class CartoonProperties {
private Cat cat;
private Mouse mouse;
}
之前的去使用这个属性类
package com.dingjiaxiong.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* ClassName: CartoonCatAndMouse
* date: 2022/10/25 13:06
*
* @author DingJiaxiong
*/
@Component
@Data
public class CartoonCatAndMouse {
private Cat cat;
private Mouse mouse;
private CartoonProperties cartoonProperties;
public CartoonCatAndMouse(CartoonProperties cartoonProperties) {
this.cartoonProperties = cartoonProperties;
cat = new Cat();
cat.setName("tom");
cat.setAge(3);
mouse = new Mouse();
mouse.setName("jerry");
mouse.setAge(4);
}
public void play(){
System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
}
}
先直接打印看看,
说明现在这些值拿的还是本类构造方法中设置的值
改一下
cat.setName(StringUtils.hasText(cartoonProperties.getCat().getName()) ? cartoonProperties.getCat().getName() : "tom");
意思是如果属性类中有值,就用属性类的值对tom 进行覆盖
直接运行
OK, 没毛病
如果配置文件中没配猫的name
就还是tom
现在达到的效果 就是如果配置里面设置 了新的,就用新的,如果没有,就用老的
现在我把整个猫都拿掉
这样会报错,因为属性类中的cat 为空了,再去拿空的name 就报错了,所以要再加个条件
cat.setName(cartoonProperties.getCat() != null && StringUtils.hasText(cartoonProperties.getCat().getName()) ? cartoonProperties.getCat().getName() : "tom");
OK,再次运行
这样就行了,现在我仅仅是把猫的名字注掉
OK, 还是可以用
按照这种判断形式,完善一下业务代码
package com.dingjiaxiong.bean;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/**
* ClassName: CartoonCatAndMouse
* date: 2022/10/25 13:06
*
* @author DingJiaxiong
*/
@Component
@Data
public class CartoonCatAndMouse {
private Cat cat;
private Mouse mouse;
private CartoonProperties cartoonProperties;
public CartoonCatAndMouse(CartoonProperties cartoonProperties) {
this.cartoonProperties = cartoonProperties;
cat = new Cat();
cat.setName(cartoonProperties.getCat() != null && StringUtils.hasText(cartoonProperties.getCat().getName()) ? cartoonProperties.getCat().getName() : "tom");
cat.setAge(cartoonProperties.getCat() != null && cartoonProperties.getCat().getAge() != null ? cartoonProperties.getCat().getAge() : 3);
mouse = new Mouse();
mouse.setName(cartoonProperties.getMouse() != null && StringUtils.hasText(cartoonProperties.getMouse().getName()) ? cartoonProperties.getMouse().getName() : "jerry");
mouse.setAge(cartoonProperties.getMouse() != null && cartoonProperties.getMouse().getAge() != null ? cartoonProperties.getMouse().getAge() : 4);
}
public void play(){
System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
}
}
现在的效果,就是配置文件的值和属性中的值融合
去掉一个单一属性
就是这样
整个猫都拿掉
如果全部拿掉
没毛病
现在就没有在真正的动画片类中去强制和配置文件绑死了【通过一个属性类解耦了】
OK, 差不多就是这样 了,但还有个小问题,在属性类中
加上这个注解后,这个属性类最终肯定会被加载成 bean
如果现在我们不用动画片那个业务类的了的话,这个属性类也就没有必要加载了
如果直接删掉这个注解
可以看到,如果不是一个bean了,就不能读取配置文件中的数据了
【解决办法】
这样就可以把它强制整个一个bean了
OK, 这个问题解决了,顺带的问题又来了
这个类现在也一定会被加载成bean,好家伙,也拿掉?
拿掉之后,到运行类中使用@Import 进行加载
这样达到的效果就是
这两个东西现在都没有强制声明成bean 了
【但是现在能用吗?试试】
没毛病
现在的感觉就是在运行类中,导入这样一个功能,
就能用了
做了这么多步骤:
核心:
OK,回顾一下
将业务功能bean运行需要的资源抽取成独立的属性类(******Properties),设置读取配置文件信息
配置文件中使用固定格式为属性类注入数据
定义业务功能bean,通常使用@Import导入,解耦强制加载bean
使用@EnableConfigurationProperties注解设定使用属性类时加载bean