瑞吉外卖01-实现管理端登录登出功能

news2024/11/26 15:46:47

开发前准备

准备数据表

结合页面原型创建数据库reggie,可以使用图形化界面或者MySQL命令运行SQL文件导入表结构(使用命令时sql文件不要放在中文目录中)

在这里插入图片描述

创建工程

创建一个SpringBoot的工程(勾选Spring Web,MySQL和MyBatis),配置pom.xml文件导入druid,lombok和MyBatisPlus依赖的坐标

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

配置applicaton.yml文件

server:
  port: 8080
spring:
application:
  # web应用的名称(默认就是工程名)
  name: reggie_take_out
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: 123456
  redis:
    host: localhost
    port: 6379
    database: 0
  cache:
    redis:
      time-to-live: 1800000  #ms ->30min
mybatis-plus:
  configuration:
  	# 在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法开启映射(默认就是true)
    map-underscore-to-camel-case: true
    # 开启日志功能
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: ASSIGN_ID
reggie:
  path: D:\SpringBoot_Reggie\reggie_take_out\src\main\resources\static\front\hello\

创建主程序类并使用@SpringBootApplication注解, 告诉SpringBoot这是一个SpringBoot应用并且是所有程序的启动入口

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

在请求控制器中创建处理请求的方法

@Slf4j
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String handle01(@RequestParam("name") String name){
        log.info("请求进来了....");
        return "Hello, Spring Boot 2!"+"你好:"+name;
    }
}

静态资源映射

Spring Boot工程中引入的静态资源需要放到static或者templates目录下才能访问到

  • 访问resources目录下的静态资源需要编写配置类config/WebMvcConfig配置一下资源映射放行这些资源

打开浏览器访问登录页面(暂无法登录)http://localhost:8080/backend/page/login/login.html

@Configuration
@Slf4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始进行静态资源映射...");
        // 根据用户的请求路径映射到对应的请求资源目录
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
    }
}

统一结果封装

编写一个通用结果类common/Result封装所有Controller的返回结果, 服务器响应给前端的所有数据最终都会包装成此种类型中

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
    private Integer code;  // 编码:1成功,0和其他数字失败
    private String errMsg;  // 错误信息
    private T data; // 数据(如响应的实体类数据)
    private Map map = new HashMap();  // 动态数据

    public static <T> Result<T> success(T data) {
        Result<T> r = new Result<>();
        r.code = 1;  //成功状态码
        r.data = data;
        return r;
    }
 
    public static <T> Result<T> error(String errMsg) {
        Result<T> r = new Result<>();
        r.errMsg = errMsg; //设置错误信息
        r.code = 0;  //默认失败状态码,后期我们可以根据自己的需求来设置其他状态码
        return r;
    }

    public Result<T> add(String msg, String value) {
        this.map.put(msg, value);
        return this;
    }
}

登录和登出功能

前端登录登出效果

在这里插入图片描述

new Vue({
    methods: {
        async handleLogin() {
            // 校验用户名和密码是否为空,validate是element框架提供的校验方法
            this.$refs.loginForm.validate(async (valid) => {
                if (valid) {
                    // 渲染登录的状态,true表示登录中
                    this.loading = true
                    // res是服务端响应的结果(一般是一个通用结果封装类) 
                    let res = await loginApi(this.loginForm)
                    if (String(res.code) === '1') {// 1表示登录成功
                        localStorage.setItem('userInfo',JSON.stringify(res.data))// data表示实体类数据
                        window.location.href= '/backend/index.html'
                    } else {
                        this.$message.error(res.msg)
                        this.loading = false
                    }
                }
            })

            logout() {
                logoutApi().then((res)=>{
                    if(res.code === 1){
                        localStorage.removeItem('userInfo')
                        window.location.href = '/backend/page/login/login.html'
                    }
                })
            },
        }
    }
}) 

<div class="right-menu">
    <!--这里动态的显示登录的用户名-->
    <div class="avatar-wrapper">{{ userInfo.name }}</div>
	<!--这里就是登出的按钮-->
    <img src="images/icons/btn_close@2x.png" class="outLogin" alt="退出" @click="logout" />
</div>

