• Spring Boot 4 实现JwtToken验证(重点)&&实现后端API(重点)&&前端:实现注册与登录模块(略)


    不用认证,即不用ajax中headers配置项
    登录+注册
    .antMatchers("/user/account/token/","/user/account/register/").permitAll()
    
    上面的跟前端没有什么联系
    仅仅只是ajax时不用headers
    前端具体的控制还在前端
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.实现JwtToken验证(重点)

    1.1添加依赖

    jjwt-api
    jjwt-impl
    jjwt-jackson

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.2</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.2</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.2</version>
        <scope>runtime</scope>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1.2 编写、修改相关类

    1.2.1实现 JwtUtil 类

    backend 目录下创建软件包 utils 并创建 JwtUtil 类。
    JwtUtil 类为jwt 工具类,用来创建、解析 jwt token

    package com.kob.backend.utils;
    
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.JwtBuilder;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import org.springframework.stereotype.Component;
    
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.util.Base64;
    import java.util.Date;
    import java.util.UUID;
    
    @Component
    public class JwtUtil {
        public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14;  // 有效期14天
        public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac";
    
        public static String getUUID() {
            return UUID.randomUUID().toString().replaceAll("-", "");
        }
    
        public static String createJWT(String subject) {
            JwtBuilder builder = getJwtBuilder(subject, null, getUUID());
            return builder.compact();
        }
    
        private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
            SecretKey secretKey = generalKey();
            long nowMillis = System.currentTimeMillis();
            Date now = new Date(nowMillis);
            if (ttlMillis == null) {
                ttlMillis = JwtUtil.JWT_TTL;
            }
    
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            return Jwts.builder()
                    .setId(uuid)
                    .setSubject(subject)
                    .setIssuer("sg")
                    .setIssuedAt(now)
                    .signWith(signatureAlgorithm, secretKey)
                    .setExpiration(expDate);
        }
    
        public static SecretKey generalKey() {
            byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
            return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");
        }
    
        public static Claims parseJWT(String jwt) throws Exception {
            SecretKey secretKey = generalKey();
            return Jwts.parserBuilder()
                    .setSigningKey(secretKey)
                    .build()
                    .parseClaimsJws(jwt)
                    .getBody();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    1.2.2实现 JwtAuthenticationTokenFilter 类

    backendconfig 目录下创建 config 软件包,并创建 JwtAuthenticationTokenFilter类。
    实现 JwtAuthenticationTokenFilter 类,用来验证 jwt token ,如果验证成功,则将 User 信息注入上下文中

    package com.kob.backend.config.filter;
    
    
    import com.kob.backend.mapper.UserMapper;
    import com.kob.backend.pojo.User;
    import com.kob.backend.service.impl.utils.UserDetailsImpl;
    import com.kob.backend.utils.JwtUtil;
    import com.sun.istack.internal.NotNull;
    import io.jsonwebtoken.Claims;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    import org.springframework.web.filter.OncePerRequestFilter;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Component
    public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
        @Autowired
        private UserMapper userMapper;
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
            String token = request.getHeader("Authorization");
    
            if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) {
                filterChain.doFilter(request, response);
                return;
            }
    
            token = token.substring(7);
    
            String userid;
            try {
                Claims claims = JwtUtil.parseJWT(token);
                userid = claims.getSubject();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
    
            User user = userMapper.selectById(Integer.parseInt(userid));
    
            if (user == null) {
                throw new RuntimeException("用户名未登录");
            }
    
            UserDetailsImpl loginUser = new UserDetailsImpl(user);
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(loginUser, null, null);
    
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    
            filterChain.doFilter(request, response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    1.2.3 配置config.SecurityConfig类

    放行登录、注册等接口。

    package com.kob.backend.config;
    
    import com.kob.backend.config.filter.JwtAuthenticationTokenFilter;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.authentication.AuthenticationManager;
    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.config.http.SessionCreationPolicy;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    //此处两个连接不需要认证,可以理解为不登陆就能访问的页面
                    .antMatchers("/user/account/token/", "/user/account/register/").permitAll()
                    .antMatchers(HttpMethod.OPTIONS).permitAll()
                    .anyRequest().authenticated();
    
            http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    2.实现后端API

    2.1 修改数据库

    在这里插入图片描述
    在这里插入图片描述

    2.2实现接口API(重点)

    在这里插入图片描述

    实现LoginService

    在这里插入图片描述

    package com.kob.backend.service.user.account;
    
    import java.util.Map;
    
    public interface LoginService {
        public Map<String, String> getToken(String username, String password);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    package com.kob.backend.service.impl.user.account;
    
    import com.kob.backend.pojo.User;
    import com.kob.backend.service.impl.utils.UserDetailsImpl;
    import com.kob.backend.service.user.account.LoginService;
    import com.kob.backend.utils.JwtUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.stereotype.Service;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @Service
    public class LoginServiceImpl implements LoginService {
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Override
        public Map<String, String> getToken(String username, String password) {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
    
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal();
            User user = loginUser.getUser();
            String jwt = JwtUtil.createJWT(user.getId().toString());
    
            Map<String, String> map = new HashMap<>();
            map.put("error_message", "success");
            map.put("token", jwt);
    
            return map;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述

    package com.kob.backend.controller.user.account;
    
    import com.kob.backend.service.user.account.LoginService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.Map;
    
    @RestController
    public class LoginController {
    
        @Autowired
        private LoginService loginService;
    
        @PostMapping("/user/account/token/")
        public Map<String, String> getToken(@RequestParam Map<String, String> map) {
            String username = map.get("username");
            String password = map.get("password");
    
            System.out.println(username + ' ' + password);
            return loginService.getToken(username, password);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    实现InfoService

    在这里插入图片描述

    package com.kob.backend.service.user.account;
    
    import java.util.Map;
    
    public interface InfoService {
        public Map<String, String> getInfo();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    package com.kob.backend.service.impl.user.account;
    
    import com.kob.backend.pojo.User;
    import com.kob.backend.service.impl.utils.UserDetailsImpl;
    import com.kob.backend.service.user.account.InfoService;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.stereotype.Service;
    
    import java.util.HashMap;
    import java.util.Map;
    @Service
    public class InfoServiceImpl implements InfoService {
    
        /**
         * 根据token返回用户信息
         * @return map存储的信息
         */
        @Override
        public Map<String, String> getInfo() {
            UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
    
            UserDetailsImpl loginUser = (UserDetailsImpl) authentication.getPrincipal();
            User user = loginUser.getUser();
    
            Map<String, String> map = new HashMap<>();
            map.put("error_message", "success");
            map.put("id", user.getId().toString());
            map.put("username", user.getUsername());
            map.put("photo", user.getPhoto());
            return map;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    package com.kob.backend.controller.user.account;
    
    import com.kob.backend.service.user.account.InfoService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.Map;
    
    @RestController
    public class InfoController {
    
        @Autowired
        private InfoService infoService;
    
        @GetMapping("/user/account/info/")
        public Map<String, String> getInfo() {
            return infoService.getInfo();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    实现RegisterService

    在这里插入图片描述

    package com.kob.backend.service.user.account;
    
    import java.util.Map;
    
    public interface RegisterService {
        public Map<String, String> register(String username, String password, String confirmedPassword);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    package com.kob.backend.service.impl.user.account;
    
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.kob.backend.mapper.UserMapper;
    import com.kob.backend.pojo.User;
    import com.kob.backend.service.user.account.RegisterService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Service;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Service
    public class RegisterServiceImpl implements RegisterService {
    
        @Autowired
        private UserMapper userMapper;
    
        @Autowired
        private PasswordEncoder passwordEncoder;
    
        @Override
        public Map<String, String> register(String username, String password, String confirmedPassword) {
            Map<String, String> map = new HashMap<>();
            if (username == null) {
                map.put("error_message", "用户名不能为空");
                return map;
            }
    
            if (password == null || confirmedPassword == null) {
                map.put("error_message", "密码不能为空");
                return map;
            }
            //删除首尾的空白字符
            username = username.trim();
            if (username.length() == 0) {
                map.put("error_message", "用户名不能为空");
                return map;
            }
    
            if (password.length() == 0 || confirmedPassword.length() == 0) {
                map.put("error_message", "密码不能为空");
                return map;
            }
    
            if (username.length() > 100) {
                map.put("error_message", "用户名长度不能大于100");
                return map;
            }
    
            if (password.length() > 100 || confirmedPassword.length() > 100) {
                map.put("error_message", "密码不能大于100");
                return map;
            }
    
            if (!password.equals(confirmedPassword)) {
                map.put("error_message", "两次输入的密码不一致");
                return map;
            }
    
            //查询用户名是否重复
            QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
            queryWrapper.eq("username", username);
            List<User> users = userMapper.selectList(queryWrapper);
            if (!users.isEmpty()) {
                map.put("error_message", "用户名已存在");
                return map;
            }
    
            // 添加一个新用户
            String encodedPassword = passwordEncoder.encode(password);
            //输入自己的图片地址
            String photo = "******************************";
            User user = new User(null, username, encodedPassword, photo);
            userMapper.insert(user);
    
            map.put("error_message", "success");
            return map;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    在这里插入图片描述

    package com.kob.backend.controller.user.account;
    
    import com.kob.backend.service.user.account.RegisterService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.Map;
    
    @RestController
    public class RegisterController {
    
        @Autowired
        private RegisterService registerService;
    
        @PostMapping("/user/account/register/")
        public Map<String, String> register(@RequestParam Map<String, String> map) {
            String username = map.get("username");
            String password = map.get("password");
            String confirmedPassword = map.get("confirmedPassword");
            return registerService.register(username, password, confirmedPassword);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    前端调试

    在这里插入图片描述

    <template>
      <NavBar></NavBar>
      <router-view></router-view>
    </template>
    
    <script>
    
    import NavBar from "@/components/NavBar.vue";
    import "bootstrap/dist/css/bootstrap.min.css";
    import "bootstrap/dist/js/bootstrap";
    import $ from 'jquery'
    
    export default {
      components:{
        NavBar
      },
    
      setup() {
        // 测试LoginService
        $.ajax({
          url: "http://127.0.0.1:8080/user/account/token/",
          type: "post",
          data: {
            username: 'syy',
            password: 'psyy',
          },
          success(resp) {
            console.log(resp);
          },
          error(resp) {
            console.log(resp); 
          }
        });
        // 测试InfoService
        $.ajax({
          url: "http://127.0.0.1:8080/user/account/info/",
          type: "get",
          headers: {
            Authorization: "Bearer " + "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4MjliMjQzYjg4YmM0NjdjYmRkMDAwMmNiMzYwZDJiMyIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY1OTU3ODUyMiwiZXhwIjoxNjYwNzg4MTIyfQ.s5nd3RgtDKkPBDDm4P87ET8biZk8H79VMII1p_O9OsA",
          },
          success(resp) {
            console.log(resp);
          },
          error(resp) {
            console.log(resp);
          }
        });
        // 测试RegisterService
        $.ajax({
          url: "http://127.0.0.1:8080/user/account/register/",
          type: "post",
          data: {
            username: "hmy",
            password: "phmy",
            confirmedPassword: "phmy",
          },
          success(resp) {
            console.log(resp);
          },
          error(resp) {
            console.log(resp);
          }
        })
      }
    }
    </script>
    
    
    <style>
    body {
      background-image: url("./assets/images/background.png");
      background-size: cover;
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    在这里插入图片描述

    3. 实现前端的登陆、注册界面(略)

    3.1实现前端的页面授权功能—重定向到登录页面(重点)

    在这里插入图片描述
    router.index.js实现

    router.beforeEach((to, from, next) => {
      if (to.meta.requestAuth && !store.state.user.is_login) {
        next({name: "user_account_login"});
      }
      else {
        next();
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.2实现登录界面的可持久化(重点)

    在这里插入图片描述

    let jwt_token = localStorage.getItem("jwt_token");
            if (jwt_token) {
                store.commit("updateToken",jwt_token);
                //判断是否合法的,就是从云端获取用户信息
                store.dispatch("getinfo",{
                    success() {
                        router.push({name: "home"});
                    },
                    error() {
    
                    }
                })
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

  • 相关阅读:
    计算机复试面试题总结
    【DL】第 12 章: 生成式深度学习
    【经验之谈·高频PCB电路设计常见的66个问题】
    springcloud下的nacos集群与gateway网关
    Zebec Protocol 成非洲利比亚展会合作伙伴,并将向第三世界国家布局
    Spring Boot 2 (七):Spring Boot 如何解决项目启动时初始化资源
    Python基础入门(持续更新中)
    koa2+vue3通过exceljs实现数据导出excel文档
    PyQt5快速开发与实战 4.12 日历与时间
    Rust迭代器简介
  • 原文地址:https://blog.csdn.net/qq_52384627/article/details/126397513