[SpringBoot] 多模块统一返回格式带分页信息

news2024/12/21 17:01:52

 ✨✨个人主页:沫洺的主页

 📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏 

                           📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专栏

💖💖如果文章对你有所帮助请留下三连✨✨

🍸效果 

在后端向前端返回统一格式data里一般按照需求是要包含分页信息的,比如总条数和按照每页的条数去返回对应的总页数等

🍹搭建多模块环境(父子项目) 

项目创建参考SpringBoot专栏里:

父项目scm-root的pom.xml

<?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.4</version>
        <relativePath/>
    </parent>
    <groupId>com.moming</groupId>
    <artifactId>scm-root</artifactId>
    <version>14-SNAPSHOT</version>
    <packaging>pom</packaging>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <modules>
        <module>scm-authority</module>
        <module>scm-app</module>
        <module>scm-dao</module>
        <module>scm-dto</module>
        <module>scm-entity</module>
        <module>scm-service</module>
        <module>scm-api</module>
        <module>scm-core</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.6</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.8.5</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>

    </build>

</project>

数据库

首先实现简单的查询业务

scm-dto模块

pom.xml依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

创建UserDto实体类

package com.moming.dto;

import lombok.Data;

@Data
public class UserDto {
    private Integer id;
    private String username;
    private String password;
}

scm-entity模块

pom.xml依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

创建UserEntity实体类

package com.moming.entity;

import lombok.Data;

@Data
public class UserEntity {
    private Integer id;
    private String username;
    private String password;
}

scm-dao模块

pom.xml依赖

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.moming</groupId>
            <artifactId>scm-entity</artifactId>
            <version>14-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

创建UserDao接口

package com.moming.dao;

import com.moming.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserDao {

    @Select("select * from tb_user order by id")
    List<UserEntity> select();

}

scm-service模块

pom.xml依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
        <dependency>
            <groupId>com.moming</groupId>
            <artifactId>scm-dao</artifactId>
            <version>14-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.moming</groupId>
            <artifactId>scm-dto</artifactId>
            <version>14-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

创建UserService业务类

package com.moming.service;

import cn.hutool.core.bean.BeanUtil;
import com.moming.dao.UserDao;
import com.moming.dto.UserDto;
import com.moming.entity.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    public List<UserDto> select(){
        List<UserEntity> entityList = userDao.select();
        List<UserDto> userDtos = BeanUtil.copyToList(entityList, UserDto.class);
        return userDtos;
    }
}

scm-app模块

pom.xml依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.9</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

        <dependency>
            <groupId>com.moming</groupId>
            <artifactId>scm-service</artifactId>
            <version>14-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

创建controller/UserController

package com.moming.controller;

import com.moming.dto.UserDto;
import com.moming.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/user")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/select")
    public List<UserDto> select(){
        return userService.select();
    }
}

创建resources/application.yml

#数据库连接信息配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db5?useSSL=false&useServerPrepStmts=true
    username: root
    password: 123456
    druid:
      initial-size: 10 # 初始化时建立物理连接的个数
      min-idle: 10 # 最小连接池数量
      maxActive: 200 # 最大连接池数量
      maxWait: 60000 # 获取连接时最大等待时间,单位毫秒
#映射文件所在位置
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  #别名
  type-aliases-package: com.moming.entity

#配置日志级别
logging:
  level:
    com.moming: debug

启动类App运行后调用接口测试

🥂统一返回格式

scm-dto模块

创建ResponseDto实体类

package com.moming.dto;

import lombok.Data;

@Data
public class ResponseDto {
    private int code;
    private String message;
    private Object data;
}

scm-app模块

创建advice/MyResponseAdvice

package com.moming.advice;

import cn.hutool.core.lang.Dict;
import cn.hutool.json.JSONUtil;
import com.moming.dto.PageInfo;
import com.moming.dto.ResponseDto;
import com.moming.local.PageInfoLocal;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;


@RestControllerAdvice(basePackages = MyResponseAdvice.BASEPACKAGES)
public class MyResponseAdvice implements ResponseBodyAdvice<Object> {
    public static final String BASEPACKAGES="com.moming.controller";

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
    @ExceptionHandler
    public  Object processException(Exception ex){
        ResponseDto responseDto = new ResponseDto();
        responseDto.setCode(1);
        responseDto.setMessage(ex.getMessage());
        return responseDto;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        ResponseDto responseDto = new ResponseDto();
        responseDto.setCode(0);
        responseDto.setMessage("");
        responseDto.setData(body);

        //处理返回类型为字符串
        if (selectedConverterType == StringHttpMessageConverter.class) {
            //hutool JSONUtil.toJsonStr字符串转换为json数据
            return JSONUtil.toJsonStr(responseDto);
        } else {
            return responseDto;
        }
    }
}

接口测试查看效果

🍻返回带分页信息格式 

业务需求:

不改变原有的代码,在返回的data中呈现总页数(pages)和(total)

分析:

首先完整的查询业务在上面已经写好了,根据业务需求要在不改变原有的代码的基础之上进行业务增强,就要使用AOP技术来实现,另外要获取总页数,那么在url接口上就需要传递每页多少条的参数(pageSize),既然实现了每页条数,那么同样的就可以传递第几页(pageNum)去动态查询某页的数据,接下来就是怎么去获取url传递的参数,可以通过AOP中的环绕通知,在环绕前使用RequestContextHolder对象去获取ServletRequestAttributes对象,然后通过它去获取HttpServletRequest对象,最后调用getParameter获取参数,获取参数之后使用PageHelper调用startPage方法会将目标方法返回值的类型改为Page类型(底层实现了ArrayList),而Page底层提供了total,pages等属性的get方法,因为属性有很多所以这里需要处理以下,通过我们自定义的PageInfo的set方法获取total,pages的值,然后使用ThreadLocal(本地线程)的机制去实现线程安全问题,ThreadLocal中填充的的是当前线程的变量,该变量对其他线程而言是封闭且隔离的(也就是线程安全的),ThreadLocal为变量在每个线程中创建了一个副本,这样每个线程就可以访问自己内部的副本变量,通过这种机制我们给当前线程脑门上贴一个变量(pageInfo),然后再获取当前线程脑门上的变量(pageInfo),最后移除当前线程脑门上的变量(pageInfo)

scm-app模块

pom.xml添加依赖

AOP坐标依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

第三方pagehelper分页坐标依赖

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.5</version>
        </dependency>

相关模块导入依赖

        <dependency>
            <groupId>com.moming</groupId>
            <artifactId>scm-core</artifactId>
            <version>14-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

创建local/PageInfoLocal

package com.moming.local;

import com.moming.dto.PageInfo;

public class PageInfoLocal {
    private static ThreadLocal<PageInfo> threadLocal = new InheritableThreadLocal<>();

    //给当前线程头上贴一个变量 pageinfo
    public static void set(PageInfo pageInfo){
        threadLocal.set(pageInfo);
    }

    //获取当前线程头上的变量 pageinfo
    public static PageInfo get(){
        return threadLocal.get();
    }

    //移除当前线程头上的变量 pageinfo
    public static void remove(){
        threadLocal.remove();
    }
}

创建aop/DaoAop

package com.moming.aop;

import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.moming.dto.PageInfo;
import com.moming.local.PageInfoLocal;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Component
@Aspect
public class DaoAop {
    //通过注解方式定义切入点
    @Pointcut("@annotation(com.moming.annotation.PageCut)")
    public void point(){}

    //环绕通知
    @Around("point()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //获取url传递的参数
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String pageNum = request.getParameter("pageNum");
        String pageSize = request.getParameter("pageSize");
        //如果只传递pageSize,则默认pageNum为1
        if( ObjectUtil.isNotEmpty(pageSize)){
            int page_num =1;
            if(ObjectUtil.isNotEmpty(pageNum)){
                page_num = Integer.valueOf(pageNum);
            }
            int page_size = Integer.valueOf(pageSize);
            PageHelper.startPage(page_num,page_size);
        }
        //目标方法List<UserEntity> select()---
        Object result = pjp.proceed();
        //如果目标方法的返回值类型为Page,则将pageInfo对象贴在当前线程脑门上
        if(result instanceof Page){
            Page page = (Page) result;
            //使用自定义的PageInfo对象获取需要的分页信息
            PageInfo pageInfo = new PageInfo();
            pageInfo.setPages(page.getPages());
            pageInfo.setTotal(page.getTotal());
            PageInfoLocal.set(pageInfo);
        }
        return result;
    }
}

在通知类里对分页信息进行封装

        //分页组件扩展开始
        PageInfo pageInfo = PageInfoLocal.get();
        try{
            if(pageInfo!=null){
                Dict dict = Dict.create()
                        .set("pages",pageInfo.getPages())
                        .set("total", pageInfo.getTotal())
                        .set("items",body);
                responseDto.setData(dict);
            }
            else {
                responseDto.setData(body);
            }
            //分页组件扩展结束
        }finally {
            //移除当前线程头上的变量标签
            if(pageInfo!=null){
                PageInfoLocal.remove();
            }
        }

advice/MyResponseAdvice

package com.moming.advice;

import cn.hutool.core.lang.Dict;
import cn.hutool.json.JSONUtil;
import com.moming.dto.PageInfo;
import com.moming.dto.ResponseDto;
import com.moming.local.PageInfoLocal;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;


@RestControllerAdvice(basePackages = MyResponseAdvice.BASEPACKAGES)
public class MyResponseAdvice implements ResponseBodyAdvice<Object> {
    public static final String BASEPACKAGES="com.moming.controller";

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
    @ExceptionHandler
    public  Object processException(Exception ex){
        ResponseDto responseDto = new ResponseDto();
        responseDto.setCode(1);
        responseDto.setMessage(ex.getMessage());
        return responseDto;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        ResponseDto responseDto = new ResponseDto();
        responseDto.setCode(0);
        responseDto.setMessage("");
        //分页组件扩展开始
        PageInfo pageInfo = PageInfoLocal.get();
        try{
            if(pageInfo!=null){
                Dict dict = Dict.create()
                        .set("pages",pageInfo.getPages())
                        .set("total", pageInfo.getTotal())
                        .set("items",body);
                responseDto.setData(dict);
            }
            else {
                responseDto.setData(body);
            }
            //分页组件扩展结束
        }finally {
            //移除当前线程头上的变量标签
            if(pageInfo!=null){
                PageInfoLocal.remove();
            }
        }

        //responseDto.setData(body);
        //处理返回类型为字符串
        if (selectedConverterType == StringHttpMessageConverter.class) {
            //hutool JSONUtil.toJsonStr字符串转换为json数据
            return JSONUtil.toJsonStr(responseDto);
        } else {
            return responseDto;
        }
    }
}

scm-core模块

pom.xml依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

创建annotation/PageCut注解

package com.moming.annotation;

import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PageCut {
}

创建dto/PageInfo实体类

package com.moming.dto;

import lombok.Data;

@Data
public class PageInfo {
    private int pages;
    private long total;
}

scm-dao模块

目标方法添加切入点注解

package com.moming.dao;

import com.moming.annotation.PageCut;
import com.moming.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserDao {

    @PageCut
    @Select("select * from tb_user order by id")
    List<UserEntity> select();

}

测试

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

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

相关文章

算法刷题路线总结与相关资料分享

算法刷题路线总结与相关资料分享前言一、算法刷题路线总结二、算法题刷题步骤三、基础数据结构与算法知识1、时间复杂度2、空间复杂度3、线性表4、栈与队列5、树四、算法学习相关资料推荐1.数据结构与算法基础2.专项刷题路线资料3.算法课程视频资料后记前言 本文为算法刷题路线…

双十一数码产品哪些值得买?双十一好物产品分享

双十一必然是数码产品最值得买的&#xff0c;因为这类产品的优惠力度往往是最大的&#xff0c;所以每年的双十一都是升级数码设备的好时机&#xff0c;今天为大家带来的是便是个人推荐的双十一数码好物。好了&#xff0c;废话不再多说&#xff0c;我们开车吧。 一、不伤耳的骨…

postman 实用教程(含带 token 访问需登录权限的接口)

下载安装 Postman 访问官网下载安装 Postman https://www.postman.com/downloads/?utm_sourcepostman-home 新建文档 右键菜单可以重命名 新建接口 选择接口类型输入接口若传入参数格式为 json &#xff0c;则选择 Body 中的 raw 和 JSON输入传入的参数&#xff08;json格式&a…

计算机网络--数据链路层

今天来讲网络协议栈的最后一层&#xff0c;数据链路层(物理层我们不考虑了)&#xff0c;我们之前学到&#xff0c;TCP协议提供了数据传输的可靠性&#xff0c;IP层决定数据报从哪到哪&#xff0c;那么数据报是如何从一个结点到下一个结点呢&#xff1f;得到相应如何返回呢&…

(02)Cartographer源码无死角解析-(09) gflags与glog简介、及其main函数讲解

本人讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文…

软件工程结构化设计

目录 结构化分析与结构化设计的关系&#xff1a; 体系结构设计概念&#xff1a; 图形工具&#xff1a; 层次图&#xff1a;调用关系​编辑 HIPO图&#xff1a;层次图IPO图 软件结构图&#xff1a; 软件设计原则&#xff1a; 模块化&#xff1a; 模块划分注意事项&#xf…

巴什博弈——范围拿物品问题

巴什博弈 巴什博弈&#xff08;Bash game&#xff09; 是一个双人博弈&#xff1a;有一堆总数为n的物品&#xff0c;2名玩家轮流从中拿取物品。每次至少拿1件&#xff0c;至多拿m件&#xff0c;不能不拿&#xff0c;最终将物品拿完者获胜。 巴什博弈除了两人轮流按一定数量拿物…

【黄啊码】MySQL入门—14、细说数据库的MVCC机制

大家好&#xff0c;我是黄啊码。上一篇文章中&#xff0c;我们讲到了锁的划分&#xff0c;以及乐观锁和悲观锁的思想。今天我们就来看下 MVCC&#xff0c;它就是采用乐观锁思想的一种方式。那么它到底有什么用呢&#xff1f; 我们知道事务有 4 个隔离级别&#xff0c;以及可能…

共谋韬略、共巢未来,电巢与韬略“战略合作签约仪式”圆满举办!

前言 2022年10月27日下午&#xff0c;电巢科技与韬略科技齐聚深圳南山&#xff0c;共同举办了隆重的战略合作签约仪式&#xff0c;双方就整合核心资源、共同打造高质量数字化内容等战略方针达成了一致&#xff0c;携手开启合作新篇章。 电巢科技和韬略科技基于相契合的发展战略…

Numpy基础教程

1 Numpy 对象2 Numpy创建numpy.array 构造器来创建numpy.emptynumpy.zerosnumpy.onesnumpy.arangeNumpy索引3 Numpy常用操作numpy.reshapenumpy.reshape(arr,newshape,order C)numpy.transposenumpy.expand_dimsnumpy.squeezeNumpy功能十分强大的python扩展库&#xff0c;数学…

基于Java+Springboot+Vue+elememt美食论坛平台设计实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取联系&#x1f345;精彩专栏推荐订阅&#x1f447;&#x1f…

07-树(Tree)结构分析

文章目录树(Tree)结构分析什么是树&#xff1f;树中的相关名词如何理解&#xff1f;什么是二叉树&#xff1f;什么是二叉搜索树&#xff1f;什么是AVL树&#xff1f;什么是2-3树&#xff1f;什么是红黑树&#xff1f;总结&#xff08;Summary&#xff09;树(Tree)结构分析 什么…

【飞桨PaddleSpeech语音技术课程】— 语音识别-流式服务

FastAPI websocket 流式语音识别服务 0. 背景 流式语音识别(Streaming ASR)或者在线语音识别(Online ASR) 是随着输入语音的数据不断增加&#xff0c;实时给出语音识别的文本结果。与之相对的是非实时或者离线语音识别&#xff0c;是传入完整的音频数据&#xff0c;一次给出整…

ppocrlabel简单教学

前言 给我们小白成员的快速上手ppocrlabel的指南 1. ppocr环境配置 建议是先创建一个虚拟环境 【直接参考】&#xff1a;https://blog.csdn.net/weixin_42708301/article/details/119864744 2. ppocrlabel环境安装 【参考文档】PaddleOCR-release-2.6\PPOCRLabel\README_c…

将STM32 内部Flash虚拟成优盘,进行IAP升级

书接上回&#xff0c;上篇文章已经成功的将 STM32 内部FLASH虚拟成优盘进行文件存储了。 【将 STM32 内部Flash虚拟成优盘】https://blog.csdn.net/qq_44810226/article/details/127508789 然后我们开始固件升级流程&#xff1a; 从上图可以看出&#xff0c;固件存储的位置是不…

Python-代码封装思想

继上文所将讲的pythonrequestsUnittest框架&#xff0c;本文将继续分享python代码的进一步封装思想&#xff0c;来提高代码的整体运行效率及整洁性&#xff0c;本文以接口测试框架为例进行讲解。 关于Unittest单元测试框架的具体使用方法链接链接&#xff08;点击跳转&#xf…

MMEngine理解

MMEngine理解1 简介1.1 架构1.2 模块介绍1.2.1 核心模块与相关组件1.2.1 公共基础模块2 上手示例2.1 构建模型2.2 构建数据集和数据加载器2.3 构建评测指标2.4 构建执行器并执行任务3. 基础模块3.1 注册器&#xff08;Registry&#xff09;3.1.1 什么是注册器3.1.2 使用流程3.1…

OSPF路由协议(二)

作者介绍&#xff1a; ⭐️作者&#xff1a;小刘在C站 ❄️每天分享课堂笔记&#xff0c;一起努力&#xff0c;共赴美好人生&#xff01; ☁️夕阳下&#xff0c;是最美的绽放。 目录 一.Router id 二.DR,BDR 三.DR BDR 选举过程 四.ospf 度量值 cost 代价 五.ospf 的数据…

部署vue项目到阿里云服务器

一般前端工程师只会使用npm run serve 在开发环境下验证&#xff0c;那么如何把npm run build 打出的包部署到服务器上进行上线呢&#xff1f;这篇文章就详细阐述这一流程。 1. 购买或试用阿里云服务器 作为新用户可以试用一个月阿里云服务器&#xff0c;阿里云官方网址如下&a…

【数据结构与算法分析】0基础带你学数据结构与算法分析07--二叉树

在学习上一章后&#xff0c;我们对树加以限制&#xff0c;如果树的度为 2&#xff0c;那么就称这颗树为 二叉树 (binary tree)。 二叉树的性质 在一棵二叉树上&#xff0c;有一些重要的性质&#xff1a; 第 i 层 (i∈N) 上最多有 2^(i−1) 个结点层次为 k(k∈N) 的树最多有 …