SpringSecurity中文文档(Servlet Authorization Architecture )

Authorization

在确定了用户将如何进行身份验证之后,还需要配置应用程序的授权规则。

Spring Security 中的高级授权功能是其受欢迎的最有说服力的原因之一。无论您选择如何进行身份验证(无论是使用 Spring Security 提供的机制和提供者,还是与容器或其他非 Spring Security 身份验证授权机构集成) ,授权服务都可以在您的应用程序中以一致和简单的方式使用。

您应该考虑附加授权规则来请求 URI 和方法。在这两种情况下,您都可以侦听并响应每个授权检查发布的授权事件。下面还有大量关于 Spring Security 授权如何工作的细节,以及在建立了基本模型之后,如何对其进行微调。

Authorization Architecture

本节描述应用于授权的 SpringSecurity 体系结构。

Authorities

身份验证讨论所有身份验证实现如何存储 GrantedAuthority 对象列表。这些代表授予主体的权限。。GrantedAuthority 对象由 AuthenticationManager 插入到 Authentication 对象中,然后在进行授权决策时由 AccessDecisionManager 实例读取。

GrantedAuthority 接口只有一个方法:

String getAuthority();

AuthorizationManager 实例使用此方法来获取 GrantedAuthority 的精确 String 表示形式。通过返回一个 String 形式的表示,GrantedAuthority 可以被大多数 AuthorizationManager 实现轻松地“读取”。如果 GrantedAuthority 不能精确地表示为 String,那么 GrantedAuthority 被认为是“复杂的”,而 getAuthority ()必须返回 null。

一个复杂的 GrantedAuthority 的示例可能是一个实现,它存储了适用于不同客户账户号码的操作列表和权限阈值。将这种复杂的 GrantedAuthority 表示为一个字符串会相当困难。因此,getAuthority() 方法应该返回 null。这表示任何 AuthorizationManager 需要支持特定的 GrantedAuthority 实现以理解其内容。

Spring Security 包括一个具体的 GrantedAuthority 实现:SimpleGrantedAuthority。这个实现允许任何用户指定的字符串被转换为 GrantedAuthority。安全架构中包含的所有 AuthenticationProvider 实例都使用 SimpleGrantedAuthority 来填充 Authentication 对象。

默认情况下,基于角色的授权规则包括 ROLE_ 作为前缀。这意味着如果有需要安全上下文具有“USER”角色的授权规则,Spring Security 默认会查找返回“ROLE_USER”的 GrantedAuthority#getAuthority。

可以使用 GrantedAuthorityDefauls.GrantedAuthorityDefault 存在来自定义前缀,以便用于基于角色的授权规则。

您可以通过公开 GrantedAuthorityDefault bean 来配置授权规则以使用不同的前缀,如下所示:

Custom MethodSecurityExpressionHandler

@Bean
static GrantedAuthorityDefaults grantedAuthorityDefaults() {return new GrantedAuthorityDefaults("MYPREFIX_");
}

使用静态方法公开 GrantedAuthorityDefault,以确保 Spring 在初始化 Spring Security 的方法 Security@Configuration 类之前发布它

Invocation Handling

SpringSecurity 提供了拦截器来控制对安全对象(如方法调用或 Web 请求)的访问。AuthorizationManager 实例对是否允许继续进行调用作出预调用决策。此外,AuthorizationManager 实例在调用后决定是否可以返回给定的值。

The AuthorizationManager

AuthorizationManager 取代 AccessDecisionManager 和 AccessDecisionVoter。

鼓励自定义 AccessDecisionManager 或 AccessDecisionVoter 的应用程序更改为使用 AuthorizationManager。

AuthorizationManager 由 Spring Security 的基于请求、基于方法和基于消息的授权组件调用,并负责制定最终的访问控制决策。AuthorizationManager 接口包含两个方法:

AuthorizationDecision check(Supplier<Authentication> authentication, Object secureObject);default AuthorizationDecision verify(Supplier<Authentication> authentication, Object secureObject)throws AccessDeniedException {// ...
}

AuthorizationManager 的 check 方法被传递所有它需要的信息,以便做出授权决策。特别是,传递安全 Object 允许检查实际安全对象调用中的所有参数。例如,假设安全对象是一个 MethodInvocation。很容易查询 MethodInvocation 是否有任何 Customer 参数,然后实现一些安全逻辑在 AuthorizationManager 中,以确保主体被允许对该客户进行操作。实现被期望返回一个正值的 AuthorizationDecision,如果访问被授权;负值的 AuthorizationDecision,如果访问被拒绝;以及一个 null AuthorizationDecision,当不作出决定时。

verify 方法调用 check 方法,并在遇到负值的 AuthorizationDecision 时,随后抛出一个 AccessDeniedException。

Delegate-based AuthorizationManager Implementations

虽然用户可以实现自己的 AuthorizationManager 来控制授权的所有方面,但 Spring Security 提供了一个授权 AuthorizationManager,它可以与各个 AuthorizationManager 协作。

RequestMatchergeneratingAuthorizationManager 将使请求与最合适的委托 AuthorizationManager 匹配。

Authorization Manager Implementations 说明了相关的类。

authorizationhierarchy

*Figure 1. Authorization Manager Implementations*

使用这种方法,可以对授权决策轮询 AuthorizationManager 实现的组合。

AuthorityAuthorizationManager

Spring Security提供的最常见的 AuthorizationManager 是 AuthorityAuthorizationManager。它配置了一组给定的权限来查找当前的Authentication。如果身份验证包含任何配置的权限,它将返回正的 AuthorizationDecision。否则它将返回一个否定的授权决策。

AuthenticatedAuthorizationManager

另一个管理器是 AuthenticatedAuthorizationManager。它可以用来区分匿名、完全认证和记住我认证的用户。许多网站允许在记住我认证下进行某些有限的访问,但要求用户通过登录来确认他们的身份,以便获得完全访问权限。

AuthorizationManagers

AuthorizationManager 中还有一些有用的静态工厂,可以将各个 AuthorizationManager 组合成更复杂的表达式。

Custom Authorization Managers

显然,您也可以实现一个自定义的 AuthorizationManager,并且可以在其中放入您想要的几乎任何访问控制逻辑。它可能与您的应用程序(业务逻辑相关)有关,也可能实现一些安全管理逻辑。例如,您可以创建一个实现,它可以查询 Open Policy Agent 或您自己的授权数据库。

您将在 Spring 网站上找到一篇 blog article ,其中描述了如何使用遗留的 AccessDecisionVoter 来拒绝实时访问那些帐户已被暂停的用户。您可以通过实现 AuthorizationManager 来实现相同的结果。

Adapting AccessDecisionManager and AccessDecisionVoters

在 AuthorizationManager 之前,Spring Security 发布了 AccessDecisionManager 和 AccessDecisionVoter。

在某些情况下,比如迁移较旧的应用程序,可能需要引入一个 AuthorizationManager 来调用 AccessDecisionManager 或 AccessDecisionVoter。

要调用现有的 AccessDecisionManager,可以执行以下操作:

Adapting an AccessDecisionManager

@Component
public class AccessDecisionManagerAuthorizationManagerAdapter implements AuthorizationManager {private final AccessDecisionManager accessDecisionManager;private final SecurityMetadataSource securityMetadataSource;@Overridepublic AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {try {Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);this.accessDecisionManager.decide(authentication.get(), object, attributes);return new AuthorizationDecision(true);} catch (AccessDeniedException ex) {return new AuthorizationDecision(false);}}@Overridepublic void verify(Supplier<Authentication> authentication, Object object) {Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);this.accessDecisionManager.decide(authentication.get(), object, attributes);}
}

然后连接到你的安全过滤器链。

或者只调用 AccessDecisionVoter,你可以这样做:

Adapting an AccessDecisionVoter

@Component
public class AccessDecisionVoterAuthorizationManagerAdapter implements AuthorizationManager {private final AccessDecisionVoter accessDecisionVoter;private final SecurityMetadataSource securityMetadataSource;@Overridepublic AuthorizationDecision check(Supplier<Authentication> authentication, Object object) {Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(object);int decision = this.accessDecisionVoter.vote(authentication.get(), object, attributes);switch (decision) {case ACCESS_GRANTED:return new AuthorizationDecision(true);case ACCESS_DENIED:return new AuthorizationDecision(false);}return null;}
}

然后连接到你的安全过滤器链。

Hierarchical Roles

应用程序中的特定角色应该自动“包含”其他角色,这是一个常见的要求。例如,在具有“管理员”和“用户”角色概念的应用程序中,您可能希望管理员能够做普通用户能够做的所有事情。要实现这一点,您可以确保所有管理用户也被分配了“用户”角色。或者,您可以修改每个需要“user”角色的访问约束,使其也包含“admin”角色。如果您的应用程序中有许多不同的角色,这可能会变得相当复杂。

角色层次结构的使用允许您配置哪些角色(或权限)应该包括其他角色。

这支持基于过滤器的授权在 HttpSecurity#authorizeHttpRequests 中,以及通过 DefaultMethodSecurityExpressionHandler 进行基于方法的安全授权,SecuredAuthorizationManager 用于 @Secured,Jsr250AuthorizationManager 用于 JSR-250 注解。您可以以以下方式一次性配置它们的行为:

@Bean
static RoleHierarchy roleHierarchy() {return RoleHierarchyImpl.withDefaultRolePrefix().role("ADMIN").implies("STAFF").role("STAFF").implies("USER").role("USER").implies("GUEST").build();
}// and, if using pre-post method security also add
@Bean
static MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) {DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();expressionHandler.setRoleHierarchy(roleHierarchy);return expressionHandler;
}

在这里,我们有四个角色的层次结构 ROLE_ADMIN ⇒ ROLE_STAFF ⇒ ROLE_USER ⇒ ROLE_GUEST。一个具有 ROLE_ADMIN 认证的用户,在评估任何基于过滤器或方法的安全约束时,将表现得好像他们拥有所有四个角色。

角色层次结构为您的应用程序提供了简化访问控制配置数据的便捷方式,以及减少您需要分配给用户的角色权限的数量。对于更复杂的需求,您可能希望定义一个逻辑映射,将您的应用程序所需的具体访问权限与分配给用户的角色之间进行转换,并在加载用户信息时进行转换。

Legacy Authorization Components

SpringSecurity 包含一些遗留组件。因为它们还没有被删除,所以出于历史目的包含了文档。他们推荐的替代品在上面。

The AccessDecisionManager

AccessDecisionManager 由 AbstractSecurityInterceptor 调用,负责做出最终的访问控制决策。AccessDecisionManager 接口包含三个方法:

void decide(Authentication authentication, Object secureObject,Collection<ConfigAttribute> attrs) throws AccessDeniedException;boolean supports(ConfigAttribute attribute);boolean supports(Class clazz);

AccessDecisionManager 的 decide 方法被传递所有它需要的信息,以便做出授权决策。特别是,传递安全 Object 允许检查实际安全对象调用中的所有参数。例如,假设安全对象是一个 MethodInvocation。您可以查询 MethodInvocation 是否有任何 Customer 参数,然后实现一些安全逻辑在 AccessDecisionManager 中,以确保主体被允许对该客户进行操作。实现被期望如果访问被拒绝则抛出一个 AccessDeniedException。

supports(ConfigAttribute) 方法在启动时被 AbstractSecurityInterceptor 调用,以确定 AccessDecisionManager 是否可以处理传递的 ConfigAttribute。supports(Class) 方法被安全拦截器实现调用,以确保配置的 AccessDecisionManager 支持安全拦截器呈现的安全 Object 的类型。

Voting-Based AccessDecisionManager Implementations

虽然用户可以实现自己的 AccessDecisionManager 来控制授权的所有方面,但 Spring Security 包括几个基于投票的 AccessDecisionManager 实现。投票决策管理器描述了相关的类。

下图显示了 AccessDecisionManager 接口:

access decision voting

*Figure 2. Voting Decision Manager*

通过使用这种方法,对授权决策进行一系列 AccessDecisionVoter 实现轮询。然后,AccessDecisionManager 根据对投票的评估决定是否抛出 AccessDeniedException。

AccessDecisionVoter 接口有三个方法:

int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);boolean supports(ConfigAttribute attribute);boolean supports(Class clazz);

具体实现返回一个整数,可能的值反映在 AccessDecisionVoter 静态字段中,这些字段被命名为 ACCESS_ABSTAIN、ACCESS_DENIED 和 ACCESS_GRANTED。一个投票实现如果对授权决策没有意见,则返回 ACCESS_ABSTAIN。如果它确实有意见,它必须返回 ACCESS_DENIED 或 ACCESS_GRANTED。

Spring Security 提供了三个具体的 AccessDecisionManager 实现,以计算投票。ConsensusBased 实现基于非弃权投票的共识来授予或拒绝访问。提供了属性来控制在投票平局或所有投票都弃权的情况下的行为。AffirmativeBased 实现如果收到一个或多个 ACCESS_GRANTED 投票(换句话说,只要有一个授权投票,就忽略否认投票),则授予访问权限。与 ConsensusBased 实现类似,有一个参数来控制如果所有投票者都弃权的行为。UnanimousBased 实现期望获得一致的 ACCESS_GRANTED 投票,以便授予访问权限,忽略弃权。如果有任何 ACCESS_DENIED 投票,则拒绝访问。与其他实现一样,如果所有投票者都弃权,也有一个参数来控制行为。

您可以实现一个自定义 AccessDecisionManager,它以不同的方式计算选票。例如,来自特定 AccessDecisionVoter 的投票可能获得额外的权重,而来自特定选民的否决投票可能具有否决权效果。

RoleVoter

Spring Security 提供的最常用的 AccessDecisionVoter 是 RoleVoter,它将配置属性视为角色名,如果用户已经分配了该角色,它将投票授予访问权。

如果任何 ConfigAttribute 以 ROLE _ 前缀开头,它将进行表决。如果有一个 GrantedAuthority 返回的 String 表示(来自 getAuthority ()方法)与一个或多个以 ROLE _ 前缀开头的 ConfigAttritribute 完全相等,它将投票授予访问权。如果没有与以 ROLE _ 开头的任何 ConfigAttribute 完全匹配,RoleVoter 将投票拒绝访问。如果没有以 ROLE _ 开头的 ConfigAttribute,则选民弃权。

AuthenticatedVoter

我们隐式看到的另一个选民是 AuthenticatedVoter,它可以用来区分匿名、完全身份验证和 remember-me 身份验证用户。许多站点允许在 remember-me 身份验证下进行某些有限的访问,但是需要用户通过登录进行完全访问来确认他们的身份。

当我们使用 IS _ AUTHENTICATION _ ANONYMOUSLY 属性授予匿名访问权限时,AuthenticatedVoter 正在处理该属性。有关更多信息,请参见 AuthenticatedVoter。

Custom Voters

您还可以实现一个自定义 AccessDecisionVoter,并在其中放入几乎任何您想要的访问控制逻辑。它可能特定于您的应用程序(与业务逻辑相关) ,也可能实现某些安全管理逻辑。例如,在 Spring 网站上,您可以找到一篇博客文章,其中描述了如何使用投票者拒绝实时访问其帐户已被暂停的用户。

after invocation

*Figure 3. After Invocation Implementation*

像 Spring Security 的许多其他部分一样,AfterInvocationManager 有一个具体的实现 AfterInvocationProviderManager,它轮询 AfterInvocationProvider 列表。允许每个 AfterInvocationProvider 修改返回对象或抛出 AccessDeniedException。实际上,多个提供程序可以修改对象,因为前一个提供程序的结果将传递给列表中的下一个提供程序。

请注意,如果您使用 AfterInvocationManager,您仍然需要配置属性,以允许 MethodSecurityInterceptor 的 AccessDecisionManager 允许一个操作。如果您使用 Spring Security 通常包含的 AccessDecisionManager 实现,对于特定安全方法调用的未定义配置属性将导致每个 AccessDecisionVoter 弃权。相应地,如果 AccessDecisionManager 属性“allowIfAllAbstainDecisions”为 false,将抛出一个 AccessDeniedException。您可以通过以下两种方式之一避免这个潜在的问题:(i)将“allowIfAllAbstainDecisions”设置为 true(尽管这通常不推荐),或者(ii)简单地确保至少有一个配置属性,AccessDecisionVoter 将投票授予访问权限。后一种(推荐)方法通常通过配置一个 ROLE_USER 或 ROLE_AUTHENTICATED 属性来实现。

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

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

相关文章

两张图片合并(右上角添加水印,兼容矢量图)保留原来的颜色

无缝合并两张图片&#xff08;封面右上角添加logo&#xff09;-- opencv &#xff1a; 进行添加logo(水印)由于使用了cv2.seamlessClone&#xff0c;cv2.seamlessClone使用了泊松克隆&#xff08;Poisson Cloning&#xff09;&#xff0c;会根据周围的颜色信息进行颜色调整&…

three-tile 一个开源的轻量级三维瓦片库

three-tile 介绍 three-tile 是一个开源的轻量级三维瓦片库&#xff0c;它基于threejs使用typescript开发&#xff0c;提供一个三维地形模型&#xff0c;能轻松给你的应用增加三维瓦片地图。 源码&#xff1a;https://github.com/sxguojf/three-tile 示例&#xff1a;https:/…

【TB作品】51单片机 Proteus仿真 00013红外proteus仿真循迹避障小车

实验报告&#xff1a;智能小车系统设计与实现 一、背景介绍 本实验旨在设计并实现一个基于STC89C52单片机控制的智能小车系统。该系统通过超声波传感器进行避障&#xff0c;通过红外接收器实现远程控制&#xff0c;同时具备循迹功能。整个系统的核心是单片机&#xff0c;它通…

YOLOv10改进 | 损失函数篇 | InnerIoU、InnerSIoU、InnerWIoU、FocusIoU等损失函数

一、本文介绍 本文给大家带来的是YOLOv10最新改进&#xff0c;为大家带来最近新提出的InnerIoU的内容同时用Inner的思想结合SIoU、WIoU、GIoU、DIoU、EIOU、CIoU等损失函数&#xff0c;形成 InnerIoU、InnerSIoU、InnerWIoU、等新版本损失函数&#xff0c;同时还结合了Focus和…

LeetCode42(接雨水)[三种解法:理解动态规划,双指针,单调栈]

接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 这是一道困难题,难度确实有点层次.我们先来朴素思想走一波. 要求能接多少雨水,我们可以具化到每个硅谷,每个硅谷能存多少雨水,那么答案就是每个…

PDA:Prompt-based Distribution Alignment for Unsupervised Domain Adaptation

文章汇总 式中&#xff0c; y s y^s ys表示源域数据的one-hot ground-truth&#xff0c; K K K为类数&#xff0c; w i w_i wi​和 z ~ s \tilde{z}_s z~s​分别表示源域经过提示调优的最终文本表示和最终图像表示的第 i i i类。 同理&#xff0c;为了进一步利用目标领域的数据…

防火墙详解(USG6000V)

0、防火墙组网模式 防火墙能够工作在三种模式下分别是路由模式、透明模式、旁路检测模式、混合模式 0.1、路由模式 路由模式&#xff1a;防火墙全部以第三层对外连接&#xff0c;即接口具有IP 地址。一般都用在防火墙是边界的场景下 防火墙需要的部署/配置&#xff1a; 接…

10、DDD分层架构

微服务架构模型有很多种&#xff0c;例如洋葱架构、CQRS和六边形架构等。虽然这些架构模式提出的时代和背景不同&#xff0c;但其核心理念都是为了设计出“高内聚&#xff0c;低耦合”的微服务&#xff0c;轻松实现微服务的架构演进。DDD分层架构的出现&#xff0c;使微服务的架…

【uniapp-ios】App端与webview端相互通信的方法以及注意事项

前言 在开发中&#xff0c;使用uniapp开发的项目开发效率是极高的&#xff0c;使用一套代码就能够同时在多端上线&#xff0c;像笔者之前写过的使用Flutter端和webview端之间的相互通信方法和问题&#xff0c;这种方式本质上实际上是h5和h5之间的通信&#xff0c;网上有非常多…

物联网实训室建设可行性报告

一、建设物联网实训室的目的和意义 随着信息技术的快速发展&#xff0c;物联网&#xff08;IoT&#xff09;已成为推动社会进步和经济发展的关键技术之一。物联网技术的集成应用&#xff0c;不仅能够提高生产效率&#xff0c;还能促进智慧城市、智能家居、智能农业等多个领域的…

python04——类(基础new)

类其实也是一种封装的思想&#xff0c;类就是把变量、方法等封装在一起&#xff0c;然后可以通过不同的实例化对其进行调用操作。 1.类的定义 class 类名&#xff1a; 变量a def __init__ (self,参数2&#xff0c;参数2...)&#xff1a;初始化函数&#xff01;&#xff01;&…

简单实现联系表单Contact Form自动发送邮件

如何实现简单Contact Form自动邮件功能&#xff1f;怎样简单设置&#xff1f; 联系表单不仅是访客与网站所有者沟通的桥梁&#xff0c;还可以收集潜在客户的信息&#xff0c;从而推动业务的发展。AokSend将介绍如何简单实现一个联系表单&#xff0c;自动发送邮件的过程&#x…

【游戏客户端】大话slg玩法架构(一)滚动基类

【游戏客户端】大话slg玩法架构&#xff08;一&#xff09;滚动基类 大家好&#xff0c;我是Lampard家杰~~ 今天我们兑现诺言&#xff0c;给大家分享SLG玩法的实现j架构&#xff0c;关于SLG玩法的介绍可以参考这篇上一篇文章&#xff1a;【游戏客户端】制作率土之滨Like玩法 PS…

机器学习统计学基础 - 最大似然估计

最大似然估计&#xff08;Maximum Likelihood Estimation, MLE&#xff09;是一种常用的参数估计方法&#xff0c;其基本原理是通过最大化观测数据出现的概率来寻找最优的参数估计值。具体来说&#xff0c;最大似然估计的核心思想是利用已知的样本结果&#xff0c;反推最有可能…

binutils ifunc 流程图

上图是x86 binutils 的流程图。 函数说明_bfd_x86_elf_link_hash_table_createInit local STT_GNU_IFUNC symbol hash.elf_x86_64_check_relocsAdd support for handling STT_GNU_IFUNC symbols_bfd_elf_x86_get_local_sym_hashFind and/or create a hash entry for local sym…

Leetcode—97. 交错字符串【中等】

2024每日刷题&#xff08;140&#xff09; Leetcode—97. 交错字符串 2d动规实现代码 class Solution { public:bool isInterleave(string s1, string s2, string s3) {int m s1.length();int n s2.length();int len s3.length();if(m n ! len) {return false;}vector<…

SpringBoot日常:封装rabbitmq starter组件

文章目录 逻辑实现RabbitExchangeEnumRabbitConfigRabbitModuleInfoRabbitModuleInitializerRabbitPropertiesRabbitProducerManagerPOM.xmlspring.factories 功能测试application.yml配置生产者&#xff1a;消费者&#xff1a;测试结果&#xff1a;总结 本章内容主要介绍编写一…

stm32 USB CDC类虚拟串口初体验

1. 目标 本文介绍CubeMX生成 USB CDC类虚拟串口工程的操作步骤。 2. 配置流程 时钟配置 usb外设需要48M时钟输入 stm32405使用外部时钟源HSE,否则配不出来48M时钟stm32h750内部有一个48M时钟 stm32f405时钟配置 stm32h750时钟配置 Connectivity ->USB_OTG_FS 和 Connect…

C++初阶:从C过渡到C++的入门基础

✨✨所属专栏&#xff1a;C✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ C发展历史 C的起源可以追溯到1979年&#xff0c;当时BjarneStroustrup(本贾尼斯特劳斯特卢普&#xff0c;这个翻译的名字不同的地⽅可能有差异)在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复…

JavaDS —— 顺序表ArrayList

顺序表 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储。在数组上完成数据的增删查改。在物理和逻辑上都是连续的。 模拟实现 下面是我们要自己模拟实现的方法&#xff1a; 首先我们要创建一个顺序表&#xff0c;顺序表…