day59,16,品优购,springboot搭建消息中间键连接阿里大于,数据库怎么做集群方案理论,用户注册流程,

什么是springboot

springboot是spring组织生产的一个后端全栈框架(不包括页面的技术)

作用:
提倡零配置, 不用整合框架结构, 直接编写业务代码, 给企业提供人员利用率, 提高开发效率.
但是springboot只适合小项目使用.

springboot搭建消息中间键连接阿里大于

在这里插入图片描述
1.pom.xml 导入jar坐标:

<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>

2.指定springboot内置tomcat的相关参数,和阿里大于子账户的账户名id和密码

server.port=9003
spring.activemq.broker-url=tcp://192.168.200.128:61616
accessKeyId=LTAIYr97uNKHy2fm
accessKeySecret=tBY0x1YclGcfPIF0IaebZoDOA0UVid

3.搭建springboot微服务框架
在这里插入图片描述
启动类Application.java:

@SpringBootApplication
public class Application {

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

监听器类SmsListener.java:

@Component
public class SmsListener {

    @Autowired
    private SmsUtil smsUtil;

    @JmsListener(destination="sms")
    public void sendSms(Map<String,String> map){
        try {
            SendSmsResponse response = smsUtil.sendSms(
                    map.get("mobile"),
                    map.get("template_code"),
                    map.get("sign_name"),
                    map.get("param")  );
            System.out.println("Code=" + response.getCode());
            System.out.println("Message=" + response.getMessage());
            System.out.println("RequestId=" + response.getRequestId());
            System.out.println("BizId=" + response.getBizId());
        } catch (ClientException e) {
            e.printStackTrace();
        }
    }

}

信息提交给阿里大于的工具类:SmsUtil.java

@Component
public class SmsUtil {

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

    @Autowired
    private Environment env;

    // TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)

    /**
     * 发送短信
     * @param mobile 手机号
     * @param template_code 模板号
     * @param sign_name 签名
     * @param param 参数
     * @return
     * @throws ClientException
     */
    public SendSmsResponse sendSms(String mobile,String template_code,String sign_name,String param) throws ClientException {

        String accessKeyId =env.getProperty("accessKeyId");
        String accessKeySecret = env.getProperty("accessKeySecret");

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

        //初始化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(mobile);
        //必填:短信签名-可在短信控制台中找到
        request.setSignName(sign_name);
        //必填:短信模板-可在短信控制台中找到
        request.setTemplateCode(template_code);
        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        request.setTemplateParam(param);

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

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

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

        return sendSmsResponse;
    }

}

启动时先启动main方法。

阿里大于创建子账户,和相关参数的获取,视频参考:day58 视频

在互联网企业, 高并发, 大数据量的情况下, 单个数据库指定在一定情况下会造成数据库宕机. 数据库怎么做集群:

  1. 业务:
    读大于写(大多数企业业务都这样)
    数据库解决方案:
    集群, 读写分离, 一台主库作为写入的数据库, 写数据库不允许读, 多台从库, 也就是读取库, 读取库
    不允许人为的往里写数据. 平时高并发读的时候, 例如: a用户从一个库中去读取数据, b用户去另一个从库中
    去读取数据, 这样高并发的读取操作就可以负载均衡了.

  2. 业务:
    写大于读(特殊业务)
    数据库解决方案:
    集群, 多个数据库, 多个数据库中存储的内容不一样, 但是多个数据库中不管是库名还是表名, 还是表结构都是
    一模一样的, 只是存储的数据不一样而已, 这种配置叫做分库, 在数据量很大的情况下还需要分表,
    同样的表结构的表有一堆, 每个表存储的内容也不一样, 也叫作水平分表, mysql最好单表的数据量保证在
    五百万条以内, 那么查询效率不会太低, 如果超过这个数据量, 命中率会成指数级下降.

用户注册流程(图解)

在这里插入图片描述
1.写用户的控制器类UserController:

@RestController
@RequestMapping("/user")
public class UserController {

    @Reference
    private UserService userService;


