瑞吉外卖02-后台功能

瑞吉外卖02-后台功能

后台登入功能

需求分析

1. 登入页面

2. 点击登入跳转至主页

3. 当前项目状态

​编辑

4. 查看登录请求  

5. 前端页面分析 

代码开发

登录逻辑分析

1. 创建实体类Employee  

2. 定义通用结果类R ​​​​​​​

3. 定义Controller层

4. 定义Mapper接口

5. Service接口 ​​​​​​​

6. Service实现类 ​​​​​​​

后台退出功能 

需求分析

1. 退出页面展示 

2. 前端页面分析 ​​​​​​​

代码开发

1. Controller层

2. service接口 

3. service实现类

后台功能存在问题及优化

问题描述

实现思路

代码实现

定义登录校验过滤器

给启动类添加注解@ServletComponentScan

本次功能代码实现(免费)​​​​​​​


瑞吉外卖02-后台功能

后台登入功能

需求分析

1. 登入页面

2. 点击登入跳转至主页

3. 当前项目状态

此时我们还什么都没有做,项目开发还在初始阶段!

只是配置的了SpringBoot静态资源放行路径

4. 查看登录请求  

可以看到我们点击登入按钮的时候,请求的路径是:http://localhost:8080/employee/login 

并且是post请求 

我们的后台代码还没有编写,所以这里就报404

故我们现在应该按照三层架构的方式来构建后台逻辑 

5. 前端页面分析 

在上述的前端代码中, 大家可以看到, 发送登录的异步请求之后, 获取到响应结果, 在响应结果中至少包含三个属性: code、data、msg 

代码开发

登录逻辑分析

1. 创建实体类Employee  

所在的包:​​​​​​​com.harmony.reggie.entity

@Data
@Setter
@Getter
public class Employee {

    // serialVersionUID用作Serializable类中的版本控件
    // JavaBean规范中要实现java.io.Serializable接口实现序列化!!!
    private static final long serialVersionUID = 1L;

    private Long id;

    private String username;

    private String name;

    private String password;

    private String phone;

    private String sex;

    // 数据库里面是id_number 在application.yml配置即可,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    private String idNumber;

    private Long status;

    // LocalDateTime : JDK8 线程安全
    private LocalDateTime createTime;

    private LocalDateTime updateTime;

    // MP中用于标识非主键的字段。将数据库列与 JavaBean 中的属性进行映射,
    // fill 字段填充标记,表示在插入时自动填充
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
}

