乐优商城day15(redis,短信微服务)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/freestyle3210/article/details/87539312

所有代码发布在 [https://github.com/hades0525/leyou]

Redis

• 1.指令
在这里插入图片描述
• 1.1通用指令

o	keys   获取符合规则的键名列表
keys pattern(正则表达式)     示例:keys *
•	在生产环境一定要禁用此命令(在redis.conf中重命名keys)
o	exists  判断键是否存在
o	del    删除键
o	select 选择库,默认16个 
select index(0-15)    
•	修改redis.conf中的database为1,只要一个库 
o	expire 设置key的过期时间
expire keyname second    
o	TTL  查看key的生命
-1表示永不过期    -2表示已过期或不存在
o	persist  让key永不过期

• 1.2字符串指令

o	set key value  存
o	get key  取
o	INCR 自增
o	DECR 自减
o	mset k1 v1 k2 v2  批量存
o	mget k1 k2 批量取

• 1.3hash指令

o	hset user:h name "had"   存
o	hget user:h name  取
o	hgetall user:h   取所有字段
o	hkeys user:h  取所有key
o	hvals uer:h  取所有值
o	hdel user:h name   删除一个key

• 2.Redis持久化
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

SpringDataRedis

• 简单使用

 @Autowired
    private StringRedisTemplate redisTemplate;
 
         redisTemplate.opsForValue().set("test","hello world");
 
       redisTemplate.opsForValue().get("test");
   
 
        BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps("user:123");
        hashOps.put("name","rose");
        hashOps.put("age","21");
 
        Map<Object, Object> entries = hashOps.entries();
    
      redisTemplate.opsForValue().set(key,code,5,TimeUnit.MINUTES);
    }

短信微服务

  1. 阿里短信服务
    • 创建阿里云账号,开通短信服务
    • 现在开通短信服务后,必须企业才能到短信签名了,所以现在不能验证短信发送
  2. 短信微服务搭建
    • 配置文件
server:
  port: 8086
spring:
  application:
    name: sms-service
  rabbitmq:
    host: 192.168.163.128
    username: leyou
    password: leyou
    virtual-host: /leyou
  redis:
    host: 192.168.163.128
#自定义配置
ly:
  sms:
    accessKeyId: JWffwFJIwada # 你自己的accessKeyId
    accessKeySecret: aySRliswq8fe7rF9gQyy1Izz4MQ # 你自己的AccessKeySecret
    signName: 乐优商城 # 签名名称
    verifyCodeTemplate: SMS_133976814 # 模板名称

• SmsProperties

@Data
@ConfigurationProperties(prefix="ly.sms")
publicclassSmsProperties{
StringaccessKeyId;
StringaccessKeySecret;
StringsignName;
StringverifyCodeTemplate;
}

• SmsUtil

@Slf4j
@Component
@EnableConfigurationProperties(SmsProperties.class)
publicclassSmsUtils{
 
@Autowired
privateSmsPropertiesprop;
 
@Autowired
privateStringRedisTemplateredisTemplate;
 
//产品名称:云通信短信API产品,开发者无需替换
staticfinalStringproduct="Dysmsapi";
//产品域名,开发者无需替换
staticfinalStringdomain="dysmsapi.aliyuncs.com";
//存入redis的key前缀
privatestaticfinalStringKEY_PREFIX="sms:phone";
//重发间隔的时间
privatestaticfinallongSMS_MIN_INTERVAL_IN_MILLIS=60000;
 
publicSendSmsResponsesendSms(StringphoneNumber,StringsignName,StringtemplateCode,StringtemplateParam){
 
//按照手机号去限流
Stringkey=KEY_PREFIX+phoneNumber;
//读取时间
StringlastTime=redisTemplate.opsForValue().get(key);
if(StringUtils.isNotBlank(lastTime)){
Longlast=Long.valueOf(lastTime);
if(System.currentTimeMillis()-last<SMS_MIN_INTERVAL_IN_MILLIS){
log.info("[短信服务]发送短信频率过高,被拦截,手机号码:{}",phoneNumber);
returnnull;
}
}
 
try{
//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout","10000");
System.setProperty("sun.net.client.defaultReadTimeout","10000");
 
//初始化acsClient,暂不支持region化
IClientProfileprofile=DefaultProfile.getProfile("cn-hangzhou",prop.getAccessKeyId(),prop.getAccessKeySecret());
DefaultProfile.addEndpoint("cn-hangzhou","cn-hangzhou",product,domain);
IAcsClientacsClient=newDefaultAcsClient(profile);
 
//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequestrequest=newSendSmsRequest();
request.setMethod(MethodType.POST);
 
//必填:待发送手机号
request.setPhoneNumbers(phoneNumber);
//必填:短信签名-可在短信控制台中找到
request.setSignName(signName);
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode(templateCode);
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
request.setTemplateParam(templateParam);
 
//hint此处可能会抛出异常,注意catch
SendSmsResponsesendSmsResponse=acsClient.getAcsResponse(request);
 
if(!"OK".equals(sendSmsResponse.getCode())){
log.info("[短信服务]发送短信失败,phoneNumber:{},原因:{}",phoneNumber,sendSmsResponse.getMessage());
}
//记录日志
log.info("[短信服务],发送短信验证码,手机号:{}",phoneNumber);
//发送短信成功,发送时间写入redis,同时指定生存时间1分钟
redisTemplate.opsForValue().set(key,String.valueOf(System.currentTimeMillis()),1,TimeUnit.MINUTES);
 
returnsendSmsResponse;
}catch(Exceptione){
log.error("[短信服务]发送异常,手机号码:{}",phoneNumber,e);
returnnull;
}
}
}

• SmsListener

@Slf4j
@Component
@EnableConfigurationProperties(SmsProperties.class)
publicclassSmsListener{
@Autowired
privateSmsUtilssmsUtils;
 
@Autowired
privateSmsPropertiesprop;
 
/**
*发送短信验证码
*@parammsg
*@throwsException
*/
@RabbitListener(bindings=@QueueBinding(
value=@Queue(value="ly.sms.queue",durable="true"),
exchange=@Exchange(value="ly.sms.exchange",
ignoreDeclarationExceptions="true"),
key={"sms.verify.code"}))
publicvoidlistenSms(Map<String,String>msg){
if(CollectionUtils.isEmpty(msg)){
//放弃处理
return;
}
Stringphone=msg.remove("phone");
 
if(StringUtils.isBlank(phone)){
//放弃处理
return;
}
//发送消息
smsUtils.sendSms(phone,prop.getSignName(),prop.getVerifyCodeTemplate(),JsonUtils.toString(msg));
 
 
}
}

• 实现的原理
• amqp发送指定格式的消息到指定的交换器和队列,listener监听到后,对消息进行处理,然后通过smsutil发送短信。

用户微服务

  1. ly-user下2个module
    ly-user-interface
    ly-usr-service
  2. ly-user-interface
    • pojo类 对password添加了注解@JsonIgnore,这样在json序列化时,就不会把password和salt返回。
@Data
@Table(name="tb_user")
publicclassUser{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
privateLongid;
 
privateStringusername;//用户名
 
@JsonIgnore
privateStringpassword;//密码
 
privateStringphone;//电话
 
privateDatecreated;//创建时间
 
@JsonIgnore
privateStringsalt;//密码的盐值
}
  1. ly-usr-service

• 配置文件

server:
  port: 8085
spring:
  application:
    name: user-service
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/yun61
    username: root
    password: 123
    driver-class-name: com.mysql.jdbc.Driver
  rabbitmq:
    host: 192.168.163.128
    username: leyou
    password: leyou
    virtual-host: /leyou
  redis:
    host: 192.168.163.128
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true
    ip-address: 127.0.0.1
 
mybatis:
  type-aliases-package: com.leyou.user.pojo

• 接口
• 校验用户数据
controller

/**
*校验用户数据
*@paramdata
*@paramtype
*@return
*/
@GetMapping("check/{data}/{type}")
publicResponseEntity<Boolean>checkData(@PathVariable("data")Stringdata,@PathVariable("type")Integertype){
returnResponseEntity.ok(userService.checkData(data,type));
}

service

/**
*验证用户数据
*@paramdata
*@paramtype
*@return
*/
publicBooleancheckData(Stringdata,Integertype){
//判断数据类型
Userrecord=newUser();
 
switch(type){
case1:
record.setUsername(data);
break;
case2:
record.setPhone(data);
break;
default:
thrownewLyException(ExceptionEnum.INVALID_USER_DATA_TYPE);
}
 
 
returnuserMapper.selectCount(record)==0;
}

• 发送验证码
controller

/**
*发送手机验证码
*@paramphone
*@return
*/
@PostMapping("code")
publicResponseEntity<Void>sendCode(@RequestParam("phone")Stringphone){
userService.sendCode(phone);
returnResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
 

service

/**
*发送验证码
*@paramphone
*/
publicvoidsendCode(Stringphone){
//生成key
Stringkey=KEY_PREFIX+phone;
//生成验证码
Stringcode=NumberUtils.generateCode(6);
 
Map<String,String>msg=newHashMap<>();
msg.put("phone",phone);
msg.put("code",code);
 
//发送验证码
amqpTemplate.convertAndSend("ly.sms.exchange","sms.verify.code",msg);
 
//保存验证码
redisTemplate.opsForValue().set(key,code,5,TimeUnit.MINUTES);
}
展开阅读全文

没有更多推荐了,返回首页