Spring Boot 入门 ( 整合 ActiveMQ , 基于阿里大于发短信 )

标签: springboot  activeMQ

1. 什么是Spring Boot

1.1 spring

  • Spring 诞生时是 Java 企业版(Java Enterprise Edition,JEE,也称 J2EE)的轻量级代替品。无需开发重量级的 Enterprise JavaBean(EJB),Spring 为企业级 Java 开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的 Java 对象(Plain Old Java Object,POJO)实现了 EJB 的功能。

spring的不足 :
1. 虽然 Spring 的组件代码是轻量级的,但它的配置却是重量级的, 大量的xml配置文件
2. 开发人员需要自行进行项目的依赖管理, 选择合理版本, 避免冲突, 避免不兼容等问题
以上问题都损耗了大量的写代码的时间 .

1.2 Spring Boot

  • Spring Boot 让 spring 的不足成为了过去。
  • Spring Boot 是 Spring 社区较新的一个项目。该项目的目的是帮助开发者更容易的创建 基于 Spring 的应用程序和服务,让更多人的人更快的对 Spring进行入门体验,为 Spring 生态系统提供了一种固定的、约定优于配置风格的框架。

Spring Boot 具有如下特性:
(1)为基于 Spring 的开发提供更快的入门体验
(2)开箱即用,没有代码生成,也无需 XML配置。同时也可以修改默认值来满足特定的需求。
(3)提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
(4)Spring Boot 并不是不对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式。

2. Spring Boot 入门小 Demo

  • 创建 Maven 工程 springboot-demo(打包方式 jar), 目录结构如下
    这里写图片描述
    controller, service, dao必须处于主函数子包中, 因为controller, service, dao 必须被spring扫描,扫描后将会被spring容器管理.

2.1 添加依赖

  • 在 pom.xml 中添加如下依赖
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
    </parent>

    <dependencies> 

        <!--springboot项目开发起步依赖坐标-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency> 

        <!--springboot热部署(自动编译, 如果是IDEA需要开启自动编译功能)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency> 

        <!-- Spring Boot与 ActiveMQ 整合 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

    </dependencies>

2.2 创建 application.properties 文件

#修改内置Tomcat的端口配置, 默认端口8080
server.port=80

#自定义参数
url = http://www.baidu.com

#配置自己的activeMQ地址
spring.activemq.broker-url=tcp://192.168.12.66:61616

注意:
1. 文件名必须叫 application.properties
2. 需放在 resource 的根目录下, 默认扫描此包中的 application.properties

2.3 引导类

  • 创建引导类 MyAppplication.java , 只需要创建一个引导类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @SpringBootApplication 其实就是以下三个注解的总和
 *      @Configuration: 用于定义一个配置类
 *      @EnableAutoConfiguration :Spring Boot 会自动根据你 jar 包的依赖来自动配置项目。
 *      @ComponentScan: 告诉Spring 哪个 packages 的用注解标识的类会被spring 自动扫描并且装入 bean 容器。
 */
@SpringBootApplication
public class MyAppplication {

    public static void main(String[] args) {
        //入口方法
        //1,加载内置tomcat服务器
        //2, 引导项目启动环境
        SpringApplication.run(MyAppplication.class,args); 
    }

}

2.4 直接写 Controller 类

  • 创建 UserController.java

import com.pojo.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.resources.Messages_pt_BR;

import java.util.HashMap;
import java.util.Map;

@RestController
public class UserController {

    // 注入环境对象, 用于获取配置文件中的参数
    @Autowired
    private Environment env;

    /**
     * 需求:springboot入门
     */
    @RequestMapping("/hello")
    public String showHello1(){
        return "hello,springboot!";
    }

    /**
     *  需求:Restful风格
     */
    @RequestMapping("/hello2/{name}")
    public String showHello2(@PathVariable String name){
        return "hello,springboot!"+name;
    }

    /**
     * 需求:获得配置文件 application.properties 文件中的自定义参数 url
     */
    @RequestMapping("/hello3")
    public String showHello3(){
        return "hello,springboot! url = "+env.getProperty("url");
    }

    /**
     * 需求:展示对象
     */
    @RequestMapping("hello4")
    public Person showHello4(){
        Person p = new Person();
        p.setId(1000);
        p.setName("张三丰");
        return  p;
    }

    /**
     * 需求:使用springboot框架内置MQ消息服务器发送及接受消息
     * 默认使用 point-to-point 模式
     */

    //注入消息模板对象
    @Autowired
    private JmsTemplate jmsTemplate;

    // 发送消息
    @RequestMapping("send/{message}")
    public String sendMessage(@PathVariable String message){
        jmsTemplate.convertAndSend("oneQueue",message);
        return "success";
    }

    // 接收消息
    @JmsListener(destination = "oneQueue")
    public void receiveMessage(String message){
        System.out.println("接受消息:"+message);
    }

}

3. 短信微服务

  • 整合activeMQ, 基于阿里大于发短信
  • 创建微服务模块 springboot-sms 结构目录如下:
    这里写图片描述

