增删改查基础项目总结

    上篇中主要负责后端部分完成了一个简单的学习辅助系统部分界面,主要针对增删改查进行了练习,过程中遇到了一些细节上的问题以及当时做的时候去查阅的一些之前没有太注意到的额外知识,所以还需要进行进一步梳理,像登录校验的方法以及cookie、session、jwt的区别和联系以及Filter和Interceptor区别和使用方式等。(学习辅助系统)

目录

1.环境搭建

2.登陆校验(重要)

2.1 会话技术

①cookie

②session

③令牌技术

3.过滤器Filter

4.拦截器 Interceptor


1.环境搭建

一个简单的单体架构项目,对于后端部分来说,首先需要进行环境搭建,准备好数据库表,然后创建springboot工程,引入相应的起步依赖,然后在配置文件中引入相应的配置信息(mybatis mysql等)。前端、后端、数据库整体关系如下图所示:

在yml配置文件中有一些需要注意的地方,很容易出现错误,如下图所示:

这里简单介绍一下@Value和@ConfigurationProperties注解的区别:

@ConfigurationProperties注解可以批量注入配置文件中的属性,支持松散绑定(松散语法),不支持SpEL,支持JSR303数据校验和复杂类型封装。

@Value注解需要一个个指定,支持三种取值方式,分别是 字面量、${key}从环境变量、配置文件中获取值以及 #{SpEL},不支持松散绑定(松散语法)、JSR303数据校验和复杂类型封装,支持SpEL。

松散语法的意思就是一个属性在配置文件中可以有多个属性名。

SpEL 使用 #{…} 作为定界符 , 所有在大括号中的字符都将被认为是 SpEL , SpEL 为 bean 的属性进行动态赋值提供了便利。

复杂类型封装指的是,在对象以及 map (如学生类中的老师类以及 scores map)等属性中,用 @Value 取是取不到值

2.登陆校验(重要)

首先用户登录之后会存一个登陆标记,然后在每一次发送请求之后会进行统一拦截,取出登陆标记,如果可以取出的话说明用户已经登陆了,所以可以直接放行,对于没有标记的需要进行拦截,无法跳转到对应界面。

登录校验的四种方法:

下面两种是用于跟踪:1、会话技术2、JWT令牌

下面两个是用于拦截校验的,可以进行Jwt令牌校验:3、过滤器Filter 4、拦截器Interceptor

2.1 会话技术

下面的请求1,2,3是同一个浏览器发出的,所以是同一个会话,可以进行共享数据;但是采用http协议时,该协议每次请求都是独立上一个请求和下一个请求没有联系,所以两次请求不知道是否是一个浏览器发出的,该协议效率比较高,但是不好确定是否是同一会话从而进行共享数据,所以要用到会话跟踪方案(会话跟踪是一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一个浏览器,确保同一次会话之间的请求可以共享数据。)

①cookie

Cookie是一段文本数据,在用户完成”身份认证或会话状态更新“后,它会被服务端放在HTTP响应包的Set-Cookie中,并发送给客户端进行保存

会话跟踪:首先客户端发送请求后例如login请求,服务端会设置一个cookie,然后响应数据时会自动连带cookie也发送到客户端,然后客户端会自动保存,然后下次请求的时候会连带这个cookie自动发送给服务端,然后服务端进行检查是否可以检查到cookie相应的值,进而会话跟踪;

cookie的优缺点:

优点:是HTTP协议中支持的技术

缺点:1.移动端APP无法使用cookie 2.cookie存储在客户端,相对来说不安全,并且可以将cookie进行拦截,并且用户可以自己去禁用cookie  3.cookie不能跨域使用

举个例子:浏览器先去访问前端ip为192.168.150.200,端口号为80,此时发送登录请求到服务端ip地址为192.168.150.100,端口号为8080,ip和端口号都不同,说明已经跨域了,此时就不能用cookie了;如下图:

②session

session是基于cookie的,他存储在服务端,相对来说安全一些。

原理:

浏览器第一次请求的时候,服务器里面会进行存储,生成一个sessionID(唯一的),然后通过cookie发送给浏览器。每次访问的浏览器不同的时候,服务器就会进行上面的操作,生成sessionID并且发送给浏览器。当同一个浏览器去访问服务器的时候,由于之前存储过sessionID,因此在登录的时候会把sessionID一起发送给服务器,登录成功之后,就会把身份信息存储到对应的sessionID下面。下次再登录,服务器发现这个sessionID有对应的身份信息,即登录过,就不需要再次登录了。

但是在服务器集群环境下不能直接使用session,后续篇章会介绍点评项目中使用redis代替session解决集群环境下的问题。本身session是基于cookie的,所以一些cookie的缺点也会带过来。

