使用Spring Boot和MongoDB构建一个反应式应用程序

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。

如果您要处理大量流数据,反应式应用程序可让您更好地扩展。 它们是非阻塞的,并且往往效率更高,因为它们在等待发生事情时不会占用处理能力。

反应系统包含异步I / O。 异步I / O背后的概念很简单:通过回收本来会在等待I / O活动时处于空闲状态的资源来缓解资源利用效率低下的问题。 异步I / O颠倒了I / O处理的常规设计:向客户端通知新数据而不是请求新数据; 这使客户可以在等待时做其他事情。

如果要构建反应式应用程序,则需要它一直到整个数据库都是反应式的。 将阻塞的JDBC驱动程序与Spring WebFlux一起使用,您会对其性能感到失望。 使用反应性NoSQL数据库(例如Cassandra,MongoDB,Couchbase和Redis),其性能将给您留下深刻的印象。

在本教程中,您将学习如何使用Spring Boot,Spring WebFlux和Spring Data创建与NoSQL数据库后端(在本例中为MongoDB)通信的反应式Web服务。

我只是对你说了几句。 让我们越过它们。

如果您已经了解NoSQL和Reactive编程,并且只想看一些代码,请随时跳过前两部分,并从“构建Spring Boot资源服务器”开始。

注意:本系列的第一部分演示了如何将Spring Boot和Spring Data与关系数据库PostgreSQL一起使用。 您可以在此处查看该帖子。

什么是NoSQL?为什么使用MongoDB?

NoSQL是任何非关系数据库的术语。 在关系数据库(例如SQL,MySQL等)中,数据存储在具有强类型且表列之间关系明确的表中。 关系数据库的紧密,定义明确的结构既是优点也是缺点。 这是一个权衡。 NoSQL数据库使该模型爆炸式增长,并提供了其他模型,这些模型可提供更大的灵活性并易于扩展。

扩展的微服务/集群模型为关系数据库带来了很多问题。 它们不是为在多台计算机上运行和保持同步而设计的。 开发NoSQL数据库部分是为了解决此问题。 通常,它们是在考虑群集和水平缩放的情况下构建的。 为了以另一种方式展示这种方式(通常是使用SQL数据库),如果需要更多功能,则必须调整数据库运行所在的服务器的大小。 它几乎是单片的,并且即使当今有现代的虚拟服务器功能,也很难动态地做到这一点。 在Internet规模上,更好的模型是拥有一个灵活的数据库集群,它们可以在数据库之间自动同步,并允许您根据需求增加实例(并在需求减少时减少实例)。 这意味着增加功率并不需要更昂贵的机器。 您可以根据需要简单地添加更多,相对便宜的计算机。

NoSQL数据库的另一个潜在好处是它们的灵活性。 像MongoDB这样的基于文档的NoSQL数据库可以在文档中存储任意数据。 可以将字段动态添加到存储的文档中,而无需增加表迁移的开销。 当然,这并不能解决版本控制的问题,仍然取决于应用程序来处理不断变化的数据结构(并不总是琐碎的),但是至少您并没有与数据库打架。

综上所述,请记住,SQL /关系数据库不会走到任何地方。 它们经过验证,快速且超级可靠。 在某些情况下,它们更便宜,更容易。 例如,对于简单的网站或博客,MySQL很难被击败。 但是即使在企业环境中, 有时您也想要关系数据库强制执行的结构。 如果您有一个相当静态的数据模型并且不需要扩展到Internet规模,则SQL可能是最佳选择。 这些类型的设计注意事项在您深入数据库选择之前值得深思,因为它是新的且浮华的。

我在本教程中使用的是MongoDB,因为一开始它很容易。 如果您使用Spring Data MongoDB,它甚至更容易!

积极反应!

反应性是另一种行话。 感觉就像人们喜欢在聚会和会议上随意表达的那种字眼,只是含糊其词。 就像“存在的”或“ ennui”。 让我们定义它。

如果您看一下Spring WebFlux文档 ,他们会很好地概述什么是反应性

术语“反应性”是指围绕响应变化而构建的编程模型-网络组件响应I / O事件,UI控制器响应鼠标事件等。 从这个意义上说,非阻塞是反应性的,因为随着操作完成或数据可用,我们现在处于响应通知的模式,而不是被阻塞。

因此,反应式意味着:非阻塞,异步且以流处理为中心。

