设计模式四:适配器模式

1、适配器模式的理解

适配器模式可以理解为有两个现成的类Adaptee和Target,它们两个是不能动的,要求必须使用B这个类来实现一个功能,但是A的内容是能复用的,这个时候我们需要编写一个转换器

适配器模式

  • Adaptee:被适配者,现有的接口或者类;
  • Adapter:适配器类,适配器模式的核心,转换作用
  • Target:目标接口或者类

适配器模式的实现步骤

  • 定义目标接口,即客户端所期望的接口。
  • 定义适配器类,继承目标接口并包含一个适配者对象。
  • 在适配器类中实现目标接口的方法,调用适配者对象的相关方法进行适配。
  • 在客户端中使用适配器类进行操作。

适用场景

  • 继承:需要用到别人的类,但是不能修改
  • 多适配者:多个不同的对象,需要让他们具有相同的方法
  • 缺省形式

适配器模式有类适配器和对象适配器两种方式,一般采用前者

2、继承场景

来公司第二天,写一个简单的业务,看到同事写的接口中5个方法有3个正好可以用的,但是还需要另外新增一个,于是我便开始了改造(新增一个方法);提交后同事大发雷霆,谁让你新增的,新增了这个方法,这个接口就失去了本来的意思。。。。。。

我去***,那算了,我还是自己写一个吧,想想怎么能在不懂他的接口前提下,复用一下他的代码,那边使用适配器模式

//同事的接口为被适配者
public interface Adaptee{void method1();void method2();void method3();void method4();void method5();
}
public class AdapteeImpl implements Adaptee {@Overridepublic void method1() {System.out.println("method1 execute......");}@Overridepublic void method2() {System.out.println("method2 execute......");}@Overridepublic void method3() {System.out.println("method3 execute......");}@Overridepublic void method4() {System.out.println("method4 execute......");}@Overridepublic void method5() {System.out.println("method5 execute......");}
}//我需要使用的接口为目标接口
public interface Target{void method1();void method2();void method3();void method6();
}
//构建适配器类Adapter
//方式一:类适配器方式
public class Adapter1 extends AdapteeImpl implements Target {@Overridepublic void method6() {System.out.println("method6 execute......");}
}public class Client {public static void main(String[] args) {Target target = new Adapter1();target.method1();target.method2();target.method3();target.method6();}
}//方式二:对象适配器方式
public class Adapter2 implements Target {private Adaptee adaptee;public Adapter2(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void method1() {adaptee.method1();}@Overridepublic void method2() {adaptee.method2();}@Overridepublic void method3() {adaptee.method3();}@Overridepublic void method6() {System.out.println("method6 execute......");}
}public class Client {public static void main(String[] args) {Target target = new Adapter2(new AdapteeImpl());target.method1();target.method2();target.method3();target.method6();}
}

3、多适配者

多个适配者,适配同一个目标接口,为每一个适配者创建一个适配器

这种是最常用的方式,在springMVC和AOP中都有用到,后面会进行解析

例:新能源汽车的发动机有电能发动机(Electric Motor)和光能发动机(Optical Motor)等,各种发动机的驱动方法不同,例如,电能发动机的驱动方法 electricDrive() 是用电能驱动,而光能发动机的驱动方法 opticalDrive() 是用光能驱动,它们是适配器模式中被访问的适配者。

客户端希望用统一的发动机驱动方法 drive() 访问这两种发动机,所以必须定义一个统一的目标接口 Motor,然后再定义电能适配器(Electric Adapter)和光能适配器(Optical Adapter)去适配这两种发动机。

在这里插入图片描述

package adapter;//目标:发动机
interface Motor {public void drive();
}//适配者1:电能发动机
class ElectricMotor {public void electricDrive() {System.out.println("电能发动机驱动汽车!");}
}//适配者2:光能发动机
class OpticalMotor {public void opticalDrive() {System.out.println("光能发动机驱动汽车!");}
}//电能适配器
class ElectricAdapter implements Motor {private ElectricMotor emotor;public ElectricAdapter() {emotor=new ElectricMotor();}public void drive() {emotor.electricDrive();}
}//光能适配器
class OpticalAdapter implements Motor {private OpticalMotor omotor;public OpticalAdapter() {omotor=new OpticalMotor();}public void drive() {omotor.opticalDrive();}
}//客户端代码
public class MotorAdapterTest {public static void main(String[] args) {System.out.println("适配器模式测试:");Motor motor=(Motor)ReadXML.getObject();motor.drive();}
}

4、缺省形式

缺省就是对于一个具有很多方法的接口,我没只需要其中几个,不想把所有的方法都实现一遍,可以写一个抽象类作为适配器,再去继承该适配器

public interface Adaptee {void model1();void model2();void model3();void model4();void model5();void model6();void model7();void model8();void model9();void model10();
}public abstract class Adapter implements Adaptee{@Overridepublic void model1() {}@Overridepublic void model2() {}@Overridepublic void model3() {}@Overridepublic void model4() {}@Overridepublic void model5() {}@Overridepublic void model6() {}@Overridepublic void model7() {}@Overridepublic void model8() {}@Overridepublic void model9() {}@Overridepublic void model10() {}
}public class Target extends Adapter{@Overridepublic void model3() {System.out.println("model3......");}@Overridepublic void model7() {System.out.println("model7......");}
}

5、spring中的适配器模式

5.1 SpringMVC
请求处理流程

HandlerAdapter 在 Spring MVC 中使用了适配器模式。HandlerAdapter 主要用于支持不同类型的处理器(如 Controller、HttpRequestHandler 或者 Servlet 等),让它们能够适配统一的请求处理流程。这样,Spring MVC 可以通过一个统一的接口来处理来自各种处理器的请求。在 Spring MVC 的工作流程中,HandlerAdapter 扮演了一个重要角色。以下是其工作原理的简化版:

在这里插入图片描述

