【微服务】springboot 实现动态修改接口返回值
目录
一、前言
二、动态修改接口返回结果实现方案总结
2.1 使用反射动态修改返回结果参数
2.1.1 认识反射
2.1.2 反射的作用
2.1.3 反射相关的类
2.1.4 反射实现接口参数动态修改实现思路
2.2 使用@ControllerAdvice 注解动态修改返回结果参数
2.2.1 注解作用
2.2.2 实现思路
2.3 使用AOP动态修改返回结果参数
三、动态修改接口返回结果操作实践
3.1 前置准备
3.2 使用反射实现结果集参数动态修改
3.2.1 自定义反射工具类
3.2.2 测试接口继承工具类
3.3 使用@ControllerAdvice实现结果集参数动态修改
3.3.1 @ControllerAdvice 简单介绍
3.3.2 @ControllerAdvice 主要作用
3.3.3 @ControllerAdvice 用法
3.3.4 @ControllerAdvice实现结果集参数动态修改
3.4 使用自定义注解+AOP实现接口参数动态修改
3.4.1 实现思路
3.4.2 自定义注解
3.4.3 自定义AOP类
3.4.4 测试接口一
3.4.5 测试接口二
四、插件化封装
4.1 操作过程
4.1.1 创建maven工程
4.1.2 导入依赖
4.1.3 代码迁移
4.1.4 配置自动装配文件
4.1.5 使用maven命令安装jar包
4.2 功能测试
4.2.1 导入上一步的依赖
4.2.2 接口改造
4.2.3 接口测试
五、写在文末
一、前言
在日常项目开发中,涉及到很多需要动态修改rest接口返回参数的场景,比如对接口中的字段统一脱敏,对接口中的某些字段进行二次加密处理,或者对某些特别的字段根据安全审计要求进行二次处理,甚至需要动态的在接口中增加额外的参数等,诸如此类的场景不胜枚举,本篇将介绍如何在springboot项目对接口返回结果进行动态修改。
二、动态修改接口返回结果实现方案总结
在springboot框架下,基于框架现有提供的技术组件,有很多种实现方式,下面分别展开来说。
2.1 使用反射动态修改返回结果参数
2.1.1 认识反射
Java的反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法;对于任意一个对象,都能够调用它的任何方法和属性。这种动态获取类的信息以及动态调用方法的功能称为Java语言的反射(reflection)机制。
2.1.2 反射的作用
通过反射机制就能在程序运行时发现该对象和类的真实信息,利用这个机制,可以动态修改类对象中的参数信息,比如运行过程中对象参数的值。
2.1.3 反射相关的类
反射中常会涉及到下面几个概念
-
Class类
-
代表类的实体,在运行的Java应用程序中表示类和接口
-
-
Field类
-
代表类的成员变量/字段
-
-
Method类
-
代表类的方法
-
-
Constructor类
-
代表类的构造方法
-
2.1.4 反射实现接口参数动态修改实现思路
完整的实现思路如下:
-
获取接口返回值;
-
拿到上一步返回值中的结果集对象
-
拆解结果集,通过反射,获取结果集中的对象实例,解析其中的字段
-
获取字段的名称,字段的返回值
-
根据业务需求,对指定的字段结果进行修改
-
伪代码如下:
public void modifyResult(List<T> result,String... params){1、解析结果集2、反射获取结果集实例3、获取并解析结果集实例中的字段信息4、结合入参,动态修改字段值,并重新设置到实例对象中
}
2.2 使用@ControllerAdvice 注解动态修改返回结果参数
2.2.1 注解作用
@ControllerAdvice 是 Spring Framework 提供的一个注解,它用于定义一个全局的异常处理器或跨切面行为(cross-cutting concern)。这个注解可以用来集中处理控制器中的一些公共关注点,如全局异常处理、数据绑定初始化等。主要作用如下:
全局异常处理
@ControllerAdvice 可以用来定义一个全局的异常处理器。当你在控制器中抛出了一个未被捕获的异常时,你可以定义一个带有 @ExceptionHandler 注解的方法来处理这个异常。这样可以避免在每个控制器或方法中重复定义相同的异常处理逻辑。
统一数据绑定初始化
除了异常处理外,@ControllerAdvice 还可以用来初始化数据绑定,这可以通过使用 @ModelAttribute 注解来实现。这种方法常用于在所有控制器方法调用前预先设置一些模型属性。
统一前置或后置处理
@ControllerAdvice 结合 @InitBinder 注解还可以用来定义全局的绑定初始化器和数据格式化器。此外,还可以使用 @ModelAttribute 注解来定义在所有控制器方法之前执行的前置处理方法,或者使用 @ModelAttribute 注解的方法来填充模型属性。
2.2.2 实现思路
使用@ControllerAdvice 注解实现接口返回值参数动态修改的思路如下:
-
解析返回结果;
-
反射获取结果中的对象实例;
-
修改对象参数;
补充说明:
如果仅仅是为了在返回的结果集增加参数,或者对某些固定参数进行处理,可以忽略反射这一步的操作
2.3 使用AOP动态修改返回结果参数
aop是一种很好的解决公共业务场景下通用问题的实现思路,像本次的需求,修改接口参数一般并不局限于某个具体接口,而是在很多场景下都可能用到,因此使用AOP来解决也是一种很好切入点,具体来说,主要实现思路如下:
-
自定义注解;
-
注解中的参数可根据实际需要添加,比如可以添加需要修改的参数名称,修改后的类型等;
-
-
为需要修改结果集参数的接口添加上一步的自定义注解;
-
自定义AOP实现类,解析接口的参数,解析返回结果,利用反射技术,将结果集中需要修改的参数重新赋值;
三、动态修改接口返回结果操作实践
基于上面探讨的几种实现方案,接下来通过实战案例代码分别演示说明。
3.1 前置准备
创建一个springboot工程,并导入如下必要的依赖
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.44</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
3.2 使用反射实现结果集参数动态修改
参考下面的操作步骤。
3.2.1 自定义反射工具类
完整的代码如下,实现思路:
-
方法接收一个泛型的对象T,和一组待修改的参数;
-
使用反射技术实例化对象T,拿到实例对象的字段信息;
-
循环遍历字段Field对象列表,然后进行参数值的重新赋值;
import lombok.extern.slf4j.Slf4j;import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;@Slf4j
public class ResultHandler {public <T> void setUserInfo(T t, String... params) {if (Objects.isNull(t)) {log.error("t 参数为空");return;}List<String> modifyParams = Arrays.stream(params).toList();Class<? extends Object> tClass = t.getClass();Field[] fields = tClass.getDeclaredFields();Arrays.stream(fields).filter(item ->modifyParams.contains(item.getName())).collect(Collectors.toList()).forEach(field -> {field.setAccessible(true);String fieldName = field.getName();Object value = null;try {value = field.get(t);field.set(t, value + "_change");} catch (IllegalAccessException e) {throw new RuntimeException(e);}});}}
3.2.2 测试接口继承工具类
如果你的接口需要动态修改返回值参数,可以继承上述工具类,如下:
@RestController
public class AviatorController extends ResultHandler{//localhost:8081/aop/post/test@PostMapping("/aop/post/test")public UserRequest testPost(@RequestBody(required = false) UserRequest userRequest) {System.out.println("进入接口");setUserInfo(userRequest,"name");return new UserRequest(userRequest.getName(),userRequest.getAddress());}}
在上面的接口中,在最终返回数据之前,调用工具类中的方法,传入返回值吗,剩下的交给工具类中的方法处理即可,启动工程之后,测试一下接口,可以看到,返回值中的name参数就被修改了
3.3 使用@ControllerAdvice实现结果集参数动态修改
3.3.1 @ControllerAdvice 简单介绍
@ControllerAdvice 是 Spring Framework 提供的一个注解,用于定义一个全局异常处理器或者跨切面的增强功能。它是一个特殊的切面(AOP Aspect),可以用于处理控制器(@Controller 或 @RestController)中的异常、数据绑定错误、模型属性预填充以及其他跨切面的关注点。@ControllerAdvice 注解通常用在需要对多个控制器进行统一处理的场景中,比如全局异常处理、数据验证失败处理、模型属性预填充等。
3.3.2 @ControllerAdvice 主要作用
@ControllerAdvice 主要有如下作用:
-
全局异常处理
-
可以捕获所有控制器中抛出的异常,并提供统一的处理逻辑。
-
使开发者能够集中处理异常,而不是在每个控制器中重复编写相同的异常处理代码。
-
-
数据绑定错误处理
-
当数据绑定失败时,可以捕获
BindException
或MethodArgumentNotValidException
等异常,并进行统一处理。 -
便于对前端传来的数据进行统一的校验和错误提示。
-
-
模型属性预填充
-
可以在请求处理之前预先填充模型属性,比如当前时间、用户信息等。
-
使得控制器方法更加简洁,减少重复代码。
-
-
跨切面关注点
-
可以用来处理一些横切关注点,比如日志记录、安全检查等。
-
通过 @ModelAttribute 或者自定义注解来实现。
-
3.3.3 @ControllerAdvice 用法
全局异常处理
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(value = {NullPointerException.class})public ResponseEntity<Object> handleNullPointerException(NullPointerException ex) {// 处理空指针异常return ResponseEntity.status(400).body("Null pointer exception occurred: " + ex.getMessage());}@ExceptionHandler(value = {IllegalArgumentException.class})public ResponseEntity<Object> handleIllegalArgumentException(IllegalArgumentException ex) {// 处理非法参数异常return ResponseEntity.status(400).body("Illegal argument exception occurred: " + ex.getMessage());}
}
数据绑定错误处理
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;import java.util.HashMap;
import java.util.Map;@ControllerAdvice
public class DataBindingExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity<Object> handleValidationExceptions(MethodArgumentNotValidException ex) {BindingResult result = ex.getBindingResult();Map<String, String> errors = new HashMap<>();result.getAllErrors().forEach((error) -> {String fieldName = ((FieldError) error).getField();String errorMessage = error.getDefaultMessage();errors.put(fieldName, errorMessage);});return ResponseEntity.badRequest().body(errors);}
}
模型属性预填充
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;@ControllerAdvice
public class ModelAttributePrePopulator {@ModelAttribute("currentUser")public String getCurrentUser() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();return authentication.getName();}
}
3.3.4 @ControllerAdvice实现结果集参数动态修改
自定义一个类实现ResponseBodyAdvice接口,如下:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import java.util.HashMap;
import java.util.Map;@ControllerAdvice
public class DataChangeAdvice implements ResponseBodyAdvice {static ObjectMapper objectMapper = new ObjectMapper();@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType,MediaType selectedContentType, Class selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {Map res = new HashMap();res.put("code",200);//如果返回值是String,直接放到Result里if (body instanceof String) {res.put("data",(String) body);return res;}//如果返回值是标准返回格式,就不需要再次封装了//如果不加这个判断,异常的结果会被封装两次else if (body instanceof Map) {return body;}String dataStr = null;try {dataStr = objectMapper.writeValueAsString(body);res.put("data",dataStr);} catch (JsonProcessingException e) {e.printStackTrace();}return res;}@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}
}
运行工程之后,测试一下上面的接口,可以看到,原本的接口返回值根据业务的需要重新做了修改
基于上述的改造,还可以继续扩展,比如通过自定义注解,在接口上面添加自定义注解,然后再在返回值中解析自定义注解,并根据实际的需要重新对注解中的参数进行修改。
3.4 使用自定义注解+AOP实现接口参数动态修改
在之前分享的一篇文章中,我们使用AOP+自定义注解的方式实现了请求参数的动态修改,使用这个方式是否也可以对接口返回的参数进行修改呢?
3.4.1 实现思路
参考下面的实现思路进行实现
-
自定义注解,
-
属性主要包括:待修改的结果参数名称,修改的格式等;
-
-
自定义AOP类,对于那些标注了上述自定义注解的接口进行拦截;
-
使用环绕通知的方式;
-
-
在AOP执行方法中调用point.proceed()获取目标方法的执行结果;
-
在结果中,使用反射,结合解析到的自定义注解,从而动态修改接口的参数值;
-
3.4.2 自定义注解
自定义一个注解,用于接口中待修改的参数进行标注
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ModifyResponseParams {Param[] value() default {};String dataFormat() default "";@Retention(RetentionPolicy.RUNTIME)@Target({})public static @interface Param {String name();String value() default "";}}
3.4.3 自定义AOP类
aop中的业务逻辑即可结合上面的实现思路进行理解,参考如下完整的示例代码,实现逻辑也是按照上述的实现思路进行构建
package com.congge.aop;import com.congge.controller.R;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;@Aspect
@Component
@Order(1)
@Slf4j
public class ResponseParamModifierAspect {@Around("@annotation(modifyResponseParams)")public Object modifyRequestParams(ProceedingJoinPoint point, ModifyResponseParams modifyResponseParams) throws Throwable {List<String> modifyParams = new ArrayList<>();for (ModifyResponseParams.Param param : modifyResponseParams.value()) {modifyParams.add(param.name());}Object t = point.proceed();if (Objects.isNull(t)) {log.error("接口返回结果为空");return t;}//获取返回结果集并解析R<?> r = (R<?>) t;Object data = r.getData();if (data instanceof List<?>) {List<?> list = (List<?>) data;list.forEach(item ->{Class<?> tClass = item.getClass();Field[] fields = tClass.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String fieldName = field.getName();if(modifyParams.contains(fieldName)){try {Object value = field.get(item);field.set(item, value + "_change");} catch (IllegalAccessException e) {throw new RuntimeException(e);}}}});}else {Object t1 = data;Class<? extends Object> tClass = t1.getClass();Field[] fields = tClass.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String fieldName = field.getName();if(modifyParams.contains(fieldName)){try {Object value = field.get(t1);field.set(t1, value + "_change");} catch (IllegalAccessException e) {throw new RuntimeException(e);}}}}return t;}}
3.4.4 测试接口一
在测试接口上面添加上述自定义注解,对需要修改的参数在注解中进行标注
@ModifyResponseParams(value = {@ModifyResponseParams.Param(name = "address"),@ModifyResponseParams.Param(name = "name")})@PostMapping("/aop/modify/v1")public R testModifyV1(@RequestBody(required = false) UserRequest userRequest) {System.out.println("进入接口");return R.ok(new UserRequest(userRequest.getName(),userRequest.getAddress()));}
使用接口工具调用一下,可以看到接口返回值中的两个参数被修改了
3.4.5 测试接口二
这一次,返回一个集合
@ModifyResponseParams(value = {@ModifyResponseParams.Param(name = "address"),@ModifyResponseParams.Param(name = "name")})@PostMapping("/aop/modify/v2")public R testModifyV2(@RequestBody(required = false) UserRequest userRequest) {System.out.println("进入接口");List<UserRequest> userRequests =Arrays.asList(new UserRequest(userRequest.getName(), userRequest.getAddress()));return R.ok(userRequests);}
使用接口工具调用一下,可以看到接口返回值中的两个参数被修改了
四、插件化封装
有了上面的实践之后,为了减少后续遇到类似的场景时的多次重复编码,可以考虑将上述AOP的实现方案使用springboot的starter机制进行插件化封装,参考如下操作步骤。
4.1 操作过程
4.1.1 创建maven工程
工程目录结构如下
4.1.2 导入依赖
主要包括下面几个核心依赖
<dependencies><!-- Spring框架基本的核心工具 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><!--阿里 FastJson依赖--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.44</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency></dependencies>
4.1.3 代码迁移
将上一小节中的几个核心实现类拷贝过来到aop包下(略)
4.1.4 配置自动装配文件
在resources目录下,参考工程结构,创建配置文件 spring.factories ,将AOP的完整类路径名称配置进去
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.congge.aop.ResponseParamModifierAspect
4.1.5 使用maven命令安装jar包
执行mvn install 命令,将工程的jar安装到本地仓库中
4.2 功能测试
4.2.1 导入上一步的依赖
在需要的工程pom中导入上一步的依赖jar的maven坐标
<dependency><groupId>com.congge</groupId><artifactId>aop_com</artifactId><version>1.0-SNAPSHOT</version></dependency>
4.2.2 接口改造
原本的接口代码逻辑保持不变,只需要将自定义注解改为上一步的注解即可
4.2.3 接口测试
启动工程之后再次调用上述接口,接口返回值参数被修改了,说明插件包中的逻辑正常生效了
五、写在文末
本文通过案例和操作详细介绍了如何在微服务项目中实现对接口返回值的参数修改,在实际应用中,可以结合案例中的思路以及自身的需求场景进行深度的拓展,希望对看到的同学有用,本篇到此结束,感谢观看。
相关文章:

【微服务】springboot 实现动态修改接口返回值
目录 一、前言 二、动态修改接口返回结果实现方案总结 2.1 使用反射动态修改返回结果参数 2.1.1 认识反射 2.1.2 反射的作用 2.1.3 反射相关的类 2.1.4 反射实现接口参数动态修改实现思路 2.2 使用ControllerAdvice 注解动态修改返回结果参数 2.2.1 注解…...

【前端开发入门】html快速入门
目录 引言一、html基础模板内容二、html文档流三、html 标签1.块级元素2.行内元素3.功能性元素4.标签嵌套 四、html编码习惯五、总结 引言 本系列教程旨在帮助一些零基础的玩家快速上手前端开发。基于我自学的经验会删减部分使用频率不高的内容,并不代表这部分内容不…...

python配置环境变量
方法一:首先卸载重新安装,在安装时勾选增加环境变量 方法二:我的电脑-属性-高级系统配置 手动添加环境变量,路径为python的安装路径 检查:查看环境变量是否安装成功 安装第三方lib winr,输入cmd pip ins…...

从0到1:培训机构排课小程序开发笔记一
业务调研 随着人们生活水平的提高,健康意识和学习需求日益增强,私教、健身和培训机构的市场需求迅速增长。高效的排课系统不仅可以提升机构的管理效率,还能提高学员的满意度。解决传统的排课方式存在的时间冲突、信息不对称、人工操作繁琐等…...

方法重载(Overload)
前言 在前面的学习中,我们学到了重写(Override),这里我们主要进行重载(Overload)的介绍,同时对重写和重载的区别进行分析。 1. 重载(Overload) #方法重载 在同一个类中定义多个同名但参数不同的方法。我们称方法与方法之间构成方法重载 在Java中&…...

[论文笔记]SGPT: GPT Sentence Embeddings for Semantic Search
引言 解码器Transformer的规模不断壮大,轻松达到千亿级参数。同时由于该规模,基于提示或微调在各种NLP任务上达到SOTA结果。但目前为止解码器Transformer还无法应用在语义搜索或语句嵌入上。 为了简单,下文中以翻译的口吻记录,比…...

基于微信小程序的旅游拼团系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...

富格林:警悟可信经验安全投资
富格林指出,黄金具有不错的投资价值,一直以来备受投资者的喜爱,近年来大家也纷纷加入现货黄金市场为己增值财富。但是要为投资安全护航的前提,是需要投资者使用合适可信的方法以及掌握相对应的投资技巧。下面富格林将总结以下可信…...

【Linux】使Ubuntu自适应窗口大小并与主机共享文件
LInux虚拟机版本ubuntu-20.04.6,VM版本VMware Workstation 17 Pro VMware Tools™ 是一组服务和模块,是VMware公司在其虚拟化平台中提供的一套工具集,旨在提高虚拟机的性能和稳定性。它们支持 VMware 产品中的多种功能特性,有助于…...

C++ 语言特性18 - static_assert 介绍
一:概述 在 C 中,static_assert 是一种用于在编译时进行断言的机制,确保某些编译时条件成立。如果条件不成立,则编译器会生成错误,阻止代码的编译。static_assert 在 C11 中引入,目的是帮助程序员在编译时捕…...

centos 7.9系统redis6.2.6哨兵模式部署
由于系统需要处理大量的数据并发请求,所以借助于Redis的高性能,可以有效提升整个系统的处理效率。这里采用redis6.2版本源码编译部署哨兵模式,提高整个系统的可用性,避免单点故障。 1. Redis基本环境安装 centos7安装redis 6.2.6 采用源码编译方式安装。 服务器主机名:…...

编程基础:详解 C++ 中的 `std::sort` 函数
编程基础:详解 C 中的 std::sort 函数 在C编程中,排序是非常常见的操作,而std::sort是C标准库中用于排序的一个高效函数。它提供了灵活的排序功能,可以使用默认排序规则或自定义的比较函数。本文将深入探讨std::sort的用法、参数要…...

51单片机的宠物自动投喂系统【proteus仿真+程序+报告+原理图+演示视频】
1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块温湿度传感器DS1302时钟模块蓝牙步进电机按键、蜂鸣器等模块构成。适用于猫猫/狗狗宠物自动喂食器等相似项目。 可实现基本功能: 1、LCD1602实时显示北京时间和温湿度 2、温湿度传感器DHT11采集环境温湿度 3、时…...

MongoDB快速实战与基本原理
目录 链接:https://note.youdao.com/ynoteshare/index.html?id=5e038498891617c552667b853742fdc1&type=note&_time=1727935558812 Mongo数据库的特点: mongo数据库和关系型数据库的区别: 编辑 关系型数据库和文档型数据库的主要概念对比: 下载和启动(具体…...

编程技巧:优化
第一种:构造回文串---构造法 题目描述 [NOIP2016 普及组] 回文日期 - 洛谷 那么这道题我们总结一些题目要求: 1.输入两个字符串,为起始和终止日期 2.年份不会出现前导0 3.如果是回文日期,答案1 4.如果月份是2,要…...

pycharm中使用anaconda创建多环境,无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
问题描述 用的IDE是: 使用anaconda创建了一个Python 3.9的环境 结果使用pip命令的时候,报错 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称 解决方案 为了不再增加系统变量,我们直接将变量添加在当前项目中你的Ter…...

【Linux】进程周边之优先级
目录 一、优先级 1.为什么要有进程优先级? 2.什么是进程优先级? 3.优先级的初始设定 3.1 PRI 和 NI 3.2如何修改优先级?(sudo/root) 3.2.1 概念: 3.2.2 如何查看进程的优先级? 3.3.3 或…...

Linux高级编程_29_信号
文章目录 进程间通讯 - 信号信号完整的信号周期信号的编号信号的产生发送信号1 kill 函数(他杀)作用:语法:示例: 2 raise函数(自杀)作用:示例: 3 abort函数(自杀)作用:语法:示例: 4 …...

uniapp修改uni-ui组件样式(对微信小程序/H5有效,vue3)
寻找要修改的样式 使用开发者工具找到具体要修改的class类名 修改 <style lang"scss">//.nav为上一级的class.nav::v-deep .uni-navbar--border {border-bottom-style: none !important;} </style>完整代码 <template><view><uni-na…...

Python 封装 socket 为 [TCP/UDP/MULTICAST] 服务端
在新线程中创建 TCP/UDP/MULTICAST 协议的服务端套接字,接收客户端的连接请求或数据,并调用 on_recv 回调函数处理数据。 #!/usr/bin/env python # -*- coding: utf-8 -*- import socket import threading import multiprocessingclass ServerSocket:de…...

c++ STL库 unordered_map
#include <iostream #include <string #include <unordered_map int main() { // 创建一个 unordered_map std::unordered_map<std::string, int> wordCount; // 插入元素 wordCount["apple"] 1; wordCount["banana"] 2;// 使用 insert…...

【接口测试】任务1:登录接口
需要技能竞赛软件测试资料的同学们可s聊我,详细了解 任务实现要求 根据系统管理员—登录—接口API文档,编写接口测试用例,分别使用PostMan及JMeter进行接口测试,需要检查系统接口是否能正常工作,返回值是否正确&#…...

二、Spring Boot集成Spring Security之实现原理
Spring Boot集成Spring Security之实现原理 一、Spring Security实现原理概要介绍二、使用WebSecurityConfiguration向Spring容器中注册FilterChainProxy类型的对象springSecurityFilterChain1、未配置securityFilterChain过滤器链时使用默认配置用于生成默认securityFilterCha…...

基于深度学习的点云处理模型PointNet++学习记录
前面我们已经学习了Open3D,并掌握了其相关应用,但我们也发现对于一些点云分割任务,我们采用聚类等方法的效果似乎并不理想,这时,我们可以想到在深度学习领域是否有相关的算法呢,今天,我们便来学…...

Javascript Object.assgin()详解以及深浅拷贝
Object.assign() 方法是 JavaScript 中用于将所有可枚举属性的值从一个或多个源对象复制到目标对象的方法。它将返回目标对象。这是一种浅拷贝,也就是说,如果源对象中的属性是一个对象或数组,那么这个属性的引用将被复制,而不是对…...

Redis篇(应用案例 - UV统计)(持续更新迭代)
目录 一、HyperLogLog 二、测试百万数据的统计 一、HyperLogLog 首先我们搞懂两个概念: UV:全称Unique Visitor,也叫独立访客量,是指通过互联网访问、浏览这个网页的自然人。 1天内同一个用户多次访问该网站,只记录…...

解锁微信小程序新技能:ECharts动态折线图搭配WebSocket,数据刷新快人一步!
在微信小程序中,数据可视化展示越来越受到开发者的重视。本文将为您介绍如何在微信小程序中使用ECharts绘制折线图,并通过WebSocket实现实时更新图表数据。 一、准备工作 创建微信小程序项目 首先,我们需要创建一个微信小程序项目。如果您已…...

上交所服务器崩溃:金融交易背后的技术隐患暴露杭州BGP高防服务器43.228.71.X
一、上交所宕机事件始末 2024 年 9 月 27 日,上交所交易系统突发崩溃,这一事件犹如一颗巨石投入平静的湖面,引起了轩然大波。当天上午,众多投资者反馈券商交易出现延迟问题,随后上交所发布了《关于股票竞价交易出现异常…...

P4、P4D、HelixSwarm 各种技术问题咨询
多年大型项目P4仓库运维经验,为你解决各种部署以及标准工业化流程问题。 Perforce 官网SDPHelixCore GuideHelixSwarm GuideHelixSwarm Download...

Linux 应用层协议HTTP
文章目录 一、初始HTTP协议二、URL格式网络中怎么通过URL进行定位资源呢?编码和解码 三、HTTP的请求格式和响应格式HTTP的请求格式HTTP的响应格式HTTP的请求方法GET方法POST方法GET Vs PostHTTP的封装和分用文件流操作浏览器获得一个完整的网页流程 HTTP的状态码对3…...