这篇文章主要介绍一下手机号注册,发送短信验证码的功能

觉得有帮助的点赞支持一下吧。

这里我们采用的是阿里大于的服务来实

大于等于号长度注解java java中大于等于怎么表示_redis


界面描述还是比较详细的,展示了短信服务的完整流程快速学习短信发送

大于等于号长度注解java java中大于等于怎么表示_大于等于号长度注解java_02


我们申请完Access Key IDAccess Key Secret短信签名短信模板就可以入门编写代码了,同时阿里云也提供了相应的接口调用机制和Demo供我们参考,基本条件完成以后接下来就实现注册功能。

首先是验证码发送服务。我们建立springboot项目采用maven导入相关依赖,pom如下:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>

resources下建立application.yml文件内容如下:

server:
  port: #端口号
spring:
  application:
    name: #新建模块名称
redis:
  host: #主机地址
leyou:
  sms:
    accessKeyId:  # 你自己的accessKeyId
    accessKeySecret:  # 你自己的AccessKeySecret
    signName:  # 签名名称
    verifyCodeTemplate:  # 模板名称

配置文件完成以后,我们需要建立实体类,监听短信以及发送短信工具类,代码如下:
实体类SmsProperties

@ConfigurationProperties(prefix = "leyou.sms")
public class SmsProperties {

    String accessKeyId;

    String accessKeySecret;

    String signName;

    String verifyCodeTemplate;
    //此处省略set和get方法了,实操自行补上

发送短信工具类SmsUtils

@Component
@EnableConfigurationProperties(SmsProperties.class)
public class SmsUtils {

    @Autowired
    private SmsProperties prop;

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

    static final Logger logger = LoggerFactory.getLogger(SmsUtils.class);

    public SendSmsResponse sendSms(String phone, String code, String signName, String template) throws ClientException {

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

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

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

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

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

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

        logger.info("发送短信状态:{}", sendSmsResponse.getCode());
        logger.info("发送短信消息:{}", sendSmsResponse.getMessage());

        return sendSmsResponse;
    }
}
此处代码和阿里云短信服务提供的demo基本一致。

监听类SmsListener

@Component
@EnableConfigurationProperties(SmsProperties.class)
public class SmsListener {

    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private SmsProperties smsProperties;
    public void sendSms(Map<String,String> msg) throws ClientException {
        if (CollectionUtils.isEmpty(msg)){
            return;
        }
        String phone = msg.get("phone");
        String code = msg.get("code");
        if (StringUtils.isNoneBlank(phone) && StringUtils.isNoneBlank(code)){
      	this.smsUtils.sendSms(phone,code,this.smsProperties.getSignName(),this.smsProperties.getVerifyCodeTemplate());
        }

    }
    此处接收验证码并发送

至此短信服务模块就构建好了,接下来我们实现验证码的产生及手机号注册。同样我们建立一个新模块作为注册功能。这里我们采用通用mapper实现增删改查,同时利用redis的过期机制来保存验证码,代码如下:
实体类User:

@Table(name = "tb_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Length(min = 4, max = 30, message = "用户名只能在4~30位之间")
    private String username;// 用户名

    @JsonIgnore //对象序列化为json字符串时忽略该属性
    @Length(min = 4, max = 30, message = "密码只能在4~30位之间")
    private String password;// 密码

    @Pattern(regexp = "^1[35678]\\d{9}$", message = "手机号格式不正确")
    private String phone;// 电话

    private Date created;// 创建时间

    @JsonIgnore
    private String salt;// 密码的盐值
	此处省略set和get方法

Controller层:

//发送验证码
    @PostMapping("code")
    public ResponseEntity<Void> sendVerifyCode(@RequestParam("phone")String phone){
        this.userService.sendVerifyCode(phone);
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }

    //注册
    @PostMapping("register")
    public ResponseEntity<Void> register(@Valid User user, @RequestParam("code")String code){
        this.userService.register(user,code);
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }

Service层:

public void sendVerifyCode(String phone) {
        //采用工具类生成验证码
        String code = NumberUtils.generateCode(6);
        if(StringUtils.isBlank(phone)){
            return;
        }
        //保存验证码到redis中
        this.redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
    }

    public void register(User user, String code) {
        //查询redis中验证码
        String redisCode =  this.redisTemplate.opsForValue().get(user.getPhone());
        //1.校验验证码
        if(!code.equals(redisCode)){
            return;
        }
        //2.生成盐
        String salt = CodecUtils.generateSalt();
        //3.加盐加密
        user.setSalt(salt);
        String password = CodecUtils.md5Hex(user.getPassword(),salt);
        user.setPassword(password);
        //4.新增用户(设置用户id和时间)
        user.setId(null);
        user.setCreated(new Date());
        this.userMapper.insertSelective(user);
    }

通用mapper接口

public interface UserMapper extends Mapper<User> {
}

整个发送验证码注册流程大致如此了。