小结:cookie和session都是传统的方案,现在主流的是令牌技术。

③令牌技术

原理:首先浏览器向服务端发送请求,然后此时服务端就会生成一个令牌,然后响应的时候将令牌响应到前端,然后前端会将此令牌存储起来,然后每次发送请求都会将此令牌发送给服务端,然后服务端进行校验,如果令牌是有效的那么就相当于是同一个会话,可以进行共享数据,例如,login请求,然后接着查询请求,先校验令牌成功后说明已经登陆过,无需再登录。

需要自己生成,如何存储,如何携带到服务端需要自己实现。令牌是存储到客户端的,是比较安全的;因为就算篡改了令牌,后面发送请求校验的时候会被检测出来。

JWT令牌:

JWT(Json Web Token)由三个部分组成,第一个部分就是头部,alg是签名算法,type是令牌类型;第二个部分是有效载荷,可以携带自定义的信息;这两个部分都是Json类型的,并且这两部分内容通过Base64编码之后就会用这64个字符来表示内容;第三部分是数字签名,是计算出来的,并不是通过Base64编码得到的,正是有了这个部分保证了安全性。

3.过滤器Filter

 过滤器是javaweb三大组件(Servlet、Filter、Listener)之一,可以把对资源的请求拦截下来,然后进行一些特殊的处理(校验、敏感字符处理等)。

Filter的练习例子:

1.定义Filter:定义一个类,实现Filter接口,然后重写方法

2.配置Filter:Filter类上加@WebFilter注解,配置拦截请求的路径,引导类上加@servletComScan注解开启Servlet组件支持。

整体的逻辑如下图:

Filter路径拦截:在@WebFilter注解中配置

过滤器链:

一个web应用中,可以配置多个过滤器,多个过滤器就构成了过滤器链

注意,注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序。

举个实践的例子:

下面实现了一个简单的登录校验Filter流程:

  1. 首先获取拦截url
  2. 判断url中是否包含login,如果包含,说明是登录请求,此时需要放行。然后服务端生成jwt令牌,然后保存到请求头中。
  3. 获取请求中的令牌(token)
  4. 判断令牌是否存在,如果不存在,返回错误结果 未登录
  5. 如果令牌存在,解析令牌,解析失败返回错误信息。
  6. 放行

具体代码如下:

//过滤器的校验:这个是最先执行的,拦截后的校验,这部分校验后才会执行controller层中的代码;例如,如果是登录请求,此处放行之后才会执行controller层的方法LoginController里面的访问web资源以及生成jwt令牌操作。
@Slf4j
//@WebFilter("/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //在Http协议中使用的是HttpServletRequest,所以要强转一下;
        HttpServletRequest req=(HttpServletRequest) servletRequest;
        HttpServletResponse resp=(HttpServletResponse) servletResponse;
        //1.获取请求url
        String url=req.getRequestURL().toString();
        log.info("请求的url为:"+url);
        //2.判断请求中是否包含login请求,如果包含说明是登录请求,放行;
        if(url.contains("login")){
            log.info("登录请求,放行!");
            filterChain.doFilter(servletRequest,servletResponse);
            return;//就不需要执行后面的部分了;
        }
        //3.获取请求头token中的令牌
        String jwt=req.getHeader("token");
        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if(!StringUtils.hasLength(jwt)){
            log.info("请求头token为空,返回未登录信息!");
//注意,在controller层中有@RestController注解可以将返回的类型转化为json格式,此处并不是controller层并没有这个注解,所以要自己转换,在pom文件中引入一个fastJSON的依赖
            Result error=Result.error("NOT_LOGIN");
            String notLogin= JSONObject.toJSONString(error);//这样返回一个json格式的字符串
            resp.getWriter().write(notLogin);//然后通过resp响应给浏览器
            return;
        }
        //5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//解析失败
            e.printStackTrace();
            log.info("解析失败,返回未登陆的错误信息!");
            Result error=Result.error("NOT_LOGIN");
            String notLogin=JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }
        //6.放行
        log.info("令牌合法,放行!");
        filterChain.doFilter(servletRequest,servletResponse);


    }
}

4.拦截器 Interceptor

拦截器的实现:

首先定义拦截器,实现HandlerInterceptor接口,并重写所有的方法。

然后在配置类中,添加定义的拦截器,并配置拦截路径:

拦截器路径:

实现案例:

//定义一个拦截器,
@Component
@Slf4j
public class LoginCheckInteceptor implements HandlerInterceptor {
    @Override//目标资源方法执行前执行,返回true放行,返回false不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        //1.获取请求url
        String url=req.getRequestURL().toString();
        log.info("请求的url为:"+url);
        //2.判断请求中是否包含login请求,如果包含说明是登录请求,放行;
        if(url.contains("login")){
            log.info("登录请求,放行!");
            return true;
        }
        //3.获取请求头token中的令牌
        String jwt=req.getHeader("token");
        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if(!StringUtils.hasLength(jwt)){
            log.info("请求头token为空,返回未登录信息!");
//注意,在controller层中有@RestController注解可以将返回的类型转化为json格式,此处并不是controller层并没有这个注解,所以要自己转换,在pom文件中引入一个fastJSON的依赖
            Result error=Result.error("NOT_LOGIN");//TODO 后面不能加!,要严格按照接口文档里写的来做,如果notlogin后面加了!就会导致前端呈现出不一样的反应。
            String notLogin= JSONObject.toJSONString(error);//这样返回一个json格式的字符串
            resp.getWriter().write(notLogin);//然后通过resp响应给浏览器
            return false;
        }
        //5.解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//解析失败
            e.printStackTrace();
            log.info("解析失败,返回未登陆的错误信息!");
            Result error=Result.error("NOT_LOGIN");
            String notLogin=JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return false;
        }
        //6.放行
        log.info("令牌合法,放行!");
        return true;
    }
    @Override//目标资源方法执行后执行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }
    @Override//视图渲染完毕后运行,最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterHandle...");
    }
}
//TODO 注册拦截器,将定义好的拦截器添加进去。
@Configuration//表明是一个配置类
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    LoginCheckInteceptor loginCheckInteceptor;

    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(loginCheckInteceptor).addPathPatterns("/**").excludePathPatterns("/login");//此处要注册一个拦截器并且表明拦截的是什么请求,注册的就是刚刚在Logincheckinteceptor中定义好的拦截器,所以前面要进行依赖注入
        //注意此处想要拦截所有请求是/**,过滤器中的是/*,用excludePathPatterns取消拦截指定请求,也就是说直接放行。
    }

}

 注意:如果过滤器和拦截器都存在的话,是这样的执行流程:

Filter过滤器是servlet里面的,拦截范围比较大,interceptor是spring里面的,只有进入spring环境才会进行拦截;在拦截器中,限制性preHandle,如果校验正确,会执行controller层中的方法,访问web资源,然后再执行postHandle和afterCompletion中的方法。执行流程如下图所示:

Filter与Interceptor的区别:

接口规范不同,过滤器实现Filter接口,Interceptor实现的是HandlerInterceptor接口

拦截范围不同:过滤器会拦截所有的资源,拦截器只会拦截spring环境中的资源。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv11融合[ECCV2024]自调制特征聚合SMFA模块及相关改进思路|YOLO改进最简教程

YOLOv11v10v8使用教程: YOLOv11入门到入土使用教程 YOLOv11改进汇总贴:YOLOv11及自研模型更新汇总 《SMFANet: A Lightweight Self-Modulation Feature Aggregation Network for Efficient Image Super-Resolution》 一、 模块介绍 论文链接&#xff1…

【51单片机】I2C总线详解 + AT24C02

学习使用的开发板:STC89C52RC/LE52RC 编程软件:Keil5 烧录软件:stc-isp 开发板实图: 文章目录 AT24C02介绍存储器 I2C总线介绍I2C时序结构数据帧AT24C02数据帧 编程实例 —— 按键控制数据大小&存储器写入读出 AT24C02介绍 …

Kafka 可观测性最佳实践

Kafka 概述 Kafka 是由 LinkedIn 开发一个分布式的基于发布订阅模式的消息队列,是一个实时数据处理系统,可以横向扩展。与 RabbitMQ、RockerMQ 等中间件一样拥有几大特点: 异步处理服务解耦流量削峰 监控 Kafka 是非常重要的,因…

智能制造基础- TPM(全面生产维护)

TPM 前言一、TPM二、TPM实施步骤三、 消除主要问题3.1 实施指南3.2 如何进行“主要问题”的消除? 四、自主维护4.1 实施指南4.2 主要工作内容4.3 如何进行“自主维护“ 五、计划维护5.1 实施指南5.2 如何实施计划维护 六、TPM 适当的 设备 设计5.1 实施指南5.2 如何…

数据库SQLite的使用

SQLite是一个C语言库,实现了一个小型、快速、独立、高可靠性、功能齐全的SQL数据库引擎。SQLite文件格式稳定、跨平台且向后兼容。SQLite源代码属于公共领域(public-domain),任何人都可以免费将其用于任何目的。源码地址:https://github.com/…

openpyxl处理Excel模板,带格式拷贝行和数据填入

本文中用openpyxl操作Excell 模板,进行行拷贝和数据填充. 主要涉及单元格格式的拷贝,合并单元格的拷贝,行高和列宽的处理. 将模板表格分为三部分,头部,中间循环填充部分,尾部.模板参数中设置头部高度,循环部分高度,剩余为尾部. 拷贝时先拷贝填充头部 ,然后根据数据循环拷贝填…

【FPGA开发】AXI-Lite总线协议解读、Verilog逻辑开发与仿真、Alex Forencich代码解读

目录 AXI是什么AXI是如何工作的AXI-Lite定义AXI-Lite的关键特性AXI-Lite信号列表AXI-Lite信号时序时钟和复位握手机制写请求通道(AW)写数据通道(W)写响应通道(B)读请求通道(AR)读数据…

zabbix 7.0 安装(服务器、前端、代理等)

https://www.zabbix.com/download 使用上面的地址,按教程执行命令安装

uniapp—android原生插件开发(2原生插件开发)

本篇文章从实战角度出发,将UniApp集成新大陆PDA设备RFID的全过程分为四部曲,涵盖环境搭建、插件开发、AAR打包、项目引入和功能调试。通过这份教程,轻松应对安卓原生插件开发与打包需求! ***环境问题移步至:uniapp—an…

【DCCMCI】多模态情感分析的层次去噪、表征解纠缠和双通道跨模态-上下文交互

abstract 多模态情感分析旨在从文本、声音和视觉数据等各种模态中提取情感线索,并对其进行操作,以确定数据中固有的情感极性。尽管在多模态情感分析方面取得了重大成就,但在处理模态表征中的噪声特征、消除模态表征之间情感信息的实质性差距…

【网络安全】线程安全分析及List遍历

未经许可,不得转载。 文章目录 线程线程安全问题遍历List的方式方式一方式二方式三方式四(Java 8)方式五(Java 8 Lambda)遍历List的同时操作ListVector是线程安全的?使用线程安全的CopyOnWriteArrayList使用线程安全的List.forEach线程 线程是程序执行的最小单位。一个程…

基于MFC实现的赛车游戏

一、问题描述 游戏背景为一环形车道图,选择菜单选项“开始游戏”则可开始游戏。游戏的任务是使用键盘上的方向键操纵赛道上的蓝色赛车追赶红色赛车,红色赛车沿车道顺时针行驶,出发点和终点均位于车道左上方。任一赛车先达到终点则比赛结束。…

SpringBoot赋能的共享汽车业务管理系统

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示: 图4-1系统工作原理…

「QT」几何数据类 之 QLineF 浮点型直线类

✨博客主页何曾参静谧的博客📌文章专栏「QT」QT5程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

Elasticsearch专栏-4.es基本用法-查询api

es基本用法-查询api 说明查询所有某一字段匹配查询多字段查询bool查询范围查询精确查询正则匹配模糊查询结果处理 说明 es对数据的检索,总结下来就是两部分,即查询和处理。查询指的是查找符合条件的数据,包括查询所有、匹配查询、布尔查询、…

讨论一个mysql事务问题

最近在阅读一篇关于隔离级别的文章,文章中提到了一种场景,我们下面来分析一下。 文章目录 1、实验环境2、两个实验的语句执行顺序3、关于start transaction和start transaction with consistent snapshot4、实验结果解释4.1、实验14.2、实验24.3、调整实…

【AIGC】腾讯云语音识别(ASR)服务在Spring Boot项目中的集成与实践

腾讯云语音识别(ASR)服务在Spring Boot项目中的集成与实践 引言 在现代软件开发中,语音识别技术的应用越来越广泛,从智能助手到自动客服系统,语音识别技术都在发挥着重要作用。腾讯云提供了强大的语音识别服务&#…

基于Spring Boot的工程认证计算机课程管理系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理基于工程教育认证的计算机课程管理平台的相…

2024年度国际荐酒师(香港)协会花式马刀开香槟表演赛在穗举行

2024年度国际荐酒师(香港)协会花式马刀开香槟表演赛在穗举行 近日,一场别开生面的花式马刀开香槟表演赛在广州四季酒店盛大举行,此次活动由国际荐酒师(香港)协会精心指导,广东海上丝绸之路文化促…

mysql全量与增量备份

binlog日志: 从上一次全量备份到下一次全量备份直接产生的数据。 一、全备和增量备份介绍 1、全量备份: 备份所有数据库或只备份一个数据库,全量备份之后,全量备份之前的binlog日志就没用了,一般生产环境会保留3-7天…