  • DispatcherServlet:前端控制器(Front Controller),负责接收所有请求并将其分发给相应的处理程序
  • HandlerMapping:处理器映射器,立请求URL与处理程序之间的映射关系,默认为RequestMappingHandlerMapping(根据@Controller注解和@RequestMapping注解来进行URL与处理程序的映射),可以在Spring配置文件(如XML配置文件或Java配置类)中显式地配置所需的HandlerMapping
  • HandlerAdapter:处理器适配器,通过handlerMapping获取到对应的处理程序handler(controller)后,通过所有注册的handlerAdaptersupports()方法找到对应的适配器来调用,当存在多个合适的HandlerAdapter时,框架会根据一定规则进行判断和选择

  1. 用户发起一个 HTTP 请求到 Spring MVC 应用。
  2. DispatcherServlet 接收到请求后,首先会调用 HandlerMapping,寻找合适的处理器(Handler)来处理这个请求。
  3. 找到合适的处理器后,DispatcherServlet 需要找到一个能够处理这个处理器的 HandlerAdapter。为此,它会遍历所有已注册的 HandlerAdapter,调用它们的 supports 方法,检查它们是否支持当前处理器。
  4. 找到支持当前处理器的 HandlerAdapter 后,DispatcherServlet 会调用该 HandlerAdapterhandle 方法,将请求委托给处理器进行处理。
  5. 处理器处理完请求后,会返回一个 ModelAndView 对象,DispatcherServlet 会将这个对象传递给适当的 ViewResolver,以解析视图并将响应返回给用户。

我们在ControllerServiceMapper中写的业务逻辑,在HandlerAdapter的处理过程中执行

以下是一个简化的 HandlerAdapter 接口示例:

public interface HandlerAdapter {boolean supports(Object handler);ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

Spring MVC 提供了一些内置的 HandlerAdapter 实现,如RequestMappingHandlerAdapterSimpleControllerHandlerAdapterHttpRequestHandlerAdapter 是 Spring MVC 中内置的几个 HandlerAdapter 实现,它们分别用于支持不同类型的处理器。

