Spring Security 安全框架 (一) 基础操作

news2024/10/3 10:38:24

1.password 登录密码

在 springboot 项目中 , 引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

启动时

在这里插入图片描述

1.1.默认密码

启动时 , 控制台可以看到 生成一个UUID 作为 密码

Using generated security password: 876205ea-25bd-47b2-9c68-e2ac52377915

用户名为 user

1.2. 配置文件配置密码

在 application.properties 配置文件 中加入

# 设置 用户名密码
spring.security.user.name=admin
spring.security.user.password=123

1.3.密码生成器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * security 配置文件
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 密码生成器
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        // 无加密密码
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * 设置 用户 密码 及 角色
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("yuan@123")
                .password("123")
                .roles("admin");
    }

}

2.登录页面

 /**
     * 配置忽略掉的 URL 地址,一般对于静态文件
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**","/img/**","/font/**");
    }

    /**
     *  请求属性配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.html")  //转向登录页面
                .loginProcessingUrl("/doLogin")  // 登录请求
                .usernameParameter("username")   // 账号标识
                .passwordParameter("password")   // 密码标识
                //.successForwardUrl("/success")  // 登录成功跳转(内部转, 登录成功跳转到指定请求)
                .defaultSuccessUrl("/success")    // 登录成功跳转(重定向, 登录成功就回到之前访问的资源)
                .failureForwardUrl("/login.html")
                .failureUrl("/login.html")
                .permitAll()
                .and()
                .logout()
                //.logoutUrl("/logout")  // GET方式 调用logout
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "POST"))  // POST 方式调用 logout
                .logoutSuccessUrl("/login.html")  // 退出转向
                .invalidateHttpSession(true)  // 清空session
                .clearAuthentication(true)    // 清空认证信息
                .permitAll()
                .and()
                .csrf().disable();
    }

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String sayHello(){
        return "hello";
    }


    @RequestMapping("/success")
    public String success(){
        return "success";
    }
}

3.返回信息

3.1.登录成功返回

//.successForwardUrl("/success")
                //.defaultSuccessUrl("/success")
                .successHandler((request,response, authentication)->{
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(new ObjectMapper().writeValueAsString(authentication.getPrincipal()));
                    out.flush();
                    out.close();
                })
{
    "password": null,
    "username": "yuan@123",
    "authorities": [
        {
            "authority": "ROLE_admin"
        }
    ],
    "accountNonExpired": true,
    "accountNonLocked": true,
    "credentialsNonExpired": true,
    "enabled": true
}

3.2.登录失败返回

//.failureForwardUrl("/login.html")
                //.failureUrl("/login.html")
                .failureHandler((request,response, exception)->{
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    String msg = "";
                    if (exception instanceof LockedException) {
                        msg = "账户被锁定,请联系管理员!";
                    } else if (exception instanceof CredentialsExpiredException) {
                        msg = "密码过期,请联系管理员!";
                    } else if (exception instanceof AccountExpiredException) {
                        msg = "账户过期,请联系管理员!";
                    } else if (exception instanceof DisabledException) {
                        msg = "账户被禁用,请联系管理员!";
                    } else if (exception instanceof BadCredentialsException) {
                        msg = "用户名或者密码输入错误,请重新输入!";
                    }
                    out.write(new ObjectMapper().writeValueAsString(msg));
                    out.flush();
                    out.close();
                })

3.3.未登录请求

.exceptionHandling()
.authenticationEntryPoint((req, resp, authException) -> {
		resp.setContentType("application/json;charset=utf-8");
		PrintWriter out = resp.getWriter();
		out.write("尚未登录,请先登录");
		out.flush();
		out.close();
	}
)

3.4.登出注销

 .logout()
 .logoutUrl("/logout")
 //.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "POST"))
 //.logoutSuccessUrl("/login.html")
 //.invalidateHttpSession(true)
 //.clearAuthentication(true)
 .logoutSuccessHandler((req, resp, authentication) -> {
 	resp.setContentType("application/json;charset=utf-8");
 	PrintWriter out = resp.getWriter();
	 out.write("注销成功");
 	out.flush();
	 out.close();
 })

4.角色授权

4.1.设置账号

将原来方法注释, 使用新的方法

 ///**
    // * 设置 用户 密码 及 角色
    // * @param auth
    // * @throws Exception
    // */
    //@Override
    //protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //    auth.inMemoryAuthentication()
    //            .withUser("yuan")
    //            .password("123")
    //            .roles("admin");
    //}


    /**
     * pring Security 支持多种数据源,例如内存、数据库、LDAP 等,
     * 这些不同来源的数据被共同封装成了一个 UserDetailService 接口,
     * 任何实现了该接口的对象都可以作为认证数据源。
     * @return
     */
    @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        // 在内存中存储, 创建两个账号 , 分别赋 admin 和  user 权限
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("admin").password("123").roles("admin").build());
        manager.createUser(User.withUsername("yuan").password("123").roles("user").build());
        return manager;
    }

4.2.增加响应方法

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    /**
     * 只要登录就只可以访问
     * @return
     */
    @RequestMapping("/hello")
    public String sayHello(){
        return "hello";
    }

    /**
     * 只有 admin 角色才能访问
     * @return
     */
    @GetMapping("/admin/hello")
    public String admin() {
        return "admin";
    }

    /**
     *  admin,  user 角色都可以访问
     * @return
     */
    @GetMapping("/user/hello")
    public String user() {
        return "user";
    }
}

4.3.设置角色权限

 /**
     *  请求属性配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and()
                ...

将使用 admin 访问 /user/hello 时会报错

{
    "timestamp": "2021-11-05T14:27:39.537+00:00",
    "status": 403,
    "error": "Forbidden",
    "message": "",
    "path": "/user/hello"
}

4.4.角色继承

    /**
     * 角色继承
     * @return
     */
    @Bean
    RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
        hierarchy.setHierarchy("ROLE_admin > ROLE_user");
        return hierarchy;
    }

这样 使用 admin 访问 /user/hello 就可以了

5.访问数据库

5.1.数据库

5.2.实体类

实现 UserDetails 接口 , 覆盖对应的方法


import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import lombok.Data;
import org.apache.ibatis.mapping.FetchType;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * 
 * @TableName sys_user
 */
@TableName(value ="sys_user")
@Data
public class UserEntity implements UserDetails, Serializable {
    /**
     * 
     */
    @TableId(type = IdType.AUTO)
    private Integer userId;

    /**
     * 
     */
    private String userName;

    /**
     * 
     */
    private String userPass;

    /**
     * 
     */
    private String salt;

    /**
     * 
     */
    private String nickName;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;


    // 账户是否没有过期
    @TableField(exist = false)
    private boolean accountNonExpired = true;

    //账户是否没有被锁定
    @TableField(exist = false)
    private boolean accountNonLocked = true;

    //密码是否没有过期
    @TableField(exist = false)
    private boolean credentialsNonExpired = true;

    //账户是否可用
    @TableField(exist = false)
    private boolean enabled = true;

    @TableField(exist = false)
    private List<RoleEntity> roles;

    // 返回用户的角色信息
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (RoleEntity role : getRoles()) {
             // 注意这里的 角色 前缀
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleCode()));
        }
        return authorities;
    }

    @Override
    public String getPassword() {
        return this.userPass;
    }

    @Override
    public String getUsername() {
        return this.userName;
    }

    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

5.3.service 查询


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 *
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity>
implements UserService, UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {

        UserEntity user = this.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUsername, name));
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        user.setRoles(this.getRolesByUserId(user.getUserId()));
        System.out.println("user = " + user);
        return user;
    }

    public List<RoleEntity> getRolesByUserId(Integer userId){
        // 通过 数据库 连表 , 根据 用户id 查询对应的 role 集合
        return this.baseMapper.selectRoleListByUserId(userId);
    }
}

5.4.security配置类

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import java.io.PrintWriter;

/**
 * security 配置类
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private UserServiceImpl userService;

    /**
     * 密码生成器
     * @return
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        // 自带加密器
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    /**
     * 角色继承
     * @return
     */
    @Bean
    RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
        hierarchy.setHierarchy("ROLE_admin > ROLE_user");
        return hierarchy;
    }

    /**
     * 配置忽略掉的 URL 地址,一般对于静态文件
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**","/img/**","/font/**");
    }



    /**
     *  请求属性配置
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/doLogin")
                .successHandler((request,response, authentication)->{
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(new ObjectMapper().writeValueAsString(authentication.getPrincipal()));
                    out.flush();
                    out.close();
                })
                .failureHandler((request,response, exception)->{
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    String msg = "";
                    if (exception instanceof LockedException) {
                        msg = "账户被锁定,请联系管理员!";
                    } else if (exception instanceof CredentialsExpiredException) {
                        msg = "密码过期,请联系管理员!";
                    } else if (exception instanceof AccountExpiredException) {
                        msg = "账户过期,请联系管理员!";
                    } else if (exception instanceof DisabledException) {
                        msg = "账户被禁用,请联系管理员!";
                    } else if (exception instanceof BadCredentialsException) {
                        msg = "用户名或者密码输入错误,请重新输入!";
                    }
                    out.write(new ObjectMapper().writeValueAsString(msg));
                    out.flush();
                    out.close();
                })
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler((req, resp, authentication) -> {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("注销成功");
                    out.flush();
                    out.close();
                })
                .and()
                .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint((req, resp, authException) -> {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        out.write("尚未登录,请先登录");
                        out.flush();
                        out.close();
                    }
                );
    }

}

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

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

相关文章

因特网的组成,边缘之间的通讯方式,数据交换的方式

边缘之间的通讯方式有俩种&#xff1a; 1.客户服务器方式 2.对等方式&#xff08;pear-to-pear&#xff09; 什么是客户端服务器方式&#xff1f; 客户 (client) 和服务器 (server) 都是指通信中所涉及的两个应用进程。 客户-服务器方式所描述的是进程之间服务和被服务的关系…

QT菜单栏,工具栏,状态栏

1. 菜单栏 用代码来实现菜单栏&#xff1a; 头文件&#xff1a;mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H ​ #include <QMainWindow> ​ QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE ​ class MainWindow : public QMai…

如何用JavaScript完美地区分双击和单击事件

通过一个悬浮球交互功能的案例来阐述问题&#xff0c;以及解决办法。 实现效果 类似微信里的悬浮窗效果&#xff0c;苹果手机的悬浮球功能效果 1.可以点击拖动&#xff0c;然后吸附在窗口边缘2.点击悬浮球&#xff0c;可以跳转界面&#xff0c;或者更改悬浮球的形态准备 1.移…

C++ 语法基础课2 —— printf 语句与判断结构

文章目录1. printf 输出格式(#include<cstdio>)1.1 int、float、double、char 等类型的输出格式1.2 所有输出的变量均可包含在一个字符串中1.2.1 练习11.2.2 练习21.3 扩展功能2. if 语句2.1 基本 if-else 语句2.1.1 练习12.1.2 练习22.1.3 练习42.2 常用比较运算符2.3 i…

金融业数字化聚焦容器云,全闪存为什么是点睛之笔?

文|螳螂观察 作者|李永华 刻板、保守、小心翼翼…… 很多人对金融业尤其是银行在数字化创新方面的印象&#xff0c;都是如此。 这个印象到底对不对&#xff1f; 答案可能是&#xff0c;既对&#xff0c;又不对。 对的地方在于&#xff0c;出于合规等要求&#xff0c;一个…

[附源码]计算机毕业设计JAVA点餐系统

[附源码]计算机毕业设计JAVA点餐系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven…

采集平台-大数据平台数据采集系统

随着社会的发展。人们也是越来越离不开互联网&#xff0c;今天小编就给大家盘点一下免费的采集平台&#xff0c;只需要点几下鼠标就能轻松爬取数据&#xff0c;不管是导出excel还是自动发布到网站都支持。详细参考图片一、二、三、四&#xff01; 企业人员 通过爬取动态网页数…

android 静默升级 卸载功能实现

一、近期需要实现一个apk静默升级卸载自启动功能&#xff0c;首先需要获取系统root权限才能执行静默升级&#xff0c;下面不墨迹直接上代码. 首先是MainActivity 页面 package com.example.tiaoshiapkjingmo;import androidx.appcompat.app.AppCompatActivity; import okhttp3.…

如何利用 promise 影响代码的执行顺序?

如何利用 promise 影响代码的执行顺序&#xff1f; 我们写代码的时候&#xff0c;经常会遇到这样的场景。2个不同组件&#xff0c;它们的生命周期本身都是相互独立&#xff0c;毫无关联的&#xff0c;但是它们调用的接口&#xff0c;存在相互依赖的情况。 我举个例子&#xf…

windows中Mysql数据库的安装和卸载

以安装包“mysql-5.7.35-win32.zip”为例&#xff0c;推荐安装5.7最新版本 一、安装 1、根据自己操作系统版本下载32位或64位的安装包&#xff0c;也可去官网下载&#xff0c;建议下载如下图压缩包 将下载的解压包解压&#xff0c;目录结构如下&#xff1a; 2、新建文件“my.…

IC工程师入门必学,Verilog零基础入门教程

近年来&#xff0c;IC行业发展火热&#xff0c;薪资待遇高&#xff0c;发展前景好&#xff0c;所以成了很多人转行的首选。但IC行业入行门槛高&#xff0c;需要具备相关的知识技能。比如工程师必须至少掌握一种HDL语言。 一般在HDL语言中&#xff0c;Verilog相对来说更加易学、…

负载均衡架构设计技巧

负载均衡算法 轮询&随机 基本原理 轮询&#xff1a;将请求依次发给服务器 随机&#xff1a;将请求随机发给服务器 适用场景 通用&#xff0c;无状态的负载均衡 优缺点 实现简单不会判断服务器状态&#xff0c;除非服务器连接丢失 问题场景 某个服务器当前因为触发…

Java面向对象---尚硅谷Java入门视频学习

1.类和对象 1.1创建过程 对象是将内存地址赋值给了变量&#xff0c;所以变量其实引用了内存中的对象&#xff0c;所以称之为引用变量&#xff0c;而变量的类型&#xff08;即类&#xff09;称之为引用数据类型。 堆&#xff08;Heap&#xff09;&#xff0c;此内存区域的唯…

关于pytorch的数据处理-数据加载Dataset

目录 1. 数据加载 2. Dataset __init__ __getitem__ __len__ 测试一下 完整代码 3. Dataset - ImageFolder 1. 数据加载 最近在使用 Unet 做图像分割&#xff0c;设计到 处理数据有关的工作&#xff0c;查了点资料&#xff0c;做一些简单的总结 在pytorch 中&#x…

Thinkphp安装报错解决办法

跟着官方文档的步骤安装thinkphp报错该如何解决&#xff1a; 前言 ThinkPHP无需安装过程&#xff0c;但是需要把ThinkPHP框架放入WEB运行环境&#xff08;前提是你的WEB运行环境没有问题&#xff09;。 一、Thinkphp安装以及报错解决方式 Thinkphp官网&#xff1a;安装ThinkP…

Mysql为何不推荐写多表SQL

前言 在大部分情况下&#xff0c;单表并不是比多表快单表优势在于理解成本与可控性有时候你觉得单表SQL不好写的时候&#xff0c;你改更新的是表结构 现状 在我们学习MySql的路程之中&#xff0c;估计不少人告诫我们不要写长语句。 至于为什么&#xff0c;确实很少人提起。 …

2.6 用一套万能文案公式来拆解4个小红书爆文案例【玩赚小红书】

公式细分人群他们的痛点数字干货分享情感共鸣 我们一个一个来看。 ​ ​ 一、《9平次卧小房间&#xff0c;再见了传统榻榻米&#xff08;附户型图&#xff09;》 家装类&#xff1a;避坑/攻略/小价钱装出大效果/装修效果拔群 标题直接点出了目标人群的需求&#xff1a;如何…

XSS进阶之CSP绕过

目录预备知识实验目的实验环境实验步骤一实验步骤二实验步骤三预备知识 1.了解Javascript、PHP和CSP的一些特性&#xff0c;比如“strict-dynamic”。 2.CSP&#xff1a;实质就是白名单制度&#xff0c;它规定哪些外部资源可以加载和执行。它的实现和执行全部由浏览器完成。资…

python实战指西<1>pygame安装,以及vscode

目录 1&#xff0c;安装pygame 1.1&#xff0c;&#xff08;如果前一个没反应的化&#xff09; 1.2如果飘红字 1&#xff0c;检查是否开了网络代理&#xff08;不要开&#xff09; 2&#xff0c;检查是否有pip模块更新需要 2.这里顺便记录一下vscode 蛇蛇的环境搭载 2.1首…

Postgresql实验系列(4)SIMD提升线性搜索性能24.5%(附带PG SIMD完整用例)

概要 接上一篇《Postgresql引入SIMD指令集》 PG引入SIMD执行集后具体有多大性能提升&#xff1f;本篇抽取PG的simd库&#xff0c;对比线性搜索场景的性能&#xff1a; 测试场景&#xff08;文章最后提供完整程序&#xff09; 构造一个存有14亿数字的数组 uint32 cnt 14100…