构建一个Spring Boot资源服务器

从GitHub仓库克隆启动项目,并检出start分支:

git clone -b start https://github.com/oktadeveloper/okta-spring-boot-mongo-webflux-example.git

入门项目是一个简单的Spring Boot入门项目,在build.gradle文件中已经具有必需的依赖build.gradle

让我们快速看一下相关性:

compile('org.springframework.boot:spring-boot-starter-webflux')  
compile('org.springframework.boot:spring-boot-starter-data-mongodb-reactive')  
compileOnly('org.projectlombok:lombok')  
compile('de.flapdoodle.embed:de.flapdoodle.embed.mongo')

第一个是针对Spring WebFlux(Spring MVC的响应版本)。 第二个引入了Spring需要的反应性MongoDB依赖关系。 第三个是名为Lombok的项目,该项目使我们免于在Java代码中键入一堆构造函数,getter和setter(您可以在其网页上查看该项目)。 最后一个依赖项是嵌入式的内存MongoDB数据库。 这个数据库非常适合测试,像这样的简单教程,并且不持久。

可以使用简单的Gradle命令运行该应用程序:

./gradlew bootRun

当然,如果您此时运行该应用程序,则不会做太多事情。 Spring Boot将加载,但是还没有定义任何控制器,资源或存储库,因此没有太多事情发生。

为MongoDB定义模型类

为了清楚起见,本教程将与我之前提到的本系列的第一部分并行。 您将要构建一个存储皮划艇类型的简单服务器。 我总是建议首先定义数据结构来开始任何项目。

com.okta.springbootmongo包中创建一个Kayak.java类文件:

package com.okta.springbootmongo;  import lombok.AllArgsConstructor;  
import lombok.Data;  
import lombok.NoArgsConstructor;  
import org.springframework.data.mongodb.core.mapping.Document;  @Document
@Data  
@AllArgsConstructor  
@NoArgsConstructor  
public class Kayak {  private String name;  private String owner;  private Number value;  private String makeModel;  
}

@Document注释与@Entity的NoSQL等效。 它告诉Spring Boot此类正在定义数据模型。 在NoSQL世界中,这意味着创建文档而不是表条目。 其他三个注释是Lombok帮助器,它们自动生成getter,setter和构造函数。

皮划艇文档具有五个属性:名称,所有者,值和类型。 这些会自动映射到MongoDB的适当BSON类型。 什么是BSON类型? 看看有关该主题的MongoDB文档 。 它们是用于将数据保留在MongoDB文档中的二进制序列化类型。 它们定义了可以存储在MongoDB数据库中的原始类型。

将ReactiveMongoRepository添加到您的Spring Boot应用程序

使用@Document批注定义Kayak类可以使Spring Boot知道数据的结构,但实际上并没有提供任何从数据库保存或加载数据的方法。 为此,您需要定义一个存储库。

这样做的代码非常简单。 在com.okta.springbootmongo包中创建一个KayakRepository.java类文件:

package com.okta.springbootmongo;  import org.springframework.data.mongodb.repository.ReactiveMongoRepository;  public interface KayakRepository extends ReactiveMongoRepository<Kayak, Long> {  
}

实际上,这为您提供了从数据库创建,更新,读取和删除文档所需的所有基本方法。 要了解操作方法,请深入研究ReactiveMongoRepository类和其他各种超类,尤其是ReactiveCrudRepository 。 查看ReactiveCrudRepository 的文档以查看已实现的方法。

ReactiveCrudRepository实际上提供了一组基本而完整的CRUD方法。 ReactiveMongoRepository在此基础上构建,以提供一些特定于MongoDB的查询功能。

使用Spring WebFlux实现控制器

添加存储库后,您有足够的能力以编程方式处理数据。 但是,没有定义Web端点。 在前面的教程中,添加REST端点,这是需要的所有是对加@RepositoryRestResource注释到KayakRepository类。 这通过所有CRUD方法为我们自动生成了功能齐全的REST资源。 但是,此快捷方式不适用于Spring WebFlux。 必须明确定义任何公共Web终结点。

添加以下KayakController.java

