发表于: 2020-01-15 16:12:19

2 1222


啥也不说就是干!!

今天完成的事情:

1、消息队列实现发短信及邮件

使用阿里云短息及邮件 API

添加相关依赖

<!--短信sdk-->
<dependency>
   <groupId>com.aliyun</groupId>
   <artifactId>aliyun-java-sdk-core</artifactId>
   <version>3.3.1</version>
   <!--<scope>system</scope>-->
   <!--<systemPath>${basedir}/lib/aliyun-java-sdk-core-3.3.1.jar</systemPath>-->
</dependency>
<dependency>
   <groupId>com.aliyun</groupId>
   <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
   <version>1.0.0</version>
   <!--<scope>system</scope>-->
   <!--<systemPath>${basedir}/lib/aliyun-java-sdk-dysmsapi-1.0.0.jar</systemPath>-->
</dependency>

<!--邮件-->
<dependency>
   <groupId>com.aliyun</groupId>
   <artifactId>aliyun-java-sdk-dm</artifactId>
   <version>3.1.0</version>
</dependency>

发送短信的方法:SmsCodeSender

@Component
public class SmsCodeSender {

@Value("${aliyun.smssdk.accessKeyId}")
private String accessKeyId;

   @Value("${aliyun.smssdk.accessKeySecret}")
private String accessKeySecret;

   @Value("${aliyun.smssdk.signName}")
private String signName;
   @Value("${aliyun.smssdk.templateCode}")
private String templateCode;

   @Value("${aliyun.smssdk.product}")
private String product;

   @Value("${aliyun.smssdk.domain}")
private String domain;

   @Value("${aliyun.smssdk.defaultConnectTimeout}")
private String defaultConnectTimeout;

   @Value("${aliyun.smssdk.defaultReadTimeout}")
private String defaultReadTimeout;

   @Autowired
   private RedisCache redisCache;

   @Value("${aliyun.smssdk.expireTime}")
private int expireTime;

   private static final String SMS_KEY_PATTERN = "sms:login_code";

   public SendSmsResponse sendMessage(SmsInfo smsInfo) {

try {
//可自助调整超时时间
           System.setProperty("sun.net.client.defaultConnectTimeout", defaultConnectTimeout);
           System.setProperty("sun.net.client.defaultReadTimeout", defaultReadTimeout);

           //初始化acsClient,暂不支持region化
           IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);

           DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);

           IAcsClient acsClient = new DefaultAcsClient(profile);

           //组装请求对象-具体描述见控制台-文档部分内容
           SendSmsRequest request = new SendSmsRequest();
           //必填:待发送手机号
           request.setPhoneNumbers(smsInfo.getPhoneNum());
           //必填:短信签名-可在短信控制台中找到
           request.setSignName(signName);
           //必填:短信模板-可在短信控制台中找到
           request.setTemplateCode("{\"code\":\"" + smsInfo.getContent() + "\"}");
           //可选:模板中的变量替换JSON串,如模板内容为"您的验证码为${code},有效时间5分钟。" ,此处的值为
           request.setTemplateParam(smsInfo.getContent());

           //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
           //request.setSmsUpExtendCode("90997");

           //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
           request.setOutId(smsInfo.getOutId());
           //hint 此处可能会抛出异常,注意catch

           SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
           if (sendSmsResponse == null) {
               smsInfo.setResCode(2);
               smsInfo.setResMsg("sendSmsResponse为空,验证码发送失败");
           } else if (!StringUtils.isEmpty(sendSmsResponse.getCode()) && sendSmsResponse.getCode().equals("OK")) {
                smsInfo.setResCode(1);
               smsInfo.setResMsg("验证码发送成功!");
               //发送成功存入缓存
               redisCache.setCacheObject(SMS_KEY_PATTERN + smsInfo.getPhoneNum() + "_" + smsInfo.getContent(),                     smsInfo, expireTime, TimeUnit.MINUTES);
           } else {
               smsInfo.setResCode(2);
               smsInfo.setResMsg(StringUtils.isEmpty(sendSmsResponse.getMessage()) ? "请稍后重试" : sendSmsResponse.getMessage());
           }
           return sendSmsResponse;
       } catch (ClientException e) {
            e.printStackTrace();
           smsInfo.setResCode(2);
           smsInfo.setResMsg("调用阿里云sms发生错误");
       }

       return null;

   }

}

