使用Spring Security+jwt+redis实现登录注册逻辑

Spring Security

Spring Security 是一个提供身份验证、授权和防御常见攻击的框架。它为保护命令式和响应式应用程序提供了一流的支持,是保护基于 Spring 的应用程序的事实标准。
这篇博客主要是记录自己第一次使用springSecurity实现登录逻辑的过程。

使用Spring Security+jwt+redis实现登录注册逻辑

1. 导入依赖
<!--jwt依赖-->
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
</dependency>
<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
</dependency>
<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
</dependency>
<!--SpringSecurity启动器-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- redis -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 创建JwtUtils工具类
package com.h3m.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;

@Data
@Component
@ConfigurationProperties(prefix = "config.jwt",ignoreInvalidFields = true)
public class JwtUtils {
    private String secret;
    private long expire;
   // private String header;  

    /**
     * 生成token, 根据用户名
     * @param username
     * @return
     */
    public String createToken(String username){
        // 获取当前时间
        Date nowDate = new Date();
        // 过期时间
        Date expireDate = new Date(nowDate.getTime() + expire * 1000);
        // 生成token
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(username)
                .setIssuedAt(nowDate)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();

    }

    /**
     * 获取token中的信息
     * @param token
     * @return
     */
    public Claims getTokenClaim(String token){
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取token中的用户名
     * @param token
     * @return
     */
    public String getUsernameFromToken(String token){
        Claims claims = getTokenClaim(token);
        if(claims == null){
            return null;
        }
        return claims.getSubject();
    }

    /**
     * Validate the token
     * @param token
     * @param userDetails
     * @return 返回true表示有效
     */
    public boolean validateToken(String token, UserDetails userDetails) {
        String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }

    /**
     * Check if the token is expired
     * @param token
     * @return 返回true表示过期
     */
    private boolean isTokenExpired(String token) {
        Date expiration = getTokenClaim(token).getExpiration();
        return expiration.before(new Date());
    }
}

  1. 创建Result结果类
package com.h3m.domain;

import com.h3m.constants.SYSConstant;
import lombok.Data;

@Data
public class Result {
    private Integer code;
    private String message;
    private Object data;

    public Result() {
    }

    public Result(Integer code) {
        this.code = code;
    }

    public Result(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Result(Integer code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    // 创建一些静态常量字段
    public static final Result ADD_SUCCESS = new Result(SYSConstant.CODE_SUCCESS,SYSConstant.ADD_SUCCESS);
    public static final Result ADD_ERROR = new Result(SYSConstant.CODE_ERROR, SYSConstant.ADD_ERROR);

    public static final Result UPDATE_SUCCESS = new Result(SYSConstant.CODE_SUCCESS, SYSConstant.UPDATE_SUCCESS);
    public static final Result UPDATE_ERROR = new Result(SYSConstant.CODE_ERROR, SYSConstant.UPDATE_ERROR);

    public static final Result DELETE_SUCCESS = new Result(SYSConstant.CODE_SUCCESS, SYSConstant.DELETE_SUCCESS);
    public static final Result DELETE_ERROR = new Result(SYSConstant.CODE_ERROR, SYSConstant.DELETE_ERROR);

    public static final Result LOGIN_SUCCESS = new Result(SYSConstant.CODE_SUCCESS, SYSConstant.LOGIN_SUCCESS);
    public static final Result LOGIN_ERROR = new Result(SYSConstant.CODE_ERROR, SYSConstant.LOGIN_ERROR);
}
  1. 创建SecurityUser实体类

​ 我们需要创建一个用于Security的实体类,并实现UserDetails接口

package com.h3m.domain.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SecurityUser implements UserDetails {
    private User CurrentUserInfo;
//    private Collection<? extends GrantedAuthority> authorities;
    private List<Access> accessList;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = accessList.stream()
                .map(access -> new SimpleGrantedAuthority(access.getAccessName()))
                .collect(Collectors.toList());
        return authorities;
    }

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

    @Override
    public String getUsername() {
        return CurrentUserInfo.getUserName();
    }

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

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

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

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

  1. 创建ResponseUtils工具类

​ 这个工具类主要是用于返回数据到前端的。

package com.h3m.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.h3m.domain.Result;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ResponseUtils {
    public static void writeResponse(HttpServletResponse response, Result result) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=UTF-8");
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonResponse = objectMapper.writeValueAsString(result);
        response.getWriter().write(jsonResponse);
    }
}

  1. 创建登录过滤器jwtLoginFilter

​ 这里我们主要是重写三个方法,实现整个登录的过滤。

package com.h3m.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.h3m.constants.SYSConstant;
import com.h3m.domain.Result;
import com.h3m.utils.JwtUtils;
import com.h3m.domain.entity.SecurityUser;
import com.h3m.domain.entity.User;
import com.h3m.utils.ResponseUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;


public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private JwtUtils jwtConfig;
    private AuthenticationManager authenticationManager;
    private RedisTemplate redisTemplate;

    public JwtLoginFilter(AuthenticationManager authenticationManager, JwtUtils jwtConfig, RedisTemplate redisTemplate) {
        this.authenticationManager = authenticationManager;
        this.jwtConfig = jwtConfig;
        this.redisTemplate = redisTemplate;
        super.setFilterProcessesUrl("/login");
    }

    /**
     * 这个方法是在用户登录的时候调用的方法
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //获取表单提供的数据
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            User user = objectMapper.readValue(request.getInputStream(), User.class);
            //校验==认证的过程
            Authentication authenticate = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword()
                            , new ArrayList<>())
            );
            return authenticate;
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("认证失败");
        }
    }

    /**
     * 这个方法是在用户登录成功后调用的方法
     * @param request
     * @param response
     * @param chain
     * @param authResult
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws ServletException, IOException {
        //得到用户名
        SecurityUser securityUser = (SecurityUser) authResult.getPrincipal();
        System.out.println("securityUser = " + securityUser);
        String username = securityUser.getUsername();

        //生成token
        String token = jwtConfig.createToken(username);

        //存入到redis  username: 权限
        redisTemplate.opsForValue().set(username, securityUser.getAuthorities());

        // 返回token
        response.addHeader("Authorization", "Bearer " + token);
        // 登录成功后,封装用户以及对应权限信息返回
        // 返回用户信息
        Result result = new Result(SYSConstant.CODE_SUCCESS, SYSConstant.LOGIN_SUCCESS, securityUser);

        ResponseUtils.writeResponse(response, result);

    }

    /**
     * 这个方法是在用户登录失败后调用的方法
     * @param request
     * @param response
     * @param failed
     * @throws AuthenticationException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws AuthenticationException, ServletException, IOException {
        ResponseUtils.writeResponse(response, new Result(SYSConstant.CODE_ERROR, "登录失败, 主要原因:"+failed.getMessage()));
    }
}

  1. 创建权限过滤器 AuthFilter
package com.h3m.filter;

import com.h3m.utils.JwtUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class AuthFilter extends BasicAuthenticationFilter {

  private JwtUtils jwtConfig;
  private RedisTemplate redisTemplate;

  public AuthFilter(AuthenticationManager authenticationManager, RedisTemplate redisTemplate, JwtUtils jwtConfig) {
    super(authenticationManager);
    this.jwtConfig = jwtConfig;
    this.redisTemplate = redisTemplate;
  }

  /**

  * 这里我们只需要重写过滤方法,在其中实现我们的逻辑即可
    	*
    	*/
      @Override
      protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
    // 从请求头中获取token所在的字段
    String authorizationHeader = request.getHeader("Authorization");

    if (authorizationHeader != null && !authorizationHeader.isEmpty() && authorizationHeader.startsWith("Bearer ")) {
      // 获取token
      String token = authorizationHeader.substring(7);
      // 解析token,获得用户名
      String username = jwtConfig.getUsernameFromToken(token);
      //从redis中获得该用户名对应的权限
      List<String> authList = (List<String>) redisTemplate.opsForValue().get(username);
      //将取出的权限存入到权限上下文中,表示当前token对应的用户具备哪些权限
      Collection<GrantedAuthority> authorities = new ArrayList<>();
      if (authList != null) {
        for (String auth : authList) {
          authorities.add(new SimpleGrantedAuthority(auth));
        }
      }
      // 生成认证信息对象
      UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null, authorities);
      // 把认证信息对象存入到权限上下文中
      SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }
    // 放行
    chain.doFilter(request, response);
      }

}
  1. 创建登出处理器
package com.h3m.handler;

import com.h3m.constants.SYSConstant;
import com.h3m.domain.Result;
import com.h3m.utils.JwtUtils;
import com.h3m.utils.ResponseUtils;
import com.mysql.cj.util.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@RequiredArgsConstructor
@Component
public class TokenLogOutHandler implements LogoutHandler {

    private final JwtUtils jwtConfig;
    private final RedisTemplate redisTemplate;
    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        //1.获取token所在请求头
        String authorizationHeader = request.getHeader("Authorization");
        if (!StringUtils.isNullOrEmpty(authorizationHeader) && authorizationHeader.startsWith("Bearer ")) {
            String token = authorizationHeader.substring(7); // 去掉 "Bearer " 前缀,得到 token
            // 使用 token 进行后续操作
            String username = jwtConfig.getUsernameFromToken(token);
            redisTemplate.delete(username);
        }
        try {
            ResponseUtils.writeResponse(response, new Result(SYSConstant.CODE_SUCCESS, "登出成功"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

  1. 创建UserDetailServiceImpl实现类
package com.h3m.service.ServiceImpl;

import com.h3m.domain.entity.Access;
import com.h3m.domain.entity.SecurityUser;
import com.h3m.domain.entity.User;
import com.h3m.domain.entity.UserRole;
import com.h3m.service.AccessService;
import com.h3m.service.RoleAccessService;
import com.h3m.service.UserRoleService;
import com.h3m.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.PortResolverImpl;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class UserDetailServiceImpl implements UserDetailsService {

    private final UserService userService;
    private final UserRoleService userRoleService;
    private final RoleAccessService roleAccessService;
    private final AccessService accessService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名从数据库查询到该用户的信息
        User user = userService.selectByUsername(username);
        if(Objects.isNull(user)) {
            throw new UsernameNotFoundException("当前用户不存在");
        }
        // 查询用户的权限信息
        // 1. 根据user_id查询用户的角色_id
        UserRole userRole = userRoleService.selectByUserId(user.getId());
        // 2. 根据角色id查询用户的权限_id
        List<BigInteger> AccessIdList = roleAccessService.selectByRoleId(userRole.getRoleId());
        // 3. 根据权限id查询用户的权限信息
        List<Access> accessList = accessService.selectByAccessIdList(AccessIdList);
        // 将权限信息转换为 GrantedAuthority 集合
//        List<GrantedAuthority> authorities = accessList.stream()
//                .map(access -> new SimpleGrantedAuthority(access.getAccessName()))
//                .collect(Collectors.toList());

        // 返回SecurityUser对象
        return new SecurityUser(user, accessList);

    }
}

  1. 创建SpringSecurity配置类
package com.h3m.config;

import com.h3m.filter.AuthFilter;
import com.h3m.filter.JwtLoginFilter;

import com.h3m.handler.TokenLogOutHandler;
import com.h3m.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletResponse;

@Configuration
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtUtils jwtConfig;
    private final TokenLogOutHandler logoutHandler;
    private final RedisTemplate redisTemplate;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
        JwtLoginFilter jwtLoginFilter = new JwtLoginFilter(authenticationManager, jwtConfig, redisTemplate);
        AuthFilter authFilter = new AuthFilter(authenticationManager, redisTemplate, jwtConfig);

        http
                .csrf().disable()
                .authorizeHttpRequests()
                .antMatchers("/login", "/user/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(jwtLoginFilter)  // 登录请求需要经过这个过滤器
                .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)  // 确保 authFilter 在合适的位置
                .logout()
                .logoutUrl("/logout")
                .addLogoutHandler(logoutHandler)
                .logoutSuccessHandler((request, response, authentication) -> response.setStatus(HttpServletResponse.SC_OK));
        return http.build();
    }


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }


}

  1. 编写接口

/login

由于我们在过滤器中已经实现了jwt的生成,以及返回信息,实际上登录接口这里我们不需要实现任何内容。

    /**
     * 登录接口
     * @return
     */
    @PostMapping("/login")
    public void login() {
        // 获取当前登录用户的信息
//        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//        SecurityUser currentUser = (SecurityUser) authentication.getPrincipal();
//        return new Result(SYSConstant.CODE_SUCCESS, SYSConstant.LOGIN_SUCCESS, currentUser);
    }

/register 我们在注册的时候需要对密码进行编码

private final PasswordEncoder passwordEncoder;
    private final UserService userService;
    private final UserRoleService userRoleService;
    @PostMapping("/register")
    public Result register(@RequestBody User user) {
        log.info("用户注册: {}", user);
        // 对密码进行加密
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        // 注册用户, 调用save方法插入一条记录
        boolean flag_1 = userService.save(user);
        // 创建默认用户角色
        UserRole userRole = new UserRole();
        userRole.setUserId(user.getId());
        // 插入一条记录, 虽然这里只传入了一个userId,但是roleId字段有默认值为2,即普通用户
        boolean flag_2 = userRoleService.save(userRole);

        if (flag_1 && flag_2) {
            return new Result(SYSConstant.CODE_SUCCESS, "注册成功");
        } else {
            return new Result(SYSConstant.CODE_ERROR, "注册失败");
        }
    }
    

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

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

相关文章

【D3.js in Action 3 精译_030】3.5 给 D3 条形图加注图表标签(下):Krisztina Szűcs 人物专访 + 3.6 本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…

Hive3.x版本调优总结

文章目录 第 1 章 Explain 查看执行计划&#xff08;重点&#xff09;1.1 创建测试用表1&#xff09;建大表、小表和 JOIN 后表的语句2&#xff09;分别向大表和小表中导入数据 1.2 基本语法1.3 案例实操 第 2 章 Hive 建表优化2.1 分区表2.1.1 分区表基本操作2.1.2 二级分区2.…

WMS系统拣货管理的优化与创新

一、WMS系统拣货管理的重要性 随着电子商务的快速发展&#xff0c;物流仓储行业面临着巨大的挑战。订单量的激增导致传统的手工拣货方式难以满足需求&#xff0c;而WMS系统的引入则解决了这一问题。通过WMS系统&#xff0c;仓库可以实现自动化、智能化的拣货管理&#xff0c;大…

小米路由器R3Gv2安装openwrt记录

前言 小米路由器R3Gv2的硬件配置与小米路由器4A千兆版一致&#xff0c;但bootloader有所不同&#xff0c;因此openwrt的固件不要互刷。另外&#xff0c;R3Gv2和R3G、4A百兆版是不同的设备&#xff0c;切勿混淆。 硬件信息 OpenWrt参数页-Xiaomi MiWiFi 3G v2 CPU&#xff1a…

小猿口算APP脚本(协议版)

小猿口算是一款专注于数学学习的教育应用,主要面向小学阶段的学生。它提供多种数学练习和测试,包括口算、速算、应用题等。通过智能化的题目生成和实时批改功能,帮助学生提高数学计算能力。此外,它还提供详细的学习报告和分析,帮助家长和教师了解学生的学习进度和薄弱环节…

[含文档+PPT+源码等]精品大数据项目-基于python爬虫实现的大数据岗位的挖掘与分析

大数据项目——基于Python爬虫实现的大数据岗位的挖掘与分析&#xff0c;其背景主要源于以下几个方面&#xff1a; 一、大数据时代的来临 随着互联网、物联网、云计算等技术的快速发展&#xff0c;数据呈现出爆炸式增长。根据国际数据公司&#xff08;IDC&#xff09;的预测&…

新电脑 Windows 系统初始配置

文章目录 前言1 前置配置2 安装软件2.1 通讯工具2.2 后端开发工具2.3 硬件开发工具2.4 前端开发工具2.4 其它工具 3 Windows 11 优化4 写在最后 前言 分区&#xff08;个人习惯&#xff09;&#xff1a;1TB SSD 分为 2 个分区&#xff0c;一个 256GB 分区为系统盘&#xff0c;剩…

003 Springboot操作RabbitMQ

Springboot整合RabbitMQ 文章目录 Springboot整合RabbitMQ1.pom依赖2.yml配置3.配置队列、交换机方式一&#xff1a;直接通过配置类配置bean方式二&#xff1a;消息监听通过注解配置 4.编写消息监听发送测试5.其他类型交换机配置1.FanoutExchange2.TopicExchange3.HeadersExcha…

【AIGC】寻找ChatGPT最佳推理步骤:CoT思维链技术的探索与应用

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;CoT思维链概述&#x1f4af;CoT思维链在大型语言模型中的应用&#x1f4af;CoT思维链改变对模型推理能力的理解和改进方式多样化应用场景挑战与未来发展总结 &#x1f4a…

力扣 前缀和

找子数组的个数了解前缀和的基础。 前缀和大致理解为到达某个位置&#xff0c;前面几个数的总和&#xff0c;即s[i1]s[i]a[i1]&#xff0c;可以通过一次循环获得。然后几个前缀和作差&#xff0c;即可得到某个位置到某个位置的和&#xff0c;根据map的键值对进行更新次数。 题…

【JavaEE】——回显服务器的实现

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;引入 1&#xff1a;基本概念 二&#xff1a;UDP socket API使用 1&#xff1a;socke…

高频股票期货ETF历史高频数据源

【数据源】 银河金融数据库&#xff08;yinhedata.com&#xff09; 提供金融数据股票、美股、期货以及ETF等高频tick数据&#xff0c;分钟级别数据。 MACD背离是指MACD指标与价格走势之间发生的方向性差异&#xff0c;这通常被视为市场可能发生趋势反转的信号。以下是一个具体…

petalinux 自动登陆 自动启动程序

PetaLinux 自动登陆 (1) cd 到项目工程目录下&#xff1b; (2) 运行命令&#xff1a;petalinux-config -c rootfs (3) 依次选择 Image Features -> serial-autologin-root 保存退出 创建APP petalinux-create apps --template install --name init-app --enable编辑文件 …

【linux】冯诺依曼架构

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;linux笔记仓 目录 01.冯诺依曼体系结构02.操作系统&#xff08;Operator System&#xff09;如何理解“管理”操作系统中实现“管理的先描述再组织” 03.系统调用与库函数系统调用库函数 01.冯诺依…

Win10 IDEA连接虚拟机中的Hadoop(HDFS)

获取虚拟机的ip 虚拟机终端输入 ip a关闭虚拟机防火墙 sudo ufw disable修改Hadoop的core-site.xml文件 将localhost修改为虚拟机局域网IP # 位置可能不一样&#xff0c;和Hadoop安装位置有关 cd /usr/local/hadoop/etc/hadoop vim core-site.xmlIDEA 连接 创建Maven项目…

【图论】(二)图论基础与路径问题

图论基础与路径问题 图的构造邻接矩阵邻接表 所有可达路径邻接矩阵存储邻接表存储 字符串接龙有向图的完全可达性 图的构造 这里仅对图论路径问题中图的构造做整理总结归纳&#xff0c;具体详细相关概念请参考代码随想录上的整理总结&#xff1a; 图论理论基础深度优先搜索理…

【万字长文】Word2Vec计算详解(一)CBOW模型

【万字长文】Word2Vec计算详解&#xff08;一&#xff09;CBOW模型 写在前面 本文用于记录本人学习NLP过程中&#xff0c;学习Word2Vec部分时的详细过程&#xff0c;本文与本人写的其他文章一样&#xff0c;旨在给出Word2Vec模型中的详细计算过程&#xff0c;包括每个模块的计…

jmeter学习(7)beanshell

beanshell preprocessor 发送请求前执行 beanshell postprocessor 发送请求前执行 获取请求相关信息 String body sampler.getArguments().getArgument(0).getValue(); String url sampler.getPath(); 获取响应报文 String responseprev.getResponseDataAsString(); 获…

论文翻译 | Fairness-guided Few-shot Prompting for LargeLanguage Models

摘要 大型语言模型已经显示出令人惊讶的执行上下文学习的能力&#xff0c;也就是说&#xff0c;这些模型可以通过对由几个输入输出示例构建的提示进行条件反射&#xff0c;直接应用于解决大量下游任务。然而&#xff0c;先前的研究表明&#xff0c;由于训练示例、示例顺序和提示…

熵权法计算评价指标权重——使用Excel VBA实现

[ 熵权法 ] 信息是系统有序程度的一个度量&#xff0c;熵是系统无序程度的一个度量&#xff1b;根据信息熵的定义&#xff0c;对于某项指标&#xff0c;可以用熵值来判断某个指标的离散程度&#xff0c;其信息熵值越小&#xff0c;指标的离散程度越大&#xff0c; 该指标对综合…