package com.okta.springbootmongo;  import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.*;  
import reactor.core.publisher.Flux;  @Controller  
@RequestMapping(path = "/kayaks")  
public class KayakController {  private KayakRepository kayakRepository;  public KayakController(KayakRepository kayakRepository) {this.kayakRepository = kayakRepository;}@PostMapping()  public @ResponseBody  Mono<Kayak> addKayak(@RequestBody Kayak kayak) {  return kayakRepository.save(kayak);  }  @GetMapping()  public @ResponseBody  Flux<Kayak> getAllKayaks() {  return kayakRepository.findAll();  }
}

该控制器添加了两个端点:

  • POST /kayaks增加了新的皮划艇
  • GET /kayaks列出所有皮划艇

您还将注意到,该类使用Spring依赖项注入将KayakRepository实例自动KayakRepository到控制器中,并且您将看到如何使用存储库持久化Kayak域类。

此类看起来非常像关系的,阻止的版本。 许多幕后工作使这种情况成为现实。 不用担心,但是,这是100%无反应的非阻塞代码。

测试您的Spring Boot服务器

至此,您已经可以完全运行皮划艇REST资源服务器。 在测试之前,请将以下方法添加到MainApplication类。 只需在应用程序加载时将一些测试数据注入数据库。

@Bean  
ApplicationRunner init(KayakRepository repository) {  Object[][] data = {  {"sea", "Andrew", 300.12, "NDK"},  {"creek", "Andrew", 100.75, "Piranha"},  {"loaner", "Andrew", 75, "Necky"}  };  return args -> {  repository  .deleteAll()  .thenMany(  Flux  .just(data)  .map(array -> {  return new Kayak((String) array[0], (String) array[1], (Number) array[2], (String) array[3]);  })  .flatMap(repository::save)  )  .thenMany(repository.findAll())  .subscribe(kayak -> System.out.println("saving " + kayak.toString()));};  
}

HTTPie是一个很棒的命令行实用工具,它使对资源服务器的请求运行变得容易。 如果未安装HTTPie,请使用brew install httpie进行brew install httpie 。 或前往他们的网站并实现它。 或者只是跟随。

确保您的Spring Boot应用正在运行。 如果不是,请使用./gradlew bootRun启动它。

针对您的资源服务器运行GET请求: http :8080/kayaks ,这是http GET http://localhost:8080/kayaks简写。

您会得到:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
transfer-encoding: chunked
[{"makeModel": "NDK","name": "sea","owner": "Andrew","value": 300.12},{"makeModel": "Piranha","name": "creek","owner": "Andrew","value": 100.75},{"makeModel": "Necky","name": "loaner","owner": "Andrew","value": 75}
]

现在尝试将新的皮划艇过帐到服务器。

http POST :8080/kayaks name="sea2" owner="Andrew" value="500" makeModel="P&H"

您应该看到:

HTTP/1.1 200 OK
Content-Length: 62
Content-Type: application/json;charset=UTF-8
{"makeModel": "P&H","name": "sea2","owner": "Andrew","value": 500
}

如果您重复GET请求http :8080/kayaks ,您将在列表中看到新的皮划艇!

设置安全认证

现在,您需要集成Okta for OAuth 2.0并将基于令牌的身份验证添加到资源服务器。 本部分与本教程第1部分中的部分完全相同,因此,如果您已完成此操作,则只需要您的客户ID,就可以跳至下一部分。

如果尚未注册,请访问developer.okta.com并注册一个免费帐户。 拥有帐户后,通过单击“ 应用程序”顶部菜单项,然后单击“ 添加应用程序”按钮,打开开发人员仪表板并创建OpenID Connect(OIDC)应用程序

反应式应用

选择单页应用程序

反应式应用

默认应用程序设置很好,除了您需要添加登录重定向URIhttps://oidcdebugger.com/debug : https://oidcdebugger.com/debug 。 您将在稍后使用它来检索测试令牌。

注意 :如果要实现像Angular或React这样的前端,则可能需要根据所使用的平台来更新默认的登录重定向URI。 由于本教程仅创建没有前端的资源服务器,因此暂时不重要。 我们所有的资源服务器将要做的就是使用授权服务器验证JSON Web令牌,而无需重定向。

另外,请注意您的客户ID ,稍后您将需要它。

反应式应用

配置您的Spring Boot服务器以进行令牌认证

现在,您需要更新一些项目文件以为OAuth 2.0配置Spring Boot。

将以下依赖项添加到您的build.gradle文件中:

dependencies {...compile('com.okta.spring:okta-spring-boot-starter:1.1.0')...
}

创建一个名为src/main/resources/application.yml的新配置文件

okta:oauth2:issuer: https://{yourOktaDomain}/oauth2/defaultgroupsClaim: groupsclientId: {yourClientId}

com.okta.springbootmongo包中创建一个SecurityConfiguration.java类:

package com.okta.springbootmongo;import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;@EnableWebFluxSecurity
public class SecurityConfiguration {@Beanpublic SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {http.authorizeExchange().anyExchange().authenticated().and().oauth2ResourceServer().jwt();return http.build();}
}

测试您的受保护服务器

停止您的Spring Boot服务器并使用以下./gradlew bootRun重新启动它: ./gradlew bootRun

从命令行运行一个简单的GET请求。

http :8080/kayaks

您会得到未经授权的401 /。

HTTP/1.1 401 Unauthorized
Cache-Control: no-store
Content-Type: application/json;charset=UTF-8

生成访问令牌

要立即访问服务器,您需要一个有效的访问令牌。 您可以使用OpenID Connect调试器来帮助您完成此任务。 在另一个窗口中,打开oidcdebugger.com 。

  • 授权URIhttps://{yourOktaDomain} /oauth2/default/v1/authorize
  • 重定向URI :不变。 这是您在上面的OIDC应用程序中添加的值。
  • 客户ID :来自您刚创建的OIDC应用程序。
  • 范围openid profile email
  • 状态 :您要通过OAuth重定向过程传递的任何值。 我将其设置为{}
  • Nonce :可以一个人呆着。 Nonce表示“编号已使用一次”,是一种简单的安全措施,用于防止同一请求被多次使用。
  • 响应类型token
  • 响应方式form_post
反应式应用

点击发送请求 。 如果您尚未登录developer.okta.com,则需要登录。如果(可能的话)已经登录,则将为您的登录身份生成令牌。

反应式应用

使用您的访问令牌

您可以通过在Bearer类型的Authorization请求标头中包含令牌来使用令牌。

将令牌存储在shell变量中:

TOKEN=eyJraWQiOiJldjFpay1DS3UzYjJXS3QzSVl1MlJZc3VJSzBBYUl3NkU4SDJfNVJr...

然后使用HTTPie发出GET请求:

http :8080/kayaks "Authorization: Bearer $TOKEN"

请注意上面的双引号。 单引号不起作用,因为shell变量未扩展。

添加基于组的授权

现在,您将通过添加基于组成员身份来控制对特定控制器端点的访问的功能,来使授权方案更加完善。

要在Okta中使用基于组的授权,您需要在访问令牌中添加一个“组”声明。 创建一个Admin组(“ 用户” >“ 组” >“ 添加组” )并将您的用户添加到其中。 您可以使用注册时使用的帐户,也可以创建一个新用户(“ 用户” >“ 添加人” )。 导航到“ API” >“ 授权服务器” ,单击“ 授权服务器”选项卡,然后编辑默认选项卡。 点击索赔标签,然后添加索赔 。 将其命名为“组”,并将其包含在访问令牌中。 将值类型设置为“ Groups”,并将过滤器设置为.*的正则表达式。

声明包含用户分配到的组。 您用来登录developer.okta.com网站的默认用户也将是“所有人”组和“管理员”组的成员。

还需要更新SecurityConfiguration类以使用基于组的授权。 更新Java文件以匹配以下内容:

package com.okta.springbootmongo;import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {@Beanpublic SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {http.authorizeExchange().pathMatchers(HttpMethod.POST, "/kayaks/**").hasAuthority("Admin").anyExchange().authenticated().and().oauth2ResourceServer().jwt();return http.build();}
}

用简单的英语来说,这告诉Spring Boot要求对/kayak端点的任何POST都具有组成员身份Admin ,对于所有其他请求,仅需要有效的JWT。

您的基于组的授权策略由以下两行定义:

.pathMatchers(HttpMethod.POST, "/kayaks/**").hasAuthority("Admin")  
.anyExchange().authenticated()

有关更多信息,请参阅ServerHttpSecurity类的文档 。

