为什么从 MVC 到 DDD,架构的本质是什么?

news/2024/4/27 23:33:39/文章来源:https://blog.csdn.net/Yao__Shun__Yu/article/details/131527128

作者:小傅哥

博客:https://bugstack.cn

沉淀、分享、成长,让自己和他人都能有所收获!😄

本文来自于小傅哥新编写的 《Java简明教程》 系列内容,本教程意在于通过简单、明了、清晰的成体系内容,教会Java学习伙伴,可以在学习后能进行Java项目开发。

今天要分享的是 MVC 和 DDD 的架构本质,通过由浅入深的介绍讲解和视频带着手把手操作创建工程架构。让无论是学习 MVC 的小白码农还是希望了解更多关于 DDD 内容的老白码农,都可以学习到一点自己需要的内容。

一、MVC 架构

如果我们尝试把编程的复杂架构缩小到最容易理解的程度,那么编程开发其实只做3件事:”定义属性创建方法调用展示“。但因为同类所需的内容较多,如一系列的属性,一堆的方法实现,一组的接口封装,那么就需要合理的把这些内容分配到不同的层次中去实现,因此有了分层架构的设计。

那么本文小傅哥会向大家介绍一套MVC架构的分层设计以及如何创建使用,并提供相应的简单的案例。你可以复制这套架构在自己的场景中使用,也更能方便编程的小白可以更快的上手开发。

注意:此套MVC架构模型适合提供HTTP服务的工程架构,适合简单的小场景开发使用。特点;轻便、简单、学习成本低。

1. 编程三步

如果说你是一个特别小的玩具项目,你甚至可以把编程的3步写到一个类里。但因为你做的是正经项目,你的各种类;对象类、库表类、方法类,就会成群结队的来。如果你想把这些成群结队的类的内容,都写到一个类里去,那么就是几万行的代码了。—— 当然你也可以吹牛逼,你一个人做过一个项目,这项目大到啥程度呢。就是有一个类里有上万行代码。

所以,为了不至于让一个类撑到爆💥,需要把黄色的对象、绿色的方法、红色的接口,都分配到不同的包结构下。这就是你编码人生中所接触到的第一个解耦操作。

2. 分层框架

MVC 是一种非常常见且常用的分层架构,主要包括;M - mode 对象层,封装到 domain 里。V - view 展示层,但因为目前都是前后端分离的项目,几乎不会在后端项目里写 JSP 文件了。C - Controller 控制层,对外提供接口实现类。DAO 算是单独拿出来用户处理数据库操作的层。

  • 如图,在 MVC 的分层架构下。我们编程3步的所需各类对象、方法、接口,都分配到 MVC 的各个层次中去。
  • 因为这样分层以后,就可以很清晰明了的知道各个层都在做什么内容,也更加方便后续的维护和迭代。
  • 对于一个真正的项目来说,是没有一锤子买卖的,最开始的开发远不是成本所在。最大的开发成本是后期的维护和迭代。而架构设计的意义更多的就是在解决系统的反复的维护和迭代时,如何降低成本,这也是架构分层的意义所在。

3. 调用流程

接下来我们再看下一套 MVC 架构中各个模块在调用时的串联关系;

  • 以用户发起 HTTP 请求开始,Controller 在接收到请求后,调用由 Spring 注入到类里的 Service 方法,进入 Service 方法后有些逻辑会走数据库,有些逻辑是直接内部自己处理后就直接返回给 Controller 了。最后由 Controller 封装结果返回给 HTTP 响应。
  • 同时我们也可以看到各个对象在这些请求间的一个作用,如;请求对象、库表对象、返回对象。

4. 架构源码

4.1 环境

  • JDK 1.8
  • Maven 3.8.6 - 下载安装maven后,本地记得配置阿里云镜像,方便快速拉取jar包。源码中 docs/maven/settings.xml 有阿里云镜像地址。
  • SpringBoot 2.7.2
  • MySQL 5.7 - 如果你使用 8.0 记得更改 pom.xml 中的 mysql 引用

4.2 架构

  • 源码https://gitcode.net/KnowledgePlanet/road-map/xfg-frame-mvc
  • 树形安装 brew install tree IntelliJ IDEA Terminal 使用 tree
