2021-07-25_基于SpringBoot短信发送学习笔记

2021-07-25  本文已影响0人  kikop

20210725_基于SpringBoot短信发送学习笔记

1概述

本篇主要是配合自定义starter进行功能验证。源码后面我会放到git上。

1.1关于spring.factories文件

spring.factories该文件用来定义需要自动配置的类,SpringBoot启动时会进行对象的实例化,会通过加载类SpringFactoriesLoader加载该配置文件,将文件中的配置类加载到spring容器。

1.2关于@SpringBootApplication

这里一定要注意@SpringBootApplication注解等价于默认属性使用@Configuration+@EnableAutoConfiguration+@ComponentScan,如果@SpringBootApplication和@ComponentScan注解同时存在,那么@SpringBootApplication注解中@ComponentScan的扫描范围会被覆盖,所以单独使用@ComponentScan的话,必须在该注解上配置项目需要扫描的包的所有范围,即项目包路径+依赖包路径。

1.3互亿无线账号注册

在互亿无线平台:https://www.ihuyi.com/ 注册账号并且认证为个人开发者(需要身份证),这个不难,不多说了。注册成功得到如下信息:

apiid、apikey。如果想真实的进行短信发送测试,需购买套餐添加签名和模板才可以。

[图片上传失败...(image-3cdae8-1627213379964)]

2代码实战

2.1自定义starter包

2.1.1maven依赖

<?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.kikop.sms</groupId>
    <artifactId>mysms-spring-boot-starter</artifactId>
    <version>2.0.0-SNAPSHOT</version>
    <name>mysms-spring-boot-starter</name>
    <description>mysms-spring-boot-starter project</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>2.1.4.RELEASE</spring-boot.version>

        <commons-pool2.version>2.6.0</commons-pool2.version>
        <commons-lang.version>2.6</commons-lang.version>


        <!--jaxen-->
        <jaxen.version>1.1.1</jaxen.version>
        <dom4j.version>1.6.1</dom4j.version>

    </properties>

    <dependencies>

        <!--1.自动装配-->
        <!--封装Starter核心依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>

        <!--2.该依赖作用是在使用IDEA编写配置文件有代码提示-->
        <!--非必需-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>

        <!-- 3.lombok 插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
            <optional>true</optional>
        </dependency>

        <!-- 4.spring-boot-starter-web-->
        <!--因为要使用RestTemplate和转换Json,所以引入这两个依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>

        <!--5.fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.45</version>
        </dependency>


        <!--6.commons-httpclient-->
        <!--commons-httpclient 是 apache-commons 项目下的一个子项目,-->
        <!--后来被 HttpComponents 取代,后者提供了更好的性能和更大的灵活性。-->
        <!--commons-httpclient的GAV地址为-->
        <!--其最新版本为3.1,且已经不再更新;-->
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>

        <!--7.httpclient-->
        <!--HttpComponents的GAV地址为-->
        <!--https://blog.csdn.net/cym0359/article/details/106826374/-->
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
        <!--<dependency>-->
        <!--<groupId>org.apache.httpcomponents</groupId>-->
        <!--<artifactId>httpclient</artifactId>-->
        <!--<version>4.5.5</version>-->
        <!--</dependency>-->


        <!--3.jaxen-->
        <!--内置dom4j-->
        <!--Jaxen是一个开源的XPath库-->
        <!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>${jaxen.version}</version>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>

            <!--1.spring-boot-maven-plugin-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <!-- 2.跳过单元测试 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>

        </plugins>

    </build>

</project>

2.1.2服务url定义

package com.kikop.sms.utils;

import lombok.Getter;

/**
 * @author kikop
 * @version 1.0
 * @project Name: mysms-spring-boot-starter
 * @file Name: Enum_Sms_URL
 * @desc 创建短信接口枚举类,用于存放短信接口API地址
 * @date 2019/9/15
 * @time 16:50
 * @by IDE: IntelliJ IDEA
 */
@Getter
public enum Enum_Sms_URL {

    SENDSMS("https://open.ucpaas.com/ol/sms/sendsms"),
    SENDBATCHSMS("https://open.ucpaas.com/ol/sms/sendsms_batch"),
    SENDSMS2("http://106.ihuyi.com/webservice/sms.php?method=Submit");

    private String url;

    Enum_Sms_URL(String url) {
        this.url = url;
    }
}

2.1.3定义SmsProperties