您可能想知道为什么它说hasAuthority()而不是hasRole()hasGroup() 。 这是因为授权是Spring调用服务器发送的文本字符串以表示权限成员身份的方式,无论是角色还是组。 hasRole()假定角色采用特定格式:“ ROLE_ADMIN”。 可以重写此方法,但是hasAuthority()是直接使用授权字符串的简单方法。 没有hasGroup()方法,因为前两个示例(如果未明确说明)涵盖了该用例。

创建一个非管理员用户

要测试基于组的授权方案,您需要一个不是管理员的用户。 转到developer.okta.com仪表板。

从顶部菜单中,选择“ 用户” >“ 人员” 。 单击添加人按钮。

给用户一个名字姓氏用户名 (也将是主要电子邮件 )。 值无关紧要,并且您将不必检查电子邮件。 您只需要知道电子邮件地址/用户名和密码,即可在一分钟内登录Okta。

密码 :将下拉菜单更改为“ 由管理员设置”

为用户分配密码。

点击保存

您刚刚创建的用户不是Admin组的成员,而是默认组Everyone的成员。

基于测试组的授权

注销您的Okta开发人员仪表板。

返回OIDC调试器并生成一个新令牌。

这次,以新的非管理员用户身份登录。 系统会要求您选择一个安全问题,然后将您重定向到https://oidcdebugger.com/debug页面,您可以在其中复制令牌。

如果愿意,可以转到jsonwebtoken.io并解码新令牌。 在有效内容中, 声明将显示用户的电子邮件/用户名,而声明将仅显示“ 所有人”组。

{"sub": "test@gmail.com","groups": ["Everyone"]
}

根据许可方案,该用户应该能够列出所有皮划艇,但不能添加新的皮划艇。

请记住,将令牌存储在shell脚本中,如下所示:

TOKEN=eyJraWQiOiI4UlE5REJGVUJOTnJER0VGaEExekd6bWJqREpSYTRTT1lhaGpsM3d4...

发出GET请求以列出所有皮划艇:

http :8080/kayaks "Authorization: Bearer $TOKEN"HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
...[{"makeModel": "NDK","name": "sea","owner": "Andrew","value": 300.12},{"makeModel": "Necky","name": "loaner","owner": "Andrew","value": 75},{"makeModel": "Piranha","name": "creek","owner": "Andrew","value": 100.75}
]

尝试使用非管理员用户令牌添加新的皮划艇:

http POST :8080/kayaks "Authorization: Bearer $TOKEN" name="sea2" owner="Andrew" value="500" makeModel="P&H"

您将被拒绝!

HTTP/1.1 403 Forbidden
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Expires: 0
...

现在,注销developer.okta.com,并使用OIDC Debugger生成一个新令牌。 这次使用您原来的管理员帐户重新登录。

将新令牌存储在shell变量TOKEN

运行POST请求:

http POST :8080/kayaks "Authorization: Bearer $TOKEN" name="sea2" owner="Andrew" value="500" makeModel="P&H"

AM! 💥

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
...
{"makeModel": "P&H","name": "sea2","owner": "Andrew","value": 500
}

一切顺利,已通过身份验证

而已! 在本教程中,您使用Spring WebFlux创建了一个Spring Boot应用程序,使用嵌入式MongoDB数据库来持久化模型类,并向其中添加了资源服务器。 之后,我向您展示了如何使用Okta和OAuth 2.0添加JWT令牌身份验证。 最后,您了解了如何使用Okta和Spring Security将基于组的授权添加到控制器中的特定端点。

如果您想查看这个完整的项目,可以在oktadeveloper / okta-spring-boot-mongo-webflux-example上的GitHub上找到该仓库 。

如果还没有,请查看本系列的第1部分: 使用PostgreSQL使用Spring Boot和JPA构建基本应用程序 。 它是同一个应用程序,但是使用了更传统的关系数据库和Spring MVC样式的阻止Web服务器。

了解有关Spring Boot,MongoDB和安全用户管理的更多信息

如果您想了解有关Spring Boot,Spring Security或Okta的更多信息,请查看以下任何出色的教程:

  • 使用Spring WebFlux构建反应性API
  • Spring Boot,OAuth 2.0和Okta入门
  • 15分钟内将单一登录添加到您的Spring Boot Web App
  • 使用多重身份验证保护您的Spring Boot应用程序安全
  • 使用Spring Boot和GraphQL构建安全的API

以下是一些来自Spring的优秀资源:

  • 对Spring Data做出反应
  • OAuth2 WebFlux文档
  • 构建反应式RESTful Web服务
  • Spring WebFlux文档