.
├── docs
│   └── mvc.drawio - 架构文档
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── cn
│   │   │       └── bugstack
│   │   │           └── xfg
│   │   │               └── frame
│   │   │                   ├── Application.java
│   │   │                   ├── common
│   │   │                   │   ├── Constants.java
│   │   │                   │   └── Result.java
│   │   │                   ├── controller
│   │   │                   │   └── UserController.java
│   │   │                   ├── dao
│   │   │                   │   └── IUserDao.java
│   │   │                   ├── domain
│   │   │                   │   ├── po
│   │   │                   │   │   └── User.java
│   │   │                   │   ├── req
│   │   │                   │   │   └── UserReq.java
│   │   │                   │   ├── res
│   │   │                   │   │   └── UserRes.java
│   │   │                   │   └── vo
│   │   │                   │       └── UserInfo.java
│   │   │                   └── service
│   │   │                       ├── IUserService.java
│   │   │                       └── impl
│   │   │                           └── UserServiceImpl.java
│   │   └── resources
│   │       ├── application.yml
│   │       └── mybatis
│   │           ├── config
│   │           │   └── mybatis-config.xml
│   │           └── mapper
│   │               └── User_Mapper.xml
│   └── test
│       └── java
│           └── cn
│               └── bugstack
│                   └── xfg
│                       └── frame
│                           └── test
│                               └── ApiTest.java
└── road-map.sql

以上是整个🏭工程架构的 tree 树形图。整个工程由 SpringBoot 驱动。

  • Application.java 是启动程序的 SpringBoot 应用
  • common 是额外添加的一个层,用于定义通用的类
  • controller 控制层,提供接口实现。
  • dao 数据库操作层
  • domain 对象定义层
  • service 服务实现层

5. 测试验证

  • 首先;整个工程由 SpringBoot 驱动,提供了 road-map.sql 测试 SQL 库表语句。你可以在自己的本地mysql上进行执行。它会创建库表。
  • 之后;在 application.yml 配置数据库链接信息。
  • 之后就可以打开 ApiTest 进行测试了。你可以点击 Application 类的绿色箭头启动工程,使用 UserController 类提供接口的方式调用程序;http://localhost:8089/queryUserInfo
- 如果你正常获取了这样的结果信息,那么说明你已经启动成功。接下来就可以对照着MVC的结构进行学习,以及使用这样的工程结构开发自己的项目。

二、DDD 架构

从最早接触 DDD 架构,到后来用 DDD 架构不断的承接项目开发,一次次在项目开发中的经验积累。对 DDD 有了不少的理解。DDD 是一种思想,落地的形态和结构会有不同的方式,甚至在编码上也会有风格的差异。但终期目标就一个;”提供代码的可维护性,降低迭代开发成本。“也是康威定律所述:”任何组织在设计一套系统时,所交付的设计方案在结构上都与该组织的沟通结构保持一致。“

但 DDD 与 MVC 相比的概率较多,贸然用理论驱动代码开发,会让整个工程变得非常混乱,甚至可能虽然是用的 DDD 但最后写出来了一片四不像的 MVC 代码。所以对于程序员👨🏻‍💻来说,先能上手一个工程,在从工程了解理论会更加容易。为此小傅哥想以此文,通过实战编码的方式向大家分享 DDD 架构,并能让大家上手的 DDD 架构。

1. 问题碰撞

你用 MVC 写代码,遇到过最大的问题是什么?🤔

简单、容易、好理解,是 MVC 架构的特点,但也正因为简单的分层逻辑,在适配较复杂的场景并且需要长周期的维护时,代码的迭代成本就会越来越高。如图;

  • 如果你接触过较大型且已经长期维护项目的 MVC 架构,你就会发现这里的 DAO、PO、VO 对象,在 Service 层相互调用。那么长期开发后,就导致了各个 PO 里的属性字段数量都被撑的特别大。这样的开发方式,将”状态”“行为“分离到不同的对象中,代码的意图渐渐模糊,膨胀、臃肿和不稳定的架构,让迭代成本增加。
  • 而 DDD 架构首先以解决此类问题为主,将各个属于自己领域范围内的行为和逻辑封装到自己的领域包下处理。这也是 DDD 架构设计的精髓之一。它希望在分治层面合理切割问题空间为更小规模的若干子问题,而问题越小就容易被理解和处理,做到高内聚低耦合。这也是康威定律所提到的,解决复杂场景的设计主要分为:分治、抽象和知识。