serialVersionUID:用作Serializable类中的版本控件,表示该类为可序列化类!JavaBean规范中要实现java.io.Serializable接口实现序列化(序列化serialVersionUID解释说明

idNumber:数据库里面是id_number 在application.yml配置即可,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射

@TableField(fill = FieldFill.INSERT):MP中用于标识非主键的字段。将数据库列与 JavaBean 中的属性进行映射,fill 字段填充标记,表示在插入时自动填充

2. 定义通用结果类R ​​​​​​​

此类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回给前端页面

所在的包:​​​​​​​com.harmony.reggie.common

/**
 * 通用返回结果,服务端返回的数据最终会封装成此对象
 * @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;
    }

}

3. 定义Controller层

所在的包:com.harmony.reggie.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) {
        // @RequestBody : 用来接收前端传递给后端的json字符串中的数据的
        return employeeService.login(request,employee);
    }
}

4. 定义Mapper接口

所在的包:com.harmony.reggie.mapper

MybatisPlus中, 自定义的Mapper接口, 需要继承自 BaseMapper

@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
}

5. Service接口 ​​​​​​​

所在的包:​​​​​​​com.harmony.reggie.service

本项目的Service接口, 在定义时需要继承自MybatisPlus提供的Service层接口 IService, 这样就可以直接调用 父接口的方法直接执行业务操作, 简化业务层代码实现。  

public interface EmployeeService extends IService<Employee> {

    R<Employee> login(HttpServletRequest request, Employee employee);

}

6. Service实现类 ​​​​​​​

该功能的业务逻辑都在这里了! 

①. 将页面提交的密码password进行md5加密处理, 得到加密后的字符串

②. 根据页面提交的用户名username查询数据库中员工数据信息

③. 如果没有查询到, 则返回登录失败结果

④. 密码比对,如果不一致, 则返回登录失败结果

⑤. 查看员工状态,如果为已禁用状态,则返回员工已禁用结果

⑥. 登录成功,将员工id存入Session, 并返回登录成功结果  

所在的包:​​​​​​​com.harmony.reggie.service.impl 

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Override
    public R<Employee> login(HttpServletRequest request, Employee employee) {
        // 1. 将页面提交的密码password进行md5加密处理, 得到加密后的字符串
        String password = employee.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        // 2. 根据页面提交的用户名username查询数据库中员工数据信息
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();

        // Employee::getUsername 查询SQL表里面的用户名
        // employee.getUsername() 获取JavaBean的用户名
        // eq()表示查询符合条件的数据
        queryWrapper.eq(Employee::getUsername,employee.getUsername());
        Employee emp = employeeMapper.selectOne(queryWrapper);

        // 3. 如果没有查询到, 则返回登录失败结果 || 密码比对,如果不一致, 则返回登录失败结果
        if(emp == null || !emp.getPassword().equals(password)){
            return R.error("登入失败");
        }

        // 4. 查看员工状态,如果为已禁用状态,则返回员工已禁用结果
        if(emp.getStatus() == 0) {
            return R.error("账号已禁用");
        }

        // 6. 登录成功,将员工id存入Session, 并返回登录成功结果
        request.getSession().setAttribute("employee",emp.getId());
        return R.success(emp);
    }
    
}

 但是这里面有几个点需要注意一下!

queryWrapper.eq(Employee::getUsername,employee.getUsername());

Employee::getUsername :用于获取对象属性名,即获取到的值就是employee类的 “username”属性名。

eq():第一个参数为表列名,第二个为你的条件

后台退出功能 

需求分析

1. 退出页面展示 

2. 前端页面分析 ​​​​​​​

代码开发

在登入功能里面有一些公用的类已经写了,这里有不重复说明了!

1. Controller层

所在的包:​​​​​​​com.harmony.reggie.controller

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

    @Autowired
    private EmployeeService employeeService;

    /**
     * 员工退出
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public R<String> logout(HttpServletRequest request) {
        return employeeService.logout(request);
    }
}

2. service接口 

所在的包:​​​​​​​com.harmony.reggie.service

public interface EmployeeService extends IService<Employee> {

    R<String> logout(HttpServletRequest request);
}

3. service实现类

所在的包:​​​​​​​com.harmony.reggie.service.impl

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Override
    public R<String> logout(HttpServletRequest request) {
        request.getSession().removeAttribute("employee");
        return R.success("退出成功");
    }

}

后台功能存在问题及优化

问题描述

前面我们已经完成了后台系统的员工登录功能开发,但是目前还存在一个问题,如下图所示:

上述这种设计并不合理,我们希望看到的效果应该是,只有登录成功后才可以访问系统中的页面,如果没有登录, 访问系统中的任何界面都直接跳转到登录页面。  

实现思路

A. 获取本次请求的URI

B. 判断本次请求, 是否需要登录, 才可以访问

C. 如果不需要,则直接放行

D. 判断登录状态,如果已登录,则直接放行

E. 如果未登录, 则返回未登录结

代码实现

定义登录校验过滤器

所在的包:​​​​​​​com.harmony.reggie.filter

/**
 * 检查用户是否已经完成登入
 *
 * @WebServlet : 声明一个自定义的 Servlet
 * @WebFilter : 声明一个Servlet 过滤器
 * @WebListener : 声明一个类为 Servlet 监听器
 */
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {

    //路径匹配器,支持通配符
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 1. 获取本次请求的URI
        String requestURL = request.getRequestURI();

        log.info("拦截到的请求: {}", requestURL);

        // 定义可以放行的资源
        String[] urls = new String[]{
                "/employee/login",
                "/employee/logout",
                "/backend/**",
                "/front/**"
        };

        // 2. 判断本次请求, 是否需要登录, 才可以访问
        boolean check = check(urls, requestURL);

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

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

        log.info("用户未登入...");

        // 5. 如果未登录, 则返回未登录结果,通过输出流的方式向客户端响应数据
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
    }

    /**
     * 路径匹配,检查本次请求是否需要放行
     *
     * @param urls
     * @param requestURI
     * @return
     */
    public boolean check(String[] urls, String requestURI) {
        for (String url : urls) {
            // URL匹配
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match) {
                return true;
            }
        }
        return false;
    }
}

给启动类添加注解@ServletComponentScan

只有给启动类添加了这个注解上面配置的过滤器类才会交给Spring容器管理! 

@Slf4j
@SpringBootApplication
@ServletComponentScan
public class ReggieApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReggieApplication.class);
        log.info("项目启动成功...");
    }
}

@ServletComponentScan、@WebServlet、@WebFilter、@WebListener 

本次功能代码实现(免费)

注意是在这个分支里面哦!!!

master是项目的主线,即项目最新的功能点实现情况! 

可以的话请给个免费的star哦~~~谢谢

reggie_v2_BackendLogin

瑞吉外卖: 瑞吉外卖项目完整代码,使用Sprinboot,SSM,MP,MySQL,Redis,Nginx等技术。 - Gitee.comicon-default.png?t=M85Bhttps://gitee.com/Harmony_TL/reggie_take_out/tree/reggie_v2_BackendLogin/

posted @ 2022-09-25 19:02  金鳞踏雨  阅读(67)  评论(0编辑  收藏  举报  来源