如果您喜欢这篇文章,您可能会喜欢我们发布的其他文章。 在Twitter上关注@oktadev ,并订阅我们的YouTube频道以获取更多有趣的教程。

“使用Spring Boot和MongoDB构建反应性应用程序”最初于2019年2月21日发布在Okta开发人员博客上。

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。

翻译自: https://www.javacodegeeks.com/2019/03/build-reactive-app-spring-boot-mongodb.html

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

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

相关文章

zune自搭虚拟服务器离线升级,Zune 30g 固件更新至 3.3 记录

换成64位Win7后Zune的桌面管理器木有了&#xff0c;而64位版的Zune 1.3桌面安装麻烦死个人&#xff0c;各大论坛的115下载连接无一例外的都断链了&#xff0c;无奈只好把Zune升级至最新的3.3。升级记录&#xff1a;1. 在Zune官网 http://www.zune.net/zh-CH 下载最新版的桌面管…

工业交换机芯片选择需要注意什么事项呢?

相信不少工业级交换机品牌&#xff0c;在其工业交换机机内的芯片选择上一定很慎重&#xff0c;因为工业交换价的芯片将影响到其以后的使用&#xff0c;工业交换机常用的芯片有Marvell和Broadcom平台。那么&#xff0c;工业交换机芯片选择要注意什么呢&#xff1f;接下来就由飞畅…

JAX-RS和OpenAPI对Hypermedia API的支持:任重而道远

或早或晚&#xff0c;大多数积极使用REST&#xff08;ful&#xff09; Web服务和API的开发人员都偶然发现了这种真正的外星事物&#xff0c;即HATEOAS &#xff1a; 超文本作为应用程序状态的引擎 。 对HATEOAS是什么以及它与REST的关系的好奇最终将导致发现Richardson成熟度模…

工业以太网交换机的光口和电口有什么区别?

对于从事安防传输设备行业的朋友们来说&#xff0c;相信大家对工业以太网交换机应该都不陌生。客户购买工业以太网交换机时&#xff0c;很多客户都会要几光几电的交换机&#xff0c;最近也接到不少客户的电话&#xff0c;都会询问工业以太网交换机的电口和光口有什么区别&#…

家用、商用、工业交换机的用途与区别

以太网交换机一般分为&#xff1a;商用(以太网)交换机、工业(以太网)交换机、家用(以太网)交换机。那么&#xff0c;家用交换机&#xff0c;商业交换机&#xff0c;工业交换机之间有什么区别呢&#xff1f;接下来我们就跟随飞畅科技的小编一起来详细了解下吧&#xff01; 商用…

将Spring Boot应用程序部署到Tomcat中

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 部署应用程序很困难。 通常&#xff0c;您需要控制台访问服务器&#xff0c;从服务器…

HD-SDI光端机是什么?其性能特点和技术参数有哪些?

HD-SDI光端机是将SDI信号与光信号互相转换的设备。SDI光端机的原理是发送端将SDI信号通过激光器调制后变为光信号,接收端将激光二极管收到的数据再编码为SDI信号。那么&#xff0c;HD-SDI光端机是什么呢&#xff1f;其性能特点和技术参数有哪些呢&#xff1f;接下来我们就跟随飞…

HD-SDI光端机有哪些优势?

3G-SDI光端机适合电视行业的高清可靠、高清性能的标准&#xff0c;杭州飞畅的3G-SDI光端机采用最新科技&#xff0c;采用H.264编码方式&#xff0c;采用高清SDI专用VIDIO SFP光模块&#xff0c;一般情况下采用SDI接口。其产品最早为广电行业客户开发使用&#xff0c;应用于电视…

PDH-SDH光端机指示灯具体含义介绍

最近有很多客户朋友来咨询有关PDH/SDH光端机各个指示灯含义的问题&#xff0c;其实在很多故障发生的时候我们都可以通过光端机各个指示灯的状态来分析故障问题&#xff0c;从而帮助解决问题。接下来我们就来为大家详细介绍一下PDH/SDH光端机指示灯的具体含义&#xff0c;感兴趣…

PDH光端机的主要作用以及特点有哪些?

