A070_手机注册


用户注册

内容介绍

1. 用户模块需求分析(掌握)
2 主站-静态网站部署与调试(掌握)
3 注册-分析与设计;(掌握)
4. 注册实现-发送短信验证码;(掌握)
5. 注册实现-整体实现(掌握)

以前做的部门,员工,店铺都是属于组织机构模块。

1.用户模块需求分析

用户注册
	登录信息
	基本信息
	安全信息
用户登录
   账号登录
   扫码登录-自己app扫描页面
   三方登录-使用三方app(微信,qq,支付宝等)
   验证码登录-自己做  reids.set(logincode+phone,xxx)
用户管理
地址管理
收藏
   商品收藏
   店铺收藏
   服务收藏
   宠物收藏
   。。。。
足迹
 。。。。

其实后台管理都要有对应的模块进行管理 用户模块 地址管理模块 收藏模块 足迹模块
在这里插入图片描述
我们只讲注册和登录。因为其他的都是crud。 但是以后写简历项目时,要说做的是用户模块,里面才是具体的功能。 要想做注册与登录,它们都是属于门户网站功能,所以要先搭建门户网站项目,但是在搭建前,先学习静态网站部署与调试.

2.静态网站部署与调试(*****)

前端项目:
vuecli项目:pethome-admin(管理员的管理界面)
Css+div:pethome_web(用户访问门户网站)

2.1.静态网站的部署-部署阶段
  1. vuecli npm管理
    npm run build 打包并部署http服务器,推荐使用Nginx,当然tomcat也可以,只是效率低。
    默认加了contextpath,要修改为空串
    在这里插入图片描述
  2. 直接引入js 传统静态
    直接拷贝到服务器就ok
2.2.静态网站动态调试-开发阶段

开发阶段:
1) vuecli可以npm run dev启动调试
2) 传统导入js开发的模式,没法直接服务器方式调试,需要安装 live-server服务器,这个服务器很简单就是node一个模块.
npm install -g live-server
live-server --port=80

2.3.创建项目模块-门户网站

创建静态项目模块

2.4.拷贝项目

拷贝前端写好项目原型
在这里插入图片描述
整一个一主页
在这里插入图片描述
替换路径
在这里插入图片描述

2.5.运行项目-搭建一个前端服务器

npm install -g live-server
live-server --port=80 把当前路径下的web资源当做一个服务的内容启动起来,并可以指定端口
在这里插入图片描述
解压image.zip 替换到images里面。

3.注册分析与设计

3.1.分析需求

在这里插入图片描述
注册分为:邮箱注册,和手机号注册
逻辑都是一样的,只是激活方式不一样。

手机号注册:
1)输入手机号
2)获取验证码并且输入
3)输入密码和确认密码
4)完成注册

3.2.设计 界面设计(ui)设计表(后台) 流程设计(后台)
3.2.1.数据库表示设计三范式

范式就是规范,就是要遵守的原则。一般要遵守有三种范式
1NF(1范式): 设计数据库表的列的时候,这些列不可拆分。 列的原子性,其实这种范式可以不用管,关系型数据库默认都满足。
2NF(2范式):表中行是唯一,通常设计一个主键来实现。
3NF(3范式): 如果一张表的数据能够通过其他表推导出来,不应该单独设计,通过外键的方式关联查询出来。

反3NF:正常情况来说,我们必须遵循3NF,但是有的时候我们为了增强查询效率,会设计一些冗余字段,变多表查询为单表查询。

3.2.2.表设计

在这里插入图片描述
用户表
在这里插入图片描述
前台用户同时支持手机号与邮箱注册。
需要注意的点
1.如果是手机号注册,用户的默认状态就是激活状态。如果是邮箱注册,需要给用户发送邮件,让用户登录邮件进行激活。目的是防止用户随便写一个不可用的邮箱注册账号。但是目前大多数新项目都不用了,都用手机号。
2.前台用户注册的密码不能是明文的形式存储在数据库,需要进行加密处理,防止用户信息泄露。

登录表
在这里插入图片描述