3.1 配置文件

  • POM 文件引入依赖
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.0.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
    <!-- 阿里大于相关配置 -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
        <version>3.2.5</version>
    </dependency>
</dependencies>
  • 创建 application.properties
#整合mq
spring.activemq.broker-url=tcp://192.168.12.66:61616
#发送短信秘钥
AccessKeyID=SQD6Aw6mg*****
accessKeySecret=KFCVQ32sJmf3Yov*****

3.2 引导类 SmsApplication.java


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SmsApplication {
    public static void main(String[] args) {
        SpringApplication.run(SmsApplication.class,args);
    }
}

3.3 工具类 SmsUtils.java

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class SmsUtils {

    //产品名称:云通信短信API产品,开发者无需替换
    static final String product = "Dysmsapi";
    //产品域名,开发者无需替换
    static final String domain = "dysmsapi.aliyuncs.com";

    @Autowired
    private Environment env;

    /**
     * 发送短信验证码
     * @param phoneNum 待发手机号
     * @param signName 短信签名
     * @param templateCode 短信模板
     * @param code 短信验证码
     */
    public SendSmsResponse sendSms(String phoneNum,String signName,String templateCode,String code) throws ClientException {

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

        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", env.getProperty("AccessKeyID"), env.getProperty("accessKeySecret"));
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        IAcsClient acsClient = new DefaultAcsClient(profile);

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

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

        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
        request.setOutId("yourOutId");

        //hint 此处可能会抛出异常,注意catch
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

        return sendSmsResponse;
    }


    public QuerySendDetailsResponse querySendDetails(String bizId) throws ClientException {

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

        //初始化acsClient,暂不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", env.getProperty("AccessKeyID"), env.getProperty("accessKeySecret"));
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象
        QuerySendDetailsRequest request = new QuerySendDetailsRequest();
        //必填-号码
        request.setPhoneNumber("15000000000");
        //可选-流水号
        request.setBizId(bizId);
        //必填-发送日期 支持30天内记录查询,格式yyyyMMdd
        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
        request.setSendDate(ft.format(new Date()));
        //必填-页大小
        request.setPageSize(10L);
        //必填-当前页码从1开始计数
        request.setCurrentPage(1L);

        //hint 此处可能会抛出异常,注意catch
        QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);

        return querySendDetailsResponse;
    }

}

3.4 监听类 SmsListener.java

import com.aliyuncs.exceptions.ClientException;
import com.utils.SmsUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class SmsListener {

    //注入对象
    @Autowired
    private SmsUtils smsUtils;

    @JmsListener(destination = "sms")
    public void sendSms(Map map){
        try {
            //从map中获取消息
            String sign_name = (String) map.get("sign_name");
            //模板code
            String template_code = (String) map.get("template_code");
            //验证码
            String code = (String) map.get("code");
            //电话号码
            String phone = (String) map.get("phone");
            // 发送短信
            smsUtils.sendSms(sign_name,template_code,code,phone);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

3.4 测试

  • 配置文件 sms.properties
    signName=十里
    templateCode=SMS_1250
  • 配置文件 applicationContext-mq-producer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--把activeMQ交给spring管理-->
    <bean id="targetConnnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <constructor-arg name="brokerURL" value="tcp://139.199.***.***:61616"/>
    </bean>

    <!--创建spring jms组件提供工厂对象,无缝接管activeMQ-->
    <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <property name="targetConnectionFactory" ref="targetConnnectionFactory"/>
    </bean>

    <!--spring jms提供消息发送模板对象-->
    <bean class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
    </bean>


    <!--发布订阅消息空间-->
    <bean class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg value="sms"/>
    </bean>

</beans>
  • 在模块 user-service (war) 中的 UserServiceImpl 类中加入方法测试:

    @Autowired
    private JmsTemplate jmsTemplate;

    @Autowired
    private RedisTemplate redisTemplate; 

    @Value("${signName}")
    private String signName; 

    @Value("${templateCode}")
    private String templateCode;

    /**
     * 发送手机验证码
     * 需要向activeMQ中的sms存map集合key包含: String phoneNum, String signName, String templateCode, String code
     *
     * @param phoneNum 手机号
     */
    @RequestMapping("/send/sms/{phoneNum}")
    public void sendSms(@PathVariable String phoneNum) {

        try {
            // 若配置文件中有中文,需要先解码再编码
            signName = new String(signName.getBytes("ISO-8859-1"), "utf-8");

            //生成一个6位数的随机验证码
            String code = String.valueOf((long) (Math.random() * 1000000));
            //将验证码存入redis
            redisTemplate.boundHashOps("phoneCode").put(phoneNum, code);
            //设置验证码的过期时间
            redisTemplate.boundHashOps("phoneCode").expire(5, TimeUnit.MINUTES);

            // 将数据存入map中
            HashMap<String, String> map = new HashMap<>();
            map.put("phoneNum", phoneNum);
            map.put("signName", signName);
            map.put("templateCode", templateCode);
            map.put("code", code);

            // 发送数据
            jmsTemplate.convertAndSend("sms", map);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
  • 启动两个模块, 浏览器访问并测试…….
原文链接:加载失败,请重新获取