SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程07---用户注册

简介: SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程07---用户注册

本节代码开源地址


代码地址


用户注册前端


1.在src/api下创建/auth/auth.js

import request from '@/utils/request'
export function userRegister(UserDTO) {
    return request({
        url: '/auth/user/register',
        method: 'post',
        data: UserDTO
    })
}

2.在src/views创建/auth/register.vue

<template>
  <div class="columns py-6">
    <div class="column is-half is-offset-one-quarter">
      <el-card shadow="never">
        <div slot="header" class="has-text-centered has-text-weight-bold">新用户入驻</div>
        <div>
          <el-form
            ref="ruleForm"
            v-loading="loading"
            :model="ruleForm"
            status-icon
            :rules="rules"
            label-width="100px"
            class="demo-ruleForm"
          >
            <el-form-item label="账号" prop="name">
              <el-input v-model="ruleForm.name" />
            </el-form-item>
            <el-form-item label="密码" prop="pass">
              <el-input v-model="ruleForm.pass" type="password" autocomplete="off" />
            </el-form-item>
            <el-form-item label="确认密码" prop="checkPass">
              <el-input v-model="ruleForm.checkPass" type="password" autocomplete="off" />
            </el-form-item>
            <el-form-item label="邮箱" prop="email">
              <el-input v-model="ruleForm.email" autocomplete="off" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="submitForm('ruleForm')">立即注册</el-button>
              <el-button @click="resetForm('ruleForm')">重置</el-button>
            </el-form-item>
          </el-form>
        </div>
      </el-card>
    </div>
  </div>
</template>
<script>
import { userRegister } from "@/api/auth/auth";
export default {
  name: "Register",
  data() {
    const validatePass = (rule, value, callback) => {
      if (value === "") {
        callback(new Error("请再次输入密码"));
      } else if (value !== this.ruleForm.pass) {
        callback(new Error("两次输入密码不一致!"));
      } else {
        callback();
      }
    };
    return {
      loading: false,
      ruleForm: {
        name: "",
        pass: "",
        checkPass: "",
        email: ""
      },
      rules: {
        name: [
          { required: true, message: "请输入账号", trigger: "blur" },
          {
            min: 2,
            max: 10,
            message: "长度在 2 到 10 个字符",
            trigger: "blur"
          }
        ],
        pass: [
          { required: true, message: "请输入密码", trigger: "blur" },
          {
            min: 6,
            max: 20,
            message: "长度在 6 到 20 个字符",
            trigger: "blur"
          }
        ],
        checkPass: [
          { required: true, message: "请再次输入密码", trigger: "blur" },
          { validator: validatePass, trigger: "blur" }
        ],
        email: [
          { required: true, message: "请输入邮箱地址", trigger: "blur" },
          {
            type: "email",
            message: "请输入正确的邮箱地址",
            trigger: ["blur", "change"]
          }
        ]
      }
    };
  },
  methods: {
    submitForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          this.loading = true;
          userRegister(this.ruleForm)
            .then(value => {
              const { code, message } = value;
              if (code === 200) {
                this.$message({
                  message: "账号注册成功",
                  type: "success"
                });
                setTimeout(() => {
                  this.loading = false;
                  this.$router.push({ path: this.redirect || "/login" });
                }, 0.1 * 1000);
              } else {
                this.$message.error("注册失败," + message);
              }
            })
            .catch(() => {
              this.loading = false;
            });
        } else {
          return false;
        }
      });
    },
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
};
</script>
<style scoped>
</style>


3.测试页面


image.png

image-20210211232353719


用户注册后端


1.实体类

