个人博客系统后端 - 用户信息管理功能实现指南(上)

news2025/5/20 3:51:29

本文记录了如何实现用获取户信息,用户信息更新,用户头像上传三大基础功能
先上接口实现截图:

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

一、项目结构概览
先介绍一下
个人博客系统采用了标准的 Spring Boot 项目结构,用户功能相关的文件主要分布在以下几个目录:

WeblogSystem/
├── src/main/java/com/zxy/weblogsystem/
│   ├── controller/        # 控制器层,处理HTTP请求
│   ├── service/           # 服务层,实现业务逻辑
│   │   └── impl/          # 服务实现类
│   ├── repository/        # 数据访问层,与数据库交互
│   ├── entity/            # 实体类,映射数据库表
│   ├── dto/               # 数据传输对象,用于API交互
│   ├── exception/         # 自定义异常类
│   └── config/            # 配置类
├── src/main/resources/
│   ├── static/            # 静态资源
│   ├── templates/         # 模板文件
│   ├── application.properties  # 应用配置
│   ├── schema.sql         # 数据库表结构
│   └── data.sql           # 初始数据
└── docs/                  # 项目文档

二、用户信息功能实现

  1. 实体类定义
    文件位置:src/main/java/com/zxy/weblogsystem/entity/User.java

功能说明:定义用户实体类,映射数据库中的 users 表。

主要内容:

@Data  // Lombok注解,自动生成getter/setter等方法
@NoArgsConstructor  // 无参构造函数
@AllArgsConstructor  // 全参构造函数
@Entity  // JPA实体类注解
@Table(name = "users")  // 指定表名
public class User {
    @Id  // 主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // 自增策略
    private Long id;
    
    @Column(nullable = false, unique = true, length = 50)
    private String username;
    
    @Column(nullable = false, length = 100)
    private String password;
    
    @Column(nullable = false, unique = true, length = 100)
    private String email;
    
    @Column(length = 50)
    private String nickname;
    
    @Column(length = 255)
    private String avatarUrl;  // 头像URL
    
    @Column(nullable = false, length = 20)
    private String role = "USER";
    
    @Column(nullable = false)
    private Integer status = 1;
    
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;
    
    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
}
  1. 数据传输对象(DTO)
    2.1 用户信息DTO
    文件位置:src/main/java/com/zxy/weblogsystem/dto/UserInfoDto.java

功能说明:用于返回用户信息的数据传输对象。

主要内容:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserInfoDto {
    private Long id;
    private String username;
    private String nickname;
    private String email;
    private String avatarUrl;
    private String role;
    private Integer status;
    private Integer followersCount;  // 粉丝数
    private Integer followingCount;  // 关注数
    private Integer articleCount;    // 文章数
    private LocalDateTime createdAt;
}

2.2 用户更新DTO
文件位置:src/main/java/com/zxy/weblogsystem/dto/UserUpdateDto.java

功能说明:用于接收用户信息更新请求的数据传输对象。

主要内容:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserUpdateDto {
    @Size(max = 50, message = "昵称长度不能超过50个字符")
    private String nickname;
    
    @URL(message = "头像URL格式不正确")
    private String avatarUrl;
}

2.3 API响应DTO
文件位置:src/main/java/com/zxy/weblogsystem/dto/ApiResponse.java

功能说明:统一的API响应格式。

主要内容:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ApiResponse<T> {
    private Integer code;
    private String message;
    private T data;
    
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "OK", data);
    }
    
    public static <T> ApiResponse<T> success(String message, T data) {
        return new ApiResponse<>(200, message, data);
    }
    
    public static <T> ApiResponse<T> error(Integer code, String message) {
        return new ApiResponse<>(code, message, null);
    }
}
  1. 数据访问层
    文件位置:src/main/java/com/zxy/weblogsystem/repository/UserRepository.java

功能说明:用户数据访问接口,提供数据库操作方法。

主要内容:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
    Optional<User> findByEmail(String email);
    boolean existsByUsername(String username);
    boolean existsByEmail(String email);
}
  1. 服务层
    4.1 用户服务接口
    文件位置:src/main/java/com/zxy/weblogsystem/service/UserService.java

功能说明:定义用户相关的业务逻辑接口。

主要内容:

public interface UserService {
    /**
     * 根据用户ID获取用户信息
     * @param userId 用户ID
     * @return 用户详细信息DTO
     */
    UserInfoDto getUserInfo(Long userId);
    
    /**
     * 根据用户ID更新用户信息
     * @param userId 用户ID
     * @param userUpdateDto 用户更新信息DTO
     * @return 更新后的用户信息DTO
     */
    UserInfoDto updateUserInfo(Long userId, UserUpdateDto userUpdateDto);
    
    /**
     * 更新用户头像
     * @param userId 用户ID
     * @param avatarUrl 头像URL
     * @return 更新后的用户信息DTO
     */
    UserInfoDto updateUserAvatar(Long userId, String avatarUrl);
}

4.2 用户服务实现类
文件位置:src/main/java/com/zxy/weblogsystem/service/impl/UserServiceImpl.java

功能说明:实现用户服务接口中定义的业务逻辑。

主要内容:

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final UserFollowRepository userFollowRepository;
    private final ArticleRepository articleRepository;
    
    @Override
    @Transactional(readOnly = true)
    public UserInfoDto getUserInfo(Long userId) {
        // 1. 查询用户基本信息
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在,ID: " + userId));
        
        // 2. 查询统计数据
        Integer followersCount = userFollowRepository.countByFollowedId(userId);
        Integer followingCount = userFollowRepository.countByFollowerId(userId);
        Integer articleCount = articleRepository.countByAuthorId(userId);
        
        // 3. 构建并返回DTO
        return UserInfoDto.builder()
                .id(user.getId())
                .username(user.getUsername())
                .nickname(user.getNickname())
                .email(user.getEmail())
                .avatarUrl(user.getAvatarUrl())
                .role(user.getRole())
                .status(user.getStatus())
                .followersCount(followersCount)
                .followingCount(followingCount)
                .articleCount(articleCount)
                .createdAt(user.getCreatedAt())
                .build();
    }
    
    @Override
    @Transactional
    public UserInfoDto updateUserInfo(Long userId, UserUpdateDto userUpdateDto) {
        // 1. 查询用户是否存在
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在,ID: " + userId));
        
        // 2. 更新用户信息
        boolean isUpdated = false;
        
        // 更新昵称
        if (userUpdateDto.getNickname() != null && !userUpdateDto.getNickname().isEmpty()) {
            user.setNickname(userUpdateDto.getNickname());
            isUpdated = true;
        }
        
        // 3. 保存更新后的用户信息
        if (isUpdated) {
            user = userRepository.save(user);
        }
        
        // 4. 查询统计数据并构建返回DTO
        return getUserInfo(userId);
    }
    
    @Override
    @Transactional
    public UserInfoDto updateUserAvatar(Long userId, String avatarUrl) {
        // 1. 查询用户是否存在
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在,ID: " + userId));
        
        // 2. 更新用户头像URL
        user.setAvatarUrl(avatarUrl);
        
        // 3. 保存更新后的用户信息
        userRepository.save(user);
        
        // 4. 查询统计数据并构建返回DTO
        return getUserInfo(userId);
    }
}
  1. 控制器层
    文件位置:src/main/java/com/zxy/weblogsystem/controller/UserController.java

功能说明:处理用户相关的HTTP请求。

主要内容:

@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;
    private final FileService fileService;
    
    /**
     * 获取用户信息
     */
    @GetMapping("/{id}")
    public ApiResponse<UserInfoDto> getUserInfo(@PathVariable Long id) {
        UserInfoDto userInfo = userService.getUserInfo(id);
        return ApiResponse.success(userInfo);
    }
    
    /**
     * 更新用户信息
     */
    @PutMapping("/{id}")
    public ApiResponse<UserInfoDto> updateUserInfo(@PathVariable Long id, @Valid @RequestBody UserUpdateDto userUpdateDto) {
        UserInfoDto updatedUserInfo = userService.updateUserInfo(id, userUpdateDto);
        return ApiResponse.success("更新成功", updatedUserInfo);
    }
    
    /**
     * 上传用户头像
     */
    @PostMapping("/{id}/avatar")
    public ApiResponse<Map<String, String>> uploadAvatar(@PathVariable Long id, @RequestParam("file") MultipartFile file) {
        // 1. 调用文件服务上传头像
        String avatarUrl = fileService.uploadAvatar(id, file);
        
        // 2. 更新用户头像信息
        userService.updateUserAvatar(id, avatarUrl);
        
        // 3. 返回头像URL
        Map<String, String> result = new HashMap<>();
        result.put("avatarUrl", avatarUrl);
        
        return ApiResponse.success("上传成功", result);
    }
}

三、文件上传功能实现

  1. 文件上传配置
    文件位置:src/main/java/com/zxy/weblogsystem/config/FileUploadConfig.java

功能说明:配置文件上传相关参数和静态资源访问。

主要内容:

@Configuration
public class FileUploadConfig implements WebMvcConfigurer {

    @Value("${file.upload.path:uploads}")
    private String uploadPath;

    @Value("${file.access.path:/uploads/}")
    private String accessPath;

    @Bean
    public MultipartResolver multipartResolver() {
        return new StandardServletMultipartResolver();
    }

    @Override
    public void addResourceHandlers(@NonNull ResourceHandlerRegistry registry) {
        // 确保上传目录存在
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }
        
        // 获取上传目录的绝对路径
        String absolutePath = uploadDir.getAbsolutePath();
        
        // 添加资源处理器,将上传路径映射到访问路径
        registry.addResourceHandler(accessPath + "**")
                .addResourceLocations("file:" + absolutePath + "/");
    }
}
  1. 文件上传异常
    文件位置:src/main/java/com/zxy/weblogsystem/exception/FileUploadException.java

功能说明:自定义文件上传异常类。

主要内容:

public class FileUploadException extends RuntimeException {
    
    public FileUploadException(String message) {
        super(message);
    }
    
    public FileUploadException(String message, Throwable cause) {
        super(message, cause);
    }
}
  1. 文件服务接口
    文件位置:src/main/java/com/zxy/weblogsystem/service/FileService.java

功能说明:定义文件上传相关的业务逻辑接口。

主要内容:

public interface FileService {
    
    /**
     * 上传头像文件
     * 
     * @param userId 用户ID
     * @param file 头像文件
     * @return 头像访问URL
     */
    String uploadAvatar(Long userId, MultipartFile file);
}
  1. 文件服务实现类
    文件位置:src/main/java/com/zxy/weblogsystem/service/impl/FileServiceImpl.java

功能说明:实现文件上传相关的业务逻辑。

主要内容:

@Service
@RequiredArgsConstructor
public class FileServiceImpl implements FileService {

    @Value("${file.upload.path:uploads}")
    private String uploadPath;

    @Value("${file.access.path:/uploads/}")
    private String accessPath;

    private static final List<String> ALLOWED_IMAGE_TYPES = Arrays.asList("image/jpeg", "image/png");

    @Override
    public String uploadAvatar(Long userId, MultipartFile file) {
        // 1. 校验文件是否为空
        if (file == null || file.isEmpty()) {
            throw new FileUploadException("上传文件不能为空");
        }

        // 2. 校验文件类型
        String contentType = file.getContentType();
        if (contentType == null || !ALLOWED_IMAGE_TYPES.contains(contentType)) {
            throw new FileUploadException("只支持JPG和PNG格式的图片");
        }

        // 3. 校验文件大小
        if (file.getSize() > 2 * 1024 * 1024) { // 2MB
            throw new FileUploadException("文件大小不能超过2MB");
        }

        try {
            // 4. 确保上传目录存在
            File uploadDir = new File(uploadPath);
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }

            // 5. 创建用户头像目录
            String userAvatarDir = uploadPath + "/avatars/" + userId;
            File userDir = new File(userAvatarDir);
            if (!userDir.exists()) {
                userDir.mkdirs();
            }

            // 6. 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename != null ? 
                    originalFilename.substring(originalFilename.lastIndexOf(".")) : ".jpg";
            String newFilename = UUID.randomUUID().toString() + fileExtension;
            
            // 7. 保存文件
            Path targetPath = Paths.get(userAvatarDir, newFilename);
            Files.copy(file.getInputStream(), targetPath);
            
            // 8. 返回文件访问URL
            return accessPath + "avatars/" + userId + "/" + newFilename;
            
        } catch (IOException e) {
            throw new FileUploadException("文件上传失败: " + e.getMessage());
        }
    }
}

四、配置文件

  1. 应用配置
    文件位置:src/main/resources/application.properties

功能说明:配置应用参数,包括数据库连接、文件上传等。

主要内容:

# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/weblog?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# JPA配置
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

# 文件上传配置
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=2MB
spring.servlet.multipart.max-request-size=10MB
spring.servlet.multipart.file-size-threshold=0

# 文件存储路径配置
file.upload.path=e:/个人博客系统/WeblogSystem/uploads
file.access.path=/uploads/
  1. 数据库表结构
    文件位置:src/main/resources/schema.sql

功能说明:定义数据库表结构。

主要内容:

-- 用户表
CREATE TABLE IF NOT EXISTS users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
    username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
    password VARCHAR(100) NOT NULL COMMENT '密码(加密)',
    email VARCHAR(100) NOT NULL UNIQUE COMMENT '邮箱',
    nickname VARCHAR(50) COMMENT '昵称',
    avatar_url VARCHAR(255) COMMENT '头像URL',
    role VARCHAR(20) NOT NULL DEFAULT 'USER' COMMENT '角色',
    status INT NOT NULL DEFAULT 1 COMMENT '状态(0=禁用,1=启用)',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    INDEX idx_email(email),
    INDEX idx_username(username)
) COMMENT '用户表';

五、功能测试

  1. 获取用户信息
    请求方法:GET

URL:/users/{id}

示例:GET http://localhost:8080/users/1

响应示例:

{
  "code": 200,
  "message": "OK",
  "data": {
    "id": 1,
    "username": "admin",
    "nickname": "管理员",
    "email": "admin@example.com",
    "avatarUrl": "/uploads/avatars/1/63675700-ad83-4e05-a64f-2e59f8a16eeb.jpg",
    "role": "ADMIN",
    "status": 1,
    "followersCount": 0,
    "followingCount": 0,
    "articleCount": 0,
    "createdAt": "2025-04-13T12:00:00"
  }
}
  1. 更新用户信息
    请求方法:PUT

URL:/users/{id}

请求体:

{
  "nickname": "新昵称"
}

示例:PUT http://localhost:8080/users/1

响应示例:

{
  "code": 200,
  "message": "更新成功",
  "data": {
    "id": 1,
    "username": "admin",
    "nickname": "新昵称",
    "email": "admin@example.com",
    "avatarUrl": "/uploads/avatars/1/63675700-ad83-4e05-a64f-2e59f8a16eeb.jpg",
    "role": "ADMIN",
    "status": 1,
    "followersCount": 0,
    "followingCount": 0,
    "articleCount": 0,
    "createdAt": "2025-04-13T12:00:00"
  }
}
  1. 上传用户头像
    请求方法:POST

URL:/users/{id}/avatar

Content-Type:multipart/form-data

请求参数:

file: 图片文件(支持jpg、png,最大2MB)
示例:POST http://localhost:8080/users/1/avatar

响应示例:

{
  "code": 200,
  "message": "上传成功",
  "data": {
    "avatarUrl": "/uploads/avatars/1/63675700-ad83-4e05-a64f-2e59f8a16eeb.jpg"
  }
}

六、总结
通过以上实现,完成了用户信息管理的三个主要功能:
获取用户信息:通过用户ID获取用户详细信息,包括基本资料和统计数据
更新用户信息:支持更新用户昵称等基本信息
上传用户头像:支持上传JPG、PNG格式的头像图片,并自动更新用户头像URL

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

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

相关文章

具身智能机器人学习路线全解析

一、引言 具身智能机器人作为融合了机器人学、人工智能、认知科学等多领域知识的前沿技术&#xff0c;正逐渐改变着我们的生活和工作方式。从工业制造到家庭服务&#xff0c;从医疗护理到太空探索&#xff0c;具身智能机器人都展现出了巨大的潜力。对于想要深入了解和学习这一…

写项目时一些疑惑:组件间的通信、createDownloadUrl和DownloadUrl,ArrayBuffer与Blob等

目录 一、[vite] Internal server error: No known conditions for "./lib/locale/lang/zh-cn" specifier in "element-plus" package 二、可以用vue和JS的代码片段,但是用不了html的代码片段 三、meta是什么东西 四、为什么代码保持一致,但是时间轴始…

手动关闭ArcGIS与ArcGIS Online连接的方法

【关闭软件启动时ArcGIS与ArcGIS Online连接方法】 打开C盘找到文件夹“C:\Program Files (x86)\Common Files\ArcGIS\bin”&#xff0c;如下图&#xff0c;删除“ArcGISConnection.exe”与“ArcGISConnectionTest.exe”文件&#xff0c;软件下次启动的时候就不会建立与ArcGIS …

大M法处理非线性约束线性化

在电力系统优化问题中&#xff0c;大M法&#xff08;Big M Method&#xff09;是一种经典的处理非线性约束线性化的技术&#xff0c;尤其适用于混合整数线性规划&#xff08;MILP&#xff09;问题。 其核心思想是通过引入足够大的常数M和辅助变量&#xff08;如二元变量或松弛…

【网络安全】谁入侵了我的调制解调器?(一)

文章目录 我被黑了159.65.76.209,你是谁?黑客攻击黑客?交出证据三年后我被黑了 两年前,在我家里使用家庭网络远程办公时,遇到了一件非常诡异的事情。当时,我正在利用一个“盲 XXE 漏洞”,这个漏洞需要借助一个外部 HTTP 服务器来“走私”文件。为了实现这一点,我在 AW…

【Nokia 7360 ISAM局端】7360局端升级步骤

引言 Nokia 7360 ISAM局端是当前主流的OLT局端之一,在测试ONT产品中经常需要对接7360局端,特别是欧美等海外运营商。测试过程中经常需要升级OLT版本,以便对齐前方客户的现网环境。本文介绍将Nokia 7360 ISAM局端升级到L6GPAA65.669版本的详细步骤。 连接带外管理口 将维护…

主数据管理:企业数字化转型的 “数据基石“ 如何为 AI 筑基?

引言&#xff1a;当数据成为新石油&#xff0c;谁在炼制 "高纯度燃料"&#xff1f; 在数字化转型的浪潮中&#xff0c;企业宛如行驶在数据海洋中的巨轮&#xff0c;AI 则是驱动巨轮破浪前行的引擎。但引擎能否高效运转&#xff0c;取决于燃料的纯度 —— 这正是主数…

使用 chromedriver 实现网络爬虫【手抄】

1、引用 selenium 包 <dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.29.0</version> </dependency> <dependency><groupId>org.seleniumhq.seleniu…

Linux之 grep、find、ls、wc 命令

Linux之 grep、find、ls、wc 命令 “ 在 Linux 世界中&#xff0c;命令行是不可或缺的一部分&#xff0c;而掌握一些常用的命令可以帮助你更有效率地管理文件和系统。本文将为你介绍四個基礎而强大的 Linux 命令&#xff1a;grep、find、ls 和 wc&#xff0c;带你开启高效文件…

AI 模型高效化:推理加速与训练优化的技术原理与理论解析

AI 模型高效化&#xff1a;推理加速与训练优化的技术原理与理论解析 文章目录 AI 模型高效化&#xff1a;推理加速与训练优化的技术原理与理论解析一、推理加速&#xff1a;让模型跑得更快的“程序员魔法”&#xff08;一&#xff09;动态结构自适应推理&#xff1a;像人类一样…

c++STL——vector的使用和模拟实现

文章目录 vector的使用和模拟实现vector的使用vector介绍重点接口的讲解迭代器部分默认成员函数空间操作增删查改操作迭代器失效问题(重要)调整迭代器 vector的模拟实现实现的版本模拟实现结构预先处理的函数尾插函数push_backswap函数赋值重载size函数reserve函数 迭代器默认成…

git更新的bug

文章目录 1. 问题2. 分析 1. 问题 拉取了一个项目后遇到了这个问题&#xff0c; nvocation failed Server returned invalid Response. java.lang.RuntimeException: Invocation failed Server returned invalid Response. at git4idea.GitAppUtil.sendXmlRequest(GitAppUtil…

github | 仓库权限管理 | 开权限

省流版总结&#xff1a; github 给别人开权限&#xff1a;仓库 -> Setting -> Cllaborate -> Add people GitHub中 将公开仓库改为私有&#xff1a;仓库 -> Setting -> Danger Zone&#xff08;危险区&#xff09; ->Change repository visibility( 更改仓…

uniapp自定义底部导航栏,解决下拉时候顶部空白的问题

一、背景 最近使用uniapp开发微信小程序&#xff0c;因为使用了自定义的顶部导航栏&#xff0c;所以在ios平台上&#xff08;Android未测试&#xff09;测试的时候&#xff0c;下拉的时候会出现整个页面下拉并且顶部留下大片空白的问题 二、任务&#xff1a;解决这个问题 经…

C++学习之密码学知识

目录 1.文档介绍 2.知识点概述 3.项目准备 4.序列化介绍 5.项目中基础组件介绍 6.基础模块在项目中作用 7.项目中其他模块介绍 8.加密三要素 9.对称加密和非堆成加密 10.对称和非对称加密特点 11.堆成加密算法des 12.des对称加密算法 13.对称加密算法aes 14.知识点…

力扣 797. 所有可能的路径

题目 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特定顺序&#xff09; graph[i] 是一个从节点 i 可以访问的所有节点的列表&#xff08;即从节点 i 到节点 graph[i][j]存在一…

第二篇:linux之Xshell使用及相关linux操作

第二篇&#xff1a;linux之Xshell使用及相关linux操作 文章目录 第二篇&#xff1a;linux之Xshell使用及相关linux操作一、Xshell使用1、Xshell安装2、Xshell使用 二、Bash Shell介绍与使用1、什么是Bash Shell(壳)&#xff1f;2、Bash Shell能干什么&#xff1f;3、平时如何使…

一种改进的CFAR算法用于目标检测(解决多目标掩蔽)

摘要 恒虚警率&#xff08;CFAR&#xff09;技术在雷达自动检测过程中起着关键作用。单元平均&#xff08;CA&#xff09;CFAR算法在几乎所有的多目标情况下都会受到掩蔽效应的影响。最小单元平均&#xff08;SOCA&#xff09;CFAR算法仅当干扰目标位于参考窗口的前后方时才具有…

无人机+智能监控:石油管道巡检迈入“空中智慧时代”

引言&#xff1a;安全与效率的双重革命 在广袤的沙漠、崎岖的山脉或人迹罕至的冻土带&#xff0c;石油管道的安全巡检曾是一项耗时耗力且风险极高的任务。如今&#xff0c;随着无人机巡检技术与视频监控管理平台的深度融合&#xff0c;石油行业正迎来一场智能化变革——从“人巡…

三层交换机SVI功能(交换机虚拟接口)实现各个实训室电脑网络可互通,原本是独立局域网

三层交换机 SVI功能&#xff08;交换机虚拟接口&#xff09; 实现VLAN路由 需求 &#xff1a;各实训室使用独立局域网&#xff0c;即每个实训有自己的IP网段&#xff0c; 每个实训室只有内部互相访问。 需求&#xff1a;为了加强各实训室学生的交流&#xff0c;学校要求我们…