  1. RequestMappingHandlerAdapter:支持基于注解的处理器,如使用 @Controller@RequestMapping 注解的处理器方法。这是 Spring MVC 中最常用的处理器类型。
  2. SimpleControllerHandlerAdapter:支持实现 org.springframework.web.servlet.mvc.Controller 接口的处理器。这是 Spring MVC 早期版本中的处理器类型,现在已经较少使用。
  3. HttpRequestHandlerAdapter:支持实现 org.springframework.web.HttpRequestHandler 接口的处理器。这种类型的处理器主要用于处理静态资源,如图片、样式表等。

举例:

@Controller
@RequestMapping("/user")
public class UserController {@GetMapping("/{id}")public String getUserById(@PathVariable("id") Long id, Model model) {// 执行业务逻辑return "userDetails";}
}

在上述例子中有一个controller,当spring接收到请求时,处理过程为:

假设我们使用了默认的配置和注解驱动。

1、首先,前端控制器(DispatcherServlet)会根据请求的 URL 路径来选择合适的 HandlerMapping。在 Spring MVC 中,默认使用的是 RequestMappingHandlerMapping,它会根据 @RequestMapping 注解以及其他相关注解来确定处理程序(handler)与请求路径之间的映射关系。

2、 对于 UserController 中的 getUserById() 方法,使用了 @GetMapping 注解,并指定了路径为 “/{id}”。因此,当客户端发送 GET 请求到 “/user/{id}” 路径时,RequestMappingHandlerMapping 就会匹配到这个处理程序(handler)。

3、 接下来,在执行处理程序之前,前端控制器还需要选择合适的 HandlerAdapter,并将请求委托给它来执行处理程序

4、对于标注有 @GetMapping、@PostMapping 等注解的方法,默认情况下会选择 RequestMappingHandlerAdapter 作为主要的 HandlerAdapter。

5、RequestMappingHandlerAdapter 是一个功能强大且灵活的适配器,能够处理包含模型数据、参数绑定、异常处理等复杂情况。

在上述例子中,当通过 RequestMappingHandlerMapping 匹配到 UserController 的 getUserById() 方法后,前端控制器就会选择 RequestMappingHandlerAdapter 来执行这个处理程序,并传递相应的请求参数和模型数据给该方法。

在 Spring MVC 中,前端控制器(DispatcherServlet)会根据请求路径和方法来选择合适的 HandlerAdapter。

选择后,HandlerAdapter 将接收到的请求参数、模型数据等信息传递给相应的处理程序(业务逻辑),并执行该处理程序。

HandlerAdapter 根据具体的处理程序类型来确定调用哪个方法,以及如何将请求数据传递给该方法。

不同类型的处理程序可能有不同的要求和处理方式。 例如,在使用注解配置的方法作为处理程序时,默认情况下会选择 RequestMappingHandlerAdapter。

RequestMappingHandlerAdapter 会根据注解中定义的规则,将请求参数、路径变量、请求体内容等绑定到方法的入参上,并调用该方法执行业务逻辑。它还能够通过模型对象(Model)来向视图传递数据。

可以说 HandlerAdapter 是负责将请求数据传递给我们自己编写的业务逻辑处理程序,并执行其中定义的方法。它是框架与业务代码之间进行通信和协调的重要环节。

自定义handlerAdapter

通常情况下,Spring MVC 默认提供的 HandlerAdapters 是能够满足大多数应用场景的,并且能够处理各种类型的处理程序(handler)。

在某些特殊情况下,可能需要自定义 HandlerAdapter 来满足特定的需求。以下是一些需要自定义 HandlerAdapter 的情况:

  1. 需要支持新的处理程序类型:如果你使用了自定义的处理程序类型,而该类型不属于 Spring MVC 默认支持的类型,那么你可以编写自己的 HandlerAdapter 来支持该类型。

  2. 特定的请求/响应方式:如果你想要处理一种不常见或非标准的请求/响应方式,例如 WebSocket、SSE(服务器发送事件)等,你可能需要编写一个适配器来处理这些方式。

  3. 定制化业务逻辑:如果你有特殊的业务需求,需要在执行业务逻辑之前或之后添加额外的逻辑操作,例如权限校验、日志记录等,你可以编写一个自定义 HandlerAdapter 来扩展框架提供的功能。

