1 需求分析
注册账号,用手机号注册,填写后发送短信验证码,
填写短信验证码正确方可注册成功。
2 实现思路
1)用户微服务生成6位的短信验证码,存入redis (以code_手机号为key),再发送给rabbitmq .
2)短信微服务从rabbitmq中提取消息,调用阿里云通信api发送短信
3)用户注册,从redis提取验证码,与用户在界面上填写的验证码进行比较,只有填写正确才能注册。
3 发送短信验证码
实现思路: 在用户服务编写API ,生成手机验证码,存入Redis并发送到RabbitMQ
(1)rabbitmq中新增队列sms ,用于存储发送的短信
(2)changgou_service_user的pom.xml引入依赖
<dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit</artifactId></dependency>
(3)修改changgou_service_user的application.yml,在spring节点下添加配置
server:port: 9008
spring:application:name: userdatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.200.128:3306/changgou_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername: rootpassword: adminmain:allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册redis:host: 192.168.200.128rabbitmq:host: 192.168.200.128
eureka:client:service-url:defaultZone: http://127.0.0.1:6868/eurekainstance:prefer-ip-address: true
feign:hystrix:enabled: trueclient:config:default: #配置全局的feign的调用超时时间 如果 有指定的服务配置 默认的配置不会生效connectTimeout: 60000 # 指定的是 消费者 连接服务提供者的连接超时时间 是否能连接 单位是毫秒readTimeout: 20000 # 指定的是调用服务提供者的 服务 的超时时间() 单位是毫秒
#hystrix 配置
hystrix:command:default:execution:timeout:#如果enabled设置为false,则请求超时交给ribbon控制enabled: trueisolation:strategy: SEMAPHOREthread:# 熔断器超时时间,默认:1000/毫秒timeoutInMilliseconds: 20000
(4)在UserService中新增方法定义
/*** 发送短信验证码* @param mobile*/public void sendSms(String mobile);/*** 增加* @param user* @param code*/public void register(User user,String code);
(5)UserServiceImpl方法实现
实现逻辑:
1)生成六位随机数验证码
2)以手机号作为key,存入redis
3)将手机号与验证码发送到MQ
@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate RabbitTemplate rabbitTemplate;/*** 1)生成六位随机数验证码* 2)以手机号作为key,存入redis* 3)将手机号与验证码发送到MQ* @param mobile*/@Overridepublic void sendSms(String mobile) {// * 1)生成六位随机数验证码String code = RandomStringUtils.randomNumeric(6);System.out.println("==================code:======="+code);// * 2)以手机号作为key,存入redisredisTemplate.boundValueOps("Code_"+mobile).set(code,12, TimeUnit.HOURS);// * 3)将手机号与验证码发送到MQMap info = new HashMap();info.put("mobile",mobile);info.put("code",code);rabbitTemplate.convertAndSend("","sms", JSON.toJSONString(info));}/***1)校验redis中是否存在验证码,用户输入验证码是否与redis中是否一致* 2)根据用户名查询用户,如果不为null,则该用户已注册* 3)填充用户信息并保存* @param user* @param code*/@Overridepublic void register(User user, String code) {//1)校验redis中是否存在验证码,用户输入验证码是否与redis中是否一致String redisCode =(String)redisTemplate.boundValueOps("Code_"+user.getPhone()).get();System.out.println("===========redisCode:"+redisCode);//2. 参数校验:redis中的code是否过期,用户输入的验证与redis中的验证码是否一致,当前用户是否已经注册过if (StringUtils.isEmpty(redisCode)){throw new RuntimeException("当前验证码已过期");}if (!redisCode.equals(code)){throw new RuntimeException("输入的验证码有误");}if (StringUtils.isEmpty(user.getUsername())){user.setUsername(user.getPhone());}//* 2)根据用户名查询用户,如果不为null,则该用户已注册User searchUser = new User();searchUser.setUsername(user.getUsername());if (userMapper.selectCount(searchUser)>0){//该用户已经注册过throw new RuntimeException("当前用户已经注册过");}//3.填充用户的信息user.setCreated(new Date());user.setUpdated(new Date());user.setPoints(0);//积分初始值为0user.setStatus("1");//状态1user.setIsEmailCheck("0");//邮箱认证user.setIsMobileCheck("1");//手机认证String password = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt());//密码加密user.setPassword(password);//4.保存用户信息userMapper.insertSelective(user);}
(6)UserController增加方法
/*** 发送短信* @param mobile* @return*/@RequestMapping("/send_sms")public Result sendSms(@RequestParam("mobile") String mobile){userService.sendSms(mobile);return new Result(true,StatusCode.OK,"发送短信成功");}/*** 注册* @param user* @param code* @return*/@PostMapping("/register")public Result register(@RequestBody User user,@RequestParam("code") String code){userService.register(user,code);return new Result(true,StatusCode.OK,"用户注册成功");}
(7)测试