当前位置: 首页 > news >正文

Spring Security系列之Handler

概述

与Spring、Spring MVC、Spring Boot一样,Spring Security里也有很多Handler接口、可以分为两大类,一类是普通的XxxHandler(见名知意),另一类是对应的ServerXxxHandler(RequestRejectedHandler除外)。

以AuthenticationSuccessHandler为例,Spring Security中用于处理认证成功事件的接口。通常与基于Servlet API的应用程序一起使用,如Spring MVC应用程序。当用户成功认证后,接口的实现类负责处理接下来的操作,如重定向到其他页面、生成认证成功的日志等。主要实现类是SavedRequestAwareAuthenticationSuccessHandler,它会将用户重定向到之前被拦截的原始请求地址。

而对应的ServerAuthenticationSuccessHandler,在Spring Security 5引入的新接口,用于处理WebFlux中的认证成功事件。WebFlux是Spring Framework 5中引入的反应式编程模型,用于构建响应式的、非阻塞的、事件驱动的应用程序。该接口的实现类负责发送响应给客户端,例如返回 JSON 格式的认证成功消息。

Spring Security里定义的Handler接口具体如下:

  • AuthenticationSuccessHandler
  • AuthenticationFailureHandler
  • LogoutHandler
  • LogoutSuccessHandler
  • AccessDeniedHandler
  • CsrfTokenRequestHandler
  • RequestRejectedHandler
  • ServerAuthenticationSuccessHandler
  • ServerAuthenticationFailureHandler
  • ServerLogoutHandler
  • ServerLogoutSuccessHandler
  • ServerAccessDeniedHandler
  • ServerCsrfTokenRequestHandler

AuthenticationSuccessHandler

AuthenticationSuccessHandler接口用来设置验证成功后的处理动作,源码如下:

public interface AuthenticationSuccessHandler {default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {this.onAuthenticationSuccess(request, response, authentication);chain.doFilter(request, response);}void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException;
}

有两个同名onAuthenticationSuccess方法:default方法,用于处理特定的认证请求AuthenticationFilter;非default方法,则用来处理登录成功的具体事项。目前有3个实现类:

  • ForwardAuthenticationSuccessHandler:实现服务端跳转
  • SimpleUrlAuthenticationSuccessHandler:同时继承AbstractAuthenticationTargetUrlRequestHandler,通过其中的handle方法实现请求重定向
  • SavedRequestAwareAuthenticationSuccessHandler:继承自SimpleUrlAuthenticationSuccessHandler,在其基础上增加请求缓存的功能,可以记录之前请求的地址,进而在登录成功后重定向到一开始访问的地址。

在这里插入图片描述
开发者也可以配置自己的SavedRequestAwareAuthenticationSuccessHandler,方法如下:

SavedRequestAwareAuthenticationSuccessHandler successHandler() {SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler;handler.setDefaultTargetUrl("/index");handler.setTargetUrlParameter("target");return handler;
}

ForwardAuthenticationSuccessHandler的onAuthenticationSuccess方法就一行:request.getRequestDispatcher(this.forwardUrl).forward(request, response);,即调用getRequestDispatcher方法进行服务端转发

AuthenticationFailureHandler

AuthenticationFailureHandler接口,用来设置用户验证失败后的处理动作,源码如下:

public interface AuthenticationFailureHandler {void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException;
}

实现类有:

  • SimpleUrlAuthenticationFailureHandler:默认,如果指定failureUrl,则跳转到该URL,未指定则返回401错误代码。也可以通过配置forwardToDestination属性将重定向改为服务器端跳转
  • ForwardAuthenticationFailureHandler:不管报哪种AuthenticationException,总是重定向到指定的URL
  • DelegatingAuthenticationFailureHandler:代理类,可根据不同的AuthenticationException类型,设置不同的Handlers
  • ExceptionMappingAuthenticationFailureHandler:可以根据不同的AuthenticationException类型,设置不同的跳转URL
  • AuthenticationEntryPointFailureHandler:可通过AuthenticationEntryPoint来处理登录异常

类继承图
在这里插入图片描述
DelegatingAuthenticationFailureHandler处理方法handle如下:

// 维护一个map,key是具体的异常类型,value是特定的Handler
private final LinkedHashMap<Class<? extends AuthenticationException>, AuthenticationFailureHandler> handlers;public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {for (Map.Entry<Class<? extends AuthenticationException>, AuthenticationFailureHandler> entry : this.handlers.entrySet()) {Class<? extends AuthenticationException> handlerMappedExceptionClass = entry.getKey();if (handlerMappedExceptionClass.isAssignableFrom(exception.getClass())) {AuthenticationFailureHandler handler = entry.getValue();handler.onAuthenticationFailure(request, response, exception);return;}}this.defaultHandler.onAuthenticationFailure(request, response, exception);
}

值得注意的是,Delegating,代理的意思。此实现类里维护一个Map(此Map集合支持通过构造函数的入参这种方式来实例化Handler类),然后在核心方法里对Map里的key进行遍历,与方法入参里的exception对比,比对成功则加以处理。最后使用默认的Handler加以处理。这种思想,在下面的几个Handler里,几乎都是如此。不同的是Map的key不一样,核心方法名不一样(一般都命名为handle()),对比项不一样(有的是对比request)。不再赘述。

LogoutHandler

LogoutHandler接口,设置logout过程中必须处理动作,logout后的重定向建议使用LogoutSuccessHandler,源码如下:

public interface LogoutHandler {void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication);
}

有如下几个实现类:

  • AbstractRememberMeServices:
  • CompositeLogoutHandler:
  • CookieClearingLogoutHandler:清除Cookie
  • CsrfLogoutHandler:通过CsrfTokenRepository清除CsrfToken
  • HeaderWriterLogoutHandler:
  • LogoutSuccessEventPublishingLogoutHandler:同时实现ApplicationEventPublisherAware,发布一个事件通知
  • OidcBackChannelLogoutHandler:
  • PersistentTokenBasedRememberMeServices
  • SecurityContextLogoutHandler
  • SpringSessionRememberMeServices
  • TokenBasedRememberMeServices

CompositeLogoutHandler接口源码如下:

private final List<LogoutHandler> logoutHandlers;
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {for (LogoutHandler handler : this.logoutHandlers) {handler.logout(request, response, authentication);}
}

分析下来,与Delegating比较类似,不同的是,维护一个List<xxxHandler>,构造函数同样支持传入指定的List<xxxHandler>,然后在具体的handle方法里(此处是logout方法)for循环遍历list,分别使用具体的Handler来一一处理。类似地,下文也有几个CompositeXxxHandler,思想与此非常相似。

LogoutSuccessHandler

LogoutSuccessHandler接口,设置logout完成后需要处理动作,在LogoutHandler后被执行,LogoutHandler完成必要的动作(该过程不应该抛异常),LogoutSuccessHandler定位是处理后续更多的步骤,如重定向等,源码如下:

public interface LogoutSuccessHandler {void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException;
}

有如下几个实现类:

  • SimpleUrlLogoutSuccessHandler:和上面的AuthenticationSuccessHandler非常类似,继承AbstractAuthenticationTargetUrlRequestHandler,通过其中的handle方法实现请求重定向
  • DelegatingLogoutSuccessHandler:
  • HttpStatusReturningLogoutSuccessHandler:设置状态码200
  • ForwardLogoutSuccessHandler:通过构造函数传入的目标URL,即targetUrl参数实现转发。

AccessDeniedHandler

AccessDeniedHandler接口,用来设置访问拒绝后的处理动作,源码如下:

public interface AccessDeniedHandler {void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException;
}

有如下几个实现类:

  • NoOpAccessDeniedHandler:熟悉的NoOp。空实现,不做任何处理
  • AccessDeniedHandlerImpl:设置403错误码,然后转发请求,让下一个Handler来处理
  • DelegatingAccessDeniedHandler:
  • CompositeAccessDeniedHandler:组合模式,for循环遍历各个Handler实现类,依次调用其handle方法进行处理
  • InvalidSessionAccessDeniedHandler:清除缓存
  • ObservationMarkingAccessDeniedHandler:
  • RequestMatcherDelegatingAccessDeniedHandler:代理模式,维护一个map映射集合。根据具体的RequestMatcher匹配对应的Handler实现类,匹配成功则加以处理。最后使用defaultHandler加以处理。
  • OAuth2AccessDeniedHandler:spring-security-oauth2包里面的实现类,同时继承AbstractOAuth2SecurityExceptionHandler类,直接调用父类里的handle方法。

CsrfTokenRequestHandler

CSRF,Cross-Site Request Forgery,跨站请求伪造是一种攻击技术,攻击者利用用户在已登录的状态下发起的请求来执行非法操作。

CsrfTokenRequestHandler是Spring Security种用于处理CSRF攻击的处理程序。具体来说,浏览器向服务器发送请求时,服务器会在响应中返回一个CSRF令牌。在后续的请求中浏览器将该令牌包含在请求中,服务器会验证该令牌的有效性,从而防止CSRF攻击。

函数式接口,源码如下:

@FunctionalInterface
public interface CsrfTokenRequestHandler extends CsrfTokenRequestResolver {void handle(HttpServletRequest request, HttpServletResponse response, Supplier<CsrfToken> csrfToken);default String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {Assert.notNull(request, "request cannot be null");Assert.notNull(csrfToken, "csrfToken cannot be null");String actualToken = request.getHeader(csrfToken.getHeaderName());if (actualToken == null) {actualToken = request.getParameter(csrfToken.getParameterName());}return actualToken;}
}

实现类包括:

  • CsrfTokenRequestAttributeHandler
  • XorCsrfTokenRequestAttributeHandler:执行异或xor运算

RequestRejectedHandler

位于org.springframework.security.web.firewall包路径下,可知与防火墙策略相关,用于处理请求被拒绝的场景。当请求因为安全策略而被拒绝时,其实现类负责向用户发送相应的错误信息或执行其他定制的行为。

源码如下:

public interface RequestRejectedHandler {void handle(HttpServletRequest request, HttpServletResponse response, RequestRejectedException requestRejectedException) throws IOException, ServletException;
}

实现类包括:

  • DefaultRequestRejectedHandler:不做处理,抛出异常
  • HttpStatusRequestRejectedHandler:通过response.sendError(this.httpError);发送错误响应状态码,默认400,支持构造方法传参
  • ObservationMarkingRequestRejectedHandler:
  • CompositeRequestRejectedHandler:组合模式,for循环遍历列表里的所有实现类,一一加以处理。

ObservationMarkingRequestRejectedHandler的handle方法如下:

private final ObservationRegistry registry;public void handle(HttpServletRequest request, HttpServletResponse response, RequestRejectedException exception) throws IOException, ServletException {Observation observation = this.registry.getCurrentObservation();if (observation != null) {observation.error(exception);}
}

有点复杂。

ServerAuthenticationSuccessHandler

与AuthenticationSuccessHandler接口定义几乎一致,不同的是,只有一个非default方法,

HttpServletRequest request, HttpServletResponse response两个参数变成一个参数WebFilterExchange webFilterExchange,返回参数void也变成响应式的Mono<Void>

public interface ServerAuthenticationSuccessHandler {Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication);
}

实现类:

  • DelegatingServerAuthenticationSuccessHandler
  • RedirectServerAuthenticationSuccessHandler
  • WebFilterChainServerAuthenticationSuccessHandler

ServerAuthenticationFailureHandler

同上面的ServerAuthenticationSuccessHandler非常类似。实现类:

  • RedirectServerAuthenticationFailureHandler
  • ServerAuthenticationEntryPointFailureHandler

ServerLogoutHandler

与上面的非常相似,实现类:

  • CsrfServerLogoutHandler
  • DelegatingServerLogoutHandler
  • HeaderWriterServerLogoutHandler
  • OidcBackChannelServerLogoutHandler
  • SecurityContextServerLogoutHandler
  • WebSessionServerLogoutHandler:将WebFilterExchange里保存的WebSession做失效处理:exchange.getExchange().getSession().flatMap(WebSession::invalidate);

ServerLogoutSuccessHandler

源码比较简单,实现类:

  • HttpStatusReturningServerLogoutSuccessHandler
  • RedirectServerLogoutSuccessHandler

ServerAccessDeniedHandler

ServerAccessDeniedHandler接口源码如下:

public interface ServerAccessDeniedHandler {Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied);
}

实现类:

  • HttpStatusServerAccessDeniedHandler
  • ServerWebExchangeDelegatingServerAccessDeniedHandler

ServerCsrfTokenRequestHandler

接口定义如下:

@FunctionalInterface
public interface ServerCsrfTokenRequestHandler extends ServerCsrfTokenRequestResolver {void handle(ServerWebExchange exchange, Mono<CsrfToken> csrfToken);default Mono<String> resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {Assert.notNull(exchange, "exchange cannot be null");Assert.notNull(csrfToken, "csrfToken cannot be null");return exchange.getFormData().flatMap((data) -> {return Mono.justOrEmpty((String)data.getFirst(csrfToken.getParameterName()));}).switchIfEmpty(Mono.justOrEmpty(exchange.getRequest().getHeaders().getFirst(csrfToken.getHeaderName())));}
}

`

参考

相关文章:

Spring Security系列之Handler

概述 与Spring、Spring MVC、Spring Boot一样&#xff0c;Spring Security里也有很多Handler接口、可以分为两大类&#xff0c;一类是普通的XxxHandler&#xff08;见名知意&#xff09;&#xff0c;另一类是对应的ServerXxxHandler&#xff08;RequestRejectedHandler除外&am…...

Thinkphp使用Elasticsearch查询

在Thinkphp中调用ES&#xff0c;如果自己手写json格式的query肯定是很麻烦的。我这里使用的是ONGR ElasticsearchDSL 构建 ES 查询。ongr ElasticsearchDSL 的开源项目地址&#xff1a;GitHub - ongr-io/ElasticsearchDSL: Query DSL library for Elasticsearch。ONGR Elastics…...

开源日志分析平台ELK实战应用

1.开源日志分析平台ELK概述及搭建过程 ELK 是一个开源的日志管理平台,由 Elasticsearch、Logstash 和 Kibana 三个组件组成。这个平台广泛用于实时日志处理和分析。下面简单介绍一下每个组件的作用以及如何搭建一个基本的 ELK 栈。 ELK 组件 Elasticsearch:是一个搜索和分析…...

css基本操作及使用

CSS 的基本简介 什么是 CSS? CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常存储在样式表中 把样式添加到 HTML 4.0 中&#xff0c;是为了解决内容与表现分别的问题 外部样式表可以极大提高工作效率 外部样式表通常存储在 CSS 文件中 …...

SpringBoot+Vue幼儿园管理系统(前后端分离)

技术栈 JavaSpringBootMavenMyBatisMySQLVueElement-UI 系统角色 教师用户管理员 功能截图...

MFC实现子控件focus焦点上下移动父控件ListView和Gridview也跟着向上下移动

项目中要实现mfc功能&#xff0c;然后子控件焦点下移&#xff0c;LIstView和Gridview父控件不会下移&#xff0c;所以就有这个文章。废话不多说直接上代码。 MFCGridView.java import android.content.Context; import android.util.AttributeSet; import android.view.View;…...

几何关系运算处理

1. 判断点在线的左边还是右边 要判断一个坐标点在直线的左侧还是右侧&#xff0c;可以使用向量叉积。具体来说&#xff0c;对于给定的直线和点&#xff0c;我们可以计算点到直线的向量与直线的方向向量的叉积。叉积的符号可以用于判断点的位置关系&#xff1a; 如果叉积为正&…...

http和https分别是什么?区别是什么?

HTTP和HTTPS是两种常见的网络协议&#xff0c;用于在Web上进行数据传输。以下是它们的简要解释和主要区别&#xff1a; HTTP&#xff08;Hypertext Transfer Protocol&#xff09; HTTP是一种应用层协议&#xff0c;用于在Web上传输数据。它是互联网上应用最为广泛的一种网络…...

第一周:计算机网络概述(上)

一、计算机网络基本概念 1、计算机网络通信技术计算机技术 计算机网络就是一种特殊的通信网络&#xff0c;其特殊之处就在于它的信源和信宿就是计算机。 2、什么是计算机网络 在计算机网络中&#xff0c;我们把这些计算机统称为“主机”&#xff08;上图中所有相连的电脑和服…...

谷歌AI搜索变革,中国引擎能跟上步伐?

全文预计1200字左右&#xff0c;预计阅读需要6分钟。 一年前&#xff0c;谷歌宣布人工智能将引领搜索的未来&#xff0c;如今&#xff0c;这一愿景正逐步实现。谷歌已在美国推出并即将全球推广"AI Overviews"&#xff0c;为用户提供由AI生成的搜索结果概览&#xff0…...

【机器学习300问】110、什么是Lasso回归模型?

LASSO回归的全称是Least Absolute Shrinkage and Selection Operator&#xff0c;中文叫“最小绝对收缩和选择算子”&#xff0c;用一个比喻来初步感受一下它的作用&#xff1a; 想象你在整理一个杂乱无章的房间&#xff0c;里面堆满了各种物品&#xff08;代表众多的预测变量&…...

Qt实现麦克风音频输入保存wav文件

一.本文目的 实现在Qt中接收麦克风数据并保存为WAV文件&#xff0c;使用QAudioInput来录音&#xff0c;并使用QFile来保存数据到WAV文件。 开发环境&#xff1a;QT5.12 本文用极简代码实现&#xff0c;核心代码只需不到100行。 完整工程代码文末链接可以直接下载。 二.代码实…...

docker_如何推送镜像到仓库(hub.docker.com)

在执行 docker push 时收到 denied: requested access to the resource is denied 错误通常意味着你没有权限将镜像推送到目标存储库。这可能有几个原因,包括: 未登录 Docker Hub:你还没有登录到 Docker Hub,或者你登录的账户没有权限推送到目标存储库。存储库不存在:目标…...

【Python】认识 Python

一、计算机基础概念 1、什么是计算机 很多老一辈的人&#xff0c;管下面这个叫做计算机。然而&#xff0c;它只是 “计算器”&#xff0c;和计算机是有很大区别的。 现在我们所说的计算机&#xff0c;不光能进行算术运算&#xff0c;还能进行逻辑判断、数据存储、网络通信等…...

Vue根据后端返回的tabList动态渲染组件信息

最近做了一个功能&#xff0c;后端根据配置信息&#xff0c;动态返回一个tabList&#xff0c;其中结构是List<String,Object> tabList; map里面的数据是 label、value 页面需要根据tablist动态渲染组件&#xff08;不同的tab都使用了组件进行了封装&#xff09; 实现效果…...

二轴机器人大米装箱机:技术创新引领智能包装新潮流

在科技日新月异的今天&#xff0c;自动化和智能化已成为各行各业追求高效、精准生产的关键。作为粮食加工行业的重要一环&#xff0c;大米装箱机的技术创新与应用价值日益凸显。其中&#xff0c;二轴机器人大米装箱机以其高效、稳定、智能的特点&#xff0c;成为市场的新宠。星…...

rtl8723DU移植 android4.4 4418 (第二部分蓝牙部分)

使用的代码&#xff1a; HMI &#xff08;8723bu&#xff09;源码 567_RTL8723DU_WiFi_linux_v5.6.5.3_35502_COEX20181130-2e2e.20191025.zip 由于之前写的所有笔记没有保存&#xff0c;这里只能是部分。 0、 前置知识 1 、kernel 的移植 2、hardwire的移植 将 驱动中的 h…...

【Vue】组件的存放目录问题

注意&#xff1a; .vue文件 本质无区别 组件分类 .vue文件分为2类&#xff0c;都是 .vue文件&#xff08;本质无区别&#xff09; 页面组件 &#xff08;配置路由规则时使用的组件&#xff09;复用组件&#xff08;多个组件中都使用到的组件&#xff09; 存放目录 分类开来的…...

开发PlugLink插件:自动生成并发布博客文章

开发PlugLink插件&#xff1a;自动生成并发布博客文章 引言 博客已经成为个人和企业分享信息、推广产品的重要工具。然而&#xff0c;手动运营博客不仅耗时&#xff0c;而且容易出错。本文将介绍如何利用PlugLink开发一个全自动博客运营程序&#xff0c;通过API链接大模型&am…...

Ant Design Pro

一&#xff1a;Ant Design pro是什么&#xff1a; Ant Design Pro 是基于 Ant Design 和 umi 的封装的一整套企业级中后台前端/设计解决方案&#xff0c;致力于在设计规范和基础组件的基础上&#xff0c;继续向上构建&#xff0c;提炼出典型模板/业务组件/配套设计资源&#x…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...