springcloudalibaba2021-SSO 单点登录_密码模式

本文只讲密码模式,因为入门简单,让大家先跑通。

下一篇:进阶:授权码模式sringcloud授权码模式------单点登录

原因:SSO-springcloud-alibaba 搜了一些,都不完整,现在记录一下自己整理的完整源码,分享出来

解决:

1.项目结构:

一个项目(alibaba_sso),2个模块(<module>auth-server</module> <module>resource-server</module>)。

2.直接放源码:

项目pom(alibaba_sso.pom)

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>
    <groupId>com.dp</groupId>
    <artifactId>alibaba_sso</artifactId>
    <version>1.0.0</version>
    <name>alibaba_sso</name>
    <description>alibaba_sso</description>
    <packaging>pom</packaging>
    <modules>
        <module>auth-server</module>
        <module>resource-server</module>
    </modules>


    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2021.0.9</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.6.0</spring-cloud-alibaba.version>
        <spring-security-oauth2.version>2.5.12</spring-security-oauth2.version>
        <jjwt.version>0.11.5</jjwt.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- Spring Cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Cloud Alibaba -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Security OAuth2 -->
            <dependency>
                <groupId>org.springframework.security.oauth.boot</groupId>
                <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                <version>${spring-security-oauth2.version}</version>
            </dependency>
            <!-- JJWT -->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt-api</artifactId>
                <version>${jjwt.version}</version>
            </dependency>
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt-impl</artifactId>
                <version>${jjwt.version}</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt-jackson</artifactId>
                <version>${jjwt.version}</version>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

auth_server:

pom

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.dp</groupId>
        <artifactId>alibaba_sso</artifactId>
        <version>1.0.0</version>
    </parent>
    <artifactId>auth-server</artifactId>
    <name>auth-server</name>
    <description>auth-server</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- Spring Security OAuth2 -->
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        </dependency>
        <!-- JJWT -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- Nacos Discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
复制代码
AuthServerApplication.java
java 复制代码
package com.dp.authserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient  // 注册到 Nacos
public class AuthServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(AuthServerApplication.class, args);
    }
}
复制代码
AuthServerConfig.java
java 复制代码
package com.dp.authserver.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.configuration.EnableWebSecurity;
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.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

/**
 * 认证服务器配置
 * ============================================
 * 认证方式:OAuth2 密码模式(Password Grant)
 *
 * 流程说明:
 * 1. 客户端使用用户名/密码向 /oauth/token 请求 token
 * 2. 认证服务器验证用户名密码,生成 JWT Token 返回
 * 3. 客户端携带 Token 访问资源服务器
 * ============================================
 */
@Configuration
@EnableWebSecurity
@EnableAuthorizationServer  // 启用 OAuth2 认证服务器
public class AuthServerConfig {

    /**
     * 密码编码器
     * 使用 BCrypt 加密,存储时自动加盐
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 用户认证管理器
     * 负责验证用户名和密码
     */
    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        return http.getSharedObject(AuthenticationManagerBuilder.class)
                .userDetailsService(userDetailsService())
                .passwordEncoder(passwordEncoder())
                .and()
                .build();
    }

    /**
     * 用户详情服务
     * 定义测试用户:admin/123456
     * 密码使用 BCrypt 加密
     */
    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        // 密码: 123456 的 BCrypt 加密结果
        manager.createUser(User.withUsername("admin")
                .password("$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi")
                .roles("USER", "ADMIN")
                .build());
        manager.createUser(User.withUsername("user")
                .password("$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi")
                .roles("USER")
                .build());
        return manager;
    }

    /**
     * JWT Token 存储
     * 使用 JWT 格式存储 Token,无需 Redis
     */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * JWT Token 转换器
     * 配置签名密钥,用于生成和验证 JWT
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        // 签名密钥(生产环境请使用更强的密钥)
        converter.setSigningKey("sso-secret-key-2024");
        return converter;
    }

    /**
     * Spring Security 配置
     * 允许所有用户访问 /oauth/token 端点
     */
    @Configuration
    public static class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .antMatchers("/oauth/token", "/oauth/authorize").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .csrf().disable()
                    .formLogin().disable()
                    .httpBasic();
        }
    }

    /**
     * OAuth2 授权服务器配置
     * 定义客户端信息和 Token 端点
     */
    @Configuration
    public static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

        private final AuthenticationManager authenticationManager;
        private final TokenStore tokenStore;
        private final JwtAccessTokenConverter jwtAccessTokenConverter;

        public AuthorizationServerConfig(
                AuthenticationManager authenticationManager,
                TokenStore tokenStore,
                JwtAccessTokenConverter jwtAccessTokenConverter) {
            this.authenticationManager = authenticationManager;
            this.tokenStore = tokenStore;
            this.jwtAccessTokenConverter = jwtAccessTokenConverter;
        }

        /**
         * 配置客户端信息
         * 定义哪些应用可以访问认证服务器
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            // 使用 BCrypt 编码客户端密码
            PasswordEncoder encoder = new BCryptPasswordEncoder();
            String encodedClientSecret = encoder.encode("gateway-secret");

            clients.inMemory()
                    .withClient("gateway-client")
                    .secret(encodedClientSecret)  // 使用 BCrypt 编码的密码
                    .authorizedGrantTypes(
                            "password",
                            "refresh_token"
                    )
                    .scopes("all", "read", "write")
                    .accessTokenValiditySeconds(3600)
                    .refreshTokenValiditySeconds(86400);
        }
        /**
         * 配置 Token 端点
         * 设置认证管理器和 Token 存储
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
            endpoints
                    .authenticationManager(authenticationManager)  // 密码模式需要
                    .tokenStore(tokenStore)                         // Token 存储
                    .accessTokenConverter(jwtAccessTokenConverter); // JWT 转换器
        }

        /**
         * 配置 Token 端点的安全策略
         * 允许表单认证和客户端认证
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) {
            security
                    .tokenKeyAccess("permitAll()")           // 允许所有访问 /oauth/token_key
                    .checkTokenAccess("isAuthenticated()")   // 检查 Token 需要认证
                    .allowFormAuthenticationForClients();    // 允许表单认证
        }
    }
}

applicaiton.yml

java 复制代码
server:
  port: 9001

spring:
  application:
    name: auth-server

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: public

logging:
  level:
    org.springframework.security: DEBUG
    org.springframework.security.oauth2: DEBUG

resource-server:

pom.xml

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.dp</groupId>
        <artifactId>alibaba_sso</artifactId>
        <version>1.0.0</version>
    </parent>
    <artifactId>resource-server</artifactId>
    <name>resource-server</name>
    <description>resource-server</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring Security OAuth2 Resource Server -->
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        </dependency>
        <!-- JJWT -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- Nacos Discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
复制代码
ResourceServerApplication.java
java 复制代码
package com.dp.resourceserver;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ResourceServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ResourceServerApplication.class, args);
    }
}
复制代码
ResourceServerConfig.java
java 复制代码
package com.dp.resourceserver.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

/**
 * 资源服务器配置
 * ============================================
 * 验证流程:
 * 1. 使用与认证服务器相同的 JWT 签名密钥
 * 2. 验证 Token 签名和有效期
 *
 * 关键:setSigningKey() 用于设置签名密钥(验证时使用)
 * ============================================
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    /**
     * JWT 签名密钥(必须与认证服务器完全一致)
     */
    private static final String JWT_SIGNING_KEY = "sso-secret-key-2024";

    /**
     * Token 存储 - 使用 JWT 格式
     */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * JWT Token 转换器 - 配置签名密钥
     *
     * 注意:使用 setSigningKey() 而不是 setVerificationKey()
     * 在 Spring Security OAuth2 中,JwtAccessTokenConverter 使用 setSigningKey() 同时处理签名和验证
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        // 设置签名密钥(必须与认证服务器相同)
        converter.setSigningKey(JWT_SIGNING_KEY);
        return converter;
    }

    /**
     * Token 服务
     */
    @Bean
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices services = new DefaultTokenServices();
        services.setTokenStore(tokenStore());
        return services;
    }

    /**
     * 配置资源ID
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId("resource-server")
                .stateless(true)
                .tokenServices(tokenServices());
    }

    /**
     * 配置接口访问权限
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                // 公开接口
                .antMatchers("/api/public/**").permitAll()
                // 用户接口需要认证
                .antMatchers("/api/user/**").authenticated()
                // 管理员接口需要 ADMIN 角色
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }
}
复制代码
UserController.java
java 复制代码
package com.dp.resourceserver.controller;


import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.Principal;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api")
public class UserController {

    /**
     * 公开接口 - 不需要 Token
     */
    @GetMapping("/public/health")
    public Map<String, Object> health() {
        Map<String, Object> result = new HashMap<>();
        result.put("status", "UP");
        result.put("service", "resource-server");
        result.put("message", "Service is running");
        return result;
    }

    /**
     * 用户信息接口 - 需要 Token
     * 通过 Principal 获取当前登录用户
     */
    @GetMapping("/user/info")
    public Map<String, Object> getUserInfo(Principal principal) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        Map<String, Object> result = new HashMap<>();
        result.put("username", principal.getName());
        result.put("authenticated", authentication.isAuthenticated());
        result.put("authorities", authentication.getAuthorities());
        result.put("service", "resource-server");

        return result;
    }

    /**
     * 管理员接口 - 需要 ADMIN 角色
     */
    @GetMapping("/admin/dashboard")
    public Map<String, Object> adminDashboard() {
        Map<String, Object> result = new HashMap<>();
        result.put("data", "Admin Dashboard Data");
        result.put("service", "resource-server");
        return result;
    }
}

application.yml

java 复制代码
server:
  port: 9002

spring:
  application:
    name: resource-server

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: public

# JWT 签名密钥(必须与认证服务器一致)
jwt:
  secret: sso-secret-key-2024

logging:
  level:
    org.springframework.security: DEBUG

3.启动

3.1 启动 nacos,我的版本是3.0.2

3.2 启动 auth-server

3.3 启动 resource-server

4.测试:(用的postman)

4.1 获取token:

http://localhost:9001/oauth/token

post

header:

Authorization:Basic Z2F0ZXdheS1jbGllbnQ6Z2F0ZXdheS1zZWNyZXQ=

body:

grant_type:password

username:admin

password:123456

scope:all

返回:

{

"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NzQ4Njg0MzEsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiIsIlJPTEVfVVNFUiJdLCJqdGkiOiJsVGNVblBSaVg4WENqX3Vva2hXeERFZHVlcXMiLCJjbGllbnRfaWQiOiJnYXRld2F5LWNsaWVudCIsInNjb3BlIjpbImFsbCJdfQ.cQ_jzo7nwuTyinx5Xt4qQt2ZCcKo5_K0s-JxPnti3G8",

"token_type": "bearer",

"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJhdGkiOiJsVGNVblBSaVg4WENqX3Vva2hXeERFZHVlcXMiLCJleHAiOjE3NzQ5NTEyMzEsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwianRpIjoiNVpMVlRSTmFwcVEtX1ZzRnlNZkp0Uk90NnlVIiwiY2xpZW50X2lkIjoiZ2F0ZXdheS1jbGllbnQifQ.x3_Mb0gYR8YDWlBc8hE2oEKzECx6ed7_YJc8v8sSgKE",

"expires_in": 3599,

"scope": "all",

"jti": "lTcUnPRiX8XCj_uokhWxDEdueqs"

}

4.2 测试数据:

http://localhost:9002/api/user/info

header:

Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NzQ4NjQ0NDAsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9BRE1JTiIsIlJPTEVfVVNFUiJdLCJqdGkiOiIwbVJDVVkzWjNuTTFiamZfSmxIaVN2ek1JWDQiLCJjbGllbnRfaWQiOiJnYXRld2F5LWNsaWVudCIsInNjb3BlIjpbImFsbCJdfQ.tlveU1Br_PsPXfZIKHYB6pXlCpkEj9cS7gc93KUGQXU

返回:

{

"authenticated": true,

"service": "resource-server",

"authorities": [

{

"authority": "ROLE_ADMIN"

},

{

"authority": "ROLE_USER"

}

],

"username": "admin"

}

4.3 http://localhost:9002/api/admin/dashboard

header 一样:权限不一样的测试

4.4 不用执行,备份收藏的postman的测试方式

原理等大家实现后,看注释就可以,先跑通。代码放deepseek也可以

相关推荐
奥升新能源平台3 天前
奥升充电最小化高可用机房部署方案
运维·安全·开源·能源·springcloud
leo_messi946 天前
2026版商城项目(一)
java·elasticsearch·k8s·springcloud
没有bug.的程序员6 天前
S 级 SaaS 平台的物理雪崩:Spring Cloud Gateway 多租户动态路由与 UserID 极限分片
java·gateway·springboot·saas·springcloud·多租户、·userid
DexterLien10 天前
使用开源 Authentik 实现 AWS 单点登录
aws·sso·saml·authentik
Dragon Wu1 个月前
SpringCache 缓存使用总结
spring boot·后端·spring·缓存·springcloud
七夜zippoe1 个月前
微服务链路追踪实战:SkyWalking vs Zipkin 架构深度解析与性能优化指南
java·开发语言·微服务·springcloud·sleuth·zipkin
梦想总是可以实现的1 个月前
SpringCloud2024 + JDK17实战:手把手教你从零搭建微服务全家桶(含Eureka+Gateway+Redis)
springcloud·微服务架构·java开发·分布式系统
九转苍翎2 个月前
微服务学习笔记(1)——SpringColud概述
spring boot·maven·springcloud
七夜zippoe2 个月前
OpenFeign全解 声明式REST客户端原理与配置实战
java·负载均衡·springcloud·openfeign·动态代理·核心配置