Bootstrap

【二,瑞吉外卖项目】-登录/退出功能(1)

登录

需求分析:
1)页面原型展示
在这里插入图片描述
2)登录页面展示(http://localhost:8080/backend/page/login/login.html)
在这里插入图片描述
3)查看登录请求信息:
输入账号密码,点击登录,发出请求,并且以json的形式将账号密码提交到服务端在页面点击F12,如图:
在这里插入图片描述
在这里插入图片描述
后台请求:controler->service->mapper-db
4)数据模型(employee表)
在这里插入图片描述
5)页面逻辑(主要是请求和返回数据的逻辑,其他页面小的效果不作分析)
在这里插入图片描述
validate:
①,校验用户名密码
②,校验通过之后,请求到loginApi,其实(loginApi)是封装到了一个js文件中(按住Ctrl左键可以关联过去),通过Ajax向后端发送请求。并且将数据(就是这个loginForm里放的用户名和密码)带过来。
③,得到的res,返回的数据(约定好1表示成功)
④,成功之后,将数据转为json保存到浏览器中,localStorage.setItem(‘userInfo’,JSON.stringify(res.data));
⑤,做页面跳转:window.location.href= ‘/backend/index.html’;
⑥登录失败提示的信息
this.$message.error(res.msg)
this.loading = false
在这里插入图片描述

在这里插入图片描述
6)后台代码开发
【返回结果类】
此类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回到前端页

/**
 * 此类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回到前端页
 * @param <T>
 */
@Data
public class R<T> {

    private Integer code; //编码:1成功,0和其它数字为失败

    private String msg; //错误信息

    private T data; //数据

    private Map map = new HashMap(); //动态数据

    public static <T> R<T> success(T object) {
        R<T> r = new R<T>();
        r.data = object;
        r.code = 1;
        return r;
    }

    public static <T> R<T> error(String msg) {
        R r = new R();
        r.msg = msg;
        r.code = 0;
        return r;
    }

    public R<T> add(String key, Object value) {
        this.map.put(key, value);
        return this;
    }

}

①实体类(略)
②mapper

@Mapper //mybatisplus
public interface EmployeeMapper extends BaseMapper<Employee> {

}

③service

@Service //引入两个泛型(mapper和实体)
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService{
}

④controller
在这里插入图片描述

 @Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    /**
     * 员工登录
     * @param request
     * @param employee
     * @return
     */
    @PostMapping("/login")
    public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){

        //1,将页面提交的密码进行MD5加密
        String password = employee.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());

//        String aa = "123456";
//        aa = DigestUtils.md5DigestAsHex(aa.getBytes());
//        System.out.println("密文:" + aa);

        //2,根据用户名查数据库
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getUsername,employee.getUsername());

        //数据库已经对username字段做了一个唯一的约束,所以可以调用getOne()查出唯一的数据
        Employee emp = employeeService.getOne(queryWrapper);

        //3,如果没有查到则返回登录失败结果
        if(emp == null){
            return R.error("登陆失败aaaaaaaaa");
        }

        //4,查到结果的话,密码比对不一致也返回失败结果
        if(!emp.getPassword().equals(password)){
            return R.error("登陆失败aaabbbbbbbbbbbbbbbbbbbbba");
        }

        //5,查看员工状态是否可用(0是禁用)
        if(emp.getStatus() == 0){
            return R.error("账号已禁用");
        }

        //6,登录成功,将用户状态存入session中
        HttpSession session = request.getSession();
        session.setAttribute("employee",emp);

        return R.success(emp);
    }
}

登出

1)需求分析
在这里插入图片描述

2)代码开发
在这里插入图片描述

3)前端,顺便移除用户信息
在这里插入图片描述

【用户】
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

完善登录功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
过滤器及其逻辑:

@Slf4j
@WebFilter(filterName = "LoginCheckFilter" ,urlPatterns = "/*")
public class LoginCheckFilter implements Filter {

    //路径匹配器,支持通配符
    public static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
    /**
     * 过滤的方法
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //{}占位符
        log.info("拦截到请求:{}",request.getRequestURI());

        //1,获取本次请求的uri
        String requestURI = request.getRequestURI();


        //定义不需要处理的请求路径
        String [] urls = new String[]{
                "/employee/login",
                "/employee/logout",
                "/backend/**",//静态资源放行
                "/front/**",//静态资源放行
        };

        //2,判断本次请求是否需要处理,也就是说用匹配器ANT_PATH_MATCHER来判断本次请求是否是以上数组的某一个
        boolean check = check(urls,requestURI);

        //3,如果不需要处理,则直接放行
        if(check){
            log.info("本次请求{}不需要处理",request.getRequestURI());
            //放行
            filterChain.doFilter(request,response);
            return;
        }

        //4,判断登录状态,如果已登录,直接放行
        Employee employee = (Employee) request.getSession().getAttribute("employee");
        if(employee != null){
            log.info("用户已登录,账号:{}",employee.getUsername());
            filterChain.doFilter(request,response);
            return;
        }

        //5,走到这里说明请求未放行 或 未登录
        //通过输出流的方式将结果写到页面(写的是json数据)
        //另外返回的提示中要与前端契合
        log.info("用户未登录");
        PrintWriter out = response.getWriter();
        out.write(JSON.toJSONString(R.error("NOTLOGIN")));

        return;
    }

    /**
     * 检查本次请求是否需要放行
     * @param urls
     * @param requestURI
     * @return
     */
    private boolean check(String [] urls,String requestURI) {
        for (String url : urls) {
            //匹配match()
           boolean match =  ANT_PATH_MATCHER.match(url,requestURI);

           //匹配上了。
           if(match){
               return true;
           }
        }
        return false;
    }
}

前端的拦截器(写在了request.js里),拦截服务端给页面的响应,并判断返回值
在这里插入图片描述
在这里插入图片描述

;