当前位置: 首页 > news >正文

vue3+springboot+mybatis+mysql项目实践--简单登录注册功能实现

这里是一次对vue3+springboot+mybatis+mysql的项目实现,简单实现前后端分离的登录注册功能,主要工具:idea,navicat

目录

一、创建vue3项目并初始配置

创建vue3项目

2.修改项目结构

1)原始目录结构

2)修改后目录结构

​编辑编写登录注册页面

1)LoginAndRegister.vue

2)Home.vue

3)router

4)Login.css

5)登录注册页面展示

二、创建springboot+mysql+mybatis项目并连接数据库

三、编写登录注册后端功能

1.登录逻辑

2.注册逻辑

3.后端代码部分

四、运行项目


一、创建vue3项目并初始配置

1.创建vue3项目

创建项目可参考我的一篇文章:

用IDEA创建自定义vue3项目_idea vue3-CSDN博客

创建后的初始目录结构:

2.修改项目结构

首先需要修改原始目录结构

1)原始目录结构

assets放图片

components中放组件,通常可复用

router是路由,所有主要页面的文件路径在其中配置

store一般是用于vuex状态管理,如存储token等

views中是主要页面

App.vue是Vue应用的根组件。

main.js是应用的入口文件,通常用于引入vue和vue router等依赖。

2)修改后目录结构

要实现登录注册功能,修改后的目录结构:


3.编写登录注册页面

1)LoginAndRegister.vue

在components文件夹下创建LoginAndRegister.vue,用于实现登录注册页面及功能,这里我的登录和注册只创建一个.vue文件,在其中通过v-if来决定登录块和注册快的元素部分是否被渲染,从而影响它们的显示。

初始时设置

v-if="loginShow"为true, v-if="registerShow"为false

当点击按钮进行切换时,将true和false切换。

注册成功后切换回登录部分。

这里为了方便以及用户习惯,虽然用户的属性有id,username,password,phone,gender五个,但注册时只填写用户名和密码,且只是简单实现功能,未对密码进行加密处理不够安全,之后可能会再更新文章,写写更安全的登录注册方式,以及登录后如何完善个人信息。

LoginAndRegister.vue:

<template><div class="container"><div class="login-box" v-if="loginShow">
<!--      菱形群--><div class="decoration1 decoration"></div><div class="decoration2 decoration"></div><div class="decoration3 decoration"></div><div class="decoration4 decoration"></div><div class="decoration5 decoration"></div><div class="decoration decoration4 decoration6"></div><div class="decoration decoration7 decoration2"></div><div class="decoration decoration8 decoration3"></div><div class="login-title"><h1>Login</h1></div><div class="login-part"><input class="login-input" v-model="username" placeholder="Username" /><input class="login-input" type="password" v-model="password" placeholder="Password" /><button class="login-button" @click="login">Login</button><div>还未注册?点击<a class="change-link" @click="changeToRegister">这里</a>注册</div></div></div><div class="login-box" v-if="registerShow"><!--      菱形群--><div class="decoration1 decoration"></div><div class="decoration2 decoration"></div><div class="decoration3 decoration"></div><div class="decoration4 decoration"></div><div class="decoration5 decoration"></div><div class="decoration decoration4 decoration6"></div><div class="decoration decoration7 decoration2"></div><div class="decoration decoration8 decoration3"></div><div class="login-title"><h1>Register</h1></div><div class="login-part"><input class="login-input" v-model="username" placeholder="Username" /><input class="login-input" type="password" v-model="password" placeholder="Password" /><button class="login-button" @click="register">Register</button><span class="change-link" @click="changeToLogin">返回登录</span></div></div>
<!--    <div class="decoration decoration1"></div>-->
<!--    <div class="decoration decoration2"></div>-->
<!--    <div class="decoration decoration3"></div>-->
<!--    <div class="decoration decoration4"></div>--></div>
</template><script>
import { ref } from 'vue'
import { useRouter } from 'vue-router' // 导入 useRouterimport '../style/Login.css' // 导入css
export default {name: 'LoginVue',setup () {const username = ref('')const password = ref('')const phone = ref('')const loginShow = ref(true)const registerShow = ref(false)const router = useRouter()const changeToRegister = async () => {loginShow.value = falseregisterShow.value = true}const changeToLogin = async () => {loginShow.value = trueregisterShow.value = false}const login = async () => {console.log('Login with:', username.value, password.value)try {const formData = new FormData()formData.append('username', username.value)formData.append('password', password.value)const response = await fetch('http://localhost:8081/api/user/login', {method: 'POST',body: formData})const data = await response.json()if (response.ok) {console.log('Link success', data)if (data.code === 200) {// 登录成功alert('登录成功!')await router.push('/home')} else {alert(data.msg)}} else {console.error('Link failed', data)}} catch (error) {console.error('Error login', error)}}const register = async () => {console.log('Register with:', username.value, password.value)try {const formData = new FormData()formData.append('username', username.value)formData.append('password', password.value)const response = await fetch('http://localhost:8081/api/user/register', {method: 'POST',body: formData})const data = await response.json()if (response.ok) {if (data.code === 200) {console.log('Register success', data)alert('注册成功!')await changeToLogin()} else {console.log('Register failed', data)alert(data.msg)}} else {console.error('Register failed', data)}} catch (error) {console.error('Error during register', error)}}return { username, password, phone, login, loginShow, registerShow, changeToRegister, register, changeToLogin }}
}
</script><style></style>

2)Home.vue

Home.vue为登录成功后跳转到的主页面。

Home.vue:

<template>
首页<br><br><button class="login-button" @click="signOut">退出登录</button>
</template><script>
import { useRouter } from 'vue-router'export default {name: 'HomeVue',setup () {const router = useRouter()const signOut = async () => {await router.push('/')}return { signOut }}
}
</script><style scoped></style>

3)router

页面路由配置,路径为/时重定向到登录页,/login为登录页,/home为首页。

index.js:

import { createRouter, createWebHistory } from 'vue-router'
import Login from '../components/LoginAndRegister.vue'
import Home from '../views/Home.vue'const routes = [{path: '/',redirect: '/login'},{path: '/login',name: 'Login',component: Login},{path: '/home',name: 'Home',component: Home}
]const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes
})export default router

4)Login.css

对登录注册页面的css设计。

Login.css:

*{margin: 0;padding: 0;
}
.container{height: 100vh;display: flex;justify-content: center;align-items: center;overflow: hidden;position: relative;
}
.login-box{background-color: white;padding: 40px 100px;border-radius: 8px;box-shadow: 0 0 5px 1px gainsboro;position: relative;
}
.login-part{display: flex;flex-direction: column;justify-content: center;margin-top: 20px;gap: 20px;
}
.login-input{width: 250px;height: 30px;border-radius: 8px;
}
.login-button{height: 40px;border-radius: 8px;background-color: #2c3e50;color: white;transition: 0.5s;
}
.login-button:hover{background-color: darkcyan;font-size: 15px;transition: 0.5s;
}
.login-button:active{background-color: darkslateblue;
}
.change-link{color: #00BFFF;text-decoration: underline;
}
.change-link:hover{color: cornflowerblue;
}.decoration {position: absolute;width: 200px;height: 200px;background: linear-gradient(to left, #FDF5E6, #96CDCD );clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);z-index: 1;
}
.decoration1 {top: 150px;left: -210px;
}
.decoration2 {top: 20px;right: -20px;width: 100px; /* 第二个菱形的大小 */height: 100px;background: linear-gradient(to right, #FFF5EE, #E6E6FA);
}
.decoration3 {top: 50px;right: -180px;width: 200px; /* 第三个菱形的大小 */height: 200px;background: linear-gradient(to right, #7FFFD4, cadetblue);
}
.decoration4 {top: 200px;right: -200px;width: 500px; /* 第三个菱形的大小 */height: 500px;z-index: -1;clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);background: linear-gradient(to right, #FFFACD, #00BFFF);
}
.decoration5 {top: -100px;right: 200px;width: 400px; /* 第三个菱形的大小 */height: 400px;z-index: -1;clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);background: linear-gradient(to right, #AFEEEE, #00BFFF);
}
.decoration6 {top: 10px;right: -680px;
}.decoration7 {top: -170px;right: -500px;
}.decoration8 {top: -140px;right: -655px;
}

5)登录注册页面展示

其中的菱形块是随便排布的,一开始是这样的:

后来多加了几个菱形块,改变他们的位置和颜色,最终效果如下:

二、创建springboot+mysql+mybatis项目并连接数据库

用springboot,mysql,mybatis简单建一个后端项目并连接数据库,参考:

idea,spring boot+MySQL+MyBatis项目创建并在网页中显示数据库表中内容_idea将数据库显示到网页-CSDN博客

对文章补充:

觉得创建实体类每次都要写set和get方法比较麻烦,可以在pom.xml中添加如下依赖:

		<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

然后在entity的实体类中用@Data注解,就可省略写set和get方法:

过程差不多,不过此次创建我的数据不太一样,主要是user表属性和数据发生变化(差别不大,换汤不换药):

遇到问题:maven一直下载依赖,很久没反应

但是在创建项目途中还是出了点儿问题的,这次使用的是新电脑创建后端项目,第一次建,结果maven启动后一直在下载各种依赖和插件,并且很久没有反应:

解决方式:

清空缓存重启idea,但效果不大。

后来发现可能是因为Maven默认使用国外的中央仓库,且我用的是idea中的maven插件,所以下载速度会很慢。

所以还是在本地下载了maven,参考教程:

maven的下载与安装教程(超详细)_maven安装-CSDN博客

按教程下载,在maven安装路径->conf->settings.xml中修改镜像的url,不过我没有配置环境变量,直接在idea中file->settings->Build,Execution,Deployment->Build Tools->Maven中,将Maven home path改为本地路径:

改完之后下载速度果然快了很多。

最终后端项目的目录结构如下:

三、编写登录注册后端功能

1.登录逻辑

获取前端传递的填写信息,包括用户名和密码,在数据库中根据用户名和密码进行查询,如果找到用户,说明用户存在且用户名与密码对应,登录成功,否则失败。

2.注册逻辑

获取前端传递的填写信息,包括用户名和密码,判断输入信息不为空后,在数据库中先根据用户名查找用户,如果找到了,即用户名已存在,注册失败,返回失败信息,如果未找到用户,则可以注册,向数据库中插入该条记录,并且注册成功后展示登录块,隐藏注册块。

3.后端代码部分

其中resources->mapper->UserMapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.example.demo.mapper.UserMapper" ><resultMap id="result" type="com.example.demo.entity.User"><result property="id" column="id" /><result property="username" column="username" /><result property="password" column="password" /><result property="phone" column="phone" /><result property="gender" column="gender"/></resultMap><!--    通过用户名和密码查找对应用户,用于登录--><select id="findUserByNameAndPwd" resultMap="result" parameterType="User">select * from userwhere username = #{username}and password = #{password}</select><!--    通过用户名查找对应用户,用于注册检验用户名是否已存在--><select id="findUserByName" resultMap="result" parameterType="User">select * from userwhere username = #{username}</select><!--    添加用户--><insert id="addUser" parameterType="User">insert into user (username, password)values ( #{username}, #{password} )</insert></mapper>

java->com.example.demo->mapper->UserMapper.java:

package com.example.demo.mapper;import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper {// 通过用户名和密码查找对应用户public User findUserByNameAndPwd(User user);// 通过用户名查找用户public User findUserByName(User user);// 添加用户public void addUser(User user);
}

java->com.example.demo->service->UserService.java:

package com.example.demo.service;import com.example.demo.entity.User;public interface UserService {// 通过用户名和密码查找对应idpublic User findUserByNameAndPwd(User user);// 通过用户名查找用户public User findUserByName(User user);
//     添加用户public void addUser(User user);
}

java->com.example.demo->service->UserServiceImpl.java:

package com.example.demo.service;import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;// 通过用户名和密码查找对应id@Resourcepublic User findUserByNameAndPwd(User user){return userMapper.findUserByNameAndPwd(user);}// 通过用户名查找用户@Resourcepublic User findUserByName(User user){return userMapper.findUserByName(user);}//     添加用户@Resourcepublic void addUser(User user){userMapper.addUser(user);}
}

java->com.example.demo->controller->UserController.java:

package com.example.demo.controller;import com.example.demo.entity.User;
import com.example.demo.result.Result;
import com.example.demo.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/user")
public class UserController {@ResourceUserService userService;// 登录@CrossOrigin@PostMapping(value = "/login")public Result login(@ModelAttribute("user") User user){String username=user.getUsername();String password=user.getPassword();System.out.println("Login received username: " + username);System.out.println("Login received password: " + password);User userCheck = new User();userCheck.setUsername(username);userCheck.setPassword(password);System.out.println(userCheck.getUsername() + " " + userCheck.getPassword());try{User findUser = userService.findUserByNameAndPwd(userCheck);if(findUser != null){return Result.success(findUser);}else {return Result.failure(401,"用户名或密码错误");}}catch (Exception e){return Result.failure(500,"服务器异常");}}// 注册@CrossOrigin@PostMapping(value = "/register")public Result register(@ModelAttribute("user") User user){
//        String username = "222";
//        String password = "222";User userCheck = new User();userCheck.setUsername(user.getUsername());userCheck.setPassword(user.getPassword());if(userCheck.getUsername() == null || userCheck.getUsername().isEmpty() || userCheck.getPassword() == null || userCheck.getPassword().isEmpty()){System.out.println("用户名或密码不可为空");return Result.failure(201,"用户名和密码不可为空");}else {System.out.println("Register received username: " + userCheck.getUsername());System.out.println("Register received password: " + userCheck.getPassword());try{// 先在数据库中查找是否已有用户名相同的用户User findUser = userService.findUserByName(userCheck);if(findUser != null){// 用户名已存在return Result.failure(202,"用户名已存在!");}else {// 新用户,数据库添加记录userService.addUser(userCheck);return Result.success(userCheck);}}catch (Exception e) {return Result.failure(500, "服务器异常");
//            }}}}
}

四、运行项目

前后端分别运行启动,这里我把后端的端口在application.properties中改为了8081,前端为默认的8080,所以在前后端项目都成功运行后,在浏览器输入http://localhost:8080即可,在开发者工具的network中查看,成功连接到后端,并且当登录注册进行测试输入时能成功返回不同的提示信息并弹窗提示:

登录成功之后:

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • seaweedfs + TiKV 部署保姆级教程
  • C语言文件操作技术详解
  • React组件间通信的几种方式
  • Spring相关的面试题
  • vue3中使用 tilwindcss报错 Unknown at rule @tailwindcss
  • QT之嵌入外部第三方软件到本窗体中
  • Java面试八股之Redis有哪些数据类型?底层实现分别是什么
  • 基于ssm的图书管理系统的设计与实现
  • jenkins打包java项目报错Error: Unable to access jarfile tlm-admin.jar
  • 部署大语言模型并对话
  • Docker 安装字体文件
  • 暑假第一次作业
  • wps 将列的内容转换为一个单元格内容,并以逗号分隔
  • python编程实例 计算字符串中空格、英文、数字、其它字符的数量 两种方式实现
  • 检索 Postgres 不同版本功能差异的神器
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • css的样式优先级
  • Java,console输出实时的转向GUI textbox
  • javascript数组去重/查找/插入/删除
  • Java深入 - 深入理解Java集合
  • Js基础知识(一) - 变量
  • k个最大的数及变种小结
  • Phpstorm怎样批量删除空行?
  • Python十分钟制作属于你自己的个性logo
  • Vue UI框架库开发介绍
  • Vue.js 移动端适配之 vw 解决方案
  • 成为一名优秀的Developer的书单
  • 关于springcloud Gateway中的限流
  • 如何选择开源的机器学习框架?
  • 王永庆:技术创新改变教育未来
  • 我是如何设计 Upload 上传组件的
  • 小程序01:wepy框架整合iview webapp UI
  • 新手搭建网站的主要流程
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • UI设计初学者应该如何入门?
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (第二周)效能测试
  • (一)Kafka 安全之使用 SASL 进行身份验证 —— JAAS 配置、SASL 配置
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)负载均衡,回话保持,cookie
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .Net Web窗口页属性
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • /etc/fstab和/etc/mtab的区别
  • /etc/skel 目录作用
  • @property括号内属性讲解
  • @RequestMapping处理请求异常
  • [ C++ ] STL---stack与queue
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)