import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Builder;ums_user
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@TableName("ums_user")
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class UmsUser implements Serializable {
    private static final long serialVersionUID = -5051120337175047163L;
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @TableField("username")
    private String username;
    @TableField("alias")
    private String alias;
    @JsonIgnore()
    @TableField("password")
    private String password;
    @Builder.Default
    @TableField("avatar")
    private String avatar = "https://s3.ax1x.com/2020/12/01/DfHNo4.jpg";
    @TableField("email")
    private String email;
    @TableField("mobile")
    private String mobile;
    @Builder.Default
    @TableField("bio")
    private String bio = "自由职业者";
    @Builder.Default
    @TableField("score")
    private Integer score = 0;
    @JsonIgnore
    @TableField("token")
    private String token;
    @Builder.Default
    @TableField("active")
    private Boolean active = true;
    /**
     * 状态。1:使用,0:已停用
     */
    @Builder.Default
    @TableField("`status`")
    private Boolean status = true;
    /**
     * 用户角色
     */
    @TableField("role_id")
    private Integer roleId;
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(value = "modify_time", fill = FieldFill.INSERT_UPDATE)
    private Date modifyTime;
}

2.mapper接口

public interface UmsUserMapper  extends BaseMapper<UmsUser> {
}

3.DTO

import lombok.AllArgsConstructor;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
@Data
@AllArgsConstructor
public class RegisterDTO {
    @NotEmpty(message = "请输入账号")
    @Length(min = 2, max = 15, message = "长度在2-15")
    private String name;
    @NotEmpty(message = "请输入密码")
    @Length(min = 6, max = 20, message = "长度在6-20")
    private String pass;
    @NotEmpty(message = "请再次输入密码")
    @Length(min = 6, max = 20, message = "长度在6-20")
    private String checkPass;
    @NotEmpty(message = "请输入电子邮箱")
    @Email(message = "邮箱格式不正确")
    private String email;
}

4.controller

@RestController
@RequestMapping("/auth/user")
public class UmsUserController {
    @Autowired
    private UmsUserService umsUserService;
    /**
     * 注册
     *
     * @param registerDTO 接收参数
     * @return
     */
    @PostMapping("/register")
    private ApiResult register(@RequestBody RegisterDTO registerDTO) {
        Boolean register = umsUserService.register(registerDTO);
        return ApiResult.success(register);
    }
}

5.service

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.notepad.blog.common.api.ApiResult;
import com.notepad.blog.common.exception.ApiAsserts;
import com.notepad.blog.domain.UmsUser;
import com.notepad.blog.domain.dto.RegisterDTO;
import com.notepad.blog.mapper.UmsUserMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.Date;
@Service
public class UmsUserService extends ServiceImpl<UmsUserMapper, UmsUser> {
    public UmsUser register(RegisterDTO registerDTO) {
        // 查询是否有相同的用户名
        String userName = registerDTO.getName();
        String email = registerDTO.getEmail();
        LambdaQueryWrapper<UmsUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsUser::getUsername, userName)
                .or()
                .eq(UmsUser::getEmail, userName);
        UmsUser umuser = this.getOne(queryWrapper);
        if (!ObjectUtils.isEmpty(umuser)) {
            ApiAsserts.fail("账号或邮箱已存在");
        }
        // 否则注册
        UmsUser umsUser = UmsUser.builder()
                .username(userName)
                .alias(userName)
                .password(registerDTO.getPass())
                .email(email)
                .createTime(new Date())
                .status(true)
                .build();
        this.save(umsUser);
        return umsUser;
    }
}

密码加密

package com.notepad.blog.common.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
    public static String getPwd(String pwd) {
        try {
            // 创建加密对象
            MessageDigest digest = MessageDigest.getInstance("md5");
            // 调用加密对象的方法,加密的动作已经完成
            byte[] bs = digest.digest(pwd.getBytes());
            // 接下来,我们要对加密后的结果,进行优化,按照mysql的优化思路走
            // mysql的优化思路:
            // 第一步,将数据全部转换成正数:
            String hexString = "";
            for (byte b : bs) {
                // 第一步,将数据全部转换成正数:
                // 解释:为什么采用b&255
                /*
                 * b:它本来是一个byte类型的数据(1个字节) 255:是一个int类型的数据(4个字节)
                 * byte类型的数据与int类型的数据进行运算,会自动类型提升为int类型 eg: b: 1001 1100(原始数据)
                 * 运算时: b: 0000 0000 0000 0000 0000 0000 1001 1100 255: 0000
                 * 0000 0000 0000 0000 0000 1111 1111 结果:0000 0000 0000 0000
                 * 0000 0000 1001 1100 此时的temp是一个int类型的整数
                 */
                int temp = b & 255;
                // 第二步,将所有的数据转换成16进制的形式
                // 注意:转换的时候注意if正数>=0&&<16,那么如果使用Integer.toHexString(),可能会造成缺少位数
                // 因此,需要对temp进行判断
                if (temp < 16 && temp >= 0) {
                    // 手动补上一个“0”
                    hexString = hexString + "0" + Integer.toHexString(temp);
                } else {
                    hexString = hexString + Integer.toHexString(temp);
                }
            }
            return hexString;
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "";
    }
    public static void main(String[] args) {
        String pwd = MD5Utils.getPwd("234");
        System.out.println(pwd);
    }
}


