所有代码发布在 [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);
}
短信微服务
- 阿里短信服务
• 创建阿里云账号,开通短信服务
• 现在开通短信服务后,必须企业才能到短信签名了,所以现在不能验证短信发送 - 短信微服务搭建
• 配置文件
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发送短信。
用户微服务
- ly-user下2个module
ly-user-interface
ly-usr-service - 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;//密码的盐值
}
- 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);
}