Type,我们的设计就算你是管理员,你想消费,你也要注册用户,意味着eployee和user中分别有记录。 也就会造成logininfo有相同电话或用户名或email等两个记录,通过type进行区分。

注意:以后只要在eployee或user操作时涉及到登录信息都要同步操作logininfo。比如添加员工也要在logininfo添加一条记录,注册用户也要在logininfo中添加。同理删除或修改也要同步。

3.2.3.流程设计

主流程:
在这里插入图片描述
发送短信验证码:
在这里插入图片描述

   验证码有效时间:3分钟
   重发时间:1分钟

   当前时间 验证码  过期时间
   15       9727     18
   16       ???用原来还是新的

   原来验证码还有效,方案设计
     方案1:每次都是新的
     15       9727     18   后到
     16       8848     19   先到

   真正存放8848,但是用户最后收到是9727。在每条短信后面加发送时间,由用户自行判断选择。
     方案2:用没有过期那个 采纳
	 15       9727     18   后到
     16       9727     19   先到

     方案3:两个都能用-可以但是存放数据变多
3.3.相关技术准备
3.3.1.随机字符串

在这里插入图片描述

3.3.2.Redis

方案1:RedisUtil

<!-- redis客户端 jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方案2:springboot springdata redis
1)导入jar

<!--spirngboot springdata对redis支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2)做配置

spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password: 123456
    jedis:
      pool:
        max-wait: 2000ms
        min-idle: 2
        max-idle: 8

3)RedisTemplate

public class RedisTest extends BaseTest {

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate template;

    @Test
    public void test() throws Exception{
        System.out.println(template);
    }

}
3.3.3.Md5技术

1 不可逆加密技术,只能加密不能解密。 只能做比对,一般用来加密用户登录密码。
我们要做的是把传入进行加密和数据库查询出来密文进行比对判断密码是否正确。
2 盐值:同一种加密算法,由于不同的盐值,加密出来就不一样。
1)整个系统使用同一个盐值,多个用户共用-定义一个常量
2)每个用户都有自己盐值,就算是相同的密码,两个用用户加密出来也不一样。

package cn.itsource.basic.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
    
//加密
    public static String encrypByMd5(String context) {
        try {  
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(context.getBytes());//update处理  
            byte [] encryContext = md.digest();//调用该方法完成计算  
  
            int i;  
            StringBuffer buf = new StringBuffer("");  
            for (int offset = 0; offset < encryContext.length; offset++) {//做相应的转化(十六进制)  
                i = encryContext[offset];  
                if (i < 0) i += 256;  
                if (i < 16) buf.append("0");  
                buf.append(Integer.toHexString(i));  
           }  
            return buf.toString();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block  
            e.printStackTrace();
            return  null;
        }  
    }

    public static void main(String[] args) {

    //加密
    //1 生成随机盐值
    String pwd = "1";
    String salt = StrUtils.getComplexRandomString(32);
    //2 通过这个盐值加密
    String md5Pwd = MD5Utils.encrypByMd5(pwd +"yhp"+ salt+"xxxx");
    System.out.println(md5Pwd);

    //密码比对
    //1 查询盐值-就是salt
    String saltTmp = salt;
    //3 加密比对
    String pwdTmp = "1";
    String inputMd5Pwd = MD5Utils.encrypByMd5(pwdTmp +"yhp"+ saltTmp+"xxxx");
    if (inputMd5Pwd.equals(md5Pwd)){
        System.out.println("登录成功!");
    }else{
        System.out.println("密码错误");
    }
}
3.3.4.短信接口

短信验证,只有三大运营商具有短信发送的能力。要发送短信只有找三大运营,或者中间商。简单说就是要找第三方的短信平台。常见的有阿里云,京东智联云,乐讯通等等非常多.我们项目中使用网建短信通:http://sms.webchinese.com.cn/Rates.shtml
注册以后查看API接口
在这里插入图片描述
下载官方案例:
在这里插入图片描述
在这里插入图片描述
设置签名
在这里插入图片描述

<!-- https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient -->
<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>
package cn.itsource.basic.util;
/**
 * 短信常量类
 */
public class SmsContants {