404页面

1.在src/views创建/error/404.vue

<template>
  <div class="columns mt-6">
    <div class="column mt-6">
      <div class="mt-6">
        <p class="content">UH OH! 页面丢失</p>
        <p class="content subtitle mt-6">
          您所寻找的页面不存在, {{ times }} 秒后,将返回首页!
        </p>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "404",
  data() {
    return {
      times: 10
    }
  },
  created() {
    this.goHome();
  },
  methods: {
    goHome: function () {
      this.timer = setInterval(() => {
        this.times--
        if (this.times === 0) {
          clearInterval(this.timer)
          this.$router.push({path: '/'});
        }
      }, 1000)
    }
  }
}
</script>
<style scoped>
</style>

2.配置路由

,{
    path: '/404',
    name: '404',
    component: () => import('@/views/error/404'),
    meta: {title: '404-Notfound'}
  },{
    path: '*',
    redirect: '404',
    hidden: true
  }


3.测试页面


http://localhost:8080/#/404


image.png

目录
相关文章
|
5月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
882 3
|
8月前
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
432 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
3月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
Spring Boot 3.x 微服务架构实战指南
|
4月前
|
消息中间件 Ubuntu Java
SpringBoot整合MQTT实战:基于EMQX实现双向设备通信
本教程指导在Ubuntu上部署EMQX 5.9.0并集成Spring Boot实现MQTT双向通信,涵盖服务器搭建、客户端配置及生产实践,助您快速构建企业级物联网消息系统。
1648 1
|
4月前
|
前端开发 安全 Java
基于springboot+vue开发的会议预约管理系统
一个完整的会议预约管理系统,包含前端用户界面、管理后台和后端API服务。 ### 后端 - **框架**: Spring Boot 2.7.18 - **数据库**: MySQL 5.6+ - **ORM**: MyBatis Plus 3.5.3.1 - **安全**: Spring Security + JWT - **Java版本**: Java 11 ### 前端 - **框架**: Vue 3.3.4 - **UI组件**: Element Plus 2.3.8 - **构建工具**: Vite 4.4.5 - **状态管理**: Pinia 2.1.6 - **HTTP客户端
540 4
基于springboot+vue开发的会议预约管理系统
|
8月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
743 1
|
3月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
333 0
|
5月前
|
前端开发 JavaScript Java
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
本系统基于SpringBoot与Vue3开发,实现校园食堂评价功能。前台支持用户注册登录、食堂浏览、菜品查看及评价发布;后台提供食堂、菜品与评价管理模块,支持权限控制与数据维护。技术栈涵盖SpringBoot、MyBatisPlus、Vue3、ElementUI等,适配响应式布局,提供完整源码与数据库脚本,可直接运行部署。
303 6
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
|
8月前
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
682 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
8月前
|
监控 Java 调度
SpringBoot中@Scheduled和Quartz的区别是什么?分布式定时任务框架选型实战
本文对比分析了SpringBoot中的`@Scheduled`与Quartz定时任务框架。`@Scheduled`轻量易用,适合单机简单场景,但存在多实例重复执行、无持久化等缺陷;Quartz功能强大,支持分布式调度、任务持久化、动态调整和失败重试,适用于复杂企业级需求。文章通过特性对比、代码示例及常见问题解答,帮助开发者理解两者差异,合理选择方案。记住口诀:单机简单用注解,多节点上Quartz;若是任务要可靠,持久化配置不能少。
734 4