2. 简化理解

在给大家讲解 MVC 架构的时候,小傅哥提到了一个简单的开发模型。开发代码可以理解为:“定义属性 -> 创建方法 -> 调用展示” 但这个模型结构过于简单,不太适合运用了各类分布式技术栈以及更多逻辑的 DDD 架构。所以在 DDD 这里,我们把开发代码可以抽象为:“触发 -> 函数 -> 连接” 如图;

  • DDD 架构常用于微服务场景,因此也一个系统的调用方式就不只是 HTTP 还包括;RPC 远程MQ 消息TASK 任务,因此这些种方式都可以理解为触发。
  • 通过触发调用函数方法,我们这里可以把各个服务都当成一个函数方法来看。而函数方法通过连接,调用到其他的接口、数据库、缓存来完成函数逻辑。

接下来,小傅哥在带着大家把这些所需的模块,拆分到对应的DDD系统架构中。

3. 架构分层

如下是 DDD 架构的一种分层结构,也可以有其他种方式,核心的重点在于适合你所在场景的业务开发。以下的分层结构,是小傅哥在使用 DDD 架构多种的方式开发代码后,做了简化和处理的。右侧的连线是各个模块的依赖关系。接下来小傅哥就给大家做一下模块的介绍。

  • 接口定义 - xfg-frame-api:因为微服务中引用的 RPC 需要对外提供接口的描述信息,也就是调用方在使用的时候,需要引入 Jar 包,让调用方好能依赖接口的定义做代理。
  • 应用封装 - xfg-frame-app:这是应用启动和配置的一层,如一些 aop 切面或者 config 配置,以及打包镜像都是在这一层处理。你可以把它理解为专门为了启动服务而存在的。
  • 领域封装 - xfg-frame-domain:领域模型服务,是一个非常重要的模块。无论怎么做DDD的分层架构,domain 都是肯定存在的。在一层中会有一个个细分的领域服务,在每个服务包中会有【模型、仓库、服务】这样3部分。
  • 仓储服务 - xfg-frame-infrastructure:基础层依赖于 domain 领域层,因为在 domain 层定义了仓储接口需要在基础层实现。这是依赖倒置的一种设计方式。
  • 领域封装 - xfg-frame-trigger:触发器层,一般也被叫做 adapter 适配器层。用于提供接口实现、消息接收、任务执行等。所以对于这样的操作,小傅哥把它叫做触发器层。
  • 类型定义 - xfg-frame-types:通用类型定义层,在我们的系统开发中,会有很多类型的定义,包括;基本的 Response、Constants 和枚举。它会被其他的层进行引用使用。
  • 领域编排【可选】 - xfg-frame-case:领域编排层,一般对于较大且复杂的的项目,为了更好的防腐和提供通用的服务,一般会添加 case/application 层,用于对 domain 领域的逻辑进行封装组合处理。

4. 架构源码

4.1 环境

  • JDK 1.8
  • Maven 3.8.6
  • SpringBoot 2.7.2
  • MySQL 5.7 - 如果你使用 8.0 记得更改 pom.xml 中的 mysql 引用

4.2 架构

  • 源码https://gitcode.net/KnowledgePlanet/road-map/xfg-frame-ddd
  • 树形安装 brew install tree IntelliJ IDEA Terminal 使用 tree
