SpringBoot 封裝本身的Starter

一.說明

咱們在使用SpringBoot的時候經常要引入一些Starter,例如spring-boot-starter-web,官方爲咱們提供了幾乎全部的默認配置,很好的下降了使用框架時的複雜度,因此在用xxx-starter的時候,能夠不用費心去寫一些繁瑣的配置文件,即便必要的配置在application.properties或application.yml中配置就能夠了,當你實現了一個Starter,能夠在不一樣的項目中複用,很是方便,今天咱們來編寫本身的Starter以以前的短信業務爲例。java

Springboot短信業務調用:juejin.im/post/5cb165…git

spring-boot-starter-xxx是官方提供Starter的命名規則,非官方Starter的命名規則官方建議爲 xxx-spring-boot-starterweb

二.搭建項目

創建SpringBoot項目,清除resources下的文件和文件夾 spring

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會有代碼提示.json

二.編寫項目基礎類

建立SendSMSDTO傳輸類,用於參數傳遞app

/** * 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地址maven

/** * 短信請求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信息spring-boot

/** * 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;
}
複製代碼

建立短信核心服務類post

/** * 短信核心服務類 * @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…

深夜發帖,十分不易,但願大佬們提出寶貴意見

相關文章
相關標籤/搜索