用户登录模块

用户登录


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

登录-持久层

规划需要执行的SQL语句

依据用户提交的用户名和密码做select查询。密码的比较在业务层执行。
select * from t_user where username=?
说明:如果在分析发现某一个功能模块已经被开发完成,所以就可以省略当前的开发步骤,这个分析过程不能省略。

接口设计和抽象方法

不用重复度开发。单元测试也是不须单独执行

登录-业务层

规划异常

1.用户名对应的密码错误,密码匹配失败的异常:PasswordNotMathException异常,运行时异常,业务异常。

2.用户名没有被找到,抛出异常:UserNameNotFoundException。运行时异常,业务异常。

3.异常的编写:
* 业务层异常需要继承ServiceException异常类。
* 在具体的异常类中定义构造方法(可以使用快捷键来生成,有五个构造方法)。

设计业务层接口和抽象方法及抽象方法的实现

1.直接在IUserService接口中编写抽象方法,login(String username,String password)。将当前登录成功的用户数据以当前用户对象的形式进行返回。状态管理:可以将数据保存在cookie或者session中,可以避免重复度很高的数据多次频繁操作数据进行获取(用户名、用户id-存放在session中,用户头像-cookie中) 。

/**
     * 用户登录功能
     * @param username 用户名
     * @param password 用户的密码
     * @return 当前匹配的用户数据,如果没有则返回null
     */
    User login(String username,String password);

2.需要在实现类中实现父接口中的抽象方法。

@Override
	    public User login(String username, String password) {
	        //根据用户名来查询用户的数据是否存在,如果不存在则抛出异常
	        User result = userMapper.findByUsername(username);
	        if(result == null){
	            throw new UserNotFoundException("用户数据不存在");
	        }
	        //检测用户的密码是否匹配
	        //1.先获取数据库加密之后的密码
	        String oldPassword = result.getPassword();
	        //2.和用户传递过来的密码进行比较
	        //2.1 先获取盐值:上一次注册自动生成的盐值
	        String salt = result.getSalt();
	        //2.2 将用户的密码按照相同的MD5算法的规则加密
	        String newMd5Password = getMD5Password(password, salt);
	        //3将密码进行比较
	        if(!newMd5Password.equals(oldPassword)){
	            throw new PasswordNotMatchException("用户密码错误");
	        }
	        //判断is_delete字段的值是否为1,表示被标记为删除
	        if(result.getIsDelete() == 1){
	            throw new UserNotFoundException("用户数据不存在");
	        }
	        //提升系统的性能
	        User user = new User();
	        user.setUid(result.getUid());
	        user.setUsername(result.getUsername());
	        user.setAvatar(result.getAvatar());
	        //将当前用户数据返回,返回的数据是为了辅助其他页面做数据展示使用(uid,username,avater)
	        return user;
	    }

3.在测试类中测试业务层登录的方法是否可以执行通过。

  @Test
	    public void login(){
	        User user = userService.login("test01", "123");
	        System.out.println(user);
	    }

4.如果一个类没有手动创建直接将这个类复制到项目,idea找不到这个类。之前的缓存导致不能够正常的找到这个类的符号。重新构建项目。
Error:(7, 31) java: 找不到符号
符号: 类 PasswordNotMatchException
位置: 程序包 com.cy.store.service.ex

登录-控制层

处理异常

业务层抛出的异常是什么,需要在统一异常处理类中进行统一的捕获和处理, 如果业务层抛出的异常类型已经在统一异常处理类中曾经处理过,则不需要重复添加。

else if(e instanceof UserNotFoundException){
	        result.setstate(5001);
	        result.setMessage("用户数据不存在");
	    }else if(e instanceof PasswordNotMatchException){
	        result.setstate(5002);
	        result.setMessage("用户名密码错误的异常");
	    }

设计请求

* 请求路径:/users/login
* 请求方式:POST
* 请求数据:String username,String password,HttpSession session
* 响应结果:JsonResult<User>

处理请求

在UserController类中编写处理请求的方法。

@RequestMapping("/login")
	public JsonResult<User> login(String username,String password){
	    User data = userService.login(username, password);
	    return new JsonResult<User>(OK,data);
	}

登录-前端页面

1.在login.html页面中依据前面所设置的请求来发送sjax请求。
2.访问页面进行用户的登录操作

用户登录会话session

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

1.封装session对象中数据的获取(封装在父类中),数据的设置。(当用户登录成功后进行数据的设置,设置到全局的session对象中)。
2.在父类中封装两个数据:获取uid和获取username对应的两个方法。用户头像暂时不考虑,将来封装cookie中来使用。

/**
	     * 获取session对象中的uid
	     * @param session   session对象
	     * @return  当前登录用户uid的值
	     */
	    protected final Integer getuidFromSession(HttpSession session){
	        return Integer.valueOf(session.getAttribute("uid").toString());
	    }
	
	    /**
	     * 获取session对象中的username
	     * @param session session对象
	     * @return 当前登录用户的username的值
	     */
	    public final String getUsernameFromSession(HttpSession session){
	        return session.getAttribute("username").toString();
	    }

3.在登录的方法中将数据封装在session对象中。

 //登录成功后,将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));

拦截器

拦截器:首先将所有的请求统一拦截到拦截器中, 可以拦截器中来定义过滤的规则,如果不满足系统的设置的过滤规则,统- -的处理是重新去打开login.html页面(重定向和转发) ,推荐使用重定向。

在SpringBoot项目中拦截器的定义和使用。SpringBoot是依靠springMVC来完成的。SpringMVC提供了一个HandlerInterceptor接口,用于表示定义一个拦截器。受限制自定义个类,在这个类实现这个接口。

1.首先自定义一个类,在这个类实现这个HandlerInterceptor接口。

package com.cy.store.interceptor;
	
	import org.springframework.web.servlet.HandlerInterceptor;
	
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	import javax.servlet.http.HttpSession;
	
	/*定义一个拦截器*/
	public class LoginInterceptor implements HandlerInterceptor {
	    /**
	     * 检测全局session对象是否有uid数据,如果有就放行,没有就重定向到登录页面
	     * @param request 请求对象
	     * @param response 响应对象
	     * @param handler 处理器(url + Controller:映射)
	     * @return  返回为true,表示放行当前的请求,返回为false,表示拦截当前的请求
	     * @throws Exception
	     */
	    @Override
	    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
	        Object obj = request.getSession().getAttribute("uid");
	        if(obj == null){
	            //说明用户没有登录过系统,则重定向到login.html首页
	        response.sendRedirect("/web/login.html");
	        return false;
	        }
	        //请求放行
	        return true;
	    }
	}

2.注册过滤器:添加白名单(哪些资源可以在不登录的情况下访问:login.html\register.html\login\reg\index.html\product.html),添加黑名单(在用户不登录的状态下可以访问的页面资源)。

3.注册过滤器的技术:借助WebMvcConfigure接口,可以将用户自定义的拦截器进行注册,才可以保证拦截器能够生效和使用。定义一个类,然后让这个类实现WebMvcConfigure接口。配置信息,建议存放在项目的config包结构下。

//将自定义的拦截器进行注册
	default void addInterceptors(InterceptorRegistry registry) {
	
    }

4.提示重定向次数过多,login.html页面无法打开。将浏览器cookie请求,再将浏览器设置为初始设置。

源码解析:

//在调用所有处理请求的方法之前被自动调用执行的方法
	public interface HandlerInterceptor {
	    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
	        return true;
	    }

	//在ModelAndView对象返回之后被调用的方法
	    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
	    }
	
	//在整个请求所有关联的资源被执行完毕最后所执行的方法
	    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
	    }
	}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值