[springboot源码探索]返回值处理

[springboot源码探索]返回值处理

开始处理返回值

public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {// ...// 返回值处理器组(组合模式,可以理解为一组返回值处理器)private HandlerMethodReturnValueHandlerComposite returnValueHandlers;public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {// 执行请求 拿到返回值Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);setResponseStatus(webRequest);if (returnValue == null) {if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {disableContentCachingIfNecessary(webRequest);mavContainer.setRequestHandled(true);return;}}else if (StringUtils.hasText(getResponseStatusReason())) {mavContainer.setRequestHandled(true);return;}mavContainer.setRequestHandled(false);Assert.state(this.returnValueHandlers != null, "No return value handlers");try {// 调用返回值处理器组处理返回值this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);}catch (Exception ex) {if (logger.isTraceEnabled()) {logger.trace(formatErrorForReturnValue(returnValue), ex);}throw ex;}}// ...
}

返回值处理器组

public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {// ...private final List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<>();@Overridepublic void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {// 从返回值处理器中选择能处理的处理器HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);if (handler == null) {throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());}handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);}private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {boolean isAsyncValue = isAsyncReturnValue(value, returnType);// 责任链模式 遍历所有的返回值处理器 找到支持的for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {continue;}if (handler.supportsReturnType(returnType)) {return handler;}}return null;}
}

返回值处理器

public interface HandlerMethodReturnValueHandler {// 是否支持要处理的返回值类型boolean supportsReturnType(MethodParameter returnType);// 处理返回值void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;}

springboot中默认的返回值处理器

  1. org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler@28072124,
  2. org.springframework.web.method.annotation.ModelMethodProcessor@7073c17f,
  3. org.springframework.web.servlet.mvc.method.annotation.ViewMethodReturnValueHandler@30172c70,
  4. org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler@2602dbd7,
  5. org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBodyReturnValueHandler@379dc032,
  6. org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor@598b8787,
  7. org.springframework.web.servlet.mvc.method.annotation.HttpHeadersReturnValueHandler@50f6546a,
  8. org.springframework.web.servlet.mvc.method.annotation.CallableMethodReturnValueHandler@609ae1c0,
  9. org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler@39df31b1,
  10. org.springframework.web.servlet.mvc.method.annotation.AsyncTaskMethodReturnValueHandler@3c6d3eb2,
  11. org.springframework.web.method.annotation.ModelAttributeMethodProcessor@5eda6851,
  12. org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor@697906ab,
  13. org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler@29ebf08c,
  14. org.springframework.web.method.annotation.MapMethodProcessor@7c26c3ad,
  15. org.springframework.web.method.annotation.ModelAttributeMethodProcessor@71b3b498

以处理ResponseBody注解的返回值处理器为例探索返回值处理过程

image-20240401094812784

public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {// ... public boolean supportsReturnType(MethodParameter returnType) {// 类上有ResponseBody注解或者方法上有ResponseBody注解return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||returnType.hasMethodAnnotation(ResponseBody.class));}public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest)throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {mavContainer.setRequestHandled(true);ServletServerHttpRequest inputMessage = createInputMessage(webRequest);ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);// Try even with null return value. ResponseBodyAdvice could get involved.// 使用消息转换器将返回值写到响应里面writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);}// ...
}
public abstract class AbstractMessageConverterMethodProcessor extends AbstractMessageConverterMethodArgumentResolverimplements HandlerMethodReturnValueHandler {// ...protected final List<HttpMessageConverter<?>> messageConverters;protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {Object body;Class<?> valueType;Type targetType;if (value instanceof CharSequence) {body = value.toString();valueType = String.class;targetType = String.class;}else {body = value;valueType = getReturnValueType(body, returnType);targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass());}if (isResourceType(value, returnType)) {outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes");if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null &&outputMessage.getServletResponse().getStatus() == 200) {Resource resource = (Resource) value;try {List<HttpRange> httpRanges = inputMessage.getHeaders().getRange();outputMessage.getServletResponse().setStatus(HttpStatus.PARTIAL_CONTENT.value());body = HttpRange.toResourceRegions(httpRanges, resource);valueType = body.getClass();targetType = RESOURCE_REGION_LIST_TYPE;}catch (IllegalArgumentException ex) {outputMessage.getHeaders().set(HttpHeaders.CONTENT_RANGE, "bytes */" + resource.contentLength());outputMessage.getServletResponse().setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());}}}// 选中的媒体类型MediaType selectedMediaType = null;// 判断响应里面有没有媒体类型(比如拦截器之类的给写了响应头)MediaType contentType = outputMessage.getHeaders().getContentType();boolean isContentTypePreset = contentType != null && contentType.isConcrete();if (isContentTypePreset) {if (logger.isDebugEnabled()) {logger.debug("Found 'Content-Type:" + contentType + "' in response");}selectedMediaType = contentType;}else {HttpServletRequest request = inputMessage.getServletRequest();// 客户端能接受的类容类型List<MediaType> acceptableTypes = getAcceptableMediaTypes(request);// 服务端可以生成的类容类型List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);if (body != null && producibleTypes.isEmpty()) {throw new HttpMessageNotWritableException("No converter found for return value of type: " + valueType);}// 可用的媒体类型List<MediaType> mediaTypesToUse = new ArrayList<>();for (MediaType requestedType : acceptableTypes) {for (MediaType producibleType : producibleTypes) {if (requestedType.isCompatibleWith(producibleType)) {mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));}}}if (mediaTypesToUse.isEmpty()) {if (body != null) {throw new HttpMediaTypeNotAcceptableException(producibleTypes);}if (logger.isDebugEnabled()) {logger.debug("No match for " + acceptableTypes + ", supported: " + producibleTypes);}return;}// 对可以用的媒体类型排序MediaType.sortBySpecificityAndQuality(mediaTypesToUse);// 给selectedMediaType赋值(找到最佳媒体类型)for (MediaType mediaType : mediaTypesToUse) {if (mediaType.isConcrete()) {selectedMediaType = mediaType;break;}else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;break;}}if (logger.isDebugEnabled()) {logger.debug("Using '" + selectedMediaType + "', given " +acceptableTypes + " and supported " + producibleTypes);}}if (selectedMediaType != null) {selectedMediaType = selectedMediaType.removeQualityValue();// 遍历所有的消息转换器 找到可以将指定类型转为媒体类型的消息转换器(例如将Person类型对象转为json字符串) 责任链模式for (HttpMessageConverter<?> converter : this.messageConverters) {GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?(GenericHttpMessageConverter<?>) converter : null);// 如果消息转换器可以写就用消息转换器写if (genericConverter != null ?((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :converter.canWrite(valueType, selectedMediaType)) {// 返回值 比如person对象body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,(Class<? extends HttpMessageConverter<?>>) converter.getClass(),inputMessage, outputMessage);if (body != null) {Object theBody = body;LogFormatUtils.traceDebug(logger, traceOn ->"Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]");addContentDispositionHeader(inputMessage, outputMessage);if (genericConverter != null) {// 用消息转换器写genericConverter.write(body, targetType, selectedMediaType, outputMessage);}else {((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);}}else {if (logger.isDebugEnabled()) {logger.debug("Nothing to write: null body");}}return;}}}if (body != null) {if (isContentTypePreset) {throw new HttpMessageNotWritableException("No converter for [" + valueType + "] with preset Content-Type '" + contentType + "'");}throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);}}// ...
}

内容协商

客户端以请求头的形式告诉服务器它能接受什么样的响应数据,和返回值处理器能生产的对比,找到返回值处理器能生产的,客户端能接受的媒体类型

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7

消息转换器

public interface HttpMessageConverter<T> {// 是否支持 将class 以mediaType的形式读进来boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);// 是否支持将clazz以mediaType的形式写出去,例如能否将Person对象转为json类型的数据boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);// 每种消息转换器都有自己支持的类型List<MediaType> getSupportedMediaTypes();T read(Class<? extends T> clazz, HttpInputMessage inputMessage)throws IOException, HttpMessageNotReadableException;void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)throws IOException, HttpMessageNotWritableException;}

springboot中默认的消息转换器

  1. org.springframework.http.converter.ByteArrayHttpMessageConverter@1ad1c363,
  2. org.springframework.http.converter.StringHttpMessageConverter@6b2aafbc,
  3. org.springframework.http.converter.StringHttpMessageConverter@446b64b3,
  4. org.springframework.http.converter.ResourceHttpMessageConverter@35ac9ebd,
  5. org.springframework.http.converter.ResourceRegionHttpMessageConverter@56c0a61e,
  6. org.springframework.http.converter.xml.SourceHttpMessageConverter@421ead7e,
  7. org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@5dcf0772,
  8. org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@50cbcca7,
  9. org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@c472300,
  10. org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@5f6494c0

MappingJackson2HttpMessageConverter

继承体系

image-20240401090902746

public class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {// ...public MappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {//每种转换器都有自己支持的类型, MappingJackson2HttpMessageConverter 支持[application/json, application/*+json]super(objectMapper, MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));}// ...
}
public abstract class AbstractJackson2HttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {// ...@Overrideprotected void writeInternal(Object object, @Nullable Type type, HttpOutputMessage outputMessage)throws IOException, HttpMessageNotWritableException {MediaType contentType = outputMessage.getHeaders().getContentType();JsonEncoding encoding = getJsonEncoding(contentType);JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);try {writePrefix(generator, object);Object value = object;Class<?> serializationView = null;FilterProvider filters = null;JavaType javaType = null;if (object instanceof MappingJacksonValue) {MappingJacksonValue container = (MappingJacksonValue) object;value = container.getValue();serializationView = container.getSerializationView();filters = container.getFilters();}if (type != null && TypeUtils.isAssignable(type, value.getClass())) {javaType = getJavaType(type, null);}ObjectWriter objectWriter = (serializationView != null ?this.objectMapper.writerWithView(serializationView) : this.objectMapper.writer());if (filters != null) {objectWriter = objectWriter.with(filters);}if (javaType != null && javaType.isContainerType()) {objectWriter = objectWriter.forType(javaType);}SerializationConfig config = objectWriter.getConfig();if (contentType != null && contentType.isCompatibleWith(MediaType.TEXT_EVENT_STREAM) &&config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {objectWriter = objectWriter.with(this.ssePrettyPrinter);}// 通过objectWriter将返回值写入到响应留中objectWriter.writeValue(generator, value);writeSuffix(generator, object);generator.flush();}catch (InvalidDefinitionException ex) {throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);}catch (JsonProcessingException ex) {throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getOriginalMessage(), ex);}}// ...
}
public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {// ...private List<MediaType> supportedMediaTypes = Collections.emptyList();// 通过构造方法给supportedMediaTypes赋值,例如MappingJackson2HttpMessageConverter的 super(objectMapper, MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));protected AbstractJackson2HttpMessageConverter(ObjectMapper objectMapper, MediaType... supportedMediaTypes) {this(objectMapper);setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));}protected boolean canWrite(@Nullable MediaType mediaType) {// MediaType.ALL即*/*if (mediaType == null || MediaType.ALL.equalsTypeAndSubtype(mediaType)) {return true;}for (MediaType supportedMediaType : getSupportedMediaTypes()) {if (supportedMediaType.isCompatibleWith(mediaType)) {return true;}}return false;}// ...
}
public abstract class AbstractGenericHttpMessageConverter<T> extends AbstractHttpMessageConverter<T>implements GenericHttpMessageConverter<T> {// ...@Overridepublic final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType,HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {final HttpHeaders headers = outputMessage.getHeaders();addDefaultHeaders(headers, t, contentType);if (outputMessage instanceof StreamingHttpOutputMessage) {StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;streamingOutputMessage.setBody(outputStream -> writeInternal(t, type, new HttpOutputMessage() {@Overridepublic OutputStream getBody() {return outputStream;}@Overridepublic HttpHeaders getHeaders() {return headers;}}));}else {// 将消息写入到响应留中,t为返回值,type,返回值的类型writeInternal(t, type, outputMessage);outputMessage.getBody().flush();}}protected abstract void writeInternal(T t, @Nullable Type type, HttpOutputMessage outputMessage)throws IOException, HttpMessageNotWritableException;// ...
}

image-20240401105910957

小结

返回值处理核心可以分成三部分

  1. 找到合适的返回值处理器(一个返回值处理器里面有多个消息转换器)
  2. 找到合适的消息转换器(在寻找消息转换器的时候用到了内容协商,客户端能接受什么样的媒体类型,服务器能生产什么样的媒体类型,找到一个最合适的浏览器能接受的,服务器能生产的媒体类型,然后遍历返回值处理器中的消息转换器,看看那个能支持内容协商找到的媒体类型)
  3. 用消息转换器将返回值写入到响应中

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

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

相关文章

C++11标准 - 声明(auto,decltype,nullptr)

C11标准 - 声明&#xff08;auto&#xff0c;decltype&#xff0c;nullptr&#xff09; 前言1. auto2. decltype3. nullptr 前言 c11提供了多种简化声明的方式&#xff0c;尤其是在使用模板时。 1. auto 在C98中auto是一个存储类型的说明符&#xff0c;表明变量是局部自动存…

ChatGPT实体化了!手机变身ChatGPT实体机器人,只需一个配件,能说话还会做梦,真的牛!

你有没有想过&#xff0c;如果有一天ChatGPT有了身体&#xff0c;跑到你办公桌上成了你的宠物&#xff0c;这是个多么有趣的场景&#xff0c;LOOI就是这样一款把幻想带进现实的产品 不得不说&#xff0c;ChatGPT让具身智能达到了新高度&#xff0c;LOOI便应运而生。 分享几个网…

什么是HTTP? HTTP 和 HTTPS 的区别?

文章目录 一、HTTP二、HTTPS三、区别参考文献 一、HTTP HTTP (HyperText Transfer Protocol)&#xff0c;即超文本运输协议&#xff0c;是实现网络通信的一种规范 在计算机和网络世界有&#xff0c;存在不同的协议&#xff0c;如广播协议、寻址协议、路由协议等等… 而HTTP是…

聊聊低代码产品的应用场景

随着数字化转型的不断深入&#xff0c;企业对于快速开发和迭代软件应用的需求也越来越迫切。而在这样的背景下&#xff0c;低代码产品应运而生&#xff0c;成为了一种热门的技术解决方案。本文将解读低代码产品的定义并探讨其应用场景。 一、低代码产品的定义 低代码产品是一种…

DFS(基础,回溯,剪枝,记忆化)搜索

DFS基础 DFS(深度优先搜索) 基于递归求解问题&#xff0c;而针对搜索的过程 对于问题的介入状态叫初始状态&#xff0c;要求的状态叫目标状态 这里的搜索就是对实时产生的状态进行分析检测&#xff0c;直到得到一个目标状态或符合要求的最佳状态为止。对于实时产生新的状态…

Linux系统Docker如何部署Nextcloud结合内网穿透实现公网访问本地资源?

文章目录 1. 安装Docker2. 使用Docker拉取Nextcloud镜像3. 创建并启动Nextcloud容器4. 本地连接测试5. 公网远程访问本地Nextcloud容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 本文主要介绍如何在Linux Ubuntu系统使用Docker快速部署Nextcl…

Html提高——视频标签音频标签及其相关属性

HTML5 在不使用插件的情况下&#xff0c;也可以原生的支持音视频格式文件的播放&#xff0c;当然&#xff0c;支持的格式是有限的。 1、video标签 1.1、video标签的语法 <video src"文件地址" controls"controls"></video> video标签的内部…

接口自动化框架Pytest —— 配置文件pytest.ini的详细使用

前言 我们在执行用例的时候&#xff0c;每次都在命令行中输入-v&#xff0c;-s等一些命令行参数的时&#xff0c;比较麻烦。其中pytest.ini这个配置文件可以快速的帮助我们解决这个问题。 配置文件 pytest.ini文件是pytest的主配置文件&#xff0c;可以改变pytest的运行方式…

【python】pip清华大学镜像

1、修改pip源为清华源&#xff1a; pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple2、结果是自动给我创建了一个文件&#xff1a; 3、打开这个文件所在的文件夹&#xff1a; 4、打开文件&#xff1a; 5、如果不想指定清华的&#xff0c;就删掉…

提升K8S故障排除效率:详解Pod内抓包的高效策略!

在Kubernetes环境中&#xff0c;故障排除是管理者日常工作中不可或缺的一部分。随着容器化应用的广泛采用&#xff0c;需要一种高效的方法来诊断和解决Pod内部的问题。本文将重点介绍如何利用抓包技术提升Kubernetes环境中Pod内部故障排除的效率。 为什么需要Pod内抓包 在Kube…

【MySQL】DQL-案例练习-DQL基本介绍&语法&执行顺序(代码演示)

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

Baidu Comate

Baidu Comate 他来了 描述功能支持的编程语言支持的 IDE支持的操作系统IDEA安装操作 描述 智能代码助手&#xff0c;其实就是写代码的辅助工具&#xff0c;可以很大程度的帮你提升编码效率&#xff0c;作为一个白嫖党&#xff0c;我觉得这个还可以。 功能 注释生成代码、增强…

Flutter 拦截系统键盘,显示自定义键盘

一、这里记录下在开发过程中&#xff0c;下单的时候输入金额需要使用自定义的数字键盘 参考链接: https://juejin.cn/post/7166046328609308685 效果图 二、屏蔽系统键盘 怎样才能够在输入框获取焦点的时候&#xff0c;不让系统键盘弹出呢&#xff1f;同时又显示我们自定义的…

LeetCode刷题【栈】

目录 栈394. 字符串解码739. 每日温度 栈 394. 字符串解码 给定一个经过编码的字符串&#xff0c;返回它解码后的字符串。 编码规则为: k[encoded_string]&#xff0c;表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。 你可以认为输入字符串总是…

Netty教程之NIO基础

NIO 介绍 NIO 全称java non-blocking IO&#xff08;非阻塞 I/O&#xff09;&#xff0c;后续提供了一系列改进的输入/输出的新特性&#xff0c;被统称为 NIO(即 New IO)&#xff0c;是同步非阻塞的。 阻塞和非阻塞是进程在访问数据的时候&#xff0c;数据是否准备就绪的一种…

mongodb sharding分片模式的集群数据库,日志治理缺失导致写入数据库报错MongoWriteConcernException的问题总结(下)

一、接着上文 上文介绍了mongodb sharding的分片集群搭建&#xff0c;本文侧重于讲述日志治理。 这里使用linux自带的日志治理工具logrotate&#xff0c;无论是哪个端口的进程&#xff0c;其日志治理方式类似。 查看/data目录下的文件大小&#xff0c; du -hs *二、Logrota…

每日一题(相交链表 )

欢迎大家来我们主页进行指导 LaNzikinh-CSDN博客 160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节…

RUST使用crates.io上的依赖完整教程

1.打开crates.io 2.搜索要使用的依赖,如rand 点击包名,进入包详情页面: 添加依赖方法有两种 1.使用cargo命令 2.直接修改Cargo.toml 使用cargo命令操作如下: 在工程目录执行如下命令: cargo add rand 执行完成后如自动向Cargo.toml中添加依赖如下: 手动修改Cargo.toml是…

漏洞挖掘 | ruoyi框架管理系统漏洞

前言&#xff1a; 在挖src的时候&#xff0c;可以通过信息收集收集弱口令&#xff0c;然后通过后台弱口令进入后台&#xff1a; 发现一个弱口令进去后&#xff1a; 【魔方老师提醒才发现&#xff0c;这个蓝色的草丛其实可以大致判断是若依系统】 看这界面&#xff0c;是不是…

XSS伪协议

XSS伪协议简介 XSS&#xff08;跨站脚本攻击&#xff09;中的伪协议是指利用一些浏览器允许的特殊协议来执行恶意脚本的一种方式。常见的伪协议包括 javascript:, data:, vbscript: 等。 攻击者可以通过构造特定的URL&#xff0c;将恶意脚本注入到网页中&#xff0c;从而实现…