Rabbit 发送短信的消息队列生产者:

@Service
public class SmsCodeSendService {

@Autowired
   private RabbitTemplate rabbitTemplate;

//    @Autowired
//    private BatchingRabbitTemplate batchingRabbitTemplate;

   public SmsInfo sendSMSLoginCode(String phoneNum){

       SmsInfo smsInfo = new SmsInfo();
       smsInfo.setId(UUID.fastUUID().toString());
       smsInfo.setContent(RandomStringUtils.randomNumeric(4));
       smsInfo.setOutId(UUID.fastUUID().toString());
       smsInfo.setPhoneNum(phoneNum);

       CorrelationData correlationData = new CorrelationData();
       correlationData.setId(smsInfo.getId());
       rabbitTemplate.convertAndSend("sms-exchange",
               "sms.login.code", //消息路由键
                smsInfo,             //发送内容
                correlationData);                      //消息唯一 id

       return smsInfo;
   }
}

发送短信消息队列消费者

@Component
public class SmsCodeReceiver {

@Autowired
   private SmsCodeSender sendSmsCodeService;


   @RabbitHandler
   @RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = "sms-code-queue", durable = "true"),
                   exchange = @Exchange(name = "sms-exchange", durable = "true",
                           type = "topic"),
                   key = "sms.login.code"
           )
)
public void onOrderMessage(@Payload SmsInfo smsInfo,
                              @Headers Map<String, Object> headers,
                              Channel channel) throws Exception {
       //消费者消费消息
       System.out.println("收到消息,开始消费....");
       System.out.println("发送短信 id:" + smsInfo.getId());
       sendSmsCodeService.sendMessage(smsInfo);
       Long deliverTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
       //给 MQ 一个反馈
       channel.basicAck(deliverTag, false);

   }
}

2、发送邮件

@Service
public class EmailSender {

@Value("${aliyun.emailsdk.accountName}")
private String accountName;

   @Value("${aliyun.emailsdk.fromAlias}")
private String fromAlias;

   @Value("${aliyun.emailsdk.tagName}")
private String tagName;


   public void sendMail(EmailInfo emailInfo){
// 如果是除杭州region外的其它region(如新加坡、澳洲Region),需要将下面的"cn-hangzhou"替换为"ap-southeast-1"、或"ap-southeast-2"。
       IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", "<your accessKey>", "<your accessSecret>");
       // 如果是除杭州region外的其它region(如新加坡region), 需要做如下处理
       //try {
       //DefaultProfile.addEndpoint("dm.ap-southeast-1.aliyuncs.com", "ap-southeast-1", "Dm",  "dm.ap-southeast-1.aliyuncs.com");
       //} catch (ClientException e) {
       //e.printStackTrace();
       //}
       IAcsClient client = new DefaultAcsClient(profile);
       SingleSendMailRequest request = new SingleSendMailRequest();
       try {
//request.setVersion("2017-06-22");// 如果是除杭州region外的其它region(如新加坡region),必须指定为2017-06-22
           request.setAccountName(accountName);
           request.setFromAlias(fromAlias);
           request.setAddressType(1);
           request.setTagName(tagName);
           request.setReplyToAddress(true);
           request.setToAddress(emailInfo.getToAddress());
           //可以给多个收件人发送邮件,收件人之间用逗号分开,批量发信建议使用BatchSendMailRequest方式
           //request.setToAddress("邮箱1,邮箱2");
           request.setSubject(emailInfo.getSubject());
           //如果采用byte[].toString的方式的话请确保最终转换成utf-8的格式再放入htmlbody和textbody,若编码不一致则会被当成垃圾邮件。
           //注意:文本邮件的大小限制为3M,过大的文本会导致连接超时或413错误
           request.setTextBody(emailInfo.getContent());

           //SDK 采用的是http协议的发信方式, 默认是GET方法,有一定的长度限制。
           //若textBody、htmlBody或content的大小不确定,建议采用POST方式提交,避免出现uri is not valid异常
           request.setMethod(MethodType.POST);

           //开启需要备案,0关闭,1开启
           //request.setClickTrace("0");

           //如果调用成功,正常返回httpResponse;如果调用失败则抛出异常,需要在异常中捕获错误异常码;错误异常码请参考对应的API文档;
           SingleSendMailResponse httpResponse = client.getAcsResponse(request);

       } catch (ServerException e) {
//捕获错误异常码
           System.out.println("ErrCode : " + e.getErrCode());
           e.printStackTrace();
       }
catch (ClientException e) {
//捕获错误异常码
           System.out.println("ErrCode : " + e.getErrCode());
           e.printStackTrace();
       }
}

}

