• [Spring实战] 整合Spring/SpringMVC/Mybatis(SSM)实现登录与注册功能(带前端)


     🍳作者:天海奈奈

    💭眼过千遍不如手锤一遍:推荐一款模拟面试,斩获大厂 o f f e r ,程序员的必备刷题平台 − − 牛客网 

    👉🏻点击开始刷题之旅

    目录

    前言

    功能展示

    功能说明

    数据库表设计

    依赖

    配置文件

    后端

    Controller

    Entity实体类

    Mapper

    Service

    Impl

    前端

    总结与改进方向


     

    前言

      不出意料,果然一个登录还是不够的 ,先说明一下,看这篇前请先去看一下上一篇这里放上上一篇的链接 [Spring实战] 整合Spring/SpringMVC/Mybatis(SSM)实现登录功能(带前端)_天海奈奈的博客-CSDN博客,对于项目的创建和依赖的配置这篇不会再讲,这篇主要在之前的基础上对数据库进行一定的修改,新写一个主页页面,实现注册功能。

    功能展示

    0b685e2c6bc34877abe518cbdb143963.gif

     

    功能说明

      之前只是在登录时验证密码时利用了MD5算法进行密码的转换与数据库中的密码去对比,注册时使用着这个工具类去将加密后的密码存到数据库中去,并在注册时检索数据库中是否已经有存在的用户名,在注册页面新加验证码功能,成功注册后自动跳转到登录页面。

    数据库表设计

    93538b1361a349008cc6ad20e690990d.png

      由于没有涉及到用户权限的功能所以没有使用到权值。这里会把sql放在这里直接复制运行就能得到这张表,但是记得去第一篇文章里面去改自己的数据库连接。

    1. SET NAMES utf8mb4;
    2. SET FOREIGN_KEY_CHECKS = 0;
    3. -- ----------------------------
    4. -- Table structure for manager
    5. -- ----------------------------
    6. DROP TABLE IF EXISTS `manager`;
    7. CREATE TABLE `manager` (
    8. `manager_id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '管理员编号',
    9. `username` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
    10. `password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
    11. `salt` int(0) NOT NULL COMMENT '盐值',
    12. `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
    13. `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '昵称',
    14. PRIMARY KEY (`manager_id`) USING BTREE
    15. ) ENGINE = InnoDB AUTO_INCREMENT = 520 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
    16. -- ----------------------------
    17. -- Records of manager
    18. -- ----------------------------
    19. INSERT INTO `manager` VALUES (1, 'MANAGER', 'ce20d2be56ca49d36ed2709e776187db', 1276, NULL, NULL);
    20. INSERT INTO `manager` VALUES (516, 'user1', 'b8ddf129011519e083c25c6b05208da0', 1197, '2022-09-12 21:39:37', '用户1');
    21. INSERT INTO `manager` VALUES (517, 'user2', '675f66d99f78db051bf8c73c3eff26a0', 1226, '2022-09-12 21:40:50', '拥护2');
    22. INSERT INTO `manager` VALUES (518, 'user3', 'e8ee397e19a484c66c0edcde9c8e6c39', 1801, '2022-09-16 15:47:58', '用户三');
    23. INSERT INTO `manager` VALUES (519, 'user4', '4dfcb81c7e01b6beaf0092ddbd8534fd', 1478, '2022-09-16 15:49:36', '用户4');
    24. SET FOREIGN_KEY_CHECKS = 1;

    依赖

    1. com.github.penggle
    2. kaptcha
    3. 2.3.2

    配置文件

    1. <bean id="kaptchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">
    2. <property name="config">
    3. <bean class="com.google.code.kaptcha.util.Config">
    4. <constructor-arg>
    5. <props>
    6. <prop key="kaptcha.border">noprop>
    7. <prop key="kaptcha.image.width">120prop>
    8. <prop key="kaptcha.textproducer.font.color">blueprop>
    9. <prop key="kaptcha.textproducer.font.size">40prop>
    10. <prop key="kaptcha.textproducer.char.length">4prop>
    11. props>
    12. constructor-arg>
    13. bean>

    依赖和配置文件在原基础上加就好

    后端

    Controller

    1. @RestController
    2. @RequestMapping("/api/manager")
    3. public class ManagerController {
    4. @Resource
    5. private ManagerService managerService;
    6. @PostMapping("/check_login1")
    7. public ResponseUtils checkLogin1(String username , String password){
    8. ResponseUtils resp ;
    9. resp = new ResponseUtils();
    10. try {
    11. Manager manager = managerService.checkLogin1(username, password);
    12. manager.setPassword(null);
    13. manager.setSalt(null);
    14. resp = new ResponseUtils().put("manager" , manager);
    15. }catch (Exception e){
    16. e.printStackTrace();
    17. resp = new ResponseUtils(e.getClass().getSimpleName(), e.getMessage());
    18. }
    19. return resp;
    20. }
    21. @PostMapping("/register")
    22. public ResponseUtils register(String username, String password, String nickname, String vc, HttpServletRequest request) {
    23. String verifyCode = (String) request.getSession().getAttribute("kaptchaVerifyCode");
    24. ResponseUtils resp;
    25. if (vc == null || verifyCode == null || !vc.equalsIgnoreCase(verifyCode)) {
    26. resp = new ResponseUtils("VerifyCodeError", "验证码错误");
    27. } else {
    28. resp = new ResponseUtils();
    29. //验证码比对成功后进行用户注册
    30. try {
    31. Manager manager = managerService.createManager(username, password, nickname);
    32. resp = new ResponseUtils();
    33. } catch (Exception e) {
    34. e.printStackTrace();
    35. resp = new ResponseUtils(e.getClass().getSimpleName(), e.getMessage());
    36. }
    37. }
    38. return resp;
    39. }
    40. }

     与上一篇其实差不多,只是增加了验证码校验,调用新写了一个Service来创建对象。

    Entity实体类

     

    1. @TableName("manager")
    2. public class Manager {
    3. @TableId(type = IdType.AUTO)
    4. private Long managerId;
    5. private String username;
    6. private String password;
    7. private Integer salt;
    8. private String nickname;
    9. private Date createTime;
    10. @Override
    11. public String toString() {
    12. return "Manager{" +
    13. "managerId=" + managerId +
    14. ", username='" + username + '\'' +
    15. ", password='" + password + '\'' +
    16. ", salt=" + salt +
    17. ", nickname='" + nickname + '\'' +
    18. ", createTime=" + createTime +
    19. '}';
    20. }
    21. public Long getManagerId() {
    22. return managerId;
    23. }
    24. public void setManagerId(Long managerId) {
    25. this.managerId = managerId;
    26. }
    27. public String getNickname() {
    28. return nickname;
    29. }
    30. public void setNickname(String nickname) {
    31. this.nickname = nickname;
    32. }
    33. public Date getCreateTime() {
    34. return createTime;
    35. }
    36. public void setCreateTime(Date createTime) {
    37. this.createTime = createTime;
    38. }
    39. public Long getUserId() {
    40. return managerId;
    41. }
    42. public void setUserId(Long userId) {
    43. this.managerId = userId;
    44. }
    45. public String getUsername() {
    46. return username;
    47. }
    48. public void setUsername(String username) {
    49. this.username = username;
    50. }
    51. public String getPassword() {
    52. return password;
    53. }
    54. public void setPassword(String password) {
    55. this.password = password;
    56. }
    57. public Integer getSalt() {
    58. return salt;
    59. }
    60. public void setSalt(Integer salt) {
    61. this.salt = salt;
    62. }
    63. }

      新加创建时间和昵称

    Mapper

    1. public interface ManagerMapper extends BaseMapper {
    2. }

    因为整合了mubatis-plus所以并不需要自己写mapper以及xml文件

    Service

    1. public interface ManagerService {
    2. public Manager checkLogin1(String username, String password);
    3. public Manager createManager(String username, String password, String nickname);
    4. }

    这里也就加一个新建对象


    Impl

    1. @Service
    2. //默认方法不开启事务
    3. @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    4. public class ManagerServiceImpl implements ManagerService {
    5. @Resource
    6. private ManagerMapper managerMapper;
    7. @Transactional(rollbackFor = Exception.class)
    8. @Override
    9. public Manager checkLogin1(String username, String password) {
    10. QueryWrapper wrapper = new QueryWrapper();
    11. wrapper.eq("username", username);
    12. Manager manager = managerMapper.selectOne(wrapper);
    13. if (manager == null) {
    14. throw new MemberException("用户不存在");
    15. }
    16. String md5 = MD5Utils.md5Digest(password, manager.getSalt());
    17. if (!md5.equals(manager.getPassword())) {
    18. throw new MemberException("您输入的密码有误");
    19. }
    20. return manager;
    21. }
    22. @Override
    23. public Manager createManager(String username, String password, String nickname) {
    24. QueryWrapper wrapper = new QueryWrapper<>();
    25. wrapper.eq("username", username);
    26. List managers = managerMapper.selectList(wrapper);
    27. if(managers.size() > 0 ){
    28. throw new MemberException("用户已存在");
    29. }
    30. Manager manager = new Manager();
    31. manager.setUsername(username);
    32. manager.setNickname(nickname);
    33. manager.setCreateTime(new Date());
    34. int salt = new Random().nextInt(1000) + 1000;
    35. manager.setSalt(salt);
    36. String md5 = MD5Utils.md5Digest(password, salt);
    37. manager.setPassword(md5);
    38. managerMapper.insert(manager);
    39. return manager;
    40. }
    41. }

      实现类里面也就先去搜索数据库看里面有没有已经存在的用户名,如果没有我们就创建一个新的。

    前端

    251ce21635424a79a7d80b0d12d7c244.png

     

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>注册title>
    6. <link rel="stylesheet" type="text/css" href="assets/element-plus/index.css">
    7. <script src="/assets/vue/vue.global.js">script>
    8. <script src="/assets/element-plus/index.full.js">script>
    9. <script src="/assets/axios/axios.js">script>
    10. <style>
    11. .login-box {
    12. border: 1px solid #DCDFE6;
    13. width: 350px;
    14. margin: 180px auto;
    15. padding: 35px 35px 15px 35px;
    16. border-radius: 5px;
    17. -webkit-border-radius: 5px;
    18. -moz-border-radius: 5px;
    19. box-shadow: 0 0 25px #909399;
    20. }
    21. .login-title{
    22. text-align: center;
    23. margin: 0 auto 40px auto;
    24. color: #303133;
    25. }
    26. style>
    27. head>
    28. <body>
    29. <div id="app">
    30. <el-form ref="registerForm" label-width="80px" :rules="rules" :model="form" class="login-box">
    31. <h2 class="login-title">注册h2>
    32. <el-form-item label="账号" prop="username">
    33. <el-input type="text" placeholder="请输入账号" v-model="form.username">el-input>
    34. el-form-item>
    35. <el-form-item label="密码" prop="password">
    36. <el-input type="password" placeholder="请输入密码" v-model="form.password">el-input>
    37. el-form-item>
    38. <el-form-item label="昵称" prop="nickname">
    39. <el-input type="text" placeholder="请输入昵称" v-model="form.nickname">el-input>
    40. el-form-item>
    41. <el-form-item label="验证码" prop="verifyCode">
    42. <el-row>
    43. <el-col :span="16">
    44. <el-input type="verifyCode" placeholder="请输入验证码" v-model="form.verifyCode">el-input>
    45. el-col>
    46. <el-col :span="8">
    47. <img id="imgVerifyCode" src="/api/verify_code"
    48. style="width: 100%;height:44px;cursor: pointer" @click="reloadVerifyCode">
    49. el-col>
    50. el-row>
    51. el-form-item>
    52. <el-form-item>
    53. <el-button type="primary" v-on:click="onSubmit('registerForm')" style="width:200px">注册el-button>
    54. el-form-item>
    55. <el-form-item>
    56. <el-button type="primary" v-on:click="returnBack" style="width:200px">退出el-button>
    57. el-form-item>
    58. el-form>
    59. div>
    60. <script>
    61. const Main = {
    62. data() {
    63. return {
    64. form: {
    65. username: ''
    66. ,password: ''
    67. ,verifyCode:''
    68. ,nickname:''
    69. }
    70. ,rules:{
    71. username: [
    72. {required: true,message : '账号不能为空' , trigger:'blur'}
    73. ],
    74. password:[
    75. {required: true,message : '密码不能为空' , trigger:'blur'}
    76. ],
    77. verifyCode: [
    78. {required:true,message : '验证码不能为空' , trigger:'blur'}
    79. ],
    80. nickname:[
    81. {required:true,message : '昵称不能为空' , trigger:'blur'}
    82. ]
    83. }
    84. }
    85. }
    86. ,methods : {
    87. onSubmit(formName){
    88. const objApp = this;
    89. const form = this.$refs[formName];
    90. form.validate((valid) => {
    91. if(valid){
    92. console.info("表单校验成功,准备提交数据");
    93. const form = this.form;
    94. const $message = this.$message;
    95. const params = new URLSearchParams();
    96. params.append("username", form.username);
    97. params.append("password", form.password);
    98. params.append("nickname", form.nickname);
    99. params.append("vc", form.verifyCode);
    100. axios.post("/api/manager/register", params)
    101. .then(function (response) {
    102. console.info(response);
    103. const json = response.data;
    104. if(json.code=="0"){
    105. $message.success({message:"注册成功,进入登录界面", offset: 100});
    106. window.location.href = "/login.html";
    107. }else{
    108. $message.error({message:json.message, offset: 100});
    109. }
    110. });
    111. }
    112. })
    113. }
    114. ,returnBack : function (){
    115. window.location.href = "/login.html";
    116. }
    117. , reloadVerifyCode: function () { //刷新验证码方案
    118. document.getElementById("imgVerifyCode").src = "/api/verify_code?ts=" + new Date().getTime();
    119. }
    120. }
    121. };
    122. //初始化Vue,绑定Main中的数据,利用ElementPlus对#app容器进行重新渲染
    123. const app = Vue.createApp(Main);
    124. app.use(ElementPlus);
    125. app.mount("#app");
    126. script>
    127. body>
    128. html>

    总结与改进方向

      下次会更新验证码将网页实时生成的验证码改为邮箱验证,到此为止还是没有使用到session,如果有需求可以自己加,到这里有着基础功能的注册与登录功能的部分就实现了。这个前端登录页面也可以作为一个通用化的页面,只需要改变里面的的api接口就能做到重复使用。

     

  • 相关阅读:
    探索 PrimeVue,一个基于 Vue 的 UI 组件库
    基础矩阵和本质矩阵
    宏定义里面为什么要加括号?
    【LeetCode:2216. 美化数组的最少删除数 | 贪心】
    未来的户外LED视频墙将怎么发展
    有没有项目经理能看得懂这九张图?求挑战
    [Docker Java 服务]Docker 容器中Java服务问题排查
    开源办公OA平台教程:如何修改O2OA配置连接本地部署的OnlyOffice Docs Server服务器?
    TcpCopy 流量复制
    SpringBoot+Dubbo+Nacos 开发实战教程
  • 原文地址:https://blog.csdn.net/weixin_57169969/article/details/126891975