    /**
     * 发送短信验证码
     * @param phone     手机号
     * @return
     */
    @RequestMapping("/sendCode")
    public Result sendCode(String phone){
        //先判断进来的电话号码是否符合规格,判断非空,和正则工具类验证
        boolean chinaPhoneLegal = PhoneFormatCheckUtils.isChinaPhoneLegal(phone);

        if (!chinaPhoneLegal || "".equals(phone)||phone == null){
            return new Result(false,"电话不符合格式或者不能为空");
        }
        //号码正确,再往手机发送验证码
        try {
            userService.sendCode(phone);
            return  new Result(true, "发送成功!");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "发送失败!");
        }
    }
    /**
     * 添加用户
     * @param user      用户对象
     * @param smscode   验证码
     * @return
     */
    @RequestMapping("/add")
    public Result add(@RequestBody User user, String smscode){
        try {
            //短信发送完成,进行手机号,和验证码的验证,提交
            boolean isCheck = userService.checkSmsCode(user.getPhone(), smscode);
            //验证通过,就封装,注册账号的对象
            if (!isCheck) {
                return new Result(false, "手机号或者验证码不正确!");
            }
            user.setStatus("Y");
            user.setCreated(new Date());
            user.setUpdated(new Date());
            user.setSourceType("1");
            userService.add(user);
            return new Result(true, "用户注册成功!");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "用户注册失败!");
        }
    }


}

2.写用户验证的接口和实现类

public interface UserService {

    public Result sendCode(String phone);

    public boolean checkSmsCode(String phone,String smscode);

    public void add(User user);
}

——————用户实现类————————————

public class UserServiceImpl implements UserService {
    //队列对象的名字,ioc容器中
    @Autowired
    private ActiveMQQueue smsDestination;
    //消息中间键模板对象
    @Autowired
    private JmsTemplate jmsTemplate;

    @Autowired
    private RedisTemplate redisTemplate;


    //发送消息,需要的阿里云通信的,模板签名和项目名称,通过配置文件赋值
    @Value("${template_code}")
    private String template_code;
    //项目名称
    @Value("${sign_name}")
    private String sign_name;

    @Autowired
    private UserDao userDao;


    @Override
    public Result sendCode(String phone) {
        //1. 生成一个随机6为数字, 作为验证码
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i < 7 ; i++) {
            int s = new Random().nextInt(10);
            sb.append(s);
        }
        //把拼接好的6个随机数,转为final,String
        final String smsCode = sb.toString();
        //2. 手机号作为key, 验证码作为value保存到redis中, 生存时间为10分钟
        redisTemplate.boundValueOps(phone).set(smsCode,60*10, TimeUnit.SECONDS);
        //3. 将手机号, 短信内容, 模板编号, 签名封装成map消息发送给消息服务器

        //往消息中间键对象,中的smsDestination点对点队列,发送消息对象
        jmsTemplate.send(smsDestination, new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                //发送消息中的具体内容是
                MapMessage message = session.createMapMessage();
                message.setString("mobile", phone);//手机号
                message.setString("template_code", template_code);//模板编码
                message.setString("sign_name", sign_name);//签名
                Map map=new HashMap();
                map.put("code", smsCode);	//验证码
                message.setString("param", JSON.toJSONString(map));
                return (Message) message;
            }
        });

        return null;
    }

    //验证方法
    @Override
    public boolean checkSmsCode(String phone, String smsCode) {
        if (phone == null || smsCode == null || "".equals(phone) || "".equals(smsCode)) {
            return false;
        }
        //1. 根据手机号到redis中获取我们自己存的验证码
        String redisSmsCode = (String) redisTemplate.boundValueOps(phone).get();
        //2. 判断页面传入的验证码和我们自己存的验证码是否一致
        if (smsCode.equals(redisSmsCode)){
            //一样,可以注册
            return true;
        }
        return false;
    }

    //保存账户的方法
    @Override
    public void add(User user) {
        userDao.insertSelective(user);
    }
}

注意实现类中的jms消息中间件模板对象的ben配置要写

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
	xmlns:jms="http://www.springframework.org/schema/jms"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context   
		http://www.springframework.org/schema/context/spring-context.xsd">
		
	
	   
    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->  
	<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">  
	    <property name="brokerURL" value="tcp://192.168.200.128:61616"/>  
	</bean>
	   
    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->  
	<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">  
	<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->  
	    <property name="targetConnectionFactory" ref="targetConnectionFactory"/>  
	</bean>  
		   
    <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->  
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">  
	    <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->  
	    <property name="connectionFactory" ref="connectionFactory"/>  
	</bean>      
    <!--这个是队列目的地,点对点的  文本信息-->  
	<bean id="smsDestination" class="org.apache.activemq.command.ActiveMQQueue">  
	    <constructor-arg value="sms"/>  
	</bean>    
	
</beans>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值