飞滴网约车项目Day01

今日完成

乘客用户中心服务

验证码发送

首先我们需要开发用户注册和登录功能,其中重点是乘客发送验证码,以下是发送验证码的时序图

REST ful 风格

在设计rest fuk 风格的时候,我们需要考虑以下的事情:

  1. 协议(http,https)
  2. 域名 (www.xxx.com/aoi/courses,api.xxx.com/courses)
  3. 路径
  4. 版本(v1,v2等)
  5. 动作(post,put,patch, delete, get)

nacos下载和配置

下载地址:https://github.com/alibaba/nacos/releases/tag/2.0.3

添加maven依赖

复制代码
<!--        nacos-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        <version>2021.1</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>2021.1</version>
    </dependency>

# 启动Nacos Server:

定位到bin目录,然后执行启动命令:

## cmd窗口
startup.cmd -m standalone

## powershell窗口
.\startup.cmd -m standalone


这将以单机模式启动Nacos服务器。

获取随机验证码

复制代码
@RestController
public class NumberCodeController {

    @GetMapping("/numberCode/{size}")
    public String numberCode(@PathVariable("size") int size) {

        System.out.println("生成验证码,验证码长度:" + size);

        JSONObject result = new JSONObject();
        result.put("code", 1);
        result.put("message", "success");
        JSONObject data = new JSONObject();

        //获取随机数
        String number = "0123456789";
        StringBuilder numberCode = new StringBuilder();
        for (int i = 0; i < size; i++) {
            int index = (int) (Math.random() * number.length());
            char c = number.charAt(index);
            numberCode.append(c);
        }
        System.out.println(numberCode.toString());

        data.put("numberCode", numberCode);
        result.put("data", data);
        return result.toString();
    }

}

统一返回类型

复制代码
public enum CommonStatusEnum {

    SUCCESS(1, "success"),
    FAIL(0, "fail");


    @Getter
    private int code;

    @Getter
    private String value;

    private CommonStatusEnum(int code, String value) {
        this.code = code;
        this.value = value;
    }


}

@Data
@Accessors(chain = true)
public class ResponseResult<T> {

    private int code;
    private String message;
    private T data;

    /**
     * 成功返回结果
     */
    public static <T> ResponseResult<T> success(T data) {
        return new ResponseResult<T>().setCode(CommonStatusEnum.SUCCESS.getCode())
                .setMessage(CommonStatusEnum.SUCCESS.getValue())
                .setData(data);
    }

    /**
     * 失败返回结果
     */
    public static <T> ResponseResult<T> fail(int code , String message) {
        return new ResponseResult<T>().setCode(code)
                .setMessage(message);
    }

    /**
     * 失败返回结果,自定义失败
     */
    public static <T> ResponseResult<T> fail(int code, String message,T data) {
        return new ResponseResult<T>().setCode(code)
                .setMessage(message)
                .setData(data);
    }

    /**
     * 失败:统一失败
     */
    public static <T> ResponseResult<T> fail(T data) {
        return new ResponseResult<T>().setData(data);
    }

}

改造后的为:

复制代码
@RestController
public class NumberCodeController {

    @GetMapping("/numberCode/{size}")
    public ResponseResult numberCode(@PathVariable("size") int size) {

        System.out.println("生成验证码,验证码长度:" + size);


        //获取随机数
        String number = "0123456789";
        StringBuilder numberCode = new StringBuilder();
        for (int i = 0; i < size; i++) {
            int index = (int) (Math.random() * number.length());
            char c = number.charAt(index);
            numberCode.append(c);
        }

        //定义返回值
        NumberCodeResponse numberCodeResponse = new NumberCodeResponse();
        numberCodeResponse.setNumberCode(Integer.parseInt(numberCode.toString()));
        return ResponseResult.success(numberCodeResponse);

    }

}

api-passenger和service-verificationCode之间的调用

复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

@FeignClient("service-verificationcode")
public interface ServiceVerificationCodeClient {

    @GetMapping("/numberCode/{size}")
    ResponseResult<NumberCodeResponse>  numberCode(@PathVariable("size") int size);
}

验证码redis使用

maven依赖

复制代码
        <!--redis使用-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

yml编写

复制代码
server:
  port: 8081

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: api-passenger
  redis:
    host: 127.0.0.1
    port: 6379

代码编写

复制代码
@Service
public class VerificationCodeService {

    // 验证码前缀
    private String verificationCodePrefix = "passenger-verification-code-";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ServiceVerificationCodeClient serviceVerificationCodeClient;

    public ResponseResult generateCode(String passengerPhone){

        // 调用验证码服务
        System.out.println("调用生成验证码服务");
        ResponseResult<NumberCodeResponse> numberCode = serviceVerificationCodeClient.numberCode(6);
        System.out.println("获取验证码为:" + numberCode.getData().getNumberCode());

        //存入redis
        System.out.println("将验证码存入redis");
        String key = verificationCodePrefix + passengerPhone;
        stringRedisTemplate.opsForValue().set(key, numberCode.getData().toString(),1, TimeUnit.MINUTES);
        
        //通过第三发短信商务发送验证码 TODO


        //返回值
        return ResponseResult.success(numberCode);

    }
}

校验验证码

骨架

复制代码
    @PostMapping("/verification-code-check")
    public ResponseResult verificationCodeCheck(@RequestBody VerificationCodeDTO verificationCodeDTO){

        String passengerPhone = verificationCodeDTO.getPassengerPhone();
        String verificationCode = verificationCodeDTO.getVerificationCode();
        return verificationCodeService.checkCode(passengerPhone, verificationCode);
    }

    /**
     * 校验验证码
     * @param passengerPhone
     * @param verificationCode
     * @return
     */
    public ResponseResult checkCode(String passengerPhone, String verificationCode){

        //1.根据手机号获取redis中的验证码

        //2.校验验证码

        //3.判断原来是否存在用户,如果不存在,则创建用户

        //4.颁发令牌
        TokenResponse tokenResponse = new TokenResponse();
        tokenResponse.setToken("token value");

        //5.返回结果
        return ResponseResult.success(tokenResponse);
    }

校验redis验证码

复制代码
    /**
     * 校验验证码
     * @param passengerPhone
     * @param verificationCode
     * @return
     */
    public ResponseResult checkCode(String passengerPhone, String verificationCode){

        //1.根据手机号获取redis中的验证码
        String key = generatorKeyByPhone(passengerPhone);
        String codeRedis = stringRedisTemplate.opsForValue().get(key);
        System.out.println("redis中的key:"+codeRedis);

        if (codeRedis == null){
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(), CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }
        if (!codeRedis.equals(verificationCode)){
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(), CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }
        stringRedisTemplate.delete(key);

        //2.校验验证码

        //3.判断原来是否存在用户,如果不存在,则创建用户

        //4.颁发令牌
        TokenResponse tokenResponse = new TokenResponse();
        tokenResponse.setToken("token value");

        //5.返回结果
        return ResponseResult.success(tokenResponse);
    }

    private String generatorKeyByPhone(String phone){
        return verificationCodePrefix + phone;
    }
}

乘客用户服务

骨架

复制代码
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/user")
    public ResponseResult loginOrRegister(@RequestBody VerificationCodeDTO verificationCodeDTO){

        String passengerPhone = verificationCodeDTO.getPassengerPhone();
        return  userService.loginOrRegister(passengerPhone);
    }
}

@Service
public class UserService {

    public ResponseResult  loginOrRegister(String passengerPhone){

        System.out.println("注册手机号被调用,手机号为:"+passengerPhone);

        //根据手机号查询用户

        //判断用户是否存在

        return ResponseResult.success(passengerPhone);
    }
}