• 【store商城项目02】登录功能的开发


    0.登录-功能概述

    通过访问登录的静态页面来看,就是将用户输入的用户名和密码,点击登录提交到后台的数据库中,若数据库中存在该用户,则跳转到index.html页面,跳转通过前端的jquery实现

    1.登录-持久层

    1.1需要执行的SQL语句

    根据用户提交的用户名进行select查询,密码的判断放在业务层

    1.2接口的设计和方法

    分析完以后发现这个功能模块已经被开发完成(UserMapper接口的findByUsername方法),所以就可以省略当前的开发步骤,但是这个分析过程不能省略后续的设计接口和抽象方法,编写映射,单元测试都不再需要进行,

    2.登录-业务层

    2.1规划异常

    1.密码不匹配的异常,PasswordNotMatchException异常类属于运行时异常,业务类异常

    package com.sdjzu.store.service.ex;
    
    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

    2.用户名不存在的异常,UsernameNotFoundException异常类属于运行时异常,业务类异常

    2.2业务层接口和抽象方法

    1.在IUserService接口中编写抽象方法login(String username,String password)

    User login(String username ,String password);
    
    • 1

    2.3业务层抽象方法的实现

        @Override
        public User login(String username, String password) {
            User byUsername = userMapper.findByUsername(username);
    
            if (byUsername == null) {
                throw new UsernameNotFoundException("该用户没有找到");
            }
            if (password.equals(byUsername.getPassword())==false) {
                throw new PasswordNotMatchException("密码不正确");
            }
            User user = new User();
            user.setUsername(byUsername.getUsername());
            user.setPassword(byUsername.getPassword());
            return user;}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.4单元测试

        @Test
        public void login(){
    
            User test1 = iUserService.login("张三", "123");
            System.out.println(test1);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.登录-控制层

    3.1处理异常

            }else if(e instanceof PasswordNotMatchException){
                objectJsonResult.setState(5001);
                objectJsonResult.setMessage("密码错误");
            }else if(e instanceof UsernameNotFoundException){
                objectJsonResult.setState(5002);
                objectJsonResult.setMessage("该用户不存在");
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.2设计请求

    请求路径:/users/login
    请求参数:String username,String password
    请求类型:POST
    响应结果:JsonResult

    3.3处理请求

    在UserController类中编写处理请求的方法.编写完成后启动主服务验证一下

        @RequestMapping("login")
        public JsonResult<User> login(String username,String password){
            User login = iuserService.login(username, password);
            return new JsonResult<User>(ok,login);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    请求处理方法的参数列表设置为非pojo类型:

    SpringBoot会直接将请求的参数名和方法的参数名直接进行比较,如果名称相同则自动完成值的依赖注入

    请求处理方法的参数列表设置为pojo类型:

    SpringBoot会将前端的url地址中的参数名和pojo类的属性名进行比较,如果这两个名称相同,则将值注入到pojo类中对应的属性上

    这两种方法都没有使用注解等等花里胡哨的,却能正常使用,原因是springboot是约定大于配置的,省略了大量配置以及注解的编写

    3.4前台验证

    在这里插入图片描述

    4.登录-前端页面

    	<script>
    		$("#btn-login").click(function(){
    			$.ajax({
    				url:"/user/login",
    				type:"POST",
    				data:$("#form-login").serialize(),
    				dataType:"JSON",
    				success:function (json){
    					if (json.state=200){
    						alert("登录成功")
    						location.href="index.html"
    					}else{
    						alert("登录失败")
    					}
    
    				},
    				error:function (xhr){
    					alert("未知原因"+xhr.message)
    				}
    			})
    		})
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    用session存储和获取用户数据
    在用户登录成功后要保存下来用户的id,username,avatar,并且需要在任何类中都可以访问存储下来的数据,也就是说存储在一个全局对象中,会话session可以实现把首次登录所获取的用户数据转移到session对象即可获取session对象的属性值用session.getAttribute(“key”),因为session对象的属性值在很多页面都要被访问,这时用session对象调用方法获取数据就显得太麻烦了,解决办法是将获取session中数据的这种行为进行封装考虑一下封装在哪里呢?放在一个干净的工具类里肯定可以,但就这个项目目录结构而言,只有可能在控制层使用session,而控制层里的类又继承BaseController,所以可以封装到BaseController里面
    综上所述,该功能的实现需要两步:

    1.在父类中封装两个方法:获取uid和获取username对应的两个方法(用户头像暂不考虑,将来封装到cookie中来使用)
    2.把首次登录所获取的用户数据转移到session对象:

    服务器本身自动创建有session对象,已经是一个全局的session对象,所以我们需要想办法获取session对象:如果直接将HttpSession类型的对象作为请求处理方法的参数,这时springboot会自动将全局的session对象注入到请求处理方法的session形参上:

    将登录模块的设计请求中的请求参数:String username,String password加上HttpSession session

    将登录模块的处理请求中login方法加上参数HttpSession session并修改代码如下

  • 相关阅读:
    541.反转字符串
    C++ Reference: Standard C++ Library reference: C Library: cstdio: perror
    java your MySQL server version for the right syntax to use near
    Guava入门~Guava caches
    单体架构与微服务架构区别
    TDengine函数大全-时序库特有函数
    C++_红黑树
    【无标题】放大放大放大
    Starknet架构之Starknet state、State commitment
    利用aop+反射拦截mybatisplus的insert方法补充公共属性
  • 原文地址:https://blog.csdn.net/yu_fu_a_bu/article/details/126319710