• 【电商项目实战】用户登录(详细篇)


    🍁博客主页:👉@不会压弯的小飞侠
    欢迎关注:👉点赞👍收藏留言
    系列专栏:👉SpringBoot电商项目实战
    学习社区: 👉不会压弯的小飞侠
    知足上进,不负野心。
    🔥欢迎大佬指正,一起学习!一起加油!

    在这里插入图片描述


    🍁用户登录

    当用户输入用户名和密码将数据提交给后台数据库进行查询,如果存在对应的用户名和密码则表示登录成功,登录成功之后跳转到系统的主页就是index.html页面,跳转在前端使用jquery来完成。

    🔥登录-持久层

    • 用户登录功能需要执行的SQL语句是根据用户名查询用户数据,再判断密码是否正确。
    • SQL语句是:SELECT * FROM t_user WHERE username=?
    • 在用户注册时持久层已编写完成,如需要可以去上篇 “电商项目实战—用户登录(详细篇)” 查看。

    🔥登录-业务层

    🔥异常处理

    • 创建UserNotFoundException和PasswordNotMatchException异常类,以上异常类应继承自ServiceException类。

    1.如果用户名不存在则登录失败,抛出com.jkj.service.exception.UserNotFoundException异常,并从父
    类生成子类的五个构造方法。

    package com.jkj.service.exception;
    
    /** 用户数据不存在的异常 */
    public class UserNotFoundException extends ServiceException {
        public UserNotFoundException() {
            super();
        }
    
        public UserNotFoundException(String message) {
            super(message);
        }
    
        public UserNotFoundException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public UserNotFoundException(Throwable cause) {
            super(cause);
        }
    
        protected UserNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.如果用户的isDelete字段的值为1,则表示当前用户数据被标记为“已删除”,需进行登录失败操作同时
    抛出UserNotFoundException。
    3.如果密码错误则进行登录失败操作,同时抛出com.jkj.service.ex.PasswordNotMatchException
    异常。

    package com.jkj.service.exception;
    
    /** 密码验证失败的异常 */
    public class PasswordNotMatchException extends ServiceException {
        public PasswordNotMatchException() {
            super();
        }
    
        public PasswordNotMatchException(String message) {
            super(message);
        }
    
        public PasswordNotMatchException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public PasswordNotMatchException(Throwable cause) {
            super(cause);
        }
    
        protected PasswordNotMatchException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    🔥接口与抽象方法

    • 在IUserService接口中添加登录功能的抽象方法。
    • 当登录成功后需要获取该用户的id,以便于后续识别该用户的身份,并且还需要获取该用户的用户
      名、头像等数据,用于显示在软件的界面中,需使用可以封装用于id、用户名和头像的数据的类型
      来作为登录方法的返回值类型。
     /**
         * 用户登录
         * @param username 用户名
         * @param password 密码
         * @return 登录成功的用户数据
         */
        User login(String username, String password);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🔥 实现抽象方法

    • 在UserServiceImpl类中添加login(String username, String password)方法并分析业务逻辑,编写逻辑代码。
    @Override
        public User login(String username, String password) {
            // 调用userMapper的findByUsername()方法,根据参数username查询用户数据
            User result = userMapper.findByUsername(username);
            // 判断查询结果是否为null
            if (result == null) {
                // 是:抛出UserNotFoundException异常
                throw new UserNotFoundException("用户数据不存在的错误");
            }
    
            // 判断查询结果中的isDelete是否为1
            if (result.getIsDelete() == 1) {
                // 是:抛出UserNotFoundException异常
                throw new UserNotFoundException("用户数据不存在的错误");
            }
    
            // 从查询结果中获取盐值
            String salt = result.getSalt();
            // 调用getMd5Password()方法,将参数password和salt结合起来进行加密
            String md5Password = getMd5Password(password, salt);
            // 判断查询结果中的密码,与以上加密得到的密码是否不一致
            if (!result.getPassword().equals(md5Password)) {
                // 是:抛出PasswordNotMatchException异常
                throw new PasswordNotMatchException("密码验证失败的错误");
            }
    
            // 创建新的User对象
            User user = new User();
            // 将查询结果中的uid、username、avatar封装到新的user对象中
            user.setUid(result.getUid());
            user.setUsername(result.getUsername());
            user.setAvatar(result.getAvatar());
            // 返回新的user对象
            return user;
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 在UserServiceTests中编写并完成单元测试。
     @Test
        public void login() {
            User user = iUserService.login("xfx", "123456");
            System.out.println(user);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 运行测试:

    在这里插入图片描述

    🔥登录-控制层

    🔥3.1 处理异常

    • 处理用户登录功能时,在业务层抛出了UserNotFoundException和PasswordNotMatchException异
      常,而这两个异常均未被处理过。则应在BaseController类的处理异常的方法中,添加这两个分支进行
      处理。
     /** @ExceptionHandler用于统一处理方法抛出的异常 */
        @ExceptionHandler({ServiceException.class, FileUploadException.class})
        public JsonResult<Void> handleException(Throwable e) {
            JsonResult<Void> result = new JsonResult<Void>(e);
            if (e instanceof UsernameDuplicateException) {
                result.setState(4000);
            }
            else if (e instanceof UserNotFoundException) {
                result.setState(4001);
            }
            else if (e instanceof PasswordNotMatchException) {
                result.setState(4002);
            }
            else if (e instanceof InsertException) {
                result.setState(5000);
            }
    
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    🔥3.3 处理请求

    • 请求路径:/users/login
    • 请求参数:String username, String password
    • 请求类型:POST
    • 响应结果:JsonResult
    • 在UserController类中添加处理登录请求的login(String username, String password)方法,编写.处理登录请求的login(String username, String password)方法代码。
        @RequestMapping("login")
        public JsonResult<User> login(String username,String password) {
            User data = userService.login(username, password);
            return new JsonResult<User>(OK,data);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 启动项目,访问http://localhost:8080/users/login?username=xfx&password=123456请求进行登录。
    • 测试如下

    在这里插入图片描述

    🔥登录-前端页面

    • 在login.html页面中body标签内部的最后,添加script标签用于编写JavaScript程序。
    <!--页脚结束-->
    		<script type="text/javascript">
    			$("#btn-login").click(function() {
    				$.ajax({
    					url: "/users/login",
    					type: "POST",
    					data: $("#form-login").serialize(),
    					dataType: "json",
    					success: function(json) {
    						if (json.state == 200) {
    							alert("登录成功!");
    							location.href = "index.html";
    						} else {
    							alert("登录失败!" + json.message);
    						}
    					}
    				});
    			});
    		</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 启动项目,访问http://localhost:8080/web/login.html进行登录
    • 用户名:xfx
    • 密码:123456

    在这里插入图片描述

    • 提示登录成功按钮

    在这里插入图片描述

    • 成功跳转到index.html页面

    在这里插入图片描述

    🔥会话

    • session对象主要存在服务器端,可以用于保存服务器的临时数据的对象,所保存的数据可以在整个项目中都可以通过访问来获取,把session的数据看做一个共享的数据。首次登录的时候所获取的用户的数据,转移到session对象即可。seession.getAttrbute(“key”)可以将获取session中的数据这种行为进行封装,封装在BaseController类中。

    • 封装session对象中数据的获取(封装父类中)、数据的设置(当用户登录成功后进行数据的设置,设置到全局的session对象)。

    • 在父类中封装两个数据:获取uid和获取username对应的两个方法。用户头像暂时不考虑,将来封装cookie中来使用。

    • 1.重新构建login()方法,登录成功后将uid和username存入到HttpSession对象中。

     /**
         * 优化登录
         * @param username
         * @param password
         * @param session
         * @return
         */
        @RequestMapping("login")
        public JsonResult<User> login(String username, String password, HttpSession session) {
            // 调用业务对象的方法执行登录,并获取返回值
            User data = userService.login(username, password);
            //登录成功后,将uid和username存入到HttpSession中
            session.setAttribute("uid", data.getUid());
            session.setAttribute("username", data.getUsername());
            // System.out.println("Session中的uid=" + getUidFromSession(session));
            // System.out.println("Session中的username=" + getUsernameFromSession(session));
    
            // 将以上返回值和状态码OK封装到响应结果中并返回
            return new JsonResult<User>(OK, data);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 2.在父类BaseController中添加从HttpSession对象中获取uid和username的方法,以便于后续快捷的获
      取这两个属性的值。
     /**
         * 从HttpSession对象中获取uid
         * @param session HttpSession对象
         * @return 当前登录的用户的id
         */
        protected final Integer getUidFromSession(HttpSession session) {
            return Integer.valueOf(session.getAttribute("uid").toString());
        }
    
        /**
         * 从HttpSession对象中获取用户名
         * @param session HttpSession对象
         * @return 当前登录的用户名
         */
        protected final String getUsernameFromSession(HttpSession session) {
            return session.getAttribute("username").toString();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    学习视频:

    【SpringBoot项目实战完整版】SpringBoot+MyBatis+MySQL电脑商城项目实战-哔哩哔哩】
    https://b23.tv/qGh9x9L

    在这里插入图片描述

  • 相关阅读:
    ActiveReports.NET 17.1.X Carack
    基于Qt C++的工具箱项目源码,含命令行工具、桌面宠物、文献翻译、文件处理工具、医学图像浏览器、插件市场、设置扩展等工具
    【Transformer系列】深入浅出理解ViT(Vision Transformer)网络模型
    Redis hash 命令总结
    JS 串口 16进制数据累加和取低位
    CAD数据文件格式DXF部分实体(圆弧、椭圆、凸度)解析[原理讲解+公式推导+java实现]
    吴恩达2022机器学习_第二部分高级学习算法笔记
    Linux如何正确安装MySQL(详细步骤)
    入耳式无线蓝牙耳机什么牌子好?入耳式音质好耳机推荐
    iNFTnews | 迪士尼如何布局Web3
  • 原文地址:https://blog.csdn.net/qq_43514330/article/details/126316909