.
├── README.md
├── docs
│   ├── dev-ops
│   │   ├── environment
│   │   │   └── environment-docker-compose.yml
│   │   ├── siege.sh
│   │   └── skywalking
│   │       └── skywalking-docker-compose.yml
│   ├── doc.md
│   ├── sql
│   │   └── road-map.sql
│   └── xfg-frame-ddd.drawio
├── pom.xml
├── xfg-frame-api
│   ├── pom.xml
│   ├── src
│   │   └── main
│   │       └── java
│   │           └── cn
│   │               └── bugstack
│   │                   └── xfg
│   │                       └── frame
│   │                           └── api
│   │                               ├── IAccountService.java
│   │                               ├── IRuleService.java
│   │                               ├── model
│   │                               │   ├── request
│   │                               │   │   └── DecisionMatterRequest.java
│   │                               │   └── response
│   │                               │       └── DecisionMatterResponse.java
│   │                               └── package-info.java
│   └── xfg-frame-api.iml
├── xfg-frame-app
│   ├── Dockerfile
│   ├── build.sh
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   ├── bin
│   │   │   │   ├── start.sh
│   │   │   │   └── stop.sh
│   │   │   ├── java
│   │   │   │   └── cn
│   │   │   │       └── bugstack
│   │   │   │           └── xfg
│   │   │   │               └── frame
│   │   │   │                   ├── Application.java
│   │   │   │                   ├── aop
│   │   │   │                   │   ├── RateLimiterAop.java
│   │   │   │                   │   └── package-info.java
│   │   │   │                   └── config
│   │   │   │                       ├── RateLimiterAopConfig.java
│   │   │   │                       ├── RateLimiterAopConfigProperties.java
│   │   │   │                       ├── ThreadPoolConfig.java
│   │   │   │                       ├── ThreadPoolConfigProperties.java
│   │   │   │                       └── package-info.java
│   │   │   └── resources
│   │   │       ├── application-dev.yml
│   │   │       ├── application-prod.yml
│   │   │       ├── application-test.yml
│   │   │       ├── application.yml
│   │   │       ├── logback-spring.xml
│   │   │       └── mybatis
│   │   │           ├── config
│   │   │           │   └── mybatis-config.xml
│   │   │           └── mapper
│   │   │               ├── RuleTreeNodeLine_Mapper.xml
│   │   │               ├── RuleTreeNode_Mapper.xml
│   │   │               └── RuleTree_Mapper.xml
│   │   └── test
│   │       └── java
│   │           └── cn
│   │               └── bugstack
│   │                   └── xfg
│   │                       └── frame
│   │                           └── test
│   │                               └── ApiTest.java
│   └── xfg-frame-app.iml
├── xfg-frame-ddd.iml
├── xfg-frame-domain
│   ├── pom.xml
│   ├── src
│   │   └── main
│   │       └── java
│   │           └── cn
│   │               └── bugstack
│   │                   └── xfg
│   │                       └── frame
│   │                           └── domain
│   │                               ├── order
│   │                               │   ├── model
│   │                               │   │   ├── aggregates
│   │                               │   │   │   └── OrderAggregate.java
│   │                               │   │   ├── entity
│   │                               │   │   │   ├── OrderItemEntity.java
│   │                               │   │   │   └── ProductEntity.java
│   │                               │   │   ├── package-info.java
│   │                               │   │   └── valobj
│   │                               │   │       ├── OrderIdVO.java
│   │                               │   │       ├── ProductDescriptionVO.java
│   │                               │   │       └── ProductNameVO.java
│   │                               │   ├── repository
│   │                               │   │   ├── IOrderRepository.java
│   │                               │   │   └── package-info.java
│   │                               │   └── service
│   │                               │       ├── OrderService.java
│   │                               │       └── package-info.java
│   │                               ├── rule
│   │                               │   ├── model
│   │                               │   │   ├── aggregates
│   │                               │   │   │   └── TreeRuleAggregate.java
│   │                               │   │   ├── entity
│   │                               │   │   │   ├── DecisionMatterEntity.java
│   │                               │   │   │   └── EngineResultEntity.java
│   │                               │   │   ├── package-info.java
│   │                               │   │   └── valobj
│   │                               │   │       ├── TreeNodeLineVO.java
│   │                               │   │       ├── TreeNodeVO.java
│   │                               │   │       └── TreeRootVO.java
│   │                               │   ├── repository
│   │                               │   │   ├── IRuleRepository.java
│   │                               │   │   └── package-info.java
│   │                               │   └── service
│   │                               │       ├── engine
│   │                               │       │   ├── EngineBase.java
│   │                               │       │   ├── EngineConfig.java
│   │                               │       │   ├── EngineFilter.java
│   │                               │       │   └── impl
│   │                               │       │       └── RuleEngineHandle.java
│   │                               │       ├── logic
│   │                               │       │   ├── BaseLogic.java
│   │                               │       │   ├── LogicFilter.java
│   │                               │       │   └── impl
│   │                               │       │       ├── UserAgeFilter.java
│   │                               │       │       └── UserGenderFilter.java
│   │                               │       └── package-info.java
│   │                               └── user
│   │                                   ├── model
│   │                                   │   └── valobj
│   │                                   │       └── UserVO.java
│   │                                   ├── repository
│   │                                   │   └── IUserRepository.java
│   │                                   └── service
│   │                                       ├── UserService.java
│   │                                       └── impl
│   │                                           └── UserServiceImpl.java
│   └── xfg-frame-domain.iml
├── xfg-frame-infrastructure
│   ├── pom.xml
│   ├── src
│   │   └── main
│   │       └── java
│   │           └── cn
│   │               └── bugstack
│   │                   └── xfg
│   │                       └── frame
│   │                           └── infrastructure
│   │                               ├── dao
│   │                               │   ├── IUserDao.java
│   │                               │   ├── RuleTreeDao.java
│   │                               │   ├── RuleTreeNodeDao.java
│   │                               │   └── RuleTreeNodeLineDao.java
│   │                               ├── package-info.java
│   │                               ├── po
│   │                               │   ├── RuleTreeNodeLineVO.java
│   │                               │   ├── RuleTreeNodeVO.java
│   │                               │   ├── RuleTreeVO.java
│   │                               │   └── UserPO.java
│   │                               └── repository
│   │                                   ├── RuleRepository.java
│   │                                   └── UserRepository.java
│   └── xfg-frame-infrastructure.iml
├── xfg-frame-trigger
│   ├── pom.xml
│   ├── src
│   │   └── main
│   │       └── java
│   │           └── cn
│   │               └── bugstack
│   │                   └── xfg
│   │                       └── frame
│   │                           └── trigger
│   │                               ├── http
│   │                               │   ├── Controller.java
│   │                               │   └── package-info.java
│   │                               ├── mq
│   │                               │   └── package-info.java
│   │                               ├── rpc
│   │                               │   ├── AccountService.java
│   │                               │   ├── RuleService.java
│   │                               │   └── package-info.java
│   │                               └── task
│   │                                   └── package-info.java
│   └── xfg-frame-trigger.iml
└── xfg-frame-types├── pom.xml├── src│   └── main│       └── java│           └── cn│               └── bugstack│                   └── xfg│                       └── frame│                           └── types│                               ├── Constants.java│                               ├── Response.java│                               └── package-info.java└── xfg-frame-types.iml