  4. 性能优化:如果你对性能有极高要求,并希望通过优化执行过程来提升系统性能,可以根据具体场景编写一个更高效的 HandlerAdapter 来替换默认实现。

总之,在需要与 Spring MVC 框架进行更深度集成、满足特定需求或优化性能时,可以考虑自定义 HandlerAdapter。但在大多数情况下,默认提供的 HandlerAdapters 能够满足开发需求。

handlerAdapter的适配器模式

可以看到处理器的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用 Controller 方法,需要调用的时候就得不断地使用 if else 来进行判断是哪一种子类然后执行。那么如果后面要扩展 Controller, 就得修改原来的代码,这样违背了 OCP 原则

在这里插入图片描述

下面手写一下handlerAdapter的选择流程

//controller类,我们自己写的逻辑,即handler
public interface Controller {}public class AnnotationController implements Controller{public void doAnnotationHandler() {System.out.println("annotation...");}
}public class HttpController implements Controller{public void doHttpHandler() {System.out.println("http...");}
}public class SimpleController implements Controller{public void doSimpleHandler() {System.out.println("simple...");}
}
//handlerAdapter类 处理器适配器
//通过handlermapping获取到对应的handler后,再查找对应的处理器适配器调用对应方法
public interface HandlerAdapter {boolean supports(Object handler);void handle(Object handler);
}public class AnnotationHandlerAdapter implements HandlerAdapter{@Overridepublic boolean supports(Object handler) {// TODO Auto-generated method stubreturn (handler instanceof AnnotationController);}@Overridepublic void handle(Object handler) {// TODO Auto-generated method stub((AnnotationController)handler).doAnnotationHandler();}
}public class HttpHandlerAdapter implements HandlerAdapter {@Overridepublic boolean supports(Object handler) {// TODO Auto-generated method stubreturn (handler instanceof HttpController);}@Overridepublic void handle(Object handler) {// TODO Auto-generated method stub((HttpController)handler).doHttpHandler();}
}public class SimpleHandlerAdapter implements HandlerAdapter{@Overridepublic boolean supports(Object handler) {// TODO Auto-generated method stubreturn (handler instanceof SimpleController);}@Overridepublic void handle(Object handler) {// TODO Auto-generated method stub((SimpleController)handler).doSimpleHandler();}
}
//DispatcherServlet类 执行整体逻辑
public class DispatchServlet {public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();//注内置的处理器适配器,也可以自定义,然后注册到DispatcherServlet类中public DispatchServlet() {handlerAdapters.add(new AnnotationHandlerAdapter());handlerAdapters.add(new HttpHandlerAdapter());handlerAdapters.add(new SimpleHandlerAdapter());}public void doDispatch() {/**   1、这里用来调用handlermapping获取对应的controller(handler)*   springmvc中默认使用的是 RequestMappingHandlerMapping*/AnnotationController annotationController = new AnnotationController();//2、通过controller(handler)选择对应的handlerAdapterHandlerAdapter handlerAdapter = getHandler(annotationController);//3、调用对应处理程序(controller的方法),处理请求handlerAdapter.handle(annotationController);}public HandlerAdapter getHandler(Controller controller) {for (HandlerAdapter handlerAdapter : handlerAdapters) {if(handlerAdapter.supports(controller)) {return handlerAdapter;}}return null;}
}
//客户端
public class Client {public static void main(String[] args) {new DispatchServlet().doDispatch();}
}
自定义适配器

要自定义一个 HandlerAdapter,你需要实现 org.springframework.web.servlet.HandlerAdapter 接口,并提供对你的自定义处理器的支持。下面是一个简单的自定义 HandlerAdapter 示例:

首先,创建一个自定义处理器:

public class CustomHandler {public String handleRequest() {return "Hello, CustomHandler!";}
}

接着,实现一个自定义的 HandlerAdapter

import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class CustomHandlerAdapter implements HandlerAdapter {@Overridepublic boolean supports(Object handler) {return handler instanceof CustomHandler;}@Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {CustomHandler customHandler = (CustomHandler) handler;String result = customHandler.handleRequest();return new ModelAndView("customView", "message", result);}@Overridepublic long getLastModified(HttpServletRequest request, Object handler) {return -1;}
}

要在 Spring MVC 应用中使用这个自定义的 HandlerAdapter,你需要将其注册到 DispatcherServlet 中。在基于 Java 配置的应用中,你可以这样做:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {@Overrideprotected void addAdapters(List<HandlerAdapter> adapters) {adapters.add(new CustomHandlerAdapter());super.addAdapters(adapters);}
}

这样,你的自定义 HandlerAdapter 就会在 Spring MVC 应用中生效,并能处理 CustomHandler 类型的处理器。

5.2 AOP

在Spring的Aop中,使用Advice(通知)来增强被代理类的功能,Advice的类型有:BeforeAdvice、AfterReturningAdvice、ThreowSadvice。

每种Advice都有对应的拦截器,MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。

各种不同类型的Interceptor,通过适配器统一对外提供接口,如下类图所示:client —> target —> adapter —> interceptor —> advice。最终调用不同的advice来实现被代理类的增强
原理springmvc类似
在这里插入图片描述

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

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

相关文章

【C++初阶】类和对象(上)

目录 一.类的引入 1.概念 2.类的定义 (1).语法规范 (2)命名规范 (3)类的访问限定符及封装 ①访问限定符 (4)类的两种定义 ①声明和定义全部放在类体中&#xff0c;需注意&#xff1a;成员函数如果在类中定义&#xff0c;编译器可能会将其当成内联函数处理。 ​编辑…

【IDEA使用安装】如何长期正常使用IDEA,告别弹窗?【2024年亲测】

IDEA最新使用指南 写在前面涉及知识1、官网下载最新版本IDEA2、安装IDEA版本3、正常使用IDEA软件4、作者寄语 写在前面 愉快的假期结束了&#xff0c;当然我们奋斗的步伐不能停止&#xff0c;随即迎来了2024年的全新挑战&#xff0c;学更多的知识&#xff0c;分享更多有用的硬…

langchain配置openai

langchain的新版很多操作都变了&#xff0c;国内使用openai也不大方便&#xff0c;好在发现了个宝藏网站&#xff0c;可以使用 网址&#xff0c;接口的调用与官网是完全一样的 langchain调用各种大模型非常方便&#xff0c;也不用担心接口经常变动&#xff0c;导致和gradio等程…

【Flink状态管理五】Checkpoint的设计与实现

文章目录 1. Checkpoint的整体设计2. Checkpoint创建源码解析2.1. DefaultExecutionGraphBuilder.buildGraph2.2. ExecutionGraph.enableCheckpointing 由于系统原因导致Flink作业无法正常运行的情况非常多&#xff0c;且很多时候都是无法避免的。对于Flink集群来讲&#xff0c…

opencv图像处理(一)

一. OpenCV 简介 OpenCV 是一个跨平台计算机视觉库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 应用领域 1、人机互动 2、物体识别 3、图像分割 4、人脸识别 5、动作识别 6、运动跟踪 7、机器人 8、运动分析 9、机器视觉 10、…

整数分块 (因数平方和)(余数之和)

整数分块 文章目录 整数分块例题1&#xff1a;因数平方和分析:具体代码&#xff1a;__int128写法逆元写法 例题2&#xff1a;余数之和思想&#xff1a;代码 一般在算法中遇到时间复杂度为1e9的&#xff0c; 那么一次 O ( n ) O(n) O(n)的遍历无法解决问题 求 ∑ i 1 n [ n i ]…

3.网络游戏逆向分析与漏洞攻防-游戏启动流程漏洞-游戏启动流程的分析

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;项目搭建 首先下图红框里是游戏启动的程序 游戏启动之后的名字&#xff08;fxgame.exe&#xff09; 一般游戏启动的架构&#xff1a; 第一种&#xff1a;登录器程序启动游戏主程序&#xff0c;然后游…

java面向对象上:类的结构之一

目录 1.相同点 2.不同点 2.1 在类中声明的位置的不同 2.2 关于权限修饰符的不同 2.3 默认初始化值的情况&#xff1a; 2.4 在内存中加载的位置 补充&#xff1a;回顾变量的分类&#xff1a; 方式一&#xff1a;按照数据类型&#xff1a; 方式二&#xff1a;按照在类中…

【Flutter】底部导航BottomNavigationBar的使用

常用基本属性 属性名含义是否必须items底部导航栏的子项List是currentIndex当前显示索引否onTap底部导航栏的点击事件&#xff0c; Function(int)否type底部导航栏类型&#xff0c;定义 [BottomNavigationBar] 的布局和行为否selectedItemColor选中项图标和label的颜色否unsel…

工业网关的功能和优势,以及如何选择合适的工业网关-天拓四方

工业网关是连接各种工业设备和系统的通信设备&#xff0c;可以实现不同设备和系统之间的数据交换和通信。它可以作为一个中心节点&#xff0c;将各种工业设备连接起来&#xff0c;形成一个统一的通信网络&#xff0c;从而实现设备的远程监控、数据采集、分析和控制等功能。在工…

抖音小店新手应该怎么做?4个必须掌握的运营步骤,助你快速入门

大家好&#xff0c;我是电商花花。 很多新手在刚开始接触电商&#xff0c;接触抖音小店的时候都会感到迷茫吗&#xff0c;不知所措&#xff0c;新店刚开始都是从没有流量&#xff0c;没有销量&#xff0c;没有订单走过来的&#xff0c;我们也是。 新手做店都是需要方法&#…

wpf grid 列之间存在间隙

上图为grid的两列布局&#xff0c;中间的白线实际为两列的间隙&#xff0c;BorderThickness"0" 并不能消除 解决方法&#xff1a; <Grid RenderOptions.EdgeMode"Aliased"> # 在grid上添加属性

二分图模型即状态整理

二分图首先是个无向图。 主要有以下几类问题&#xff1a; 1.二分图&#xff0c;不存在奇数环&#xff0c;染色法不存在矛盾 2.匈牙利算法&#xff0c;匹配&#xff0c;最大匹配&#xff0c;匹配点&#xff0c;增广路径 3.最小点覆盖&#xff0c;最大独立集&#xff0c;最小路径…

在VS里使用C#制作窗口应用

新建项目 创建项目的时候搜索net&#xff0c;选择这个。 打开应该是这样 第一个控件 选择公共控件 - PictureBox - 拖入Form 在Image处选择上传本地资源&#xff0c;建议上传一个小一点的图片。 修改一下尺寸。 ctrls 保存 从“属性”切换到“事件” 双击Click事件…

DBSCAN密度聚类介绍 样本点 样本集合 半径 邻域 核心对象 边界点 密度直达 密度可达 密度相连

DBSCAN密度聚类介绍 样本点 样本集合 半径 邻域 核心对象 边界点 密度直达 密度可达 密度相连 简介概念定义原理DBSCAN的优点DBSCAN的缺点小尝试制作不易&#xff0c;感谢三连&#xff0c;谢谢啦 简介 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications wi…

【算法】动态规划1,最小花费爬楼梯,解码方法

一、动态规划简介 动态规划 , 英文名称 Dynamic Programming , 简称 DP , 不是具体的某种算法 , 是一种算法思想 ; 动态规划 , 没有具体的步骤 , 只有一个核心思想 ; 动态规划 的 核心思想 是 由大化小 , 大规模问题 使用 小规模问题 计算结果 解决 , 类似于 分治算法 ; 二、…

srs集群下行edge处理逻辑

官方关于源站集群的介绍&#xff1a; Origin Cluster | SRS 下行边缘是指观众端从边缘edge拉流&#xff0c;边缘edge回源到源站origin节点拉流&#xff0c;然后再 把流转给客户端 边缘处理类SrsPlayEdge 当服务器收到播放请求时&#xff0c;创建对应的consumer消费者。在创…

Docker后台启动镜像,如何查看日志信息

执行 docker run -d -p 9090:8080 core-backend-image 命令后&#xff0c;Docker 会在后台运行一个新的容器实例&#xff0c;并映射宿主机的 9090 端口到容器的 8080 端口。要查看启动的容器日志&#xff0c;您需要先获取容器的 ID 或名称&#xff0c;然后使用 docker logs 命令…

Linux系统之iptables应用SNAT与DNAT

一、SNAT&#xff1a; 1.应用环境 局域网主机共享单个公网IP地址接入Internet &#xff08;私有IP不能在Internet中正常路由&#xff09; 2.SNAT原理 源地址转换&#xff0c;根据指定条件修改数据包的源IP地址&#xff0c;通常被叫做源映谢数据包从内网发送到公网时&#x…

Fiddler与wireshark使用

Fiddler解决三个问题 1、SSL证书打勾&#xff0c;解析https请求 2、响应回来乱码&#xff0c;不是中文 3、想及时中止一下&#xff0c;查看实时的日志 4、搜索对应的关键字 问题1解决方案&#xff1a; 标签栏Tools下 找到https&#xff0c;全部打勾 Actions里面 第一个 t…