Spring Boot 自定义腾讯位置服务 WebService API Starter
本章节将介绍如何自定义 Spring Boot Starter,并且结合 Github Actions 自动上传 Maven 中央仓库。
📍 腾讯位置服务 WebService API Spring Boot Starter (🌟 点个 star ,不迷路)
前言
最近有一个需求,需要对接腾讯位置服务 WebService API,但找来找去发现官方并没有提供 Java SDK,考虑到后续其他项目也会有这个需求后,干脆索性自己封装一个 starter,并希望上传 Maven 中央仓库,实现像集成 MyBatis Plus 一样方便,直接引入依赖即可,让 Spring Boot 完成自动装配,并不需要关心具体配置以及代码,实现松耦合。
自定义
命名规范
Spring 官方提供 starter 通常命名为 spring-boot-starter-{name} :
Spring 官方建议非官方提供的 starter 命名应遵守 {name}-spring-boot-starter 格式
比如 mybatis 出品:mybatis-spring-boot-starter
创建项目
starter 是基于 Spring Boot 项目创建而成,使用 IDEA 初始化 Spring Boot 项目后,删除 src
文件夹,并新建两个 Module
,分别是 {name}-spring-boot-starter(启动器)
以及 {name}-spring-boot-autoconfigure(自动配置包)
,新建完成后删除启动类。
文件夹命名规范参考:mybatis-spring-boot-starter,项目架构大致如下:
bash
├─pom.xml
│
├─lbs-spring-boot-autoconfigure
│ │ pom.xml
│ │
│ └─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─starimmortal
│ │ │
│ │ └─resources
│ └─test
│ └─java
└─lbs-spring-boot-starter
│ pom.xml
│
└─src
├─main
│ ├─java
│ │ └─com
│ │ └─starimmortal
│ │
│ └─resources
└─test
└─java
提示:最终版本包含了 lbs-client-core 业务核心模块,在这里没有体现,根据个人开发习惯不同,可以选择将业务代码写在
{name}-spring-boot-autoconfigure
下,但这里还是推荐将业务核心功能单独封装成一个模块。
模块依赖
xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>lbs-client-core</module>
<module>lbs-spring-boot-starter</module>
<module>lbs-spring-boot-autoconfigure</module>
</modules>
<groupId>com.starimmortal</groupId>
<artifactId>lbs-spring-boot</artifactId>
<version>1.0.0</version>
<name>lbs-spring-boot</name>
<description>Tencent LBS WebService API Spring Boot Starter</description>
<url>https://github.com/ElanYoung/lbs-spring-boot/tree/main</url>
<properties>
<argLine>-Dfile.encoding=UTF-8</argLine>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<java.version>1.8</java.version>
<spring-boot-dependencies.version>2.7.12</spring-boot-dependencies.version>
<lombok.version>1.18.28</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Lombok 插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
开源项目强烈建议使用 dependencyManagement 来管理 Maven 依赖,否则可能会出现版本兼容问题!
{name}-spring-boot-autoconfigure
注意:lbs-client-core 模块是单独封装好腾讯位置服务 WebService API 业务核心模块,大家可以根据自己不同业务创建底层核心模块。
xml
<?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>
<parent>
<artifactId>lbs-spring-boot</artifactId>
<groupId>com.starimmortal</groupId>
<version>1.0.0</version>
</parent>
<artifactId>lbs-spring-boot-autoconfigure</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 客户端核心功能 -->
<dependency>
<groupId>com.starimmortal</groupId>
<artifactId>lbs-client-core</artifactId>
<version>1.0.0</version>
</dependency>
<!-- 自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- Configuration Processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
{name}-spring-boot-starter
xml
<?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>
<packaging>jar</packaging>
<parent>
<artifactId>lbs-spring-boot</artifactId>
<groupId>com.starimmortal</groupId>
<version>1.0.0</version>
</parent>
<artifactId>lbs-spring-boot-starter</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring Boot 自动配置 -->
<dependency>
<groupId>com.starimmortal</groupId>
<artifactId>lbs-spring-boot-autoconfigure</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
配置属性类
提示:此配置属性类作用将体现在 application.yml 配置文件上。
LbsProperties
是一个配置实体类,里面包含了腾讯位置服务 WebService API 相关配置项。
使用 @ConfigurationProperties
注解,会自动把 application.yml
文件中以 lbs
前缀开头外部属性跟 LbsProperties
中类字段进行绑定,自动注入到 LbsProperties
对象中。
java
@ConfigurationProperties(prefix = LbsProperties.LBS_PREFIX)
public class LbsProperties {
/**
* 属性前缀
*/
public static final String LBS_PREFIX = "lbs";
/**
* 密钥
*/
private String key;
/**
* 签名校验
*/
private String sk;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getSk() {
return sk;
}
public void setSk(String sk) {
this.sk = sk;
}
}
自动配置类
LbsAutoConfiguration
类使用了 @Configuration
注解标记为配置类,并且使用 @EnableConfigurationProperties
注解会自动注入 LbsProperties
类实例。
此外,最关键点在于该类里面创建了 lbsClient
bean实例,这是自动配置精髓。
java
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(LbsProperties.class)
public class LbsAutoConfiguration {
private final LbsProperties lbsProperties;
public LbsAutoConfiguration(LbsProperties lbsProperties) {
this.lbsProperties = lbsProperties;
}
@Bean
public LbsClient lbsClient() {
return new LbsClient(lbsProperties.getKey(), lbsProperties.getSk());
}
}
提示:
LbsClient
类属于 lbs-client-core 模块中主要核心代码,里面封装了腾讯位置服务 WebService API 相关接口。
spring.factories
为了实现自动装配,需在 {name}-spring-boot-autoconfigure
模块中的 resources
目录下新建 META-INF
文件夹,然后创建 spring.factories
文件,并写入以下内容:
java
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.starimmortal.lbs.autoconfigure.LbsAutoConfiguration
注意:Spring Boot 2.7 已经标记 spring.factories 加载自动化配置方式为过期,Spring Boot 3 中将完全移除原有方式。
为了上下兼容,需在 META-INF
目录下创建 spring
文件夹,并且新建 org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件,写入以下内容:
java
com.starimmortal.lbs.autoconfigure.LbsAutoConfiguration
bash
├── src
│ └── main
│ └── resources
│ ├── META-INF
│ │ └── spring
│ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
打包安装
bash
mvn clean install
测试
具体手册可以github.com/ElanYoung/l... star 哦
引入依赖
xml
<dependency>
<groupId>com.starimmortal</groupId>
<artifactId>lbs-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
参数配置
注意:请填写自己开发者密钥与签名校验
yml
# 腾讯位置服务
lbs:
# 开发者密钥
key: OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77
# 签名校验
sg: ER1w0iqvajsow4a5tAC7OPfBVboHzMe
IP定位
java
import com.starimmortal.lbs.LbsClient;
import com.starimmortal.lbs.response.IpLocationResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/lbs")
public class LbsController {
@Autowired
private LbsClient lbsClient;
@GetMapping("/ip")
public IpLocationResponse ipLocation() {
return lbsClient.ipLocation("221.224.9.195");
}
}
发布 Maven 中央仓库
准备 Sonatype JIRA 账号
登录或注册 issues.sonatype.org 社区账号:注册地址
密码要求如下:
- 密码必须至少有 12 个字符。
- 密码必须至少包含 1 个大写字符。
- 密码必须至少包含 1 个特殊字符,例如 &、%、™ 或 É。
- 密码必须包含至少 3 种不同的字符,例如大写字母、小写字母、数字和标点符号。
- 密码不得与用户名或电子邮件地址相似。
创建问题
点击仪表盘面板右上角 "新建" 按钮,按照以下步骤向 Sonotype 提交新建项目工单:
- 项目:Community Support - Open Source Project Repository Hosting (OSSRH)
- 问题类型:New Project
- 概要:Github 项目名
- Group Id:io.github.[Github 用户名] 或 个人域名(逆序填写)
- Project URL: 项目地址
- SCM URL: 版本控制地址
项目与问题类型使用默认选项即可
填写完毕后,点击新建,等待审核,管理员会让你在GitHub上建立个项目用于验证身份。
当Issue的Status变为RESOLVED后,就可以进行下一步操作了。
验证 Group Id 所有权
Group Id 使用 Github 账号方式需按照提示在 Github 上创建临时项目;
Group Id 使用个人域名方式需按照提示解析 DNS TXT 记录
GPG
GPG(GNU Privacy Guard) 是基于 OpenPGP 标准实现的加密软件,它提供了对文件的非对称加密和签名验证功能。所有发布到 Maven 仓库的文件都需要进行 GPG 签名,以验证文件的合法性。
安装
Mac
bash
brew install gpg
Windows
生成 GPG 密钥对
bash
# 密钥生成命令
gpg --generate-key
# 密钥查看命令
gpg --list-keys
删除 GPG 密钥对
bash
# 删除私钥
gpg --delete-secret-keys <pub字符串>
# 删除公钥
gpg --delete-keys <pub字符串>
上传公钥
bash
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys <pub字符串>
验证公钥
bash
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-keys <pub字符串>
配置文件
settings.xml
配置文件路径:Maven 安装目录下 conf
目录下 settings.xml
文件
xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<servers>
<server>
<id>ossrh</id>
<username>your-jira-id</username>
<password>your-jira-password</password>
</server>
</servers>
<profiles>
<profile>
<id>ossrh</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<gpg.executable>gpg</gpg.executable>
<gpg.passphrase>your-gpg-passphrase</gpg.passphrase>
</properties>
</profile>
</profiles>
</settings>
注意:server中id值要与snapshotRepository中id值和repository中id值保持一致。
pom.xml
- 项目信息
xml
<groupId>com.starimmortal</groupId>
<artifactId>lbs-spring-boot</artifactId>
<version>1.0.0</version>
<name>lbs-spring-boot</name>
<description>Tencent LBS WebService API Spring Boot Starter</description>
<url>https://github.com/ElanYoung/lbs-spring-boot/tree/main</url>
- 开源协议
xml
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
</license>
</licenses>
- 开发者信息
xml
<developers>
<developer>
<name>ElanYoung</name>
<email>991658923@qq.com</email>
<organizationUrl>https://doc.starimmortal.com</organizationUrl>
</developer>
</developers>
- 版本管理
xml
<scm>
<url>https://github.com/StarImmortal/leaf-spring-boot</url>
<connection>https://github.com/StarImmortal/leaf-spring-boot.git</connection>
</scm>
- 远程仓库
xml
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
- 插件
xml
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<show>private</show>
<nohelp>true</nohelp>
<charset>UTF-8</charset>
<encoding>UTF-8</encoding>
<docencoding>UTF-8</docencoding>
<doclint>none</doclint>
<detectJavaApiLink>false</detectJavaApiLink>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Gpg Signature -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- 用于gpg非交互式密码输入 -->
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</plugin>
<!-- Nexus Staging Maven插件是将组件部署到OSS并将其发布到Central Repository -->
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.13</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
打包上传
bash
mvn clean deploy -P release
查看是否发布成功
- 方式一:Sonatype Nexus 面板上查看
- 方式二:releases 中央仓库文件目录中查看
- 方式三:MavenCentral 搜索栏查找
Github Actions
前提条件
-
OSSRH 账号密码
-
GPS 私钥
- 查看私钥
bash
gpg --list-secret-keys --keyid-format LONG
- 导出私钥
bash
gpg --armo --export-secret-keys <私钥>
- GPG Passphrase
配置文件
在项目根目录下新建 .github/workflows/release.yml
文件,内容如下:
yaml
name: Java CI With Maven
on:
release:
types: [ published ]
jobs:
build:
runs-on: ubuntu-latest
steps:
# 拉取源码
- uses: actions/checkout@v3
# 安装JDK环境
- name: Set up JDK 8
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'temurin'
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
- name: Publish package
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
run: |
cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import;
mvn clean deploy -U -P release -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} -DskipTests
Releases
提示:发布 Releases 后会自动触发 Actions