以上是整个🏭工程架构的 tree 树形图。整个工程由 xfg-frame-app 模的 SpringBoot 驱动。这里小傅哥在 domain 领域模型下提供了 order、rule、user 三个领域模块。并在每个模块下提供了对应的测试内容。这块是整个模型的重点,其他模块都可以通过测试看到这里的调用过程。

4.3 领域

一个领域模型中包含3个部分;model、repository、service 三部分;

  • model 对象的定义
  • repository 仓储的定义
  • service 服务实现

以上3个模块,一般也是大家在使用 DDD 时候最不容易理解的分层。比如 model 里还分为;valobj - 值对象、entity 实体对象、aggregates 聚合对象;

  • 值对象:表示没有唯一标识的业务实体,例如商品的名称、描述、价格等。
  • 实体对象:表示具有唯一标识的业务实体,例如订单、商品、用户等;
  • 聚合对象:是一组相关的实体对象的根,用于保证实体对象之间的一致性和完整性;

关于model中各个对象的拆分,尤其是聚合的定义,会牵引着整个模型的设计。当然你可以在初期使用 DDD 的时候不用过分在意领域模型的设计,可以把整个 domain 下的一个个包当做充血模型结构,这样编写出来的代码也是非常适合维护的。

4.4 环境(开发/测试/上线)

源码xfg-frame-ddd/pom.xml