<div class="right-menu">
    // userInfo就是登录成功后后端响应的用户信息
    <div class="avatar-wrapper">{{ userInfo.name }}</div>
	<img src="images/icons/btn_close@2x.png" class="outLogin" alt="退出" @click="logout" />
</div>

function loginApi(data) {
    return $axios({
        'url': '/employee/login',
        'method': 'post',
        data
    })
}

function logoutApi(){
    return $axios({
        'url': '/employee/logout',
        'method': 'post',
    })
}

登录和登出的业务流程

第一步: 创建对应的实体类Employee

@Data
public class Employee implements 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;
    private String idNumber;
    private Integer status;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    // 这两个先不用管,后面再说
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
}

第二步: 创建对应的Mapper和Service

// 直接将Mapper接口动态生成的代理类交给Spring容器管理(不需要再扫描mapper接口)
@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
}
public interface EmployeeService extends IService<Employee> {
}

//继承ServiceImpl实现EmployeeService接口,别忘了@Service注解
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {
}

第三步: 在Controller中编写登录方法

在这里插入图片描述

@RestController
@RequestMapping("/employee")
public class EmployeeController {
    @Autowired
    private EmployeeService employeeService;
    /**
     * 登入功能
     * @param request   
     * @param employee
     * @return
     */
    // 登录页面发送post请求提交用户名和密码
    @PostMapping("/login")
    // 将页面提交的用户名和密码封装到Employee对象中
    public Result<Employee> login(HttpServletRequest request, @RequestBody Employee employee) {
        String password = employee.getPassword();
        // spring内部提供的工具类可以将密码进行MD5加密处理
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        // 根据页面提交的用户名查询数据库
        LambdaQueryWrapper<Employee> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Employee::getUsername, employee.getUsername());
        Employee emp = employeeService.getOne(lqw);
        // 没有查询到员工则返回登录失败的结果
        if (emp == null) {
            return Result.error("登陆失败");
        }
        // 与查询到的员工密码进行比对,如果不一致则返回登录失败的结果
        if (!emp.getPassword().equals(password)) {
            return Result.error("登录失败");
        }
        // 查看查询到员工的状态,如果是已禁用状态,则返回员工已禁用结果
        if (emp.getStatus() == 0) {
            return Result.error("该用户已被禁用");
        }
        // 登录成功,将员工id存入Session并返回登录结果
        request.getSession().setAttribute("employee",emp.getId());
        return Result.success(emp);
    }
} 

第四步: 在Controller中编写退出方法

/**
* 登出功能
* @param request
* @return
*/
@PostMapping("/logout")
public Result<String> logout(HttpServletRequest request) {
    // 清理Session中保存的当前登录员工的id
    request.getSession().removeAttribute("employee");
    // 返回结果
    return Result.success("退出成功");
}

登录状态校验

我们不登录直接访问 http://localhost/backend/index.html也可以正常访问首页显然是不合理的,所以需要用到过滤器或拦截器

过滤器或拦截器中判断用户是否登录,只有登录成功才能看到首页面,未登录状态则跳转到登录页面

在这里插入图片描述

