三、用户登录功能的实现
用户登录
功能分析
用户进入登陆页面,输入用户名和密码,点击登录按钮,向后台程序发送请求,后台根据用户信息在数据库中进行查找,如果用户名和密码均正确,则会跳转到对应的主页面,即index.html
持久层
规划要执行的SQL语句
分析:一般逻辑是根据用户名查询数据库返回用户记录给业务层,由于密码存储一般是经过加密后的数据,数据库中与用户输入一般不一致,所以密码等其他信息的校验一般放在业务层去进行
| 1 | select * from t_user where username=?; | 
相关持久层的功能在用户注册模块已经实现
业务层
规划异常
密码错误异常
用户名正确,密码错误引发的异常,PasswordNotMatchException
| 1 | package com.bang.store.service.ex; | 
用户名不存在异常
用户名数据库中不存在所引发的异常,UsernameNotFoundException
| 1 | package com.bang.store.service.ex; | 
设计接口和抽象方法
直接在IUserService接口中编写登录方法login(String username,String password)
如果登录成功,将用户数据对象需要作为方法返回值返回
状态管理:将相关数据保存在cookie或者session中,可以避免重复度很好的数据多次频繁操作数据库获取
| 1 | /** | 
接口实现类
| 1 | public User login(String username, String password) { | 
控制层
处理异常
根据业务层抛出异常,在统一异常处理基类中做出对应的处理
| 1 | else if (e instanceof UsernameNotFoundException) { | 
设计请求
| 1 | 请求路径:/user/login | 
处理请求
在UserController类中编写对应的请求处理方法
| 1 | 
 | 
前端页面
在login.html页面中找到对应表单,在表单中找到登录按钮,将登录按钮与指定时间绑定,按钮点击,向后端指定程序发送请求
| 1 | <script> | 
用户会话Session
session对象主要存储在服务器端,可以用于保存服务器的临时数据,其在整个项目中都可以被访问,可以在不同模块之间进行数据共享。
对于用户登录功能,可以将用户当前首次登录输入的信息数据存储在session对象中,供整个会话期间,其他模块共用。
| 1 | //session对象存储数据 | 
可能在一个项目中,多次用到session对象存储数据或者从session对象中读取数据,为了减少代码冗余,应该将这两个操作封装到函数中
可以封装到工具类,但是由于这两个操作只会在控制层使用,而本项目控制层存在基类,所以将该方法定义在控制层基类BaseController中
由于存储操作要视具体情况而定,所以只封装从session对象读取数据功能
| 1 | /** | 
相关位置将数据存取到session对象中
在UserController类中的login函数中将相关数据存取到session对象
| 1 | 
 | 
用户登录拦截器
拦截器
会首先将用户所有请求统一拦截到拦截器中进行处理,所以可以到拦截器中自定义过滤规则,达到拦截请求、过滤响应的目的
比如:对于当前项目(商城系统),访问其他页面会全部拦截到拦截器,判断用户是否登录,如果没有则统一会打开login.html用户登录页面,打开其他页面,可以使用重定向或者请求转发技术来完成
推荐使用重定向技术,如果两个模块不在同一个服务器上,转发可能会出现错误
SpringBoot中如何拦截器的使用
SpringMVC提供了一个HandleInterceptor接口,用于表示拦截器
使用步骤
- 自定义一个类,实现 - HandleInterceptor接口,项目一般会将所有拦截器统一放在一个目录下,本项目中统一放在- com.bang.store.interceptor包下- 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
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50- package com.bang.store.interceptor; 
 import org.springframework.web.servlet.HandlerInterceptor;
 import org.springframework.web.servlet.ModelAndView;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 /**
 * 定义用户登录拦截器
 */
 public class LoginInterceptor implements HandlerInterceptor {
 //在所有请求处理方法之前被调用执行,即在请求到达Dispatcher中央处理器之前
 //拦截器的重点关注位置
 /**
 * 功能:检测session对象中是否含有uid数据,如果有则放行请求,否则重定向到用户登录界面
 * @param request 请求对象
 * @param response 响应对象
 * @param handler 处理器
 * @return 如果返回值为true,正常放行;如果为false,则表示拦截,不放行,
 * @throws Exception
 */
 
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 //获取session对象
 HttpSession session = request.getSession();
 //获取uid数据
 Object uid = session.getAttribute("uid");
 if(uid==null){ //表明用户没有登录
 response.sendRedirect("/web/login.html"); //重定向到登录页面
 return false; //拦截请求
 }
 return true; //用户登录后则直接放行
 }
 //请求执行后被调用
 
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
 }
 //所有关联操作完成之后调用
 
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
 HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
 }
 }
- 注册拦截器 - 添加白名单与黑名单,即当前拦截器只对那些请求起作用、对哪些请求不起作用 - 比如:注册、登录页面不能够被拦截,否则任何界面都无法进入,造成死循环 
- 拦截器注册操作 - 借助 - WebMVCConfigure接口,可以将用户定义的拦截器进行注册,才能使拦截器生效- 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- package com.bang.store.configure; 
 import com.bang.store.interceptor.LoginInterceptor;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.HandlerInterceptor;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 import java.util.ArrayList;
 import java.util.List;
 //注解,让SpringBoot识别
 public class LoginInterceptorConfigure implements WebMvcConfigurer {
 /**
 * 添加拦截器
 * @param registry
 */
 
 public void addInterceptors(InterceptorRegistry registry) {
 //实例化自定义拦截器
 HandlerInterceptor loginInterceptor = new LoginInterceptor();
 //配置白名单
 List<String> whiteList = new ArrayList<String>();
 whiteList.add("/web/login.html");
 whiteList.add("/web/register.html");
 whiteList.add("/web/product.html");
 whiteList.add("/index.html");
 //注册拦截器
 registry.addInterceptor(loginInterceptor)
 .addPathPatterns("/web/**") //配置黑名单,即拦截器要拦截的路径
 .excludePathPatterns(whiteList); //配置白名单,即拦截器不拦截的路径
 }
 }





