写点什么

自定义 spring boot starter 三部曲之二:实战开发

作者:程序员欣宸
  • 2022 年 7 月 14 日
  • 本文字数:10473 字

    阅读完需:约 34 分钟

自定义spring boot starter三部曲之二:实战开发

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


  • 本文是《自定义 spring boot starter 三部曲》的第二篇,上一篇中我们通过学习 spring cloud 的 starter,对 spring boot 的 starter 有了初步了解,也设计好了实战内容,今天就来一起实现;

本章内容概述

  1. 创建工程 customizestarter;

  2. 创建模块 customizeapi;

  3. 创建模块 addservice;

  4. 创建模块 minusservice;

  5. 创建模块 customizeservicestarter;

  6. 构建工程 customizestarter,并安装到本地 maven 仓库;

  7. 创建工程 customizestartertestdemo;

  8. 构建工程 customizestartertestdemo,得到 jar 包;

  9. 启动 customizestartertestdemo 工程的 jar 包,并带上一个启动参数,验证支持负数的减法服务;

  10. 启动 customizestartertestdemo 工程的 jar 包,验证不支持服务的减法服务;

源码下载

  • 您也可以选择直接从 GitHub 下载 customizestarter 和 customizestartertestdemo 这两个工程的源码,地址和链接信息如下表所示:



  • 这个 git 项目中有多个文件夹,本章源码分别在 customizestarter 和 customizestartertestdemo 这两个文件夹下,如下图红框所示:



  • 接下来开始开发吧;

创建工程 customizestarter

  • 创建一个名为 customizestarter 的 maven 工程,以**spring-boot-starter-parent</font>作为父工程,同时自身又是后续几个模块的父工程,pom.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>    <groupId>com.bolingcavalry</groupId>    <artifactId>customizestarter</artifactId>    <packaging>pom</packaging>    <version>0.0.1-SNAPSHOT</version>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> </parent>
<modules> <!--加法服务--> <module>addservice</module> <!--减法服务--> <module>minusservice</module> <!--接口和异常定义--> <module>customizeapi</module> <!--启动器--> <module>customizeservicestarter</module> </modules></project>
复制代码

创建模块 customizeapi

  • 在工程 customizestarter 下创建模块 customizeapi,这是个 java 工程,里面是加法和减法服务的接口,和一个业务异常的定义;

  • customizeapi 的 pom.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">    <parent>        <artifactId>customizestarter</artifactId>        <groupId>com.bolingcavalry</groupId>        <version>0.0.1-SNAPSHOT</version>        <relativePath>../</relativePath>    </parent>    <modelVersion>4.0.0</modelVersion>    <artifactId>customizeapi</artifactId></project>
复制代码


  • 异常定义类:


package com.bolingcavalry.api.exception;
/** * @author wilzhao * @description 执行减法服务时抛出的异常 * @email zq2599@gmail.com * @time 2018/10/13 14:20 */public class MinusException extends Exception{ public MinusException(String message) { super(message); }}
复制代码


  • 加法服务的接口类 AddService:


package com.bolingcavalry.api.service;
/** * @author wilzhao * @description 加法服务对应的接口 * @email zq2599@gmail.com * @time 2018/10/13 10:07 */public interface AddService { /** * 普通加法 * @param a * @param b * @return */ int add(int a, int b);}
复制代码


  • 减法服务定义类,注意减法 API 声明了异常抛出,因为如果已经配置了不支持负数的减法服务,那么被减数如果小于减数就抛出异常:


package com.bolingcavalry.api.service;
import com.bolingcavalry.api.exception.MinusException;
/** * @author wilzhao * @description 减法服务 * @email zq2599@gmail.com * @time 2018/10/13 12:07 */public interface MinusService { /** * 普通减法 * @param minuend 减数 * @param subtraction 被减数 * @return 差 */ int minus(int minuend, int subtraction) throws MinusException;}
复制代码

创建模块 addservice

  • 在工程 customizestarter 下创建模块 addservice,这是个 java 工程,里面包含了加法相服务的实现,pom.xml 内容如下,注意由于要实现加法接口,因此需要依赖模块 customizeapi:


<?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>customizestarter</artifactId>        <groupId>com.bolingcavalry</groupId>        <version>0.0.1-SNAPSHOT</version>        <relativePath>../</relativePath>    </parent>    <artifactId>addservice</artifactId>    <modelVersion>4.0.0</modelVersion>
<dependencies> <dependency> <groupId>com.bolingcavalry</groupId> <artifactId>customizeapi</artifactId> <version>${project.version}</version> </dependency> </dependencies></project>
复制代码


  • 加法接口的实现类 AddServiceImpl 很简单,如下:


package com.bolingcavalry.addservice.service.impl;
import com.bolingcavalry.api.service.AddService;
/** * @author wilzhao * @description 加法服务的实现 * @email zq2599@gmail.com * @time 2018/10/13 10:59 */public class AddServiceImpl implements AddService { public int add(int a, int b) { return a + b; }}
复制代码

创建模块 minusservice

  • 在工程 customizestarter 下创建模块 minusservice,这是个 java 工程,里面包含了减法相服务的实现,pom.xml 内容如下,注意由于要实现减法接口,因此需要依赖模块 customizeapi:


<?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>customizestarter</artifactId>        <groupId>com.bolingcavalry</groupId>        <version>0.0.1-SNAPSHOT</version>        <relativePath>../</relativePath>    </parent>    <modelVersion>4.0.0</modelVersion>    <artifactId>minusservice</artifactId>    <dependencies>        <dependency>            <groupId>com.bolingcavalry</groupId>            <artifactId>customizeapi</artifactId>            <version>${project.version}</version>        </dependency>    </dependencies></project>
复制代码


  • 一共有两个减法接口的实现类,第一个不支持负数结果,如果被减数小于减数就抛出异常 MinusException:


package com.bolingcavalry.minusservice.service.impl;
import com.bolingcavalry.api.exception.MinusException;import com.bolingcavalry.api.service.MinusService;
/** * @author wilzhao * @description 减法服务的实现,不支持负数 * @email zq2599@gmail.com * @time 2018/10/13 14:24 */public class MinusServiceNotSupportNegativeImpl implements MinusService {
/** * 减法运算,不支持负数结果,如果被减数小于减数,就跑出MinusException * @param minuend 被减数 * @param subtraction 减数 * @return * @throws MinusException */ public int minus(int minuend, int subtraction) throws MinusException { if(subtraction>minuend){ throw new MinusException("not support negative!"); }
return minuend-subtraction; }}
复制代码


  • 第二个减法接口的实现类支持负数返回:


package com.bolingcavalry.minusservice.service.impl;
import com.bolingcavalry.api.exception.MinusException;import com.bolingcavalry.api.service.MinusService;
/** * @author wilzhao * @description 支持负数结果的减法服务 * @email zq2599@gmail.com * @time 2018/10/13 14:30 */public class MinusServiceSupportNegativeImpl implements MinusService {
/** * 减法实现,支持负数 * @param minuend 减数 * @param subtraction 被减数 * @return * @throws MinusException */ public int minus(int minuend, int subtraction) throws MinusException { return minuend - subtraction; }}
复制代码

创建模块 customizeservicestarter

  • 在工程 customizestarter 下创建模块 customizeservicestarter,这是个 java 工程,里面需要依赖 spring boot 配置相关的库,由于要在配置中实例化加法和减法服务的实现,因此 customizeapi、addservice、minusservice 这些模块都要在 pom.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">    <parent>        <artifactId>customizestarter</artifactId>        <groupId>com.bolingcavalry</groupId>        <version>0.0.1-SNAPSHOT</version>        <relativePath>../</relativePath>    </parent>    <artifactId>customizeservicestarter</artifactId>    <modelVersion>4.0.0</modelVersion>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <!--仅编译时才需要--> <scope>provided</scope> </dependency> <dependency> <groupId>com.bolingcavalry</groupId> <artifactId>customizeapi</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.bolingcavalry</groupId> <artifactId>addservice</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.bolingcavalry</groupId> <artifactId>minusservice</artifactId> <version>${project.version}</version> </dependency> </dependencies></project>
复制代码


  • 创建配置类 CustomizeConfiguration,注意 getSupportMinusService 和 getNotSupportMinusService 这两个方法上的注解配置,如果环境变量**com.bolingcavalry.supportnegative</font>存在并且等于 true,那么 getSupportMinusService 方法就返回了 MinusService 接口的实例,如果当前环境没有 MinusService 接口的实例,就由 getNotSupportMinusService 方法就返回一个,并且有会在控制台打印创建了哪种实现:


package com.bolingcavalry.customizeservicestarter;
import com.bolingcavalry.addservice.service.impl.AddServiceImpl;import com.bolingcavalry.api.service.AddService;import com.bolingcavalry.api.service.MinusService;import com.bolingcavalry.minusservice.service.impl.MinusServiceNotSupportNegativeImpl;import com.bolingcavalry.minusservice.service.impl.MinusServiceSupportNegativeImpl;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
/** * @author wilzhao * @description 一句话介绍 * @email zq2599@gmail.com * @time 2018/10/13 14:36 */@Configurationpublic class CustomizeConfiguration {
@Bean public AddService getAddService(){ System.out.println("create addService"); return new AddServiceImpl(); }
/** * 如果配置了com.bolingcavalry.supportnegative=true, * 就实例化MinusServiceSupportNegativeImpl * @return */ @Bean @ConditionalOnProperty(prefix="com.bolingcavalry",name = "supportnegative", havingValue = "true") public MinusService getSupportMinusService(){ System.out.println("create minusService support minus"); return new MinusServiceSupportNegativeImpl(); }
/** * 如果没有配置com.bolingcavalry.supportnegative=true, * 就不会实例化MinusServiceSupportNegativeImpl, * 这里的条件是如果没有MinusService类型的bean,就在此实例化一个 * @return */ @Bean @ConditionalOnMissingBean(MinusService.class) public MinusService getNotSupportMinusService(){ System.out.println("create minusService not support minus"); return new MinusServiceNotSupportNegativeImpl(); }}
复制代码


  • 在 src\main\resources 目录下创建一个目录**META-INF</font>,里面创建一个文件 spring.factories,内容是如下,表示如果当前应用支持 spring boot 的自动配置,就会被 spring boot 框架实例化并注册到 spring 容器内:


org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.bolingcavalry.customizeservicestarter.CustomizeConfiguration
复制代码

构建工程 customizestarter

  • 到这里 customizestarter 工程的编码就结束了,在工程内 pom.xml 所在目录(也就是 customizestarter 内的第一层目录),执行以下命令可以编译构建并安装到本地 maven 仓库:


mvn clean install -Dmaven.test.skip=true -U
复制代码


  • 如果编译构建和安装都成功了,可以看到类似如下输出:


[INFO] Installing C:\temp\201810\07\customizestarter\customizeservicestarter\pom.xml to C:\Users\12167\.m2\repository\com\bolingcavalry\customizeservicestarter\0.0.1-SNAPSHOT\customizeservicestarter-0.0.1-SNAPSHOT.pom[INFO] ------------------------------------------------------------------------[INFO] Reactor Summary:[INFO][INFO] customizestarter ................................... SUCCESS [  0.748 s][INFO] customizeapi ....................................... SUCCESS [  3.266 s][INFO] addservice ......................................... SUCCESS [  0.427 s][INFO] minusservice ....................................... SUCCESS [  0.344 s][INFO] customizeservicestarter ............................ SUCCESS [  0.495 s][INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 5.954 s[INFO] Finished at: 2018-10-14T00:17:46+08:00[INFO] Final Memory: 29M/221M[INFO] ------------------------------------------------------------------------
复制代码


  • 现在 starter 已经准备好了,我们做一个 spring boot 的 web 应用来验证一下;

创建工程 customizestartertestdemo

  • 工程 customizestartertestdemo 是个简单的 spring boot 应用,pom.xml 如下,可见并无特别之处,只是多了 customizeservicestarter 的依赖:


<?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>com.bolingcavalry</groupId> <artifactId>customizestartertestdemo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>customizestartertestdemo</name> <description>Demo project for Spring Boot</description>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
<dependency> <groupId>com.bolingcavalry</groupId> <artifactId>customizeservicestarter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
复制代码


  • 开发一个 Controller 类,用于调用 AddService 和 MinusService 对应的服务:


package com.bolingcavalry.customizestartertestdemo.controller;
import com.bolingcavalry.api.exception.MinusException;import com.bolingcavalry.api.service.AddService;import com.bolingcavalry.api.service.MinusService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;
/** * @author wilzhao * @description 调用加法和减法服务的测试类 * @email zq2599@gmail.com * @time 2018/10/13 16:00 */@RestControllerpublic class CalculateController {
@Autowired private AddService addService;
@Autowired private MinusService minusService;
@RequestMapping(value = "/add/{added}/{add}", method = RequestMethod.GET) public String add(@PathVariable("added") int added, @PathVariable("add") int add){ return added + " 加 " + add + " 等于 : " + addService.add(added, add); }
@RequestMapping(value = "/minus/{minuend}/{subtraction}", method = RequestMethod.GET) public String minus(@PathVariable("minuend") int minuend, @PathVariable("subtraction") int subtraction) throws MinusException { return minuend + " 减 " + subtraction + " 等于 : " + minusService.minus(minuend, subtraction); }}
复制代码


  • 启动类如下:


package com.bolingcavalry.customizestartertestdemo;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class CustomizestartertestdemoApplication {
public static void main(String[] args) { SpringApplication.run(CustomizestartertestdemoApplication.class, args); }}
复制代码

构建工程 customizestartertestdemo

  • 在 customizestartertestdemo 工程的 pom.xml 所在目录下执行以下命令即可构建成功:


mvn clean package -Dmaven.test.skip=true
复制代码


  • 命令执行成功后,即可在 target 目录下见到 customizestartertestdemo-0.0.1-SNAPSHOT.jar 文件,如下图:



  • 现在编码和构建已经全部完成,我们可以来验证了;

验证支持负数的减法服务

  • 在 customizeapi 模块的 CustomizeConfiguration 类中,有如下方法和注解:


@Bean    @ConditionalOnProperty(prefix="com.bolingcavalry",name = "supportnegative", havingValue = "true")    public MinusService getSupportMinusService(){        System.out.println("create minusService support minus");        return new MinusServiceSupportNegativeImpl();    }
复制代码


  • 从上述代码可见,只要环境变量"com.bolingcavalry.supportnegative"等于 true,注册到 spring 容器的就是 MinusServiceSupportNegativeImpl 类的实例;

  • customizestartertestdemo-0.0.1-SNAPSHOT.jar 文件所在目录下,执行以下命令启动应用:


java -Dcom.bolingcavalry.supportnegative=true -jar customizestartertestdemo-0.0.1-SNAPSHOT.jar
复制代码


  • 在控制台中可以看见**create minusService support minus</font>,表示注册到 spring 容器的是 MinusServiceSupportNegativeImpl 类的实例,如下所示:


2018-10-14 12:04:54.233  INFO 16588 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]create addServicecreate minusService support minus2018-10-14 12:04:54.845  INFO 16588 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@443b7951: startup date [Sun Oct 14 12:04:50 CST 2018]; root of context hierarchy
复制代码


  • 在浏览器访问 http://localhost:8080/minus/1/2,可见返回计算结果为负数:


验证不支持负数的减法服务

  • 前面已经分析过,CustomizeConfiguration 类的 getNotSupportMinusService 方法执行的条件是环境变量"com.bolingcavalry.supportnegative"等于 true,如果没有这个环境变量,getNotSupportMinusService 方法就不会执行,spring 容器中就没有 MinusService 接口的实例;

  • CustomizeConfiguration 类中,有如下方法和注解:


    @Bean    @ConditionalOnMissingBean(MinusService.class)    public MinusService getNotSupportMinusService(){        System.out.println("create minusService not support minus");        return new MinusServiceNotSupportNegativeImpl();    }
复制代码


  • 从上述代码可见,spring 容器中如果没有 MinusService 接口的实例,getNotSupportMinusService 方法就会被执行,在 spring 容器中注册 MinusServiceNotSupportNegativeImpl 实例;

  • 因此接下来的我们启动的应用如果没有环境变量"com.bolingcavalry.supportnegative",就可以使用到不支持负数的减法服务了;

  • 停掉之前启动的应用,然后执行以下命令启动应用:


java -jar customizestartertestdemo-0.0.1-SNAPSHOT.jar
复制代码


  • 在控制台中可以看见**create minusService not support minus</font>,表示注册到 spring 容器的是 MinusServiceNotSupportNegativeImpl 类的实例,如下所示:


2018-10-14 12:15:05.994  INFO 16608 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]create addServicecreate minusService not support minus2018-10-14 12:15:06.592  INFO 16608 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@443b7951: startup date [Sun Oct 14 12:15:02 CST 2018]; root of context hierarchy
复制代码


  • 在浏览器访问 http://localhost:8080/minus/1/2,由于 MinusServiceNotSupportNegativeImpl 实例不支持负数减法,会直接抛出异常,如下图:



  • 至此,自定义 spring boot starter 的编码实战就完成了,希望本篇可以给您用来作参考,助您做出自己所需的 starter;

  • 下一篇我们一起去看看 spring boot 的源码,对这个高效的扩展功能做更深入的了解;

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

发布于: 2022 年 07 月 14 日阅读数: 52
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
自定义spring boot starter三部曲之二:实战开发_Java_程序员欣宸_InfoQ写作社区