SpringBoot封装自己的Starter
https://juejin.im/post/5cb880c2f265da03981fc031
一.说明
我们在使用SpringBoot的时候常常要引入一些Starter,例如spring-boot-starter-web,官方为我们提供了几乎所有的默认配置,很好的降低了使用框架时的复杂度,所以在用xxx-starter的时候,可以不用费心去写一些繁琐的配置文件,即使必要的配置在application.properties或application.yml中配置就可以了,当你实现了一个Starter,可以在不同的项目中复用,非常方便,今天我们来编写自己的Starter以之前的短信业务为例。
Springboot短信业务调用:juejin.im/post/5cb165…
spring-boot-starter-xxx是官方提供Starter的命名规则,非官方Starter的命名规则官方建议为 xxx-spring-boot-starter
二.搭建项目
建立SpringBoot项目,清除resources下的文件和文件夹
 Maven依赖如下:
 <dependencies>
        <!--封装Starter核心依赖  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <!--非必需,该依赖作用是在使用IDEA编写配置文件有代码提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <!-- lombok 插件  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
            <optional>true</optional>
        </dependency>
        <!-- 因为要使用RestTemplate和转换Json,所以引入这两个依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.45</version>
        </dependency>
</dependencies>
复制代码
spring-boot-configuration-processor不是必须的,它的作用是和编译时生成 spring-configuration-metadata.json,此文件主要给IDEA使用.配置此JAR相关配置属性在 application.yml中,你可以用Ctrl+鼠标左键点击属性名,IDE会跳转到你配置此属性的类中.并且编写application.yml会有代码提示.
二.编写项目基础类
创建SendSMSDTO传输类,用于参数传递
/**
 * SMSDTO参数类
 * @Author Sans
 * @CreateTime 2019/4/20
 * @attention
 */
@Data
public class SendSMSDTO {
    /**
     * 模板ID
     */
    private String templateid;
    /**
     * 参数
     */
    private String param;
    /**
     * 手机号
     */
    private String mobile;
    /**
     * 用户穿透ID,可以为空
     */
    private String uid;
}
复制代码
创建RestTemplateConfig配置类,用于调用短信接口
/**
 * RestTemplateConfig配置
 * @Author Sans
 * @CreateTime 2019/4/20
 * @attention
 */
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate( ) {
        return new RestTemplate();
    }
}
复制代码
创建短信接口枚举类,用于存放短信接口API地址
/**
 * 短信请求API枚举
 * @Author Sans
 * @CreateTime 2019/4/20
 * @attention
 */
@Getter
public enum ENUM_SMSAPI_URL {
    SENDSMS("https://open.ucpaas.com/ol/sms/sendsms"),
    SENDBATCHSMS("https://open.ucpaas.com/ol/sms/sendsms_batch");
    private String url;
    ENUM_SMSAPI_URL(String url) {
        this.url = url;
    }
}
复制代码
三.编写Starter自动配置类
创建SmsProperties配置属性类,该类主要用于读取yml/properties信息
/**
 * SMS配置属性类
 * @Author Sans
 * @CreateTime 2019/4/20
 * @attention 使用ConfigurationProperties注解可将配置文件(yml/properties)中指定前缀的配置转为bean
 */
@Data
@ConfigurationProperties(prefix = "sms-config")
public class SmsProperties {
    private String appid;
    private String accountSid;
    private String authToken;
}
复制代码
创建短信核心服务类
/**
 * 短信核心服务类
 * @Author Sans
 * @CreateTime 2019/4/20
 * @attention
 */
public class SmsService {
    @Autowired
    private RestTemplate restTemplate;
    private String appid;
    private String accountSid;
    private String authToken;
    /**
     * 初始化
     */
    public SmsService(SmsProperties smsProperties) {
       this.appid = smsProperties.getAppid();
       this.accountSid = smsProperties.getAccountSid();
       this.authToken = smsProperties.getAuthToken();
    }
    /**
     * 单独发送
     */
    public String sendSMS(SendSMSDTO sendSMSDTO){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sid", accountSid);
        jsonObject.put("token", authToken);
        jsonObject.put("appid", appid);
        jsonObject.put("templateid", sendSMSDTO.getTemplateid());
        jsonObject.put("param", sendSMSDTO.getParam());
        jsonObject.put("mobile", sendSMSDTO.getMobile());
        if (sendSMSDTO.getUid()!=null){
            jsonObject.put("uid",sendSMSDTO.getUid());
        }else {
            jsonObject.put("uid","");
        }
        String json = JSONObject.toJSONString(jsonObject);
        //使用restTemplate进行访问远程Http服务
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<String>(json, headers);
        String result = restTemplate.postForObject(ENUM_SMSAPI_URL.SENDSMS.getUrl(), httpEntity, String.class);
        return result;
    }
    /**
     * 群体发送
     */
    public String sendBatchSMS(SendSMSDTO sendSMSDTO){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sid", accountSid);
        jsonObject.put("token", authToken);
        jsonObject.put("appid", appid);
        jsonObject.put("templateid", sendSMSDTO.getTemplateid());
        jsonObject.put("param", sendSMSDTO.getParam());
        jsonObject.put("mobile", sendSMSDTO.getMobile());
        if (sendSMSDTO.getUid()!=null){
            jsonObject.put("uid",sendSMSDTO.getUid());
        }else {
            jsonObject.put("uid","");
        }
        String json = JSONObject.toJSONString(jsonObject);
        //使用restTemplate进行访问远程Http服务
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> httpEntity = new HttpEntity<String>(json, headers);
        String result = restTemplate.postForObject(ENUM_SMSAPI_URL.SENDBATCHSMS.getUrl(), httpEntity, String.class);
        return result;
    }
}
复制代码
创建SmsAutoConfiguration自动配置类,该类主要用于创建核心业务类实例
/**
 * 短信自动配置类
 * @Author Sans
 * @CreateTime 2019/4/20
 * @attention
 */