发送邮件消息队列生产者

@Service
public class EmailSendService {

@Autowired
   private RabbitTemplate rabbitTemplate;

//    @Autowired
//    private BatchingRabbitTemplate batchingRabbitTemplate;

   public EmailInfo sendEmail(String address,String subject,String content){

EmailInfo emailInfo = new EmailInfo();
       emailInfo.setToAddress(address);
       emailInfo.setSubject(subject);
       emailInfo.setContent(content);
       emailInfo.setId(UUID.fastUUID().toString());
       CorrelationData correlationData = new CorrelationData();
       correlationData.setId(emailInfo.getId());
       rabbitTemplate.convertAndSend("email-exchange",
               "email.register", //消息路由键
               emailInfo,             //发送内容
               correlationData);                      //消息唯一 id

       return emailInfo;
   }
}

发送邮件消息队列消费者

@Component
public class EmailReceiver {

@Autowired
   private EmailSender sendEmailService;


   @RabbitHandler
   @RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = "email-queue", durable = "true"),
                   exchange = @Exchange(name = "email-exchange", durable = "true",
                           type = "topic"),
                   key = "email.#"
           )
)
public void onEmailMessage(@Payload EmailInfo emailInfo,
                              @Headers Map<String, Object> headers,
                              Channel channel) throws Exception {
       //消费者消费消息
       System.out.println("收到消息,开始消费....");
       System.out.println("发送邮件 id:" + emailInfo.getId());
       sendEmailService.sendMail(emailInfo);
       Long deliverTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
       //给 MQ 一个反馈
       channel.basicAck(deliverTag, false);

   }
}

在Controller 中写对应的接口

@PostMapping("/sendSmsCode")
public CommonResult<Boolean> sendSmsCode(
       @NotBlank
       @Pattern(regexp = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$",message = "手机号格式不正确") String phoneNum){
authService.sendSMSCode(phoneNum);
   return CommonResult.success(true,"验证码发送成功,请注意查收");
}

@PostMapping("/sendEmail")
public CommonResult<Boolean> sendEmail(@RequestParam String toAddress,String content,String subject){
   authService.sendEmail(toAddress,subject,content);
   return CommonResult.success(true,"邮件发送成功,请注意查收");
}

对应的 Service 实现类

@Override
public SmsInfo sendSMSCode(String phone) {
   return smsCodeSendService.sendSMSLoginCode(phone);
}

@Override
public EmailInfo sendEmail(String toAddress, String subject, String content) {
   return emailSendService.sendEmail(toAddress,subject,content);
}

调用第三方 api 没啥好说的,就是根据文档来配置,调用 API 方法,传参数。

短信跟邮件由于没有付费充值,所以暂时没法真实的的发送,这里只是模拟一下过程

明天计划的事情:

学习 SpringBoot 文件上传,及阿里云图片存储

遇到的问题:

收获:

集成第三方的短信邮件服务



返回列表 返回列表
评论

    分享到