第一步: 设置过滤器,/*表示处理所有请求

@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
    //Spring提供的工具类,专门用于路径匹配
    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 requestURI = request.getRequestURI();
        // 将拦截到的URI输出到日志,{}是占位符将自动填充request.getRequestURI()的内容
        log.info("拦截到请求:{}",requestURI);

        // 定义不需要处理的所有请求
        String[] urls = new String[]{
                "/employee/login",
                "/employee/logout",
            	// 访问backend和front目录下的静态页面的请求不需要拦截,但是页面中通过Ajax请求渲染的数据需要拦截
                "/backend/**",
                "/front/**"
        };
        //2.判断本次请求是否需要处理
        boolean check = check(urls, requestURI);
        //3.如果不需要处理,则直接放行
        if (check) {
            log.info("本次请求:{},不需要处理",requestURI);
            filterChain.doFilter(request,response);
            return;
        }
        //4.对于需要处理的请求,需要判断登录状态,如果已登录则直接放行
        if (request.getSession().getAttribute("employee") != null) {
            log.info("用户已登录,id为{}",request.getSession().getAttribute("employee"));
            filterChain.doFilter(request,response);
            return;
        }
        //5.如果未登录则返回一个Result对象且msg为NOTLOGIN
        log.info("用户未登录");
        // ,
        // 导入fastjson的坐标将Result对象转化为Json格式的字符串,然后通过输出流方式响应给客户端
        response.getWriter().write(JSON.toJSONString(Result.error("NOTLOGIN")));

    }

    public boolean check(String[] urls, String requestURI){
        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match) {
                //匹配
                return true;
            }
        }
        //不匹配
        return false;
    }
}

第二步: 前端设置响应拦截器,获取后端响应的用户信息,如果用户未登录则自动重定向到登录页面

// 响应拦截器
service.interceptors.response.use(res => {
    if (res.data.code === 0 && res.data.msg === 'NOTLOGIN') {// 返回登录页面
        console.log('---/backend/page/login/login.html---')
            localStorage.removeItem('userInfo')
            // 跳转到登录页面
            window.top.location.href = '/backend/page/login/login.html'
    } else {
        return res.data
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1206163.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

本地化工具:Soluling Localization Crack

Soluling 是一个本地化工具&#xff0c;包含本地化项目所需的所有功能。Solling 使本地化变得非常容易。Soluling 是桌面应用程序和命令行工具的组合 。Solling支持100多种文件格式。通过 Soluling&#xff0c;您可以本地化桌面应用程序、移动应用程序、Web 应用程序、文档和在…

【赠书第4期】机器学习与人工智能实战:基于业务场景的工程应用

文章目录 前言 1 机器学习基础知识 2 人工智能基础知识 3 机器学习和人工智能的实战案例 4 总结 5 推荐图书 6 粉丝福利 前言 机器学习与人工智能是当前最热门的领域之一&#xff0c;也是未来发展的方向。随着科技的不断进步&#xff0c;越来越多的企业开始关注和投入机…

C语言精选练习题:(8)使用冒泡排序排序整形数组

每日一言 纵使天光终将熄灭&#xff0c;我们也要歌颂太阳。 --我来到这世上为的是看太阳–巴尔蒙特 题目 输入10个整数&#xff0c;然后使用冒泡排序对数组内容进行升序排序&#xff0c;然后打印出数组的内容 解题思路 创建一个数组用循环将10个整数存到数组中使用冒泡排序打…

Apache Airflow (六) :DAG catchup 参数设置

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

Android自定义控件:一款多特效的智能loadingView

先上效果图&#xff08;如果感兴趣请看后面讲解&#xff09;&#xff1a; 1、登录效果展示 2、关注效果展示 1、【画圆角矩形】 画图首先是onDraw方法&#xff08;我会把圆代码写上&#xff0c;一步一步剖析&#xff09;&#xff1a; 首先在view中定义个属性&#xff1a;priv…

Leetcode刷题详解——黄金矿工

1. 题目链接&#xff1a;1219. 黄金矿工 2. 题目描述&#xff1a; 你要开发一座金矿&#xff0c;地质勘测学家已经探明了这座金矿中的资源分布&#xff0c;并用大小为 m * n 的网格 grid 进行了标注。每个单元格中的整数就表示这一单元格中的黄金数量&#xff1b;如果该单元格…

第 19 章 网络编程

网络可以使不同物理位置上的计算机达到资源共享和通信的目的&#xff0c;在Java中也提供了专门的网络开发程序包--java.net&#xff0c;以方便开发者进行网络程序的开发&#xff0c;本章将讲解TCP与UDP程序开发 19.1 网络编程简介 将地理位置不同的、具有独立功能的多台计算机…

Leetcode-110 平衡二叉树

递归实现 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

优选算法精品解析

1.双指针(前后/左右双指针) 1.1 283.移动零 快排双指针的核心算法 左边所有数 < tmp,右边所有数 > tmp,以tmp这个数为标准 1.2 1089.复习零 如果一对双指针从左向右不行,那么就从右向左,换一个方向 1.3 202.快乐数 双指针中的快慢指针: slow1,fast2 1.4 11.最多盛水的…

如何使用免费的 Vecteezy 旅行视频

网址&#xff1a;https://www.vecteezy.com/ Vecteezy 是一个提供免费和付费矢量图形、模板、视频和其他创意资源的网站。该网站拥有大量旅行视频&#xff0c;可用于各种目的&#xff0c;例如个人使用、商业用途或教育用途。 要下载 Vecteezy 的免费旅行视频&#xff0c;请按…

类和对象(4):Date类.运算符重载 1

一、赋值运算符重载 1.1 运算符重载 运算符重载是具有特殊函数名的函数&#xff0c;函数名字为&#xff1a;关键词operator需要重载的运算符符号。 不能重载C/C中未出现的符号&#xff0c;如&#xff1a;operator。重载操作符必须有一个类类型参数。不能改变用于内置类型运算…

详细推导MOSFET的跨导、小信号模型、输出阻抗、本征增益

目录 前言 什么是跨导 什么是小信号模型 什么是输入阻抗和输出阻抗 什么是MOS管的输出阻抗 什么是MOS管的本征增益 共源极放大电路的输入和输出阻抗 一些其它MOS拓扑电路的增益 负载为恒流源 负载为二极管 前言 相信很多人在学习集成电路领域的时候 都对MOS管的…

HTML设置标签栏的图标

添加此图标最简单的方法无需修改内容&#xff0c;只需按以下步骤操作即可&#xff1a; 1.准备一个 ico 格式的图标 2.将该图标命名为 favicon.ico 3.将图标文件置于index.html同级目录即可 为什么我的没有变化&#xff1f; 答曰&#xff1a;ShiftF5强制刷新一下网页就行了

C#,数值计算——多项式计算,Poly的计算方法与源程序

1 文本格式 using System; using System.Text; namespace Legalsoft.Truffer { /// <summary> /// operations on polynomials /// </summary> public class Poly { /// <summary> /// polynomial c[0]c[1]xc[2]x^2 ..…

西门子精智屏数据记录U盘插拔问题总结

西门子精智屏数据记录U盘插拔问题总结 注意: 数据记录过程中不允许带电插拔 U 盘! 数据记录的相关功能可参考以下链接中的内容: TIA博途wincc V16 如何进行变量周期归档?

Java 之集合框架的详细介绍

文章目录 总的介绍1. **Collection 接口**2. **List 接口**3. **Set 接口**4. **Map 接口**5. **HashMap、LinkedHashMap、TreeMap**6. **Queue 接口**7. **Deque 接口** ArrayList 类1. **创建 ArrayList&#xff1a;**2. **添加元素&#xff1a;**3. **插入元素&#xff1a;*…

centos利用find提权反弹shell

需要说明的是利用find命令进行提权的方式已经不存在了&#xff0c;因为Linux默认不会为find命令授予suid权限&#xff0c;这里只是刻意的制造出了一种存在提权的环境 首先我们先介绍一下find命令&#xff0c;find命令主要用来在Linux中查找文件使用&#xff0c;它可以进行最基础…

Brute Force

Brute Force "Brute Force"&#xff08;暴力破解&#xff09;指的是一种通过尝试所有可能的组合来获取访问、解密或破解信息的攻击方法。这种攻击方法通常是基于暴力和不断尝试的&#xff0c;不依赖漏洞或弱点。通常用于破解密码、破坏系统或获取未经授权的访问权限…

如何在thingsboard的规则链中对一个遥测属性进行求平均值

背景 有这样一个需求,一个温度传感器每5秒,上传一次数据。要求算出该设备2分钟内的平均温度,如果超过某个值,则发送告警邮件。 具体操作实现 下面在规则链中实现求平均值。 使用的节点是 配置如下 必填 Timeseries keys,是要求的平均值的属性名。 我这里求的是四个…

AI大模型低成本快速定制秘诀:RAG和向量数据库

文章目录 1. 前言2. RAG和向量数据库3. 论坛日程4. 购票方式 1. 前言 当今人工智能领域&#xff0c;最受关注的毋庸置疑是大模型。然而&#xff0c;高昂的训练成本、漫长的训练时间等都成为了制约大多数企业入局大模型的关键瓶颈。 这种背景下&#xff0c;向量数据库凭借其独特…