@Configuration
@EnableConfigurationProperties(SmsProperties.class)//使@ConfigurationProperties注解生效
public class SmsAutoConfiguration {
    @Bean
    public SmsService getBean(SmsProperties smsProperties){
        SmsService smsService = new SmsService(smsProperties);
        return smsService;
    }
}
复制代码
四.创建spring.factories文件
spring.factories该文件用来定义需要自动配置的类,SpringBoot启动时会进行对象的实例化,会通过加载类SpringFactoriesLoader加载该配置文件,将文件中的配置类加载到spring容器
在src/main/resources新建META-INF文件夹,在META-INF文件夹下新建spring.factories文件.配置内容如下:
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sms.starter.config.SmsAutoConfiguration
复制代码
五.打包和测试
使用Maven插件,将项目打包安装到本地仓库
 新建测试项目,引入我们自己的Starter,Maven依赖如下:
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 添加我们自己的starter-->
        <dependency>
            <groupId>com.sms.starter</groupId>
            <artifactId>sms-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
</dependencies>
复制代码
配置测试项目的application.yml
sms-config:
  account-sid:  //这里填写平台获取的ID和KEY
  auth-token:   //这里填写平台获取的ID和KEY
  appid:        //这里填写平台获取的ID和KEY
复制代码
参数填写自己的手机号和申请的模板以及对应的参数
/**
 * 测试短信DEMO
 * @Author Sans
 * @CreateTime 2019/4/20
 * @attention
 */
@RestController
@RequestMapping("/sms")
public class TestController {
    @Autowired
    private SmsService smsService;
    /**
     * 短信测试
     * @Attention
     * @Author: Sans
     * @CreateTime: 2019/4/20
     */
    @RequestMapping(value = "/sendsmsTest",method = RequestMethod.GET)
    public String sendsmsTest(){
        //创建传输类设置参数
        SendSMSDTO sendSMSDTO  = new SendSMSDTO();
        sendSMSDTO.setMobile("");     //手机号
        sendSMSDTO.setTemplateid(""); //模板
        sendSMSDTO.setParam("");      //参数
        return smsService.sendSMS(sendSMSDTO);
    }
}
复制代码
六.后续补充
在引入自己封装的Starter的时候,有的人会报错****类的bean没有找到问题,是因为@SpringBootApplication扫描包的范围是启动类所在同级包和子包,但是不包括第三方的jar包.如果需要扫描maven依赖添加的Jar,我们就要单独使用@ComponentScan注解扫描包. 针对这种情况解决方式有两种:
第一种:是你封装的Starter项目下父级包名称和测试项目的父级包名一样,例如这两个项目包名都叫com.sans,这样可以不使用@ComponentScan注解,很显然这样做有局限性,不推荐.
第二种:是可以单独使用@ComponentScan注解扫描第三方包,但是这里一定要注意@SpringBootApplication注解等价于默认属性使用@Configuration+@EnableAutoConfiguration+@ComponentScan,如果@SpringBootApplication和@ComponentScan注解同时存在,那么@SpringBootApplication注解中@ComponentScan的扫描范围会被覆盖,所以单独使用@ComponentScan的话,必须在该注解上配置项目需要扫描的包的所有范围,即项目包路径+依赖包路径.
/**
 * @ComponentScan注解扫描多个包下示例
 */
@ComponentScan({"com.test","sms.test"})
复制代码
项目源码: gitee.com/liselotte/s…
深夜发帖,十分不易,希望大佬们提出宝贵意见
作者:Sans_
链接:https://juejin.im/post/5cb880c2f265da03981fc031
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
SpringBoot封装自己的Starter的更多相关文章
- 如何使用SpringBoot封装自己的Starter
		
作者:Sans_ juejin.im/post/5cb880c2f265da03981fc031 一.说明 我们在使用SpringBoot的时候常常要引入一些Starter,例如spring-boot ...
 - SpringBoot起飞系列-自定义starter(十)
		
一.前言 到现在,我们可以看出来,如果我们想用一些功能,基本上都是通过添加spring-boot-starter的方式来使用的,因为各种各样的功能都被封装成了starter,然后把相关服务注入到容器中 ...
 - springboot封装JsonUtil,CookieUtil工具类
		
springboot封装JsonUtil,CookieUtil工具类 yls 2019-9-23 JsonUtil public class JsonUtil { private static Obj ...
 - SpringBoot系列之自定义starter实践教程
		
SpringBoot系列之自定义starter实践教程 Springboot是有提供了很多starter的,starter翻译过来可以理解为场景启动器,所谓场景启动器配置了自动配置等等对应业务模块的一 ...
 - 深入springboot原理——一步步分析springboot启动机制(starter机制)
		
前言 使用过springboot的同学应该已经知道,springboot通过默认配置了很多框架的使用方式帮我们大大简化了项目初始搭建以及开发过程.本文的目的就是一步步分析springboot的启动过程 ...
 - SpringBoot原理—分析SpringBoot启动机制(starter机制)
		
一:前言使用过springboot的同学应该已经知道,springboot通过默认配置了很多框架的使用方式帮我们大大简化了项目初始搭建以及开发过程.本文的目的就是一步步分析springboot的启动过 ...
 - SpringBoot 系列  - 自己写starter
		
原文地址: https://www.xncoding.com/2017/07/22/spring/sb-starter.html 前言: Spring Boot由众多Starter组成,随着版本的推移 ...
 - SpringBoot编写自定义的starter 专题
		
What’s in a name All official starters follow a similar naming pattern; spring-boot-starter-*, where ...
 - SpringBoot四大神器之Starter
		
SpringBoot的starter主要用来简化依赖用的.本文主要分两部分,一部分是列出一些starter的依赖,另一部分是教你自己写一个starter. 部分starters的依赖 Starter( ...
 
随机推荐
- Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 1099 bytes) in
			
解释是可用内存已耗尽,这关系到PHP的memory_limit的设置问题. 我在网上看到,有两种方法解决 1.修改php.ini memory_limit = 128 这种方法需要重启服务器,很显然, ...
 - leetcode-easy-trees-108. Convert Sorted Array to Binary Search Tree
			
mycode 81.75 # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x) ...
 - T83312 【音乐会】达拉崩吧·上
			
T83312 [音乐会]达拉崩吧·上 题解 线段树板子题 把原来的 + 变成 ^ 但是注意一下懒标记,这里讲一下小技巧 代码 #include<bits/stdc++.h> using n ...
 - fstab中使用设备的uuid
			
设备定位的方法有: 设备名称, 如:/dev/sda1, 随着linux内核加载模块顺序在每次启动的时候可能会不同, 在插拔U盘/移动硬盘的时候, 设备分配到的名称可能不同,这样fs映射就会失败 因此 ...
 - CAN-FD协议浅析
			
引言 随着电子.半导体.通讯等行业的快速发展,汽车电子智能化的诉求也越来越强,消费者希望驾驶动力性.舒适性.经济性以及娱乐性更强的汽车.汽车制造商为了提高产品竞争力,将越来越多的电子控制系统加入到汽车 ...
 - android开源图表库MPAndroidChart(曲线图、直方图、饼状图)
			
github地址:https://github.com/PhilJay/MPAndroidChart 添加依赖: Add the following to your project level bui ...
 - WPF 模拟迅雷TabControl界面
			
WPF模拟迅雷TabControl界面 点击查看下载 <!--TabControl样式--> <Style x:Key="TabControlStyle" Tar ...
 - Dart学习笔记-运算符-条件表达式-类型转换
			
Dart学习笔记-运算符-条件表达式-类型转换 一.运算符 1.算术运算符 + (加)- (减)* (乘)/ (除)~/ (取整) %(取余) 2.关系运算符 == (等等) != (不等) > ...
 - HDP-2.6.0.3
			
http://public-repo-1.hortonworks.com/HDP/centos6/2.x/updates/2.6.0.3/HDP-2.6.0.3-centos6-rpm.tar.gz ...
 - http 协议里的 200、301、302、401、403、405、500 分别代表什么?
			
http 协议里的 200.301.302.401.403.405.500 分别代表什么? 详细描述: 打开某些网页时,无法正常打开,出现 200.301.302.401.403.405.500 这此 ...