登录注册功能开发

news2024/11/17 6:29:57

本篇文章记录怎么实现一个简单的登陆注册功能。
讲解里的代码是不完全的,具体的代码我会放在文章最后

文章目录

  • 准备
  • 为什么要有登录:
  • 简述注册功能:
  • 简述登录功能
  • 完全代码:
    • 数据实体部分:
      • Users类:
      • UsersLoginDTO类:
      • RegisterDTO类:
    • 拦截器部分:
      • application.yml文件对应内容:
      • JwtProperties类:
      • JwtUtil工具类
      • JwtTokenAdminInterceptor拦截器类:
      • WebMvcConfiguration 配置类:
    • 登录注册部分
      • UserController类
      • UserService接口
      • UserServiceImpl实现类
      • UserMapper类:

准备

要实现登录注册功能,首先我们就要有用户表来记录用户的数据。
我们的用户表大概就是这样的:
有id,用户名,密码,姓名,邮箱,权限等级这些字段。
在这里插入图片描述

为什么要有登录:

不知道大家是否想过,为什么要进行登录呢?
其实,在我们的项目开发中,我们要对各种请求进行拦截加以限制,这样才能保证我们项目的安全性,不然随随便便什么人就可以把我们项目的数据给拿走了。
在项目的配置中,我们会写拦截器用于拦截请求,将合法合规的请求放行。
项目配置:

@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Autowired
    private JwtTokenAdminInterceptor tokenAdminInterceptor;

    protected void addInterceptors(InterceptorRegistry registry){
        log.info("开始注册自定义拦截器");
        registry.addInterceptor(tokenAdminInterceptor)
                .addPathPatterns("/api/**")//加入拦截
                .excludePathPatterns("/api/users/login")//不拦截的请求
                .excludePathPatterns("/api/users/register")
                .excludePathPatterns("/api/category/list")
                .excludePathPatterns("/api/users/sendEmail/**");

        log.info("自定义拦截器注册完成");

    }
}

这里的JwtTokenAdminIntercepor则是拦截器,在这里面实现拦截与放行的功能。
JwtTokenAdminIntercepor

/**
 * jwt令牌校验的拦截器
 */
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;
    /**
     * 校验jwt
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法,直接放行
            return true;
        }
        System.out.println("开始校验jwt");
        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getAdminTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token);
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.ID).toString());
            Integer role = (Integer) claims.get(JwtClaimsConstant.ROLE);
            log.info("当前id:{}", empId);
            log.info("当前角色:{}", role);
            BaseContext.setCurrentId(empId);
            BaseContext.setCurrentRole(role);//设置当前角色
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            log.error("jwt校验失败:{}", ex.getMessage());
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }
    }
}

简述注册功能:

这个功能就很简单,不过是发送请求往表中加入用户数据罢了。
这是我们UserController类中的注册,我们这里使用的邮箱进行验证,关于邮箱验证的知识,可以查看文章:邮箱验证

	@PostMapping("/register")
    @ApiOperation("用户注册")
    public Result register(@RequestBody RegisterDTO registerDTO){
        log.info("用户注册:{}", registerDTO);
        String code = registerDTO.getCode();
        log.info("前端输入的验证码{}", code);
        String eml = registerDTO.getEmail();
        log.info("前端的对象为{},邮箱=》{}",registerDTO,eml);
        String s = redisTemplate.opsForValue().get(eml);
        log.info("从redis中获取code->{}",s);
        if(s==null){
            throw new RuntimeException(MessageConstant.CODE_EXPIRED);
        }
        if (Objects.equals(s, code)) {
            log.info("验证码正确{}", code);
            userService.register(registerDTO);
            return Result.success(MessageConstant.Register_SUCCESS);
        }else{
            throw new RuntimeException(MessageConstant.CODE_EXPIRED);
        }
    }

注册功能实现类部分:

public void register(RegisterDTO registerDTO) {
        String userName = registerDTO.getUsername();
        String password = registerDTO.getPassword();

        if(userName == null || password == null){//用户名密码不能为空
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_IS_NULL);
        }

        Users user = userMapper.getByUserName(userName);
        if(user!= null){//查看用户名是否已存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_ALREADY_EXIST);
        }

        Users users = Users.builder()
                .username(userName)
                .password(DigestUtils.md5DigestAsHex(password.getBytes()))
                .name(registerDTO.getName())
                .email(registerDTO.getEmail())
                .role(StatusConstant.NORMAL)
                .build();
        userMapper.insert(users);//向用户表中插入数据
    }

大概就这样,用户注册功能就可以被实现。

简述登录功能

登录功能就是重头戏了,用户登录后再发送请求,我们就要验证这个请求的发送者是不是我们的用户,这个就比较重要了。
其实,登录功能的逻辑就是:1.验证登录对应的用户数据是否在我们的数据库表中。2.在数据库中,则生成相关的JWT令牌,方便后续用户发送请求验证。
UserController部分:

	@PostMapping("/login")//请求方法
    @ApiOperation("用户登录")//取名
    public Result<UsersLoginVO> login(@RequestBody UsersLoginDTO userLoginDTO){
        Users user = userService.login(userLoginDTO);

        // 开始生成token
        Map<String,Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.ID,user.getId());
        claims.put(JwtClaimsConstant.ROLE,user.getRole());

        // token令牌
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        UsersLoginVO usersLoginVO = UsersLoginVO.builder()
                .id(user.getId())
                .username(user.getUsername())
                .token(token)
                .role(user.getRole())
                .email(user.getEmail())
                .name(user.getName())
                .build();

        return Result.success(usersLoginVO);
    }

service实现类部分:

	@Override
    public Users login(UsersLoginDTO userLoginDTO) {
        String userName = userLoginDTO.getUsername();
        String password = userLoginDTO.getPassword();

        Users users = userMapper.getByUserName(userName);

        if (users == null) {// 用户不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        if(StatusConstant.DIS.equals(users.getRole())){// 账户被锁定
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_LOCKED);
        }
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if(!password.equals(users.getPassword())){ // 密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        return users;

    }

完全代码:

按以下顺序创建复制粘贴即可

数据实体部分:

Users类:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Users implements Serializable {
    private Long id;
    private String username;
    private String password;
    private String name;
    private String email;
    private Integer role;
}

UsersLoginDTO类:

@Data
public class UsersLoginDTO {
    private String username;
    private String password;
}

RegisterDTO类:

@Data
public class RegisterDTO {
    private String username;
    private String password;
    private String name;
    private String email;
    private String code;
}

拦截器部分:

application.yml文件对应内容:

codehome:
  jwt:
    # 设置jwt签名加密时使用的秘钥
    admin-secret-key: itcast
    # 设置jwt过期时间
    admin-ttl: 604800000
    # 设置前端传递过来的令牌名称
    admin-token-name: token

JwtProperties类:

@Component
@ConfigurationProperties(prefix = "codehome.jwt")
@Data
public class JwtProperties {

    /**
     * 管理端员工生成jwt令牌相关配置
     */
    private String adminSecretKey;
    private long adminTtl;
    private String adminTokenName;

    /**
     * 用户端微信用户生成jwt令牌相关配置
     */
    private String userSecretKey;
    private long userTtl;
    private String userTokenName;

}

JwtUtil工具类


public class JwtUtil {
    /**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘钥
     *
     * @param secretKey jwt秘钥
     * @param ttlMillis jwt过期时间(毫秒)
     * @param claims    设置的信息
     * @return
     */
    public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
        // 指定签名的时候使用的签名算法,也就是header那部分
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 生成JWT的时间
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置过期时间
                .setExpiration(exp);

        return builder.compact();
    }

    /**
     * Token解密
     *
     * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
     * @param token     加密后的token
     * @return
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims;
    }

}

JwtTokenAdminInterceptor拦截器类:

@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;
    /**
     * 校验jwt
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法,直接放行
            return true;
        }
        System.out.println("开始校验jwt");
        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getAdminTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token);
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.ID).toString());
            Integer role = (Integer) claims.get(JwtClaimsConstant.ROLE);
            log.info("当前id:{}", empId);
            log.info("当前角色:{}", role);
            BaseContext.setCurrentId(empId);
            BaseContext.setCurrentRole(role);//设置当前角色
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            log.error("jwt校验失败:{}", ex.getMessage());
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }
    }
}

WebMvcConfiguration 配置类:

@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Autowired
    private JwtTokenAdminInterceptor tokenAdminInterceptor;

    protected void addInterceptors(InterceptorRegistry registry){
        log.info("开始注册自定义拦截器");
        registry.addInterceptor(tokenAdminInterceptor)
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/users/login")
                .excludePathPatterns("/api/users/register")
                .excludePathPatterns("/api/category/list")
                .excludePathPatterns("/api/users/sendEmail/**");

        log.info("自定义拦截器注册完成");

    }

    /**
     * 通过knife4j生成接口文档
     * @return
     */
    @Bean
    public Docket docket() {
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("代码芝士后端接口文档")
                .version("1.0")
                .description("代码芝士后端接口文档")
                .build();
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.codehome.server.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

    /**
     * 设置静态资源映射
     * @param registry
     */
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    /**
     * 消息转换器
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters){
        log.info("开始扩展消息转换器");
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(new JacksonObjectMapper());

        converters.add(0,converter);
    }
}

登录注册部分

UserController类

@RestController
@RequestMapping("/api/users")
@Api(tags = "用户模块")
@Slf4j
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private JwtProperties jwtProperties;


    @PostMapping("/login")//请求方法
    @ApiOperation("用户登录")//取名
    public Result<UsersLoginVO> login(@RequestBody UsersLoginDTO userLoginDTO){
        Users user = userService.login(userLoginDTO);

        // 开始生成token
        Map<String,Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.ID,user.getId());
        claims.put(JwtClaimsConstant.ROLE,user.getRole());

        // token令牌
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        UsersLoginVO usersLoginVO = UsersLoginVO.builder()
                .id(user.getId())
                .username(user.getUsername())
                .token(token)
                .role(user.getRole())
                .email(user.getEmail())
                .name(user.getName())
                .build();

        return Result.success(usersLoginVO);
    }

    @PostMapping("/register")
    @ApiOperation("用户注册")
    public Result register(@RequestBody RegisterDTO registerDTO){
        userService.register(registerDTO);
        return Result.success(MessageConstant.Register_SUCCESS);
    }
}

UserService接口

public interface UserService {
    Users login(UsersLoginDTO userLoginDTO);
    void register(RegisterDTO registerDTO);
}

UserServiceImpl实现类

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public Users login(UsersLoginDTO userLoginDTO) {
        String userName = userLoginDTO.getUsername();
        String password = userLoginDTO.getPassword();

        Users users = userMapper.getByUserName(userName);

        if (users == null) {// 用户不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        if(StatusConstant.DIS.equals(users.getRole())){// 账户被锁定
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_LOCKED);
        }
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if(!password.equals(users.getPassword())){ // 密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        return users;

    }

    @Override
    public void register(RegisterDTO registerDTO) {
        String userName = registerDTO.getUsername();
        String password = registerDTO.getPassword();

        if(userName == null || password == null){
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_IS_NULL);
        }

        Users user = userMapper.getByUserName(userName);
        if(user!= null){
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_ALREADY_EXIST);
        }

        Users users = Users.builder()
                .username(userName)
                .password(DigestUtils.md5DigestAsHex(password.getBytes()))
                .name(registerDTO.getName())
                .email(registerDTO.getEmail())
                .role(StatusConstant.NORMAL)
                .build();
        userMapper.insert(users);
    }

UserMapper类:

@Mapper
public interface UserMapper {

    @Select("select * from users where username = #{userName}")
    Users getByUserName(String userName);


    @Insert("insert into users (username, password, name, email, role) values (#{username}, #{password}, #{name}, #{email}, #{role})")
    void insert(Users users);
}

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

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

相关文章

ME31L-创建计划协议

ME31L创建计划协议 一般常用的就是LA和LPA LP不需要审批&#xff0c;LPA需要审批。 计划协议和采购申请实现的功能相同。 计划协议创建界面和创建合同的界面相同。 ME38可以分配交货计划行。 输入计划协议号。回车。 双击行项目后&#xff0c;维护行项目字段。 然后可以在货…

一个线程在sleep的时候set一个信号会起作用吗

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

代码随想录第29天|贪心

134.加油站 代码随想录 代码随想录 索引01234gas12345cost34512 计算每个加油站的剩余油量&#xff0c;累计sum&#xff0c;一旦<0就从下一个重新计数。 我还没理解为什么我们不需要计算环路的sum&#xff0c;而是只需要遍历一次。 因为使用了两个变量&#xff1a;curSu…

Java ExecutorService:你真的了解它吗?

文章目录 一、什么是ExecutorService&#xff1f;二、ExecutorService的核心功能三、如何创建和使用ExecutorService&#xff1f; 时光匆匆&#xff0c;又来到另一个里程碑&#xff0c;感谢粉丝们的陪伴&#xff0c;有你们真好~ 不水文啦&#xff0c;一起加油叭~ 一、什么是Exe…

【Java】Jsoup 解析HTML报告

一、需求背景 有好几种报告文件&#xff0c;目前是人肉找报告信息填到Excel上生成统计信息 跟用户交流了下需求和提供的几个文件&#xff0c;发现都是html文件 其实所谓的报告的文件&#xff0c;就是一些本地可打开的静态资源&#xff0c;里面也有js、img等等 二、方案选型 前…

adb环境变量配置(附详细图解)

adb环境变量配置&#xff08;附详细图解&#xff09; 1、找到ADB工具的位置。通常&#xff0c;如果你Android Studio已经安装了Android SDK&#xff0c;ADB工具位于SDK的platform-tools目录下。我这里的目录是C:\Users\user\AppData\Local\Android\Sdk\platform-tools\adb.exe…

微信防封指南请收好

一、新号与老号的添加限制 建议新注册的微信号主动添加好友的数量不宜过多&#xff0c;推荐每日添加不超过5个好友&#xff1b;对于老号&#xff0c;建议每日添加不超过20个好友。保持适度的添加速度&#xff0c;避免被系统判定为异常操作。 二、避免使用营销性词汇 在发送消…

【计算机视觉】图像处理基本知识

一 基本的图像操作和处理 1.1 PIL&#xff1a;Python图像处理类库 PIL&#xff08;Python Imaging Library&#xff0c;图像处理库&#xff09;提供了通用的图像处理功能&#xff0c;以及大量有用的基本图像操作。PIL库已经集成在Anaconda库中&#xff0c;推荐使用Anaconda&a…

openmetadata自定义连接器开发教程

openmetadata自定义连接器开发教程 一、开发通用自定义连接器教程 官网教程链接&#xff1a; 1.https://docs.open-metadata.org/v1.3.x/connectors/custom-connectors 2.https://github.com/open-metadata/openmetadata-demo/tree/main/custom-connector &#xff08;一&…

【ARM】SMMU系统虚拟化(3)_ VMSAv8-64 address translation stages

讲解颗粒度granule size如何影响地址转换的过程&#xff1a; 对于每个颗粒度来说&#xff1a; 输入的地址范围如何影响起始的lookup levels。对于stage2 转换来说&#xff0c;给链接的转换页表造成的可能的影响。TTBR 地址和indexing对于起始的lookup 1.以4KB的translation g…

初始JVM ! ! ! 相信我,中国人不骗中国人,这一篇也就入门了!!!

目录 1.JVM到底是什么&#xff1f; 2.JVM的三大核心是什么&#xff1f; 1. 解释和运行 2. 内存管理 3. 即时编译&#xff08;JIT&#xff09; 3.常见的Jvm虚拟机有哪些&#xff1f; 1.3.1 Java虚拟机规范 1.3.2 Java虚拟机规范 4. JVM的组成 4.1、类的生命周期 4.1…

Android手机端远程控制ESP32引脚电平实例

一、背景介绍 ESP32是一款高度集成的低功耗系统级芯片&#xff0c;它结合了双核处理器、无线通信、低功耗特性和丰富的外设&#xff0c;适用于各种物联网&#xff08;IoT&#xff09;应用&#xff0c;如果与Android结合&#xff0c;在手机端远程控制ESP32引脚高低电平输出&…

武汉流星汇聚:依托亚马逊平台助力初创企业出海,共创国际品牌辉煌

在全球跨境电商的浩瀚蓝海中&#xff0c;亚马逊如同一座灯塔&#xff0c;以其庞大的市场规模、强大的品牌影响力和成熟的运营体系&#xff0c;引领着无数企业扬帆出海&#xff0c;探索未知的市场机遇。对于中国卖家而言&#xff0c;亚马逊不仅是通往全球消费者的桥梁&#xff0…

一文详解:企业优化仓库管理——WMS系统

如有你有一间小仓库&#xff0c;几位工人埋头于一摞摞的纸质单据中&#xff0c;手工记录着每一次货物的进出与变动。目前看来&#xff0c;这样的时间和效率&#xff0c;作为管理者的你还可以接受。 但是&#xff0c;令你头疼的是&#xff0c;随着企业规模的扩大&#xff0c;你…

springboot信息安全技术在投票网站-计算机毕业设计源码12740

目录 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能分析 …

ai自动配音工具

AI拟音大师&#xff0c;给你的无声视频添加生动而且同步的音效 &#x1f61d;文件夹是一种基于文本的视频到音频生成框架,可以生成高质量的音频,在语义上相关,并与输入视频时间同步。 下载地址&#xff1a;https://pan.quark.cn/s/5a2be1cc5551

微服务概述及如何搭建微服务

1. 微服务架构—SpringCloud 1.1 单体应用架构 将项目所有模块【功能】打成jar包或者war包&#xff0c;然后部署一个进程 优点&#xff1a; 部署简单&#xff1a;由于是完整的结构体&#xff0c;可以直接部署在一个服务器上即可技术单一&#xff1a;项目不需要复杂的技术栈&am…

windows启动nacos时报Caused by: java.lang.UnsatisfiedLinkErro错误

Caused by: java.lang.UnsatisfiedLinkError: C:\Users\Administrator\AppData\Local\Temp\2\librocksdbjni6009210463092880400.dll: Can’t find dependent libraries 因为电脑没有vc&#xff0c;或vc版本问题&#xff0c;下载对应的vc安装就可以了 VC“2015-2022”运行库官…

基础复习(反射、注解、动态代理)

反射 反射&#xff0c;指的是加载类的字节码到内存&#xff0c;并以编程的方法解刨出类中的各个成分&#xff08;成员变量、方法、构造器等&#xff09;。 1.获取类的字节码 &#xff08;3种方式&#xff09; public class Test1Class{public static void main(String[] arg…

全球社区的建立:Facebook在跨文化交流中的角色

在全球化日益加深的今天&#xff0c;跨文化交流成为了人们日常生活中的重要部分。Facebook作为全球最大的社交网络平台之一&#xff0c;正在发挥着越来越重要的作用。通过其广泛的用户基础和丰富的功能&#xff0c;Facebook不仅连接了来自不同国家和地区的人们&#xff0c;也在…