package com.kikop.sms.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author kikop
 * @version 1.0
 * @project Name: mysms-spring-boot-starter
 * @file Name: SmsProperties
 * @desc 创建SmsProperties配置属性类,并注入到 spring容器中
 * 该类主要用于读取yml/properties信息
 * @date 2019/9/15
 * @time 16:52
 * @by IDE: IntelliJ IDEA
 */
@Data
@ConfigurationProperties(prefix = "mysms2")
public class SmsProperties {

    private String appid;

    private String accountSid;

    private String authToken;


    private String apiid;

    private String apikey;
}

2.1.4定义参数数据结构

package com.kikop.sms.dto;

import lombok.Data;

/**
 * @author kikop
 * @version 1.0
 * @project Name: mysms-spring-boot-starter
 * @file Name: SmsDTO
 * @desc 传输类,用于参数传递
 * @date 2019/9/15
 * @time 16:46
 * @by IDE: IntelliJ IDEA
 */
@Data
public class SmsDTO {

    /**
     * 模板ID
     */
    private String templateid;

    /**
     * 用户穿透ID
     * 可以为空
     */
    private String uid;

    /**
     * 参数
     */
    private String param;

    /**
     * 手机号(可多个)
     */
    private String mobile;


}

2.1.5定义ISmsService

package com.kikop.sms.service;

import com.kikop.sms.dto.SmsDTO;

/**
 * @author kikop
 * @version 1.0
 * @project Name: mysms-spring-boot-starter
 * @file Name: ISmsService
 * @desc 创建短信核心服务接口
 * @date 2019/9/15
 * @time 16:54
 * @by IDE: IntelliJ IDEA
 */
public interface ISmsService {


    /**
     * 单独发送
     */
    String sendsms(SmsDTO sendSMSDTO);


    /**
     * 群体发送
     */
    String sendsms_batch(SmsDTO sendSMSDTO);


    /**
     * 查询余额
     */
    String queryAccount(SmsDTO sendSMSDTO);
}

2.1.6定义HYWXSmsServiceImpl

package com.kikop.sms.service.impl;

import com.kikop.sms.dto.SmsDTO;
import com.kikop.sms.properties.SmsProperties;
import com.kikop.sms.service.ISmsService;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;

import java.net.URLEncoder;

/**
 * @author kikop
 * @version 1.0
 * @project Name: sms-spring-boot-starter
 * @file Name: SmsService
 * @desc 创建短信核心服务类(基于互亿无线云)
 * 注意,这里没加@Component,在 SmsAutoConfiguration 中手动 new
 * @date 2019/9/15
 * @time 16:54
 * @by IDE: IntelliJ IDEA
 */
public class HYWXSmsServiceImpl implements ISmsService {

    @Autowired
    private RestTemplate restTemplate;

    private String appid;
    private String accountSid;
    private String authToken;

    private String apiid;
    private String apikey;


    public HYWXSmsServiceImpl(SmsProperties smsProperties) {
        this.appid = smsProperties.getAppid();
        this.accountSid = smsProperties.getAccountSid();
        this.authToken = smsProperties.getAuthToken();

        this.apiid = smsProperties.getApiid();
        this.apikey = smsProperties.getApikey();
    }


    /**
     * 单独发送
     */
    public String sendsms(SmsDTO sendSMSDTO) {
        String Url = "http://106.ihuyi.com/webservice/sms.php?method=Submit";
        String SubmitResult = null;
        try {

            HttpClient client = new HttpClient();
            PostMethod method = new PostMethod(Url);
            client.getParams().setContentCharset("UTF-8"); // GBK
            method.setRequestHeader("ContentType",
                    "application/x-www-form-urlencoded;charset=UTF-8");

//        int mobile_code = (int) ((Math.random() * 9 + 1) * 100000);
//        String content = new String("您的验证码是:" + mobile_code + "。请不要把验证码泄露给其他人。");

            String account = this.apiid;
            String password = this.apikey;
            String mobile = sendSMSDTO.getMobile();
            // 您的验证码是:1234。请不要把验证码泄露给其他人。
            String content = null;
            content = URLEncoder.encode(sendSMSDTO.getParam(), "UTF-8");

            NameValuePair[] data = {//提交短信
//                    new NameValuePair("signature", "互亿无线"),
                    new NameValuePair("account", account), //查看用户名 登录用户中心->验证码通知短信>产品总览->API接口信息->APIID
                    new NameValuePair("password", password), //查看密码 登录用户中心->验证码通知短信>产品总览->API接口信息->APIKEY
                    //new NameValuePair("password", util.StringUtil.MD5Encode("密码")),
                    new NameValuePair("mobile", mobile),
                    new NameValuePair("content", content),
                    new NameValuePair("format", "json"),
            };
            method.setRequestBody(data);

            client.executeMethod(method);

            SubmitResult = method.getResponseBodyAsString();

            //System.out.println(SubmitResult);

            return SubmitResult;
//            Document doc = DocumentHelper.parseText(SubmitResult);
//            Element root = doc.getRootElement();
//
//            String code = root.elementText("code");
//            String msg = root.elementText("msg");
//            String smsid = root.elementText("smsid");
//
//            System.out.println(code);
//            System.out.println(msg);
//            System.out.println(smsid);
//
//            if ("2".equals(code)) {
//                System.out.println("短信提交成功");
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SubmitResult;

    }

    /**
     * 群体发送
     */
    public String sendsms_batch(SmsDTO sendSMSDTO) {
        return null;
    }


    public String queryAccount(SmsDTO sendSMSDTO) {
        String Url = "http://106.ihuyi.com/webservice/sms.php?method=GetNum";
        String SubmitResult = null;
        try {

            HttpClient client = new HttpClient();
            PostMethod method = new PostMethod(Url);
            client.getParams().setContentCharset("UTF-8");
            method.setRequestHeader("ContentType",
                    "application/x-www-form-urlencoded;charset=UTF-8");

            String account = this.apiid;
            String password = this.apikey;
            String mobile = sendSMSDTO.getMobile();

            NameValuePair[] data = {//提交短信
                    new NameValuePair("account", account), //查看用户名 登录用户中心->验证码通知短信>产品总览->API接口信息->APIID
                    new NameValuePair("password", password), //查看密码 登录用户中心->验证码通知短信>产品总览->API接口信息->APIKEY
                    //new NameValuePair("password", util.StringUtil.MD5Encode("密码")),
                    new NameValuePair("format", "json"),
            };
            method.setRequestBody(data);
            client.executeMethod(method);
            SubmitResult = method.getResponseBodyAsString();
//            System.out.println(SubmitResult);
            return SubmitResult;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SubmitResult;
    }

    // 互亿无线
//    public String queryAccount(SmsDTO sendSMSDTO) {
//
//        String SubmitResult = null;
//        try {
//            // https://www.ihuyi.com/api/sms.html
//            // http://106.ihuyi.com/webservice/sms.php?method=Submit
//            // &account=APIID&password=APIKEY&mobile=手机号码
//            // &content=您的验证码是:1234。请不要把验证码泄露给其他人。
//            String reqServer = "http://106.ihuyi.com/webservice/sms.php?method=GetNum";
//            String account = this.apiid;
//            String password = this.apikey;
//
//            JSONObject reqSmsPayLoad = new JSONObject();
//            // 基础配置,在开发平台认证后获取
//            reqSmsPayLoad.put("account", account);
//            reqSmsPayLoad.put("password", password);
//            reqSmsPayLoad.put("format", "json");
//
//            String reqSmsPayLoadStrJson = JSONObject.toJSONString(reqSmsPayLoad);
//
//            // 使用restTemplate进行访问远程Http服务
//            HttpHeaders headers = new HttpHeaders();
//            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//            HttpEntity<String> httpEntity = new HttpEntity<String>(reqSmsPayLoadStrJson, headers);
//
//            //单发短信API
//            SubmitResult = restTemplate.postForObject(reqServer, httpEntity, String.class);
//
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        }
//        return SubmitResult;
//    }

}

2.1.7定义自动配置类

package com.kikop.sms.config;

import com.kikop.sms.properties.SmsProperties;
import com.kikop.sms.service.ISmsService;
import com.kikop.sms.service.impl.HYWXSmsServiceImpl;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @author kikop
 * @version 1.0
 * @project Name: mysms-spring-boot-starter
 * @file Name: SmsAutoConfiguration
 * @desc 创建核心业务类实例
 * @date 2019/9/15
 * @time 17:09
 * @by IDE: IntelliJ IDEA
 */
@Configuration
@EnableConfigurationProperties(SmsProperties.class)
public class SmsAutoConfiguration {

    /**
     * 构建短信业务服务
     *
     * @param smsProperties
     * @return
     */
    @Bean
    public ISmsService smsService(SmsProperties smsProperties) {
        return new HYWXSmsServiceImpl(smsProperties);
    }

    /**
     * 创建RestTemplateConfig配置类,用于调用短信接口
     *
     * @return
     */
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

2.1.8新建spring.factories

在src/main/resources新建META-INF文件夹,在META-INF文件夹下新建spring.factories文件.配置内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.kikop.sms.config.SmsAutoConfiguration

2.2打包和测试

2.2.1新建测试项目,引入我们自己的Starter,Maven依赖如下:

<?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>pom</packaging>



    <parent>
        <artifactId>technicaltools</artifactId>
        <groupId>com.kikop</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>


    <groupId>com.kikop</groupId>
    <artifactId>mysmsspringbootdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>${project.artifactId}</name>
    <description>mysmsspringbootdemo project</description>

    <modules>
        <module>mycustomsmsdemo</module>
    </modules>

    <dependencies>

        <!--lombok:用到slf4j的依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <!--<version>1.18.10</version>-->
            <version>${lombok.version}</version>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <dependencyManagement>

        <dependencies>

            <!-- 1.改动 Spring Boot,基于 2.1.4.RELEASE,主要是解决 maven的单继承问题 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <!--<version>2.3.7.RELEASE</version>-->
                <!--<version>2.0.4.RELEASE</version>-->
                <!--现在我们设置成了pom,说明导入的是一个父模块-->
                <type>pom</type>
                <!--scope标签中的值import代表把父模块中的jar包导入进来-->
                <scope>import</scope>
            </dependency>
        </dependencies>

    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.2.2定义MySmsConfig

package com.kikop.config;

import org.springframework.context.annotation.Configuration;

/**
 * @author kikop
 * @version 1.0
 * @project Name: mycustomsmsdemo
 * @file Name: MySmsConfig
 * @desc
 * @date 2021/3/30
 * @time 8:00
 * @by IDE: IntelliJ IDEA
 */
@Configuration
public class MySmsConfig {
}

2.2.3资源配置

2.2.3.1application.yml

spring:
# 1.指定环境:开发v
 profiles:
  active: dev

mysms:
 appid: e0b4acef2846b8e08188aea9fb0e
 accountSid: 60637ea52ed10f3267c1184b0260
 authToken: 491be330eac**********05c9c846058

mysms2:
 apiid: 37657
 apikey: f1b372975828bc35816ed5873db9

2.2.3.2application-dev.properties

server.port=8080
server.servlet.context-path=/mysmsdemodev

2.2.4定义MySmsApplication

package com.kikop;

import com.kikop.sms.dto.SmsDTO;
import com.kikop.sms.properties.SmsProperties;
import com.kikop.sms.service.ISmsService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication

// 注解扫描多个包下示例,内嵌包中有@Component注解,需开启如下内容
//@ComponentScan({"com.kikopxxx", "com.kikop"})
public class MySmsApplication {


    public static void main(String[] args) {


        ConfigurableApplicationContext configurableApplicationContext =
                SpringApplication.run(MySmsApplication.class, args);


        // 1.获取配置
        SmsProperties smsProperties = configurableApplicationContext.getBean(SmsProperties.class);
        System.out.println("apiid:" + smsProperties.getApiid());
        System.out.println("apikey:" + smsProperties.getApikey());


        // 3.发送短信
        // http://docs.ucpaas.com/doku.php?id=error_code
        // https://www.ihuyi.com/api/sms.html
//        ISmsService smsService = configurableApplicationContext.getBean(ISmsService.class);
//        SmsDTO smsDTO = new SmsDTO();
//        String mobile_code = "123456";
//        smsDTO.setParam("您的验证码是:123456。请不要把验证码泄露给其他人。");
//        smsDTO.setMobile("13776647245");
//        System.out.println(smsService.sendsms(smsDTO));

        // 4.queryAccount
        // http://docs.ucpaas.com/doku.php?id=error_code
        // https://www.ihuyi.com/api/sms.html
        ISmsService querySmsService = configurableApplicationContext.getBean(ISmsService.class);
        SmsDTO smsDTOQ = new SmsDTO();
        System.out.println(querySmsService.queryAccount(smsDTOQ));
    }

}

// 输出如下内容:
{"code":2,"msg":"查询成功","num":9}

参考

1SpringBoot 实现发送短信

https://juejin.cn/post/6844903817922740232

2SpringBoot 封装自己的Starter

https://juejin.cn/post/6844903827519307784

3短信开发指导

https://www.ihuyi.com/demo/sms/java.html

https://user.ihuyi.com/new/sms/send/send

上一篇下一篇

猜你喜欢

热点阅读