《果然新鲜》电商项目(21)- 会员注册功能

Posted IT老刘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《果然新鲜》电商项目(21)- 会员注册功能相关的知识,希望对你有一定的参考价值。

引言

在上一节《果然新鲜》电商项目(20)- 项目配置信息分类(Apollo Namespace命名空间),主要讲解如何在Apollo配置中心里分类配置信息,对项目的配置信息进一步优化。

本文进入主题,主要实现会员注册功能。通过本文的讲解,可以让大家熟练的使用Feign客户端。

1.会员注册流程图

2. 会员服务模块

2.1 会员数据库部分

微服务项目中,一般一个微服务对应一个数据库。所以会员服务要有会员数据库,微信要有微信数据库,现在在mysql里面建立会员数据库。

直接在Navicat里选择连接,新建数据库“guoranxinxian-member”:

2.1.1.数据库表设计

数据库脚本:

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `USER_ID` int(12) NOT NULL AUTO_INCREMENT COMMENT 'user_id',
  `MOBILE` varchar(11) NOT NULL COMMENT '手机号',
  `EMAIL` varchar(50) NOT NULL COMMENT '邮箱号',
  `PASSWORD` varchar(64) NOT NULL COMMENT '密码',
  `USER_NAME` varchar(50) DEFAULT NULL COMMENT '用户名',
  `SEX` tinyint(1) DEFAULT '0' COMMENT '性别  1男  2女',
  `AGE` tinyint(3) DEFAULT '0' COMMENT '年龄',
  `CREATE_TIME` timestamp NULL DEFAULT NULL COMMENT '注册时间',
  `IS_AVALIBLE` tinyint(1) DEFAULT '1' COMMENT '是否可用 1正常  2冻结',
  `PIC_IMG` varchar(255) DEFAULT NULL COMMENT '用户头像',
  `QQ_OPENID` varchar(50) DEFAULT NULL COMMENT 'QQ联合登陆id',
  `WX_OPENID` varchar(50) DEFAULT NULL COMMENT '微信公众号关注id',
  PRIMARY KEY (`USER_ID`),
  UNIQUE KEY `MOBILE_UNIQUE` (`MOBILE`),
  UNIQUE KEY `EMAIL_UNIQUE` (`EMAIL`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8 COMMENT='用户会员表';

新建成功:

2.1.2 项目数据库配置

step1:定义实体类(含Swagger注释):

package com.guoranxinxian.member.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Date;

@Data
@ApiModel(value = "用户中注册")
public class UserEntity 

    /**
     * userid
     */
    @ApiModelProperty(value = "用户id")
    private Long userid;
    /**
     * 手机号码
     */
    @ApiModelProperty(value = "手机号码")
    private String mobile;
    /**
     * 邮箱
     */
    @ApiModelProperty(value = "邮箱")
    private String email;
    /**
     * 密码
     */
    @ApiModelProperty(value = "密码")
    private String password;
    /**
     * 用户名称
     */
    @ApiModelProperty(value = "用户名称")
    private String userName;
    /**
     * 性别 0 男 1女
     */
    @ApiModelProperty(value = "用户性别")
    private char sex;
    /**
     * 年龄
     */
    @ApiModelProperty(value = "用户年龄")
    private Long age;
    /**
     * 注册时间
     */
    @ApiModelProperty(value = "创建时间")
    private Date createTime;
    /**
     * 修改时间
     *
     */
    @ApiModelProperty(value = "修改时间")
    private Date updateTime;
    /**
     * 账号是否可以用 1 正常 0冻结
     */
    @ApiModelProperty(value = "账号是否可以用 1 正常 0冻结")
    private char is_avalible;
    /**
     * 用户头像
     */
    @ApiModelProperty(value = " 用户头像")
    private String pic_img;
    /**
     * 用户关联 QQ 开放ID
     */
    @ApiModelProperty(value = "用户关联 QQ 开放ID")
    private Date qq_openid;
    /**
     * 用户关联 微信 开放ID
     */
    @ApiModelProperty(value = "用户关联 微信 开放ID")
    private Date WX_OPENID;

<dependencies>
    <!-- swagger-spring-boot -->
    <dependency>
        <groupId>com.spring4all</groupId>
        <artifactId>swagger-spring-boot-starter</artifactId>
        <version>1.7.0.RELEASE</version>
    </dependency>
</dependencies>

step2:会员项目定义Mapper,启动类记得添加@MapperScan(basePackages = "com.guoranxinxian.service.member.mapper")

  <!-- mybatis相关依赖 -->
  <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.1.1</version>
  </dependency>
  
<!-- mysql 依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>
package com.guoranxinxian.mapper;

import com.guoranxinxian.member.dto.UserEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
 * description: 用户mapper
 */
public interface UserMapper 

    @Insert("INSERT INTO `user` VALUES (null,#mobile, #email, #password, #userName, null, null, null, '1', null, null, null);")
    int register(UserEntity userEntity);

    @Select("SELECT * FROM user WHERE MOBILE=#mobile;")
    UserEntity existMobile(@Param("mobile") String mobile);


step3:配置数据库相关信息(也可以配置apollo):

spring:
  datasource:
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/guoranxinxian-member?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai

2.2 会员接口部分

2.2.1 验证手机号接口(供微信服务使用)

step1:定义接口(注意Feign调用接口,使用的是POST请求)

package com.guoranxinxian.service;

import com.guoranxinxian.api.BaseResponse;
import com.guoranxinxian.member.dto.UserEntity;
import com.guoranxinxian.weixin.dto.AppEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Api(tags = "会员服务接口")
public interface MemberService 

    @ApiOperation(value = "会员服务调用微信服务")
    @GetMapping("/memberInvokWeixin")
    public AppEntity memberInvokWeixin();

    /**
     * 根据手机号码查询是否已经存在,如果存在返回当前用户信息
     * @param mobile
     * @return
     */
    @ApiOperation(value = "根据手机号码查询是否已经存在")
    @ApiImplicitParams(
            @ApiImplicitParam(paramType = "query", name = "mobile", dataType = "String", required = true, value = "用户手机号码"), )
    @PostMapping("/existMobile")
    BaseResponse<UserEntity> existMobile(@RequestParam("mobile") String mobile);


step2:接口实现:

@RestController
public class MemberServiceImpl extends BaseApiService<UserEntity> implements MemberService 

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AppServiceFeign appServiceFeign;

    @GetMapping("/memberInvokWeixin")
    public AppEntity memberInvokWeixin() 
        return appServiceFeign.getApp();
    

    @Override
    public BaseResponse<UserEntity> existMobile(String mobile) 
        // 1.验证参数
        if (StringUtils.isEmpty(mobile)) 
            return setResultError("手机号码不能为空!");
        
        // 2.根据手机号码查询用户信息 单独定义code 表示是用户信息不存在把
        UserEntity userEntity = userMapper.existMobile(mobile);
        if (userEntity == null) 
            return setResultError(Constants.HTTP_RES_CODE_EXISTMOBILE_203, "用户信息不存在!");
        
        // 对特殊铭感字段需要做脱敏
        userEntity.setPassword(null);
        return setResultSuccess(userEntity);
    

2.2.2 Feign远程调用注册码验证接口

定义Feign接口:

package com.guoranxinxian.feign;

import com.guoranxinxian.service.VerificaCodeService;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient("guoranxinxian-shop-service-weixin")
public interface VerificaCodeServiceFeign extends VerificaCodeService 


2.2.3 会员注册接口

step1:定义接口(注意请求参数RequestBodyRequestParam,接口需要填,Swagger用到)

package com.guoranxinxian.service;

import com.alibaba.fastjson.JSONObject;
import com.guoranxinxian.api.BaseResponse;
import com.guoranxinxian.member.dto.UserEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

@Api(tags = "会员注册接口")
public interface MemberRegisterService 
    /**
     * 用户注册接口
     *
     * @param userEntity
     * @return
     */
    @PostMapping("/register")
    @ApiOperation(value = "会员用户注册信息接口")
    BaseResponse<JSONObject> register(@RequestBody UserEntity userEntity,
                                      @RequestParam("registCode") String registCode);



step2:接口实现(这里写了Feign远程调用微信服务“注册码验证”接口,先贴上代码,下面会讲到)

package com.guoranxinxian.impl;

import com.alibaba.fastjson.JSONObject;
import com.guoranxinxian.api.BaseResponse;
import com.guoranxinxian.constants.Constants;
import com.guoranxinxian.entity.BaseApiService;
import com.guoranxinxian.feign.VerificaCodeServiceFeign;
import com.guoranxinxian.mapper.UserMapper;
import com.guoranxinxian.member.dto.UserEntity;
import com.guoranxinxian.service.MemberRegisterService;
import com.guoranxinxian.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MemberRegisterServiceImpl extends BaseApiService<JSONObject> implements MemberRegisterService 

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private VerificaCodeServiceFeign verificaCodeServiceFeign;

    @Transactional
    public BaseResponse<JSONObject> register(@RequestBody UserEntity userEntity, String registCode) 
        // 1.参数验证
        String userName = userEntity.getUserName();
        if (StringUtils.isEmpty(userName)) 
            return setResultError("用户名称不能为空!");
        
        String mobile = userEntity.getMobile();
        if (StringUtils.isEmpty(mobile)) 
            return setResultError("手机号码不能为空!");
        
        String password = userEntity.getPassword();
        if (StringUtils.isEmpty(password)) 
            return setResultError("密码不能为空!");
        
        // 2.验证码注册码是否正确 暂时省略 会员调用微信接口实现注册码验证
        BaseResponse<JSONObject> verificaWeixinCode = verificaCodeServiceFeign.verificaWeixinCode(mobile, registCode);
        if (!verificaWeixinCode.getRtnCode().equals(Constants.HTTP_RES_CODE_200)) 
            return setResultError(verificaWeixinCode.getMsg());
        
        // 3.对用户的密码进行加密 // MD5 可以解密 暴力破解
        String newPassword = MD5Util.MD5(password);
        userEntity.setPassword(newPassword);
        // 4.调用数据库插入数据
        return userMapper.register(userEntity) > 0 ? setResultSuccess("注册成功") : setResultError("注册失败!");
    


3.微信服务模块

3.1.Feign远程调用手机号验证接口

定义会员Feign接口:

 <dependency>
     <groupId>com.guoranxinxian</groupId>
     <artifactId>guoranxinxian-shop-service-api-member</artifactId>
     <version>1.0-SNAPSHOT</version>
 </dependency>
package com.guoranxinxian.feign;

import com.guoranxinxian.service.MemberService;
import org.springframework.cloud.openfeign.FeignClient;

@FeignClient("guoranxinxian-shop-service-member")
public interface MemberServiceFeign extends MemberService 


3.2 微信获取注册码并验证手机号

package com.guoranxinxian.mp.handler;

import com.guoranxinxian.api.BaseResponse;
import com.guoranxinxian.constants.Constants;
import com.guoranxinxian.feign.MemberServiceFeign;
import com.guoranxinxian.member.dto.UserEntity;
import com.guoranxinxian.mp.builder.TextBuilder;
import com.guoranxinxian.util.RedisUtil;
import com.guoranxinxian.util.RegexUtils;
import me.chanjar.weixin.common以上是关于《果然新鲜》电商项目(21)- 会员注册功能的主要内容,如果未能解决你的问题,请参考以下文章

《果然新鲜》电商项目(40)- SSO单点登录(退出功能)

《果然新鲜》电商项目(25)- 会员唯一登录

《果然新鲜》电商项目(29)- 门户注册功能

《果然新鲜》电商项目(19)- 公众号获取注册码功能

《果然新鲜》电商项目(26)- Redis如何与数据库状态保持一致?

《果然新鲜》电商项目(28)- 获取验证码功能