挺久没写文章了,今天写一篇关于二维码的吧。本篇文章会带大家做一个二维码的启动器,各位感兴趣的可以动手搞一下。如果公司内部有需求的话,还可以做成依赖放到公司自己的仓库中。
你不想看到的东西,我都扔了,你可以放心的住进来了
要我说, springboot 启动器真是个好东西,把原先繁琐的配置都省掉了,但它们并不是消失了,而是换了一种方式在你身边。
创建 maven 聚合工程
聚合工程下面包含两个子工程:QRCode-spring-boot-starter 和 QRCode-spring-boot-autoconfigure
父工程的 pom 文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>Qr-code-starters</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>QRCode-spring-boot-starter</module>
<module>QRCode-spring-boot-autoconfigure</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
其中 QRCode-spring-boot-starter 这个项目下面是没有包含任何代码的,只有一个 pom 文件,pom 文件会引入 QRCode-spring-boot-autoconfigure 这个依赖。外部使用启动器的时候也是导入 QRCode-spring-boot-starter 这个依赖即可:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>Qr-code-starters</artifactId>
<groupId>test</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>QRCode-spring-boot-starter</artifactId>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>QRCode-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
编写自动配置的相关内容
在 springboot 中,所有启动器的编写都大差不差的。首先是在 pom 文件中导入所需的依赖; 其次就是编写 @ConfigurationProperties 注解修饰的配置类,用于封装使用到的所有配置,通常以 Properties 结尾;然后就是编写以 AutoConfiguration 结尾的配置类,配置类通过 @Bean 注解 + 各种条件注解往 ioc 容器中注入 bean 实例;最后一步,也是关键的一步,就是要在 resources 目录下创建一个名为 META-INF 的子目录。在这个子目录下,创建一个名为 spring.factories 的文件,这个文件中要指明启动器中包含了哪些自动配置类。
本篇文章是以二维码为例子,那就肯定要导入生成二维码要用到的依赖了:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>Qr-code-starters</artifactId>
<groupId>test</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>QRCode-spring-boot-autoconfigure</artifactId>
<dependencies>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</project>
编写用于封装配置的 QRCodeProperties:
// 在配置文件中可以通过 prefix + 属性名的方式将属性值封装到该类中
@ConfigurationProperties(prefix = QRCodeProperties.QRCODE_PREFIX)
public class QRCodeProperties {
public static final String QRCODE_PREFIX = "qrcode";
private Integer width = 360;
private Integer height = 360;
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
}
编写自动配置类 QRCodeAutoConfiguration:
@EnableConfigurationProperties(value = QRCodeProperties.class) // 用于导入配置类
// 自动配置类通常都是要在满足一定条件的情况下才可以生效,因此 @Conditional 系的注解不可少
@ConditionalOnClass(value = {QRCodeWriter.class, BarcodeFormat.class, MatrixToImageWriter.class, BitMatrix.class})
@Configuration
public class QRCodeAutoConfiguration {
@ConditionalOnMissingBean
@Bean
public QRCodeGenerator defaultQRCodeGenerator(QRCodeProperties properties){
return new QRCodeGenerator(properties);
}
@ConditionalOnMissingBean
@Bean
public BarcodeFormat defaultBarcodeFormat(){
return BarcodeFormat.QR_CODE;
}
}
QRCodeGenerator 就是负责生成二维码的类:
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class QRCodeGenerator implements InitializingBean {
private Integer width = 360;
private Integer height = 360;
@Autowired(required = false)
private BarcodeFormat format ;
public QRCodeGenerator(){}
public QRCodeGenerator(QRCodeProperties properties){
this.width = properties.getWidth();
this.height = properties.getHeight();
}
public byte[] getQRCodeImage(String text) throws WriterException, IOException {
Assert.notNull(text,"text is not allow null ");
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(text, format, width, height);
ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", pngOutputStream);
return pngOutputStream.toByteArray();
}
@Override
public void afterPropertiesSet() throws Exception {
if (format == null)
format = BarcodeFormat.QR_CODE;
}
}
关键一步,在 resources 目录下创建一个名为 META-INF 的子目录。在这个子目录下,创建一个名为 spring.factories 的文件:
spring.factories 中的内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
spring.boot.qrCode.autoconfigure.QRCodeAutoConfiguration
等号右边跟的是自动配置类的全类名,也可以跟多个自动配置类,比如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
到这,一个简单的二维码启动器就完成了,其他项目需要用到的话,直接在 pom 文件中引入即可。
大家平时在编写配置文件时,idea 一般都会有以下的提示:
这种提示其实就是 META-INF 目录下的 spring-configuration-metadata.json 文件在发挥作用,这种提示还是很有必要的,能够让使用你这个启动器的开发人员明白每个配置的作用是啥。
{
"properties": [
{
"name": "qrcode.width",
"type": "java.lang.Integer",
"description": "qrcode width",
"sourceType": "spring.boot.qrCode.autoconfigure.QRCodeProperties"
},
{
"name": "qrcode.height",
"type": "java.lang.Integer",
"description": "qrcode height",
"sourceType": "spring.boot.qrCode.autoconfigure.QRCodeProperties"
}
]
}
加上了这个 .json 文件后就有了下面的效果:
笔者在这里只是做了一个简单的启动器,主要是想向大家展示一个启动器的编写流程。整个过程不难,各位看官可以动手实践一下。
笔者最近一直想培养一个兴趣爱好,各位屏幕前的大仙如果有推荐的话,可以在评论区中说下。说不定,误打误撞的就能发展成一门副业。毕竟,谁不羡慕把爱好当成事业的人呢。