在之前小编为大家介绍了光端机的详细分类&#xff0c;相信很多看过的朋友对pdh光端机这一块不陌生了吧&#xff0c;但是对于pdh光端机的作用以及特点你还了解吗&#xff0c;今天&#xff0c;飞畅科技的小编就来为大家详细介绍下pdh光端机的作用以及特点&#xff0c;感兴趣的朋友…

python将html存为pdf_用Python将HTML转为PDF。

上期提到了如何获取公众号文章信息&#xff0c;这回就说下怎么将网页转为PDF&#xff0c;方便日常学习。html而后扩散一下以前一个比赛的结果(华章计算机抖音大赛)。数据库顺便谈谈本身对从此送书的一个想法。微信另外以前的送书活动&#xff0c;有中奖的读者没有联系我&#x…

使用Gradle – 2019版从Travis可靠发布到Maven Central

得益于在2018年和2019年末实现的显式登台存储库创建功能集&#xff0c;使您&#xff08;自动&#xff09;从Travis&#xff08;不仅是&#xff09;发布到Maven Central更加可靠。 背景 如果您仅想获取信息&#xff0c;如何使您的工件从Travis发布更可靠&#xff0c;请前进到另…

spring admin mysql_easyadmin: 简易的java后台管理框架,基于SpringBoot+FreeMark+ace admin+mysql...

easyadmin数据库一定要用utf8mb4编码&#xff0c;记得先执行manager.sql&#xff0c;再执行initdata.sql,其中tenant表不用管&#xff0c;这是我打算做的另外一个项目设计的表&#xff0c;因为直接复制的本项目&#xff0c;怕到时候忘记&#xff0c;所以没有删除拦截器相关文档…

SDI高清视频光端机特点有哪些?

SDI视频光端机设计和生产是适用于电视行业的高可靠、高性能的串行数字光传输设备&#xff0c;信号格式从19.4Mbps到1.485Gbps, 系统支持SMPTE292、SMPTE259M、SMPTE297M、SMPTE305M、SMPTE310M以及DVB-ASI(EN50083-9)等数字电视格式的信号,满足工业级产品的要求。那么&#xff…

SDI光端机是什么?SDI光端机产品介绍及监控方案!

SDI光端机就是光信号传输的中端设备。光纤价格的降低使它在各个领域得到很好的应用&#xff0c;因此各个光端机的厂家就好比是雨后春笋般发展起来。但是这里的厂家大部分技术并不是完全成熟&#xff0c;开发新技术需要耗资和人力、物力等&#xff0c;这就产生厂家多是中小企业&…

adf可以自定义溶剂吗_ADF Faces。 立即的自定义客户端事件

adf可以自定义溶剂吗在本文中&#xff0c;我将重点介绍ADF Faces Javascript API方法以从客户端触发自定义事件。 例如&#xff1a; function cliListener(actionEvent) {AdfCustomEvent.queue(actionEvent.getSource(), "servListener",null, true);}我们可以使用a…

VGA光端机技术原理及应用领域介绍

VGA光端机采用纯数字传输模式&#xff0c;能从根本上克服普通铜芯电缆传输系统在传输高频带信号时造成的拖尾、重影等现象&#xff0c;清晰的重现图象画面。VGA光端机传输的是光信号&#xff0c;没有电磁辐射&#xff0c;系统具有极高的保密性。同时VGA光端机把显示设备和信号源…

java getbytes 长度_JAVA中的getBytes()方法

在Java中&#xff0c;String的getBytes()方法是得到一个操作系统默认的编码格式的字节数组。这个表示在不同情况下&#xff0c;返回的东西不一样&#xff01;String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示&#xff0c;如&…

按应用领域来划分,电话光端机主要分为哪几类

我们都知道&#xff0c;电话光端机就是把传统的电话信号转换成光信号并在光纤上进行传输的设备。但是对于电话光端机的分类这块&#xff0c;大家可能了解的并不是很清楚&#xff0c;电话光端机根据不同的分类方式&#xff0c;有着不同的分法&#xff0c;今天飞畅科技的小编主要…

光纤收发器长距离的传输过程出现死机的解决方案

光纤收发器是网络通信中必不可少的一种设备&#xff0c;但是&#xff0c;我们在使用过程中难免会遇到各种各样的问题&#xff0c;其中&#xff0c;光纤收发器出现死机可以说是很常见的一种故障&#xff0c;那么&#xff0c;光纤收发器经常会出现死机到底是什么原因&#xff0c;…