SpringBoot+拦截器(Interceptor)

记录一下SpringBoot的拦截器(Interceptor)使用

拦截器(Interceptor)是AOP面向切面编程的思想来实现的,对于只写代码的来说,具体如何实现不需要多关心,只需要关心如何去使用,会用在那些地方。

当http请求进入Springboot应用程序后,会去调用 Controller 层,在进入Controller处理应用业务之前,这个请求是需要通过经过拦截器(Interceptor)的,可能是一个也可能是多个,根据需求来,在Controller处理完业务逻辑之后,也要经过拦截器(Interceptor),最终将结果返回给请求着,即使不返回,也会经过的。

在拦截器(Interceptor)中,最常的应用有几个方面

1.校验token(最常用):根据请求token拦截校验是否允许访问特定资源 比如用户列表,开放的请求地址url需要额外的拦截器配置 比如登录
2.记录日志: 记录请求信息的日志数据
3.数据统计: 统计请求某一资源的次数,统计请求进入到响应的处理时间等
4.其他一些实际需求的功能

目前使用的是SpringBoot2.0.5版本

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.5.RELEASE</version><relativePath/> <!-- lookup parent from repository -->
</parent>

自定义 Interceptor一般是实现 org.springframework.web.servlet.HandlerInterceptor接口
myw
源码是这样的

/** Copyright 2002-2017 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.springframework.web.servlet;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;/*** Workflow interface that allows for customized handler execution chains.* Applications can register any number of existing or custom interceptors* for certain groups of handlers, to add common preprocessing behavior* without needing to modify each handler implementation.** <p>A HandlerInterceptor gets called before the appropriate HandlerAdapter* triggers the execution of the handler itself. This mechanism can be used* for a large field of preprocessing aspects, e.g. for authorization checks,* or common handler behavior like locale or theme changes. Its main purpose* is to allow for factoring out repetitive handler code.** <p>In an asynchronous processing scenario, the handler may be executed in a* separate thread while the main thread exits without rendering or invoking the* {@code postHandle} and {@code afterCompletion} callbacks. When concurrent* handler execution completes, the request is dispatched back in order to* proceed with rendering the model and all methods of this contract are invoked* again. For further options and details see* {@code org.springframework.web.servlet.AsyncHandlerInterceptor}** <p>Typically an interceptor chain is defined per HandlerMapping bean,* sharing its granularity. To be able to apply a certain interceptor chain* to a group of handlers, one needs to map the desired handlers via one* HandlerMapping bean. The interceptors themselves are defined as beans* in the application context, referenced by the mapping bean definition* via its "interceptors" property (in XML: a &lt;list&gt; of &lt;ref&gt;).** <p>HandlerInterceptor is basically similar to a Servlet Filter, but in* contrast to the latter it just allows custom pre-processing with the option* of prohibiting the execution of the handler itself, and custom post-processing.* Filters are more powerful, for example they allow for exchanging the request* and response objects that are handed down the chain. Note that a filter* gets configured in web.xml, a HandlerInterceptor in the application context.** <p>As a basic guideline, fine-grained handler-related preprocessing tasks are* candidates for HandlerInterceptor implementations, especially factored-out* common handler code and authorization checks. On the other hand, a Filter* is well-suited for request content and view content handling, like multipart* forms and GZIP compression. This typically shows when one needs to map the* filter to certain content types (e.g. images), or to all requests.** @author Juergen Hoeller* @since 20.06.2003* @see HandlerExecutionChain#getInterceptors* @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter* @see org.springframework.web.servlet.handler.AbstractHandlerMapping#setInterceptors* @see org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor* @see org.springframework.web.servlet.i18n.LocaleChangeInterceptor* @see org.springframework.web.servlet.theme.ThemeChangeInterceptor* @see javax.servlet.Filter*/
public interface HandlerInterceptor {/*** Intercept the execution of a handler. Called after HandlerMapping determined* an appropriate handler object, but before HandlerAdapter invokes the handler.* <p>DispatcherServlet processes a handler in an execution chain, consisting* of any number of interceptors, with the handler itself at the end.* With this method, each interceptor can decide to abort the execution chain,* typically sending a HTTP error or writing a custom response.* <p><strong>Note:</strong> special considerations apply for asynchronous* request processing. For more details see* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.* <p>The default implementation returns {@code true}.* @param request current HTTP request* @param response current HTTP response* @param handler chosen handler to execute, for type and/or instance evaluation* @return {@code true} if the execution chain should proceed with the* next interceptor or the handler itself. Else, DispatcherServlet assumes* that this interceptor has already dealt with the response itself.* @throws Exception in case of errors*/default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return true;}/*** Intercept the execution of a handler. Called after HandlerAdapter actually* invoked the handler, but before the DispatcherServlet renders the view.* Can expose additional model objects to the view via the given ModelAndView.* <p>DispatcherServlet processes a handler in an execution chain, consisting* of any number of interceptors, with the handler itself at the end.* With this method, each interceptor can post-process an execution,* getting applied in inverse order of the execution chain.* <p><strong>Note:</strong> special considerations apply for asynchronous* request processing. For more details see* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.* <p>The default implementation is empty.* @param request current HTTP request* @param response current HTTP response* @param handler handler (or {@link HandlerMethod}) that started asynchronous* execution, for type and/or instance examination* @param modelAndView the {@code ModelAndView} that the handler returned* (can also be {@code null})* @throws Exception in case of errors*/default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable ModelAndView modelAndView) throws Exception {}/*** Callback after completion of request processing, that is, after rendering* the view. Will be called on any outcome of handler execution, thus allows* for proper resource cleanup.* <p>Note: Will only be called if this interceptor's {@code preHandle}* method has successfully completed and returned {@code true}!* <p>As with the {@code postHandle} method, the method will be invoked on each* interceptor in the chain in reverse order, so the first interceptor will be* the last to be invoked.* <p><strong>Note:</strong> special considerations apply for asynchronous* request processing. For more details see* {@link org.springframework.web.servlet.AsyncHandlerInterceptor}.* <p>The default implementation is empty.* @param request current HTTP request* @param response current HTTP response* @param handler handler (or {@link HandlerMethod}) that started asynchronous* execution, for type and/or instance examination* @param ex exception thrown on handler execution, if any* @throws Exception in case of errors*/default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,@Nullable Exception ex) throws Exception {}}

preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法

这个方法是在http请求进来之后处理之前被调用的 返回是 Boolean 类型,返回 false 时,表示直接掐断请求,直接结束了,那么也就不会进入Controller;返回 true 时,会继续进入下一个拦截器同样的方法(preHandler)直到所有的preHandler方法都通过才进入Controller。

postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法
http请求处理好业务后,从Controller控制器返回后调用,视图解析器之前,也就是在渲染数据返回数据之前被调用。

afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法
当对应的拦截器preHandle返回值是 true 时才会在整个请求结束之后执行,视图解析器之后,也可以理解为postHandler后

自定义CustomHandlerInterceptor.java

package boot.example.interceptor.config;import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class CustomHandlerInterceptor implements HandlerInterceptor{/*** Controller逻辑执行之前进行拦截*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle:");String uri = request.getRequestURI();System.out.println("拦截的uri:"+uri);if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;System.out.println("拦截 Controller:"+ handlerMethod.getBean().getClass().getName());System.out.println("拦截方法:"+handlerMethod.getMethod().getName());}//拦截token,没有token的不允许继续往下执行String token = request.getHeader("token");if(token == null){return false;}long startTime = System.currentTimeMillis();System.out.println("start-time: " + startTime);request.setAttribute("startTime", startTime);return true;}/*** Controller逻辑执行完毕但是视图解析器还为进行解析之前进行拦截*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle:");long endTime = System.currentTimeMillis();long startTime = (Long) request.getAttribute("startTime");System.out.println("post-end-time: " + endTime);System.out.println("post-差值ms:" + (endTime - startTime));HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}/*** Controller逻辑和视图解析器执行完毕进行拦截*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion:");long startTime = (Long) request.getAttribute("startTime");long endTime = System.currentTimeMillis();System.out.println("after-end-time: " + endTime);System.out.println("after-差值ms:" + (endTime - startTime));HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

配置拦截器
bean方式(不推荐)

package boot.example.interceptor.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 使用bean的方式**/
@Configuration
public class InterceptorConfig {@Beanpublic CustomHandlerInterceptor customHandlerInterceptor(){return new CustomHandlerInterceptor();}@Beanpublic WebMvcConfigurer webMvcConfigurer(){return new WebMvcConfigurer() {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(customHandlerInterceptor()).addPathPatterns("/**")//.excludePathPatterns("/").excludePathPatterns("/index/**");}};}}

重写方式来配置(推荐)

package boot.example.interceptor.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 重写方式来配置,推荐**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Beanpublic CustomHandlerInterceptor customHandlerInterceptor(){return new CustomHandlerInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(customHandlerInterceptor()).addPathPatterns("/**")//.excludePathPatterns("/").excludePathPatterns("/index/**");}}

测试-BootIndexController.java

package boot.example.interceptor.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class BootIndexController {@RequestMapping("/")@ResponseBodypublic String index() {return "index";}@RequestMapping("/index/hello")@ResponseBodypublic String indexHello() {return "hello world";}@RequestMapping("/inter/hello")@ResponseBodypublic String interHello(){return "inter world";}@RequestMapping("/inter/sleep")@ResponseBodypublic String sleepHello() throws InterruptedException {// 假装处理2sThread.sleep(2000);return "inter world";}}

表示拦截所有的url请求

.addPathPatterns(“/**”)

表示放开拦截的url请求

.excludePathPatterns(“/”)
.excludePathPatterns(“/index/**”)

请求无拦截的情况,直接返回数据,不会经过拦截器
myw

请求有拦截的情况,没有token是访问不到资源的
myw
查看控制台
myw
随意写个token
myw
可以看到拦截通过了 执行了对应的三个方法 在这里有测试的故意延迟
myw
一个应用可能有多个拦截器,有的时候拦截器需要执行的先后顺序,默认的情况下是按照注册的先后顺序
拦截器ONE
CustomOrderOneHandlerInterceptor.java

package boot.example.interceptor.config;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class CustomOrderOneHandlerInterceptor implements HandlerInterceptor{/*** Controller逻辑执行之前进行拦截*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("CustomOrderOneHandlerInterceptor: preHandle");return true;}/*** Controller逻辑执行完毕但是视图解析器还为进行解析之前进行拦截*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("CustomOrderOneHandlerInterceptor: postHandle");}/*** Controller逻辑和视图解析器执行完毕进行拦截*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("CustomOrderOneHandlerInterceptor: afterCompletion");}
}

拦截器TWO
CustomOrderTwoHandlerInterceptor.java

package boot.example.interceptor.config;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class CustomOrderTwoHandlerInterceptor implements HandlerInterceptor{/*** Controller逻辑执行之前进行拦截*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("CustomOrderTwoHandlerInterceptor: preHandle");return true;}/*** Controller逻辑执行完毕但是视图解析器还为进行解析之前进行拦截*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("CustomOrderTwoHandlerInterceptor: postHandle");}/*** Controller逻辑和视图解析器执行完毕进行拦截*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("CustomOrderTwoHandlerInterceptor: afterCompletion");}
}

拦截器配置
OderInterceptorConfig.java

package boot.example.interceptor.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 重写方式来配置,推荐**/
@Configuration
public class OderInterceptorConfig implements WebMvcConfigurer {@Beanpublic CustomOrderOneHandlerInterceptor customOrderOneHandlerInterceptor(){return new CustomOrderOneHandlerInterceptor();}@Beanpublic CustomOrderTwoHandlerInterceptor customOrderTwoHandlerInterceptor(){return new CustomOrderTwoHandlerInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(customOrderOneHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index/**");registry.addInterceptor(customOrderTwoHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index/**");}}

可以看到customOrderOneHandlerInterceptor()在customOrderTwoHandlerInterceptor()之前,启动程序打开访问打开控制台查看打印日志确认
myw
交换顺序可以看到TWO在ONE之前执行
myw
使用order自定义顺序 可以看到值小的比值大的先执行
myw
使用拦截器重定向
当访问

http://localhost:8080

重定向

http://localhost:8080/home

CustomRedirectOneHandlerInterceptor.java

package boot.example.interceptor.config;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class CustomRedirectOneHandlerInterceptor implements HandlerInterceptor{/*** Controller逻辑执行之前进行拦截*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("CustomRedirectOneHandlerInterceptor: preHandle");System.out.println("CustomRedirectOneHandlerInterceptor Request url: " + request.getRequestURL());response.sendRedirect(request.getContextPath()+ "/home");return false;}/*** Controller逻辑执行完毕但是视图解析器还为进行解析之前进行拦截*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("CustomRedirectOneHandlerInterceptor: postHandle");}/*** Controller逻辑和视图解析器执行完毕进行拦截*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("CustomRedirectOneHandlerInterceptor: afterCompletion");}
}

CustomRedirectTwoHandlerInterceptor.java


package boot.example.interceptor.config;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class CustomRedirectTwoHandlerInterceptor implements HandlerInterceptor{/*** Controller逻辑执行之前进行拦截*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("CustomRedirectTwoHandlerInterceptor: preHandle");System.out.println("CustomRedirectTwoHandlerInterceptor Request url: " + request.getRequestURL());return true;}/*** Controller逻辑执行完毕但是视图解析器还为进行解析之前进行拦截*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("CustomRedirectTwoHandlerInterceptor: postHandle");}/*** Controller逻辑和视图解析器执行完毕进行拦截*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("CustomRedirectTwoHandlerInterceptor: afterCompletion");}
}

BootIndexController.java

package boot.example.interceptor.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class BootIndexController {@RequestMapping("/")@ResponseBodypublic String index() {return "/";}@RequestMapping("/home")@ResponseBodypublic String indexHello() {return "/home";}}

用postman访问
myw
浏览器输入http://localhost:8080会跳转的
myw
myw

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

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

相关文章

GBASE南大通用-一文读懂如何用Zabbix监控GBase 8c

南大通用GBase 8c是基于openGauss3.0构建的一款多模多态的分布式数据库&#xff0c;支持行存、列存、内存等多种存储模式和单机、主备式、分布式等多种部署形态&#xff0c;具备多模多态、极高性能、极高可用、极致弹性、极致安全等特性&#xff0c;为金融、政务、互联网等行业…

CGAL的主成分分析

此软件包提供了分析二维和三维对象集的功能。它提供了所有有界对象的轴对齐边界框、质心和主成分分析的计算&#xff0c;以及加权点集的重心。请注意&#xff0c;与大多数CGAL软件包不同&#xff0c;该软件包使用近似方法&#xff08;特别是线性最小二乘拟合&#xff09;&#…

数据采集遇到验证码校验的一般破解方式简述

背景 百度自动采集是一种高效的数据采集方法&#xff0c;但是在采集过程中经常会遇到图片验证码的问题&#xff0c;从而导致采集失败。那么有没有什么方法可以绕过图片验证呢&#xff1f;本文将为您详细介绍。 解决方案 一、使用OCR技术识别验证码 OCR技术可以识别图片中的…

vue实现滑动切换:切换选项时滑块有滑动过渡的效果

效果图 思路&#xff1a; 1. 高亮的色块是独立的一个盒子&#xff0c;需要插入当前激活的内容用来撑开色块盒子的宽度&#xff0c;这样色块的宽度就会和当前激活的内容宽度一致&#xff0c;色块的字体颜色设置透明即可 2. 色块滑动的距离是读当前激活元素的offsetLeft&#x…

文献阅读:LoRA: Low-Rank Adaptation of Large Language Models

文献阅读&#xff1a;LoRA: Low-Rank Adaptation of Large Language Models 1. 文章简介2. 方法介绍3. 实验 & 结论 1. 基础实验 1. Bert系列模型2. GPT系列模型 2. 消解实验 1. 作用矩阵考察2. 中间维度考察3. 扰动程度分析 4. 总结 & 思考 文献链接&#xff1a;htt…

SLAM学习入门--机器学习

文章目录 机器学习逻辑回归&#xff08;LR&#xff09;基本原理为什么 LR 要使用 sigmoid 函数&#xff1f;LR 可以用核函数么&#xff1f;为什么 LR 用交叉熵损失而不是平方损失&#xff1f;LR 能否解决非线性分类问题&#xff1f;LR为什么要离散特征&#xff1f;逻辑回归是处…

Linux文件系统结构及相关命令2 什么是Shell? help cd cd的用法 ls 的用法

Shell 是一种用于与操作系统进行交互的命令行解释器。它是用户与操作系统内核之间的接口&#xff0c;接受用户的命令并将其传递给操作系统进行执行。 在大多数的 Unix-like 操作系统&#xff08;如 Linux 和 macOS&#xff09;以及类 Unix 系统中&#xff0c;Shell 是默认的命…

如何开发一个google插件(二)

前言 在上一篇文章如何开发一个google插件(一)里主要介绍了google插件的基本结构。 在这篇文章中主要结合reactwebpack进行一个代码演示&#xff0c;源码地址&#xff1a;源码地址 下载源码后打开浏览器的扩展程序管理->加载已解压的扩展程序&#xff0c;即可调试插件 此…

在线客服选择要点分析:如何挑选适合您需求的客服解决方案

选择一款好的在线客服系统&#xff0c;可以帮助企业多渠道的触达客户&#xff0c;与客户进行高效的沟通&#xff0c;最终达成转化的目的。 市面上现在成熟的客服系统产品有很多&#xff0c;企业在进行选择时要考虑以下几点&#xff1a; 1、企业需求 市场上的客服系统产品主要…

ArkTS - 组件生命周期

一、先说下自定义组件 在arkTs中&#xff0c;自定义组件分为两种&#xff08;我的总结&#xff09;&#xff1a; 一种是&#xff1a;根组件&#xff0c;就是被装饰器Entry装饰的入口组件&#xff0c;这也是自定义组件(父组件)。 另一种是&#xff1a;没有被Entry装饰的自定义…

分布式存储考点梳理 + 高频面试题

欢迎来到分布式存储模环节&#xff0c;本文我将和你一起梳理面试中分布式系统的数据库的高频考点&#xff0c;做到温故知新。 面试中如何考察分布式存储 广义的分布式存储根据不同的应用领域&#xff0c;划分为以下的类别&#xff1a; 分布式协同系统 分布式文件系统 分布式…

Xline command 去重机制(一)—— RIFL 介绍

为什么要对 command 去重&#xff1f; 在一个接收外部 command 的系统中&#xff0c;通常一个 command 至少要执行一次&#xff0c;我们称其为 at-least-once semantics。如果一个 command 执行失败&#xff0c;系统内部经常会实现一套重试结构来尝试恢复这个问题&#xff0c;…

HTML 基础

文章目录 01-标签语法标签结构 03-HTML骨架04-标签的关系05-注释06-标题标签07-段落标签08-换行和水平线09-文本格式化标签10-图像标签图像属性 11-路径相对路径绝对路径 12-超链接标签13-音频14-视频 01-标签语法 HTML 超文本标记语言——HyperText Markup Language。 超文本…

【分布式配置中心】聊聊Apollo的安装与具体配置变更的原理

【管理设计篇】聊聊分布式配置中心 之前就写过一篇文章&#xff0c;介绍配置中心&#xff0c;但是也只是简单描述了下配置中心的设计点。本篇从apollo的安装到部署架构到核心原理进一步解读&#xff0c;大概看了下apollo的原理&#xff0c;感觉没有必要深究&#xff0c;所以就…

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项样题卷③

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项&#xff08;高职组&#xff09; 样题&#xff08;第3套&#xff09; 目录 2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项&#xff08;高职组&#xff09; 样题&#xff08;第3套&#xff09; 模块…

【北亚数据恢复】mysql表被truncate,表数据被delete的数据恢复案例

云服务器数据恢复环境&#xff1a; 华为ECS云服务器&#xff0c;linux操作系统&#xff0c;mysql数据库&#xff08;innodb引擎&#xff09;。作为网站服务器使用。 云服务器故障&#xff1a; 在执行mysql数据库版本更新测试时&#xff0c;误将本应该在测试库上执行的sql脚本执…

亚马逊云科技Amazon Q,一款基于生成式人工智能的新型助手

近日&#xff0c;亚马逊云科技宣布推出Amazon Q&#xff0c;这是一款基于生成式人工智能&#xff08;AI&#xff09;的新型助手&#xff0c;专为辅助工作而设计&#xff0c;可以根据您的业务量身定制。通过连接到公司的信息存储库、代码、数据和企业系统&#xff0c;可以使用Am…

个人游戏启动器 | 游戏数据库 playnite 折腾记录

环境&#xff1a;Windows 11 问题&#xff1a;使用平板串联PC游戏后&#xff0c;需要一个本地的PC启动器 解决办法&#xff1a;使用playnite搭配插件 背景&#xff1a;我是个单机游戏爱好者&#xff0c;因为某些原因&#xff0c;需要串流游玩&#xff0c;需要一个方便手柄操作的…

arkts状态管理使用(@State、@Prop、@Link、@Provide、@Consume、@objectLink和@observed)

一、状态管理 1.在声明式UI中&#xff0c;是以状态驱动视图更新&#xff1a; ①状态&#xff08;State&#xff09;:指驱动视图更新的数据&#xff08;被装饰器标记的变量&#xff09; ②视图&#xff08;View&#xff09;:基于UI描述渲染得到用户界面 注意&#xff1a; ①…

【零基础入门VUE】VueJS - 模板

✍面向读者&#xff1a;所有人 ✍所属专栏&#xff1a;零基础入门VUE专栏https://blog.csdn.net/arthas777/category_12537076.html 我们在前面的章节中学习了如何在屏幕上以文本内容的形式输出。在本章中&#xff0c;我们将学习如何在屏幕上以 HTML 模板的形式获取输出。 为了…