细说 Deque 以及用法和注意点
Deque 概述
Deque(双端队列)是 Java 中的一个接口,属于 java.util 包。它继承自 Queue 接口,提供了在双端队列的两端插入和删除元素的能力。这意味着它可以作为栈(后进先出,LIFO)或队列(先进先出,FIFO)使用。
实现
Java 中的 Deque 接口有多种实现,最常见的是 ArrayDeque 和 LinkedList:
ArrayDeque: 使用可调整大小的数组实现的双端队列。它比 LinkedList 更快,用作栈或没有大小限制的队列时更有效。不支持存储 null 元素。
LinkedList: 既是 List 实现又是 Deque 实现。相比于 ArrayDeque,LinkedList 的元素插入和删除操作可能稍慢,但在列表中间插入和删除元素时较快。支持存储 null 元素。
常用方法
添加元素:
addFirst(E e): 在双端队列的前端添加一个元素。
addLast(E e): 在双端队列的末尾添加一个元素。
offerFirst(E e): 在双端队列的前端插入一个元素,返回是否成功。
offerLast(E e): 在双端队列的末尾插入一个元素,返回是否成功。
删除元素:
removeFirst(): 移除并返回双端队列的第一个元素。
removeLast(): 移除并返回双端队列的最后一个元素。
pollFirst(): 移除并返回双端队列的第一个元素,如果队列为空则返回 null。
pollLast(): 移除并返回双端队列的最后一个元素,如果队列为空则返回 null。
检查元素:
getFirst(): 返回双端队列的第一个元素。
getLast(): 返回双端队列的最后一个元素。
peekFirst(): 返回双端队列的第一个元素,如果队列为空则返回 null。
peekLast(): 返回双端队列的最后一个元素,如果队列为空则返回 null。
用法
作为栈使用: 使用 addFirst() 或 push() 添加元素,使用 removeFirst() 或 pop() 删除元素。
作为队列使用: 使用 addLast() 或 offer() 添加元素,使用 removeFirst() 或 poll() 删除元素。
注意点
容量限制: ArrayDeque 有初始化大小,但可以动态扩展。注意大量元素插入时可能导致内存重新分配。
Null 值: ArrayDeque 不允许插入 null 元素。尝试添加或检查 null 元素会抛出 NullPointerException。
线程安全: Deque 实现不是线程安全的。如果在多线程环境中使用,需要外部同步或使用 ConcurrentLinkedDeque。
性能: 使用正确的实现(ArrayDeque vs LinkedList)可以提高性能。一般而言,除非需要列表操作,否则优先考虑 ArrayDeque。
迭代器: Deque 迭代器通常从双端队列的头部开始遍历到尾部。但也可以使用 descendingIterator() 以相反的顺序遍历。
通过理解和遵循这些基本准则,可以更有效地使用 Java 中的 Deque 接口及其实现。
微信多开脚本
自己编写的。
https://wwd.lanzn.com/ike171q91zjc
不过不支持win11系统。win10下自动寻找微信路径,允许输入要打开的个数。
ps: 可能需要关闭所有的微信再执行脚本,如果性能太好响应速度太快,以至于运行脚本只能打开一个的话,建议找个大文件(比如1G以上的视频)从一个地方copy另一个地方,让电脑变卡,然后再运行脚本。
收起阅读 »微信支付开放接口V2,V3版本文档
原网址:https://wechatpay.js.org/openapi/
收起阅读 »docker-compose up 和 docker-compose start 的区别
docker-compose up 和 docker-compose start 是 Docker Compose 中的两个不同命令,它们在功能和用途上有一些关键区别:
docker-compose up
用途:用于创建并启动服务。如果服务的容器还不存在,docker-compose up 会根据 docker-compose.yml 文件中的定义构建容器(如果镜像不存在,还会构建镜像),然后启动一个或多个容器。
行为:默认情况下,docker-compose up 会在前台运行,并显示所有容器的输出日志。如果使用 -d 标志(即 docker-compose up -d),它会在后台运行。
特点:当 docker-compose.yml 文件中的配置发生变化时,docker-compose up 会重新创建容器以匹配最新的配置。这包括服务的镜像、环境变量、端口映射等的更新。
适用场景:主要用于开发环境或者首次部署应用时,以确保容器的配置是最新的。
docker-compose start
用途:用于启动已经存在但被停止的容器。docker-compose start 只作用于通过 docker-compose up 创建但后来被停止的容器。
行为:docker-compose start 不会重建容器,也不会重新创建服务。它仅仅将停止的容器重新启动,保持其原有状态。
特点:它不会应用 docker-compose.yml 文件中的任何更新。如果自容器停止以来服务定义已经改变,这些变化不会被应用。
适用场景:主要用于临时停止后重新启动服务,适用于不需要更新配置和镜像的场景。
总结来说,docker-compose up 主要用于首次启动服务或者在服务配置变更后重新启动服务,它会根据 docker-compose.yml 文件创建和启动容器。而 docker-compose start 用于将已经存在但被停止的容器重新启动,不会重新创建或修改容器。
Spring安全认证
任何安全框架的核心目标之一是验证调用者的声明,调用者就是他们声称的身份。身份验证是验证凭据和调用者声明的过程。在这篇文章中,我们将了解Spring Security认证架构的核心及其各个组件。
让我们看一下安全身份验证过程中涉及的类和过滤器的顶级工作流程。
Spring Security附带了一组安全过滤器。对服务器的每个请求都会被这些过滤器拦截。这些过滤器将根据逻辑处理请求,并通过或拒绝传入的请求,让我们看看身份验证过程的不同步骤。
1. 传入 HTTP 请求
每个传入请求都将经过一系列过滤器以进行身份验证和授权过程。看上图中的步骤1,每个请求都经过安全过滤器链。请记住以下几点。
每个请求都会通过过滤器,直到到达相关的身份验证过滤器。
每个请求都可以通过一组不同的安全过滤器。我们可以通过请求模式甚至基于请求标头来配置过滤器。
在上图中,登录请求经过过滤器链并到达UsernamePasswordAuthenticationFilter.
类似地,基本身份验证请求会经过过滤器链,直到到达BasicAuthenticationFilter。
2.基于用户凭证的AuthenticationToken
对于用户登录,一旦身份验证请求到达身份验证过滤器,它将从请求负载中提取用户名和密码。Spring security 将根据用户名和密码创建一个 Authentication 对象。这是身份验证对象创建的样子:
UsernamePasswordAuthenticationToken authentication
= new UsernamePasswordAuthenticationToken(username, password);
3. 认证管理器
身份验证管理器是Spring 安全身份验证过程的核心。是定义Spring Security 的 FiltersAuthenticationManager如何执行身份验证的 API 。
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication) throwsAuthenticationException;}
在我们继续之前,让我们先介绍一下 AuthenticationManager 的要点。
在内部,他们AuthenticationProvider 负责执行身份验证过程。
ProviderManagermanager 是最常用的实现AuthenticationProvider.
ProviderManager将请求委托给列表AuthenticationProvider(我们将在本系列中详细讨论这一点)。
4. 身份验证提供者
它们AuthenticationProvider负责处理请求并执行特定的身份验证。它提供了一种获取用户详细信息的机制,我们可以用它来执行身份验证。界面如下所示AuthenticationProvider:
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
boolean supports(Class<?> authentication);
}
我们AuthenticationProvider不能直接执行,但我们可以使用AuthenticationProvider.
如果您好奇,这里是一些 OOTB 身份验证提供商的列表。
DaoAuthenticationProvider。
JAAS认证
开放身份验证
X509认证
SAML 2.0
OAuth 2.0
记住我身份验证提供者
Ldap身份验证提供者
5. 自定义身份验证提供程序
对于企业应用程序,我们可能需要一个自定义的身份验证提供程序。实现AuthenticationProvider接口来为您的应用程序创建自定义身份验证提供程序。
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
String username = authentication.getName();
String pwd = authentication.getCredentials().toString();
if ("javadevjournal".equals(username) && "pass".equals(pwd)) {
return new UsernamePasswordAuthenticationToken(username, password, Collections.emptyList());
} else {
throw new BadCredentialsException("User authentication failed!!!!");
}
}
@Override
public boolean supports(Class<?>auth) {
return auth.equals(UsernamePasswordAuthenticationToken.class);
}
}
最后一步是使用 Spring security 配置我们的自定义身份验证提供程序。我们通过创建自定义配置类并扩展WebSecurityConfigurerAdapter.
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
CustomAuthenticationProvider customAuthenticationProvider;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//configuring our custom auth provider
auth.authenticationProvider(customAuthProvider);
}
}
6. Spring Security 用户详细信息服务
并非全部(但很少有)身份验证提供程序可能需要UserDetailsService通过用户名(例如 )获取存储在数据库中的用户详细信息DaoAuthenticationProvider。大多数标准 Web 应用程序可能会UserDetailsService在登录过程中使用 来获取用户信息。界面如下UserDetailsService所示:
package org.springframework.security.core.userdetails;
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
为我们的应用程序定义自定义 UserDetailsService是一个常见的用例。
7. 认证和认证异常
在身份验证过程中,如果用户身份验证成功,我们将发送回一个完全初始化的 Authentication 对象。对于失败的身份验证,AuthenticationException将被抛出。完全填充的身份验证对象包含以下详细信息:
用户凭据。
授予权限列表(用于授权)。
认证标志。
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
8. 设置身份验证SecurityContext
成功身份验证的最后一步是在SecurityContext. 它包裹SecurityContext着SecurityContextHolder. 请记住以下几点:
这SecurityContextHolder是 Spring Security 存储有关经过身份验证的用户的详细信息的位置。
Spring security 不会验证如何 SecurityContextHolder填充。
如果它在 中找到值 SecurityContextHolder,则假定当前用户是经过身份验证的用户。
SecurityContextHolder这就是填充的方式
SecurityContext context = //get the context from security holder
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
概括
在这篇文章中,我们看到了Spring Security的架构 和认证流程。我们还详细了解了spring security 的身份验证架构。总而言之,我们涵盖了以下内容。本文的源代码可在GitHub上获取。
spring security认证的整体架构是怎样的?
身份验证过滤器如何协同工作。
身份验证管理器的目的是什么?
身份验证提供商概述。
重要的是SecurityContextHolder
spring security中 UsernamePasswordAuthenticationToken 内部处理的详细步骤。
在Spring Security框架中,UsernamePasswordAuthenticationToken
的处理涉及以下步骤:
接收HTTP请求:每个来自客户端的请求通过一系列的过滤器链进行验证和授权处理。对于登录请求,它会经过多个安全过滤器,直到到达
UsernamePasswordAuthenticationFilter
。基于用户凭证生成AuthenticationToken:一旦登录请求到达认证过滤器,它会从请求中提取用户名和密码,然后创建一个基于这些信息的
Authentication
对象,即UsernamePasswordAuthenticationToken
。AuthenticationManager:是Spring Security认证过程的核心,定义了Spring Security的过滤器如何执行认证。
AuthenticationManager
有多个实现,但最常用的是ProviderManager
,它会将认证请求委托给一系列的AuthenticationProvider
。AuthenticationProviders:这些是具体执行认证过程的组件。它们负责处理请求并执行特定的认证。
AuthenticationProvider
可以有多种实现,例如DaoAuthenticationProvider
、LdapAuthenticationProvider
等,以支持不同类型的认证机制。自定义AuthenticationProvider:在需要特定认证逻辑的情况下,可以通过实现
AuthenticationProvider
接口来创建自定义的认证提供者。然后,需要在Spring Security配置中注册这个自定义的认证提供者。UserDetailsService:某些认证提供者可能需要使用
UserDetailsService
来从数据库中按用户名检索用户详细信息。这通常用于标准Web应用程序中,以在登录过程中获取用户信息。认证和异常处理:如果用户成功通过认证,系统将返回一个完全初始化的
Authentication
对象;如果认证失败,将抛出AuthenticationException
。成功的认证对象将包含用户凭证、授权权限列表和认证状态。在SecurityContext中设置认证信息:认证成功后,最后一步是在
SecurityContext
中设置认证对象,这是通过SecurityContextHolder
来完成的。Spring Security不会验证如何填充SecurityContextHolder
;如果它发现SecurityContextHolder
中有值,它会假设当前用户是经过认证的
AI在线小助手
1. 我们的网站:
网址是 www.xcat.cn。支持手机微信内打开,或者公众号下方菜单打开,或者电脑浏览器打开,建议电脑浏览器里用。
以下操作都是在公众号【我的AI智能助手】里完成
2. 第一次使用:
在公众号【我的AI智能助手
】菜单里的【菜单
】->【打赏
】,打赏成功即可打开上述网站使用。
3. 关于续费:
1. 续费操作是在在公众号【我的AI智能助手
】菜单里的【菜单
】->【打赏
】,打赏成功即可续费。
2. 我们的使用是按月冲的,没啥年费会员啥的,如果你中途不需要使用,到期后可以停着,下次需要使用的时候继续续费即可。
比如你1月用过,2,3,4月都用不到,5月的时候又需要了,那5月充值就会从充值的那天开始算。
网站目前有GPT3.5
、GPT4.0
,文件上传提问
以及其他一些功能,进去可以看到。