利用Java反射机制实现短信接口更换

此推文主要说明Java的反射机制,以及在实际应用中的一个小demo,文末有阿里、腾讯的短信端口的实现代码。

Java反射:

反射,为什么叫“反”射,先从“正”开始说。在Java中如果要创建一个类,首先我们要知道这个类是啥,然后通过new创建,比如 Test test=new Test();

而反射恰恰相反,反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法

短信接口:

     短信发送是我们自己开发项目是常用到的内容,比如说用户登录、注册、更改密码、更改手机绑定都是需要我们用短信验证码的,还有推广,我们调用短信接口给特定用户发送推广短信。

这个时候就出现了问题,现在的短信提供商有很多,在某些特殊情况下我们需要更改短信调用服务商,但是又不想拆开代码重新更改,反射登场。

0反射使用

使用反射获取对象的一般步骤:

  • 获取类的class对象实例
    Class test=Class.forName("com.kaixiaobai.test")
  • 根据Class对象实例获取Constructor对象
    Constructor cons=test.getConstructor()
  • 使用Constructor对象的newInstance()方法获取反射类对象
  • 如果要调用方法,可以使用getMthod,比如
    Method settest=test.getMethod(方法名,参数类型...)
  • 如果是获取属性可以使用getFields(),或者是getDeclaredFields(),两个的区别是前者不能获取私有属性,而后者可以

完整代码附上

阿里云短信接口,引入依赖
<dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-core</artifactId>
      <version>4.5.18</version>
</dependency>

AliSms类
package util.SMSutil;

import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.aliyun.tea.*;
import com.aliyun.dysmsapi20170525.*;
import com.aliyun.dysmsapi20170525.models.*;
import com.aliyun.teaopenapi.*;
import com.aliyun.teaopenapi.models.*;


@Component
public class AliSms {
    //@Value("${ali.accessKeyId}")
    private String accessKeyId="";
    //@Value("${ali.accessKeySecret}")
    private String accessKeySecret="";

    public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new com.aliyun.dysmsapi20170525.Client(config);
    }

    public String sendsms(String phone,String code,int type) {//阿里云短信接口
        String template=null;
        /*
        type=1;短信注册
        type=2;短信绑定
        type=3;短信更改绑定
        type=4;短信修改密码
        */
        switch (type){
            case 1:
                template="SMS";
                break;
            case 2:
                template="SMS";
                break;
            case 3:
                template="SMS";
                break;
            case 4:
                template="SMS";
                break;
        }
        com.aliyun.dysmsapi20170525.Client client = null;
        try {
            client = AliSms.createClient(accessKeyId, accessKeySecret);
        } catch (Exception e) {
            e.printStackTrace();
        }
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phone)
                .setSignName("21天习惯打卡")
                .setTemplateCode(template)
                .setTemplateParam("{\"code\":\"" + code + "\"}");
        String result = null;
        try {
            result = client.sendSms(sendSmsRequest).getBody().getMessage();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

02 阿里云短信接口

短信接口需要先去阿里云平台申请短信签名模板,然后在申请短信模板,申请通过后即可操作。

注意@Value()参数注入,加注释的原因是因为利用反射机制,不经过ioc容器无法依赖注入,就会导致value注入的是空值

腾讯云短信接口
引入依赖
<dependency>
      <groupId>com.tencentcloudapi</groupId>
      <artifactId>tencentcloud-sdk-java</artifactId>
      <version>4.0.11</version>
</dependency>

TencentSms类

package util.SMSutil;

import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class TencentSms {
    //@Value("${tencent.SecretId}")
    private String SecretId="";
    //@Value("${tencent.SecretKey}")
    private String SecretKey="NVN";

    public String sendsms(String phone,String code,int type) {
        String template=null;
        /*
        type=1;短信注册
        type=2;短信绑定
        type=3;短信更改绑定
        type=4;短信修改密码
        */
        switch (type){
            case 1:
                template="8";
                break;
            case 2:
                template="8";
                break;
            case 3:
                template="8";
                break;
            case 4:
                template="8";
                break;
        }
        Credential cred = new Credential(SecretId, SecretKey);
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setReqMethod("POST");
        httpProfile.setConnTimeout(60);
        httpProfile.setEndpoint("sms.tencentcloudapi.com");
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setSignMethod("HmacSHA256");
        clientProfile.setHttpProfile(httpProfile);
        SmsClient client = new SmsClient(cred, "", clientProfile);
        SendSmsRequest req = new SendSmsRequest();
        req.setSmsSdkAppid("");//短信模板应用id
        req.setSign("21天习惯打卡");//短信签名名称
        req.setSenderId("");//港澳台短信发送,默认为空
        req.setTemplateID(template);
        String phoneNumbers = "+86"+phone;
        req.setPhoneNumberSet(new String[]{phoneNumbers});
        String[] templateParams = {code};
        req.setTemplateParamSet(templateParams);
        SendSmsResponse res = null;
        try {
            res = client.SendSms(req);
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
        return res.getSendStatusSet()[0].getCode();

    }
}

0腾讯短息接口

配置要求跟阿里的差不多,也要注意value注入

要注意:短信应用id是在应用管理里的,不是短信签名的id

反射类

package com.today.clock.util.SMSutil;

import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Component
public class SendSms {

    public String SendSms(String phone,String code,int type){
        String classname="=util.SMSutil.TencentSms";//可以设置缓存然后获取
        Class send=null;
        Method method=null;
        try {
            send=Class.forName(classname);

            try {
                method=send.getDeclaredMethod("sendsms",String.class,String.class,int.class);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        String massage=null;
        try {
            try {
                massage= (String) method.invoke(send.newInstance(),phone,code,type);
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return massage;
    }
}

coding完成,遇到啥问题欢迎call我,反射的基础步骤还有一个应用小demo,反射的应用非常广泛,很多框架都用到了反射机制

利用Java反射机制实现短信接口更换

原创文章,作者:程序员凯小白,如若转载,请注明出处:http://www.kaixiaobai.com/archives/849

发表评论

登录后才能评论