<profile><id>dev</id><activation><activeByDefault>true</activeByDefault></activation><properties><profileActive>dev</profileActive></properties>
</profile>
<profile><id>test</id><properties><profileActive>test</profileActive></properties>
</profile>
<profile><id>prod</id><properties><profileActive>prod</profileActive></properties>
</profile>
  • 定义环境;开发、测试、上线。

源码xfg-frame-app/application.yml

spring:config:name: xfg-frameprofiles:active: dev # dev、test、prod
  • 除了 pom 的配置,还需要在 application.yml 中指定环境。这样就可以对应的加载到;application-dev.ymlapplication-prod.ymlapplication-test.yml 这样就可以很方便的加载对应的配置信息了。尤其是各个场景中切换会更加方便。

4.5 切面

一个工程开发中,有时候可能会有很多的统一切面和启动配置的处理,这些内容都可以在 xfg-frame-app 完成。

源码cn.bugstack.xfg.frame.aop.RateLimiterAop

@Slf4j
@Aspect
public class RateLimiterAop {private final long timeout;private final double permitsPerSecond;private final RateLimiter limiter;public RateLimiterAop(double permitsPerSecond, long timeout) {this.permitsPerSecond = permitsPerSecond;this.timeout = timeout;this.limiter = RateLimiter.create(permitsPerSecond);}@Pointcut("execution(* cn.bugstack.xfg.frame.trigger..*.*(..))")public void pointCut() {}@Around(value = "pointCut()", argNames = "jp")public Object around(ProceedingJoinPoint jp) throws Throwable {boolean tryAcquire = limiter.tryAcquire(timeout, TimeUnit.MILLISECONDS);if (!tryAcquire) {Method method = getMethod(jp);log.warn("方法 {}.{} 请求已被限流,超过限流配置[{}/秒]", method.getDeclaringClass().getCanonicalName(), method.getName(), permitsPerSecond);return Response.<Object>builder().code(Constants.ResponseCode.RATE_LIMITER.getCode()).info(Constants.ResponseCode.RATE_LIMITER.getInfo()).build();}return jp.proceed();}private Method getMethod(JoinPoint jp) throws NoSuchMethodException {Signature sig = jp.getSignature();MethodSignature methodSignature = (MethodSignature) sig;return jp.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());}}

使用

# 限流配置
rate-limiter:permits-per-second: 1timeout: 5
  • 这样你所有的通用配置,又和业务没有太大的关系的,就可以直接写到这里了。—— 具体可以参考代码。

5. 测试验证

  • 首先;整个工程由 SpringBoot 驱动,提供了 road-map.sql 测试 SQL 库表语句。你可以在自己的本地mysql上进行执行。它会创建库表。
  • 之后;在 application.yml 配置数据库链接信息。
  • 之后就可以打开 ApiTest 进行测试了。你可以点击 Application 类的绿色箭头启动工程,使用触发器里的接口调用测试,或者单元测试RPC接口,小傅哥也提供了泛化调用的方式。
  • 如果你正常获取了这样的结果信息,那么说明你已经启动成功。接下来就可以对照着DDD的结构进行学习,以及使用这样的工程结构开发自己的项目。

三、实战 - DDD 项目

纸上得来终觉浅,码农学习要实战!

无论是 MVC 还是各类 DDD 所呈现的架构,还是需要看到实际的代码,以及参与实战开发才能更好的吸收。否则都是理论仍旧难以让人下手。

所以小傅哥为大家准备了一些学习项目,这些项目都是非常具有架构思维以及设计模式的应用级实战项目架构设计和落地。对于一些小白来说,如果能早早的接触到这样的项目,就相当于是提前进入企业实习了。可以极大的提到编程思维以及开发能力。

这些项目包括:《Lottery 抽奖系统 - 基于领域驱动设计的四层架构实践》、《API网关:中间件设计和落地》、《ChatGPT 微服务应用体系搭建》、《IM 仿微信》、《SpringBoot Starter 中间件设计和落地》等。这里小傅哥只列3张图,你就知道有多牛皮了!

第1张:Lottery

架构

工程

第2张:API网关

架构

工程

第3张:ChatGPT


实战项目:https://bugstack.cn/md/zsxq/introduce.html

此外,小傅哥还给大家准备了一系列的《Java简明教程》视频,进入B站即可学习!

https://www.bilibili.com/video/BV1kV411g7GX

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

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

相关文章

IP 扫描程序:轻松发现、扫描和跟踪 IP 空间

什么是 IP 扫描 IP 扫描是实时持续监控网络 IP 地址空间的过程。包括 ICMP ping 扫描和 SNMP 扫描在内的网络协议数量用于扫描网络中的 IP 地址。网络管理员依靠 IP 扫描程序轻松检查和管理 IP 地址空间。使用网络 IP 扫描程序进行 IP 扫描可查看 IP 地址空间利用率和性能。 …

网络io模型、同步异步及libuv

网络io模型及基础概念 概念说明 用户空间与内核空间 操作系统的核心是内核&#xff0c;独立于普通的应用程序&#xff0c;可以访问受保护的内存空间&#xff0c;也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核&#xff08;kernel&#xff09;&#xff0…

Unity3D:工具栏

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 工具栏 在 Unity Editor 顶部可以看到工具栏。 工具栏不是窗口&#xff0c;是 Unity 界面中唯一无法重新排列的部分。 有关场景视图中的其他工具&#xff0c;请参阅叠加。 工具栏…

微服务:Springboot集成Hystrix实现熔断、降级、隔离

文章目录 前言知识积累Springboot集成Hystrix1、maven依赖引入2、application开启feign的hystrix支持&#xff08;客户端配置限流降级熔断&#xff09;3、入口类增加EnableFeignClients EnableHystrix 开启feign与hystrix4、feign调用增加降级方法服务端配置限流降级熔断(选择使…

中移物联车联网项目,在 TDengine 3.0 的应用

小T导读&#xff1a;在中移物联网的智慧出行场景中&#xff0c;需要存储车联网设备的轨迹点&#xff0c;还要支持对车辆轨迹进行查询。为了更好地进行数据处理&#xff0c;他们在 2021 年上线了 TDengine 2.0 版本的 5 节点 3 副本集群。 3.0 发布后&#xff0c;它的众多特性吸…

关于visual studio 2010 及以上版本 引入boost库的最新解决方法

之前没有怎么用到boost库&#xff0c;出来实习需要去编译一些代码&#xff0c;需要引入boost第三方库&#xff0c;在这过程中&#xff0c;一直出现 LINK : fatal error LNK1104: 无法打开文件“libboost_filesystem-vc100-mt-gd-x3 错误&#xff0c; 但是也确实是跟其他教程学过…

myCobot机器人ChatGPT应用:设计原则和模型能力

我们将 ChatGPT 的功能扩展到机器人&#xff0c;并通过语言直观地控制机器人手臂、无人机和家庭助理机器人等多个平台。 你有没有想过用你自己的话告诉机器人该怎么做&#xff0c;就像你对人类一样&#xff1f;只是告诉你的家庭助理机器人&#xff1a;“请加热我的午餐”&…

MYSQL根据标签查询数据

场景条件&#xff1a; 1.根据用户id查询到该id绑定的标签&#xff08;可能是多个标签也可能是单个标签&#xff09; 2.根据标签的id查询到绑定标签id的信息表 SELECT labelID FROM LRrelation WHERE relationID 1 SELECT * FROM notification SELECT * FROM notification…

6.30学习-函数柯里化,回调解决异步多线程

6.30学习-函数柯里化&#xff0c;回调解决异步多线程 1.函数柯里化1.1 确定参数的函数柯里化1.2参数不确定的函数柯里化1.3 用法1.3.1 给setTimeout传递进来的函数添加参数 2.回调解决异步多线程 1.函数柯里化 函数柯里化&#xff0c;经常可能就面试的时候听说过&#xff0c;反…

如何在半导体行业运用IPD?

半导体产业链具体包括上游半导体原材料与设备供应、中游半导体产品制造和下游应用。其中&#xff0c;半导体材料处于上游供应环节&#xff0c;材料品类繁多&#xff0c;按制造流程可细分为前端制造材料和后端封装材料。半导体设备&#xff0c;即在芯片制造和封测流程中应用到的…

智谱AI-算法实习生(知识图谱方向)实习面试记录

岗位描述 没错和我的经历可以说是match得不能再match了&#xff0c;但是还是挂了hh。 面试内容 给我面试的是唐杰老师的博士生&#xff0c;方向是社交网络数据挖掘&#xff0c;知识图谱。不cue名了&#xff0c;态度很友好的 &#xff0c;很赞。 date&#xff1a;6.28 Q1 自…

服务器解析漏洞与cms靶场搭建教程

文章目录 一、解析漏洞定义1.CVE-2017-157152.AddHandler3.IIS64.IIS75.nginx 二、Kali安装docker并搭建DVWA靶场1.安装docker2.启动docker3.安装docker的DVWA容器4.启动dvwa 三、kali搭建vulhub与CVE-2017-15715复现1.安装vulhub2.安装CVE-2017-15715漏洞利用靶场3.启动靶场4.…

液晶铝薄膜的干蚀特性

引言 对于先进的薄膜晶体管液晶显示器(TFT-LCD)制造工艺来说&#xff0c;薄膜层已逐渐取代传统的湿法蚀刻工艺。对于栅电极&#xff0c;一般使用铝(Al)&#xff0c;在Al中加入一些金属&#xff0c;除了可以保持低电阻率和增强Al薄膜的耐腐蚀性外&#xff0c;还可以防止在后退火…

spfa求负环

1.虫洞 Wormholes&#xff08;裸spfa判断负环问题&#xff09; 信息学奥赛一本通&#xff08;C版&#xff09;在线评测系统 (ssoier.cn)http://ybt.ssoier.cn:8088/problem_show.php?pid1507 #include<bits/stdc.h> using namespace std; const int N510,M5210; int d…

判断数组中所有元素是否均为实数对象 numpy.isrealobj()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断数组中所有元素 是否均为实数对象 numpy.isrealobj() [太阳]选择题 请问关于以下代码的说法错误的是&#xff1f; import numpy as np a np.array([1, 2, 3]) b np.array([1, 1 2j, …

docker学习(七)docker daemon

1.Docker 的CS模式 1.1.Docker 的C/S模式介绍 在 Docker Client 中来运行 Docker 的各种命令&#xff0c;这些命令会传送给在 Docker 的宿主机上运行的 Docker 守护进程。而 Docker 守护进程是负责实现 Docker 各种功能的。 如图所示&#xff0c;Docker 守护进程运行在宿主机…

第四章 数组

前言 学习方法 可以多看几遍视频把上课的代码&#xff0c;自己加加注释&#xff0c;在自己写之前&#xff0c;可以画一个流程图照着流程图把代码自己实现一遍 不要怀疑自己&#xff0c;不要遇到困难就觉得自己不行&#xff0c;遇到困难就解决困难&#xff0c;编程初学者都是…

SSH连接vmware 虚拟机 centos

检查虚拟机设置的网络连接是否为NAT模式 点击左上角“编辑” -> “虚拟网络编辑器” 在虚拟网络编辑器中查看IP地址 &#xff0c;点击NAT模式后&#xff0c;点击“NAT设置 记住自己的网关,下面在服务器中配置需要 进入服务器的 /etc/sysconfig/network-scripts/ 编辑 i…

浑元太极马老师和小薇-UMLChina建模知识竞赛第4赛季第7轮[更新]

DDD领域驱动设计批评文集 欢迎加入“软件方法建模师”群 《软件方法》各章合集 参考潘加宇在《软件方法》和UMLChina公众号文章中发表的内容作答。在本文下留言回答。 第7轮一直无人得分&#xff0c;再次更换题目。 因有的题目之前已经出过&#xff0c;本轮需要最先答对全…

Android View 事件派发流程

原文链接 Android View 事件派发流程 自从乔帮主横空出世推出了iPhone以来&#xff0c;触控式的操作便成了21世纪智能设备的标准输入方式。对于同是智能操作系统的Android来说&#xff0c;也不例外。事件&#xff0c;特别是触控事件对于移动应用程序开发来说是一个非常重要的&…