    public static final String UID = "xxx";         //用户名
public static final String KEY = "yyyy";        //秘钥
}
package cn.itsource.basic.util;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
/**
 * 短信发送工具类
 */
public class SmsUtil {
    /**
     * 发送短信
     * @param phones 手机们 a,b
     * @param content 发送内容
     * @return 返回值
     */
    public static String  sendSms(String phones,String content){
        PostMethod post = null;
        try {
            HttpClient client = new HttpClient();
            post = new PostMethod("http://utf8.api.smschinese.cn");
            post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf8");//在头文件中设置转码
            NameValuePair[] data ={ new NameValuePair("Uid", SmsContants.UID),
                    new NameValuePair("Key", SmsContants.KEY),
                    new NameValuePair("smsMob",phones),
                    new NameValuePair("smsText",content)};
            post.setRequestBody(data);

            client.executeMethod(post);
            int statusCode = post.getStatusCode();
            System.out.println("statusCode:"+statusCode); //200 404 400
            String result = new String(post.getResponseBodyAsString().getBytes("utf8"));
            return result;

        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (post != null) {

                post.releaseConnection();
            }
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(SmsUtil
                .sendSms("13330964748", "您的验证码为:8848"));
    }
}

建议从官网自己copy

4.发送短信验证码

4.1.发送短信后台
4.1.1.搭建用户模块
 User loginInfo

在这里插入图片描述

type-aliases-package: cn.itsource.org.domain,cn.itsource.org.query,cn.itsource.user.domain,cn.itsource.user.query
4.1.2.后台设计

在这里插入图片描述

4.1.3.后台实现

Controller

package cn.itsource.user.controller;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.user.service.IVerifyCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

@RestController
@RequestMapping("/verifycode")
public class VerifyCodeController {

    @Autowired
    private IVerifyCodeService verifyCodeService;
    //一定情况下Map能够代替类使用
    @PostMapping("/smsCode")
    public AjaxResult sendSmsCode(@RequestBody Map<String,String> params){
        String phone = params.get("phone");
        try {
            verifyCodeService.sendSmsCode(phone);
            return AjaxResult.me();
        }
        catch (BusinessException e){
            e.printStackTrace();
            return AjaxResult.me().setMessage("发送失败!"+e.getMessage());
        }
        catch (Exception e) {
            return AjaxResult.me().setMessage("系统错误!"+e.getMessage());
        }
    }
}

接口:

package cn.itsource.user.service;

public interface IVerifyCodeService {
    void sendSmsCode(String phone);
}

实现类:

package cn.itsource.user.service.impl;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.util.SmsUtil;
import cn.itsource.basic.util.StrUtils;
import cn.itsource.user.constant.UserConstants;
import cn.itsource.user.domain.LoginInfo;
import cn.itsource.user.domain.User;
import cn.itsource.user.mapper.LoginInfoMapper;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.service.IVerifyCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;

    @Override
    public void sendSmsCode(String phone) {
        //1 校验
        //1.1 手机号不能为null
        if (!StringUtils.hasLength(phone))
            throw new BusinessException("请输入手机号!");
        //1.2 不能被注册
        User user = userMapper.loadByPhone(phone);
        if (user!=null)
            throw new BusinessException("用户已经被注册!");
        //2 判断原来的是否有效
        Object codeObj = redisTemplate
                .opsForValue().get(UserConstants.REGISTER_CODE_PREFIX + phone); //code:time
        String code = "";
        //2.1 如果有效
        if (codeObj!=null){
            String codeStr = (String) codeObj;
            //2.1.1 判断是否已过重发时间
            String time = codeStr.split(":")[1]; //114555558888
            long intervalTime = System.currentTimeMillis() - Long.valueOf(time);
            if (intervalTime<=1*60*1000){
                //2.1.1.1 如果没有过提示错误
                throw new BusinessException("请勿重复发送短信验证码!");
            }
            //2.1.1.2 如果过了,就使用原来验证码
            code = codeStr.split(":")[0];
        }else{
            //2.2 如果没有
            //2.2.1 重新生成验证码
            code = StrUtils.getComplexRandomString(4);
        }
        //3 保存验证码到redis
        redisTemplate.opsForValue().set(UserConstants.REGISTER_CODE_PREFIX + phone
                ,code+":"+System.currentTimeMillis()
                ,3, TimeUnit.MINUTES);
        //4 调用短信接口发送短信
//        SmsUtil.sendMsg(phone,"您的验证码为:"+code+",请在3分钟之内使用!");
        System.out.println("您的验证码为:"+code+",请在3分钟之内使用!");

    }
}
server:
  port: 8080
spring:
  redis:
    database: 0
    host: localhost
    port: 6379
    password: 123456
    jedis:
      pool:
        max-wait: 2000ms
        min-idle: 2
        max-idle: 8
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/pethome?useUnicode=true&characterEncoding=UTF-8
  mail:
    host: smtp.qq.com
    username: 64009120@qq.com
    password: qzbxiwjfrweecacf
mybatis:
  type-aliases-package: cn.itsource.org.domain,cn.itsource.org.query,cn.itsource.user.domain,cn.itsource.user.query

4.2.发送短信前台

集成vue和axios
1)拷贝vue&axios js库
从pethome_admin nodemodul拷贝

2)在register.html配置

<!--引入vue和axios-->
<script src="./plugins/vue/dist/vue.min.js"></script>
<script src="./plugins/axios/dist/axios.js"></script>
<!--<script>-->
<!--//给vue添加一个全局属性-->
<!--Vue.prototype.$http=axios;-->
<!--//配置axios的全局基本路径-->
<!--axios.defaults.baseURL='http://localhost:80/'-->
<!--</script>-->
<script src="./js/common.js"></script>
<script>
       //配置axios的前缀
       axios.default.baseURI='http://localhost:8080;
       //把axios配置为全局变量
       Vue.prototype.$http = axios //给Vue这个类添加一个原型的属性,这个类的对象都能调用
       //屏蔽vue的警告
       Vue.config.productionTip = false
</script>

<!--vue的js写法-->
<script type="text/javascript">
        //创建vue是需要给他传递一个对象
        new Vue({
               el:"#registerDiv", //id在hmtl模板中要对应
               data:{ //数据模型
                  msg:"zs"
        },
        methods:{//方法
        },
        mounted(){
                window.alert(this.$http)
        }
})
</script>

Html

<!--绑定-->
<form method="post" v-model="phoneUserForm">
<div class="user-phone">
	     <label for="phone"><i class="am-icon-mobile-phone am-icon-md"></i></label>
	     <input type="tel" v-model="phoneUserForm.phone" name="phone" id="phone" placeholder="请输入手机号">
    </div>																			
<div class="verification">
	     <label for="code"><i class="am-icon-code-fork"></i></label>
	     <input type="tel" v-model="phoneUserForm.smsCode" name="smsCode" id="code" placeholder="请输入验证码">
	     <button type="button" v-on:click="sendMobileCode" >获取</button>
</div>
    <div class="user-pass">
		<label for="password"><i class="am-icon-lock"></i></label>
		<input  type="password"  v-model="phoneUserForm.password" name="password"  placeholder="设置密码">
    </div>										
    <div class="user-pass">
		<label for="passwordRepeat"><i class="am-icon-lock"></i></label>
		<input type="password"  v-model="phoneUserForm.confirmPassword" name="confirmPassword"  placeholder="确认密码">
    </div>	
</form>
  methods:{
					sendMobileCode(){
						//1.判断手机号不为空
						if(!this.phoneUserForm.phone){
							alert("手机号不能为空");
							return;
						}
//2.获取按钮 禁用按钮 发送时灰化不能使用 发送成功倒计时60才能使用 如果发送失败立即可以发送
						var sendBtn = $(event.target);
						sendBtn.attr("disabled",true);
						this.$http.post('/verifycode/sendSmsCode',
								{"phone":this.phoneUserForm.phone}).then((res) => {
							console.log(res);
							var ajaxResult = res.data;
							if(ajaxResult.success){
								alert("手机验证码已经发送到您的手机,请在5分钟内使用");
								//3.1.发送成:倒计时
								var time = 60;
								var interval = window.setInterval( function () {
									//每一条倒计时减一
									time = time - 1 ;
									//把倒计时时间搞到按钮上
									sendBtn.html(time);
									//3.2.倒计时完成恢复按钮
									if(time <= 0){
										sendBtn.html("重发");
										sendBtn.attr("disabled",false);
										//清除定时器
										window.clearInterval(interval);
									}
								},1000);
							}else{
								//3.3.发送失败:提示,恢复按钮
								sendBtn.attr("disabled",false);
								alert("发送失败:"+ajaxResult.message);
							}
						});
					}
				}

5.完成注册功能

跳转到注册页面index.html
<a class="am-btn-warning btn" href="register.html" target="_blank">注册</a>

5.1.前台提交数据
phoneReg(){
    let para = Object.assign({}, this.phoneUserForm);
    this.$http.post('/user/register/phone',para).then((res) => {
        var ajaxResult = res.data;
        //注册成功跳转到登录页面
        if (ajaxResult.success){
            location.href="login.html";
        }else{
            alert(ajaxResult.message)
        }
    });
}
5.2.后台数据处理
package cn.itsource.user.controller;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.user.dto.UserDto;
import cn.itsource.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController
{
    @Autowired
    private IUserService userService;

    /**
     * @param userDto
     *    方案1:自定义一个对象接收 用它
     *     方案2:Map
     * @return 成功与否
     */
    @PostMapping("/register/phone")
    public AjaxResult register(@RequestBody UserDto userDto){

        try {
            return userService.register(userDto);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("注册失败!"+e.getMessage());
        }
    }
}
package cn.itsource.user.service;
import cn.itsource.basic.service.IBaseService;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.user.domain.User;
import cn.itsource.user.dto.UserDto;
public interface IUserService extends IBaseService<User> {
    AjaxResult register(UserDto userDto);
}
package cn.itsource.user.service.impl;
import cn.itsource.basic.service.impl.BaseServiceImpl;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.MD5Utils;
import cn.itsource.basic.util.PageList;
import cn.itsource.user.domain.LoginInfo;
import cn.itsource.user.domain.User;
import cn.itsource.user.dto.UserDto;
import cn.itsource.user.mapper.LoginInfoMapper;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.UUID;

@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LoginInfoMapper loginInfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public AjaxResult register(UserDto userDto) {

        //1 校验
        //1.1 null校验
        if (StringUtils.isEmpty(userDto.getPhone())||StringUtils.isEmpty(userDto.getSmsCode())
                ||StringUtils.isEmpty(userDto.getPassword())||StringUtils.isEmpty(userDto.getConfirmPassword()))
            return AjaxResult.me().setSuccess(false).setMessage("请输入相关的内容后再注册!");
        //1.2 确认密码校验
        if (!userDto.getPassword().equals(userDto.getConfirmPassword()))
            return AjaxResult.me().setSuccess(false).setMessage("两次密码不一致!");
        //1.3 手机是否被注册
        User user = userMapper.loadByPhone(userDto.getPhone());
        if (user!=null)
            return AjaxResult.me().setSuccess(false).setMessage("该用户已经被注册!");
        //1.4 验证码是否OK
        Object value = redisTemplate.opsForValue().get("registerCode" + userDto.getPhone());
        if (value==null)
            return AjaxResult.me().setSuccess(false).setMessage("请重获取验证码后再操作!");
        String codeStr = (String) value; //"code:time"
        String code =codeStr.split(":")[0];
        if (!userDto.getSmsCode().equals(code))
            return AjaxResult.me().setSuccess(false).setMessage("请输入正确验证码!");

        //2 相关表保存 loginInfo(返回自增id) User
        LoginInfo loginInfo = userDto2LoginInfo(userDto);
        loginInfoMapper.save(loginInfo);
        User userTmp = loginInfo2User(loginInfo);
        userMapper.save(userTmp);
        return AjaxResult.me();
    }

    private User loginInfo2User(LoginInfo loginInfo) {
        User user = new User();
        user.setUsername(loginInfo.getUsername());
        user.setEmail(loginInfo.getEmail());
        user.setPhone(loginInfo.getPhome());
        user.setSalt(loginInfo.getSalt());
        user.setPassword(loginInfo.getPassword());
        user.setState(1);
        user.setCreatetime(new Date());
        user.setInfo(loginInfo);
        return user;
    }

    //把UserDto转换为loginInfo
    private LoginInfo userDto2LoginInfo(UserDto userDto) {
        LoginInfo info = new LoginInfo();
        info.setUsername(userDto.getPhone()); //给默认值,以后自己改
        info.setPhome(userDto.getPhone());
        String salt = UUID.randomUUID().toString();
        String password = MD5Utils.encrypByMd5(userDto.getPassword()+salt);
        Integer type = 1;
        Integer disable = 1;
        info.setSalt(salt);
        info.setPassword(password);
        info.setType(type);
        info.setDisable(disable);
        return info;
    }
}
package cn.itsource.user.dto;
import lombok.Data;
/**
 * 1 entity domain pojo 数据库操作绑定
 * 2 dto-data transfer  Object,vo value Object 这种对象一般用来接收参数,
 * query也算是一种特殊dto对象
 */
@Data
public class UserDto {
    //电话
    private String phone;
    //验证码
    private String verifyCode;
    //密码
    private String password;
    //确认密码
    private String confirmPwd;
}

6.员工同步操作登录信息

 Service
//Employee操作要同步操作logininfo
@Transactional
@Override
public void add(Employee employee) {
    initEmployee(employee);// 处理密码和盐值等信息
    LoginInfo info= employee2LoginInfo(employee);
    loginInfoMapper.save(info);
    employee.setInfo(info);
    employeeMapper.save(employee);
}

private LoginInfo employee2LoginInfo(Employee employee) {
    LoginInfo info = new LoginInfo();
    BeanUtils.copyProperties(employee,info);
    info.setType(0); //0 是员工 1 用户
    return info;
}

private void initEmployee(Employee employee) {
    String salt = StrUtils.getComplexRandomString(32);
    String securityPwd = MD5Utils.encrypByMd5(employee.getPassword()+salt);

    employee.setSalt(salt);
    employee.setPassword(securityPwd);
}

@Transactional
@Override
public void del(Long id) {
    //通过员工id查询Employee进而获取loginInfoid
    Employee employee = employeeMapper.loadById(id);
    //删除loginInfo
    loginInfoMapper.remove(employee.getLogininfo_id());
    //删除员工
    employeeMapper.remove(id);
}

Test

public class EmployeeServiceImplTest extends BaseTest {

    @Autowired
    private IEmployeeService employeeService;
    @Test
    public void add() {
        Employee employee = new Employee();
        employee.setUsername("yhptest");
        employee.setEmail("yhp@itsource.cn");
        employee.setPhone("13330964748");
        employee.setPassword("1");
        employee.setAge(18);
        Shop shop = new Shop();
        shop.setId(27L);
        employee.setShop(shop);
        employeeService.add(employee);
    }
}

店铺

@Override
public void settledIn(Shop shop) {
    //对用户进行校验
    // 1 判断是否存在,提示“已经入驻,请直接登陆!如果忘记了请找回密码!”
    Employee admin = shop.getAdmin();
    Employee employee = employeeMapper.loadByUser(admin);
    if (employee!=null)
         //不仅要错误,还要提示信息
        throw new BusinessException("已经入驻,请直接登陆!如果忘记了请找回密码!");
    // 2 如果不存在,走入驻流程
    // 2.1 保存管理员信息并放回自增id
    employeeService.add(admin);
    // 2.2 给shop添加admin.id,再保存Shop----名称可以重复但是店铺地址在方圆几公里不能重复入驻,由审核人员把控。
    shopMapper.save(shop);     //上一步保存完毕shop.admin里面就有id
    //让管理员关联店铺id
    admin.setShop(shop);
    employeeMapper.update(admin);
}

6.课程总结

6.1.重点
6.2.难点
6.3.如何掌握
6.4.排错技巧(技巧)

7.常见问题

8.课后练习

1.完成邮件激活店铺账号功能

9.面试题

10.扩展知识或课外阅读推荐(可选)

10.1.扩展知识
10.2.课外阅读
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值