聊聊rocketmq5的RocketMQClientTemplate

本文主要研究一下rocketmq5的RocketMQClientTemplate

rocketmq-spring

自从rocketmq推出了5版本之后,rocketmq-spring就区分了4.x与5.x版本,4.x版本是rocketmq-spring开头,5.x版本是rocketmq-v5-client开头;rocketmq5的RocketMQClientTemplate对应的是旧版的RocketMQTemplate,他们都同样继承了org.springframework.messaging.core.AbstractMessageSendingTemplate,只是各自扩展的方法发生的变化。

RocketMQTemplate

主要是:

  • sendAndReceive
  • syncSend、syncSendDelayTimeSeconds、syncSendDelayTimeMills、syncSendDeliverTimeMills、syncSendOrderly
  • asyncSend、asyncSendOrderly
  • sendOneWay、sendOneWayOrderly
  • sendMessageInTransaction

RocketMQClientTemplate

主要是:

  • syncSendNormalMessage、syncSendFifoMessage、syncSendDelayMessage
  • asyncSendNormalMessage、asyncSendFifoMessage、asyncSendDelayMessage
  • asyncSendWithObjectPayload、asyncSendWithStringPayload、asyncSendWithBytePayload、asyncSendWithMessagePayload
  • sendMessageInTransaction
  • receive、receiveAsync
  • ack、ackAsync

MessageSendingOperations

org/springframework/messaging/core/MessageSendingOperations.java

public interface MessageSendingOperations<D> {/*** Send a message to a default destination.* @param message the message to send*/void send(Message<?> message) throws MessagingException;/*** Send a message to the given destination.* @param destination the target destination* @param message the message to send*/void send(D destination, Message<?> message) throws MessagingException;/*** Convert the given Object to serialized form, possibly using a* {@link org.springframework.messaging.converter.MessageConverter},* wrap it as a message and send it to a default destination.* @param payload the Object to use as payload*/void convertAndSend(Object payload) throws MessagingException;/*** Convert the given Object to serialized form, possibly using a* {@link org.springframework.messaging.converter.MessageConverter},* wrap it as a message and send it to the given destination.* @param destination the target destination* @param payload the Object to use as payload*/void convertAndSend(D destination, Object payload) throws MessagingException;/*** Convert the given Object to serialized form, possibly using a* {@link org.springframework.messaging.converter.MessageConverter},* wrap it as a message with the given headers and send it to* the given destination.* @param destination the target destination* @param payload the Object to use as payload* @param headers the headers for the message to send*/void convertAndSend(D destination, Object payload, Map<String, Object> headers) throws MessagingException;/*** Convert the given Object to serialized form, possibly using a* {@link org.springframework.messaging.converter.MessageConverter},* wrap it as a message, apply the given post processor, and send* the resulting message to a default destination.* @param payload the Object to use as payload* @param postProcessor the post processor to apply to the message*/void convertAndSend(Object payload, @Nullable MessagePostProcessor postProcessor) throws MessagingException;/*** Convert the given Object to serialized form, possibly using a* {@link org.springframework.messaging.converter.MessageConverter},* wrap it as a message, apply the given post processor, and send* the resulting message to the given destination.* @param destination the target destination* @param payload the Object to use as payload* @param postProcessor the post processor to apply to the message*/void convertAndSend(D destination, Object payload, MessagePostProcessor postProcessor) throws MessagingException;/*** Convert the given Object to serialized form, possibly using a* {@link org.springframework.messaging.converter.MessageConverter},* wrap it as a message with the given headers, apply the given post processor,* and send the resulting message to the given destination.* @param destination the target destination* @param payload the Object to use as payload* @param headers the headers for the message to send* @param postProcessor the post processor to apply to the message*/void convertAndSend(D destination, Object payload, @Nullable Map<String, Object> headers,@Nullable MessagePostProcessor postProcessor) throws MessagingException;}

spring-messaging的MessageSendingOperations接口定义了send、convertAndSend方法

AbstractMessageSendingTemplate

org/springframework/messaging/core/AbstractMessageSendingTemplate.java

public abstract class AbstractMessageSendingTemplate<D> implements MessageSendingOperations<D> {/*** Name of the header that can be set to provide further information* (e.g. a {@code MethodParameter} instance) about the origin of the* payload, to be taken into account as a conversion hint.* @since 4.2*/public static final String CONVERSION_HINT_HEADER = "conversionHint";protected final Log logger = LogFactory.getLog(getClass());@Nullableprivate D defaultDestination;private MessageConverter converter = new SimpleMessageConverter();/*** Configure the default destination to use in send methods that don't have* a destination argument. If a default destination is not configured, send methods* without a destination argument will raise an exception if invoked.*/public void setDefaultDestination(@Nullable D defaultDestination) {this.defaultDestination = defaultDestination;}/*** Return the configured default destination.*/@Nullablepublic D getDefaultDestination() {return this.defaultDestination;}/*** Set the {@link MessageConverter} to use in {@code convertAndSend} methods.* <p>By default, {@link SimpleMessageConverter} is used.* @param messageConverter the message converter to use*/public void setMessageConverter(MessageConverter messageConverter) {Assert.notNull(messageConverter, "MessageConverter must not be null");this.converter = messageConverter;}/*** Return the configured {@link MessageConverter}.*/public MessageConverter getMessageConverter() {return this.converter;}@Overridepublic void send(Message<?> message) {send(getRequiredDefaultDestination(), message);}protected final D getRequiredDefaultDestination() {Assert.state(this.defaultDestination != null, "No 'defaultDestination' configured");return this.defaultDestination;}@Overridepublic void send(D destination, Message<?> message) {doSend(destination, message);}protected abstract void doSend(D destination, Message<?> message);@Overridepublic void convertAndSend(Object payload) throws MessagingException {convertAndSend(payload, null);}@Overridepublic void convertAndSend(D destination, Object payload) throws MessagingException {convertAndSend(destination, payload, (Map<String, Object>) null);}@Overridepublic void convertAndSend(D destination, Object payload, @Nullable Map<String, Object> headers)throws MessagingException {convertAndSend(destination, payload, headers, null);}@Overridepublic void convertAndSend(Object payload, @Nullable MessagePostProcessor postProcessor)throws MessagingException {convertAndSend(getRequiredDefaultDestination(), payload, postProcessor);}@Overridepublic void convertAndSend(D destination, Object payload, @Nullable MessagePostProcessor postProcessor)throws MessagingException {convertAndSend(destination, payload, null, postProcessor);}@Overridepublic void convertAndSend(D destination, Object payload, @Nullable Map<String, Object> headers,@Nullable MessagePostProcessor postProcessor) throws MessagingException {Message<?> message = doConvert(payload, headers, postProcessor);send(destination, message);}/*** Convert the given Object to serialized form, possibly using a* {@link MessageConverter}, wrap it as a message with the given* headers and apply the given post processor.* @param payload the Object to use as payload* @param headers the headers for the message to send* @param postProcessor the post processor to apply to the message* @return the converted message*/protected Message<?> doConvert(Object payload, @Nullable Map<String, Object> headers,@Nullable MessagePostProcessor postProcessor) {MessageHeaders messageHeaders = null;Object conversionHint = (headers != null ? headers.get(CONVERSION_HINT_HEADER) : null);Map<String, Object> headersToUse = processHeadersToSend(headers);if (headersToUse != null) {if (headersToUse instanceof MessageHeaders) {messageHeaders = (MessageHeaders) headersToUse;}else {messageHeaders = new MessageHeaders(headersToUse);}}MessageConverter converter = getMessageConverter();Message<?> message = (converter instanceof SmartMessageConverter ?((SmartMessageConverter) converter).toMessage(payload, messageHeaders, conversionHint) :converter.toMessage(payload, messageHeaders));if (message == null) {String payloadType = payload.getClass().getName();Object contentType = (messageHeaders != null ? messageHeaders.get(MessageHeaders.CONTENT_TYPE) : null);throw new MessageConversionException("Unable to convert payload with type='" + payloadType +"', contentType='" + contentType + "', converter=[" + getMessageConverter() + "]");}if (postProcessor != null) {message = postProcessor.postProcessMessage(message);}return message;}/*** Provides access to the map of input headers before a send operation.* Subclasses can modify the headers and then return the same or a different map.* <p>This default implementation in this class returns the input map.* @param headers the headers to send (or {@code null} if none)* @return the actual headers to send (or {@code null} if none)*/@Nullableprotected Map<String, Object> processHeadersToSend(@Nullable Map<String, Object> headers) {return headers;}}

AbstractMessageSendingTemplate对MessageSendingOperations的接口做了实现,它定义了doSend(D destination, Message<?> message)需要子类实现

RocketMQClientTemplate

rocketmq-v5-client-spring-boot/src/main/java/org/apache/rocketmq/client/core/RocketMQClientTemplate.java

@SuppressWarnings({"WeakerAccess", "unused"})
public class RocketMQClientTemplate extends AbstractMessageSendingTemplate<String> implements DisposableBean {private static final Logger log = LoggerFactory.getLogger(RocketMQClientTemplate.class);private ProducerBuilder producerBuilder;private SimpleConsumerBuilder simpleConsumerBuilder;private volatile Producer producer;private volatile SimpleConsumer simpleConsumer;private RocketMQMessageConverter rocketMQMessageConverter = new RocketMQMessageConverter();private String charset = "UTF-8";@Overrideprotected void doSend(String destination, Message<?> message) {SendReceipt sendReceipt = syncSendGrpcMessage(destination, message, null, null);if (log.isDebugEnabled()) {log.debug("send message to `{}` finished. result:{}", destination, sendReceipt);}}/*** @param destination      formats: `topicName:tags`* @param message          {@link Message} the message to be sent.* @param messageDelayTime Time for message delay* @param messageGroup     message group name* @return SendReceipt Synchronous Task Results*/public SendReceipt syncSendGrpcMessage(String destination, Message<?> message, Duration messageDelayTime, String messageGroup) {if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {log.error("send request message failed. destination:{}, message is null ", destination);throw new IllegalArgumentException("`message` and `message.payload` cannot be null");}SendReceipt sendReceipt = null;try {org.apache.rocketmq.client.apis.message.Message rocketMsg = this.createRocketMQMessage(destination, message, messageDelayTime, messageGroup);Producer grpcProducer = this.getProducer();try {sendReceipt = grpcProducer.send(rocketMsg);log.info("Send message successfully, messageId={}", sendReceipt.getMessageId());} catch (Throwable t) {log.error("Failed to send message", t);}} catch (Exception e) {log.error("send request message failed. destination:{}, message:{} ", destination, message);throw new MessagingException(e.getMessage(), e);}return sendReceipt;}    private org.apache.rocketmq.client.apis.message.Message createRocketMQMessage(String destination, Message<?> message, Duration messageDelayTime, String messageGroup) {Message<?> msg = this.doConvert(message.getPayload(), message.getHeaders(), null);return RocketMQUtil.convertToClientMessage(getMessageConverter(), charset,destination, msg, messageDelayTime, messageGroup);}    //......
}

RocketMQClientTemplate继承了AbstractMessageSendingTemplate,其doSend方法调用的是syncSendGrpcMessage;该方法主要是调用父类的doConvert转换为spring-messaging的Message,之后再通过RocketMQUtil.convertToClientMessage转换为org.apache.rocketmq.client.apis.message.Message,最后通过grpcProducer.send(rocketMsg)进行发送

syncSendNormalMessage

    public SendReceipt syncSendNormalMessage(String destination, Object payload) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, null, null);}public SendReceipt syncSendNormalMessage(String destination, String payload) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, null, null);}public SendReceipt syncSendNormalMessage(String destination, Message<?> message) {return syncSendGrpcMessage(destination, message, null, null);}public SendReceipt syncSendNormalMessage(String destination, byte[] payload) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, null, null);}

syncSendNormalMessage主要是通过MessageBuilder构建Message,然后通过syncSendGrpcMessage进行发送

syncSendFifoMessage

    public SendReceipt syncSendFifoMessage(String destination, Object payload, String messageGroup) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, null, messageGroup);}public SendReceipt syncSendFifoMessage(String destination, String payload, String messageGroup) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, null, messageGroup);}public SendReceipt syncSendFifoMessage(String destination, byte[] payload, String messageGroup) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, null, messageGroup);}public SendReceipt syncSendFifoMessage(String destination, Message<?> message, String messageGroup) {return syncSendGrpcMessage(destination, message, null, messageGroup);}

syncSendFifoMessage也是通过MessageBuilder构建Message,只是通过syncSendGrpcMessage进行发送时指定了messageGroup

syncSendDelayMessage

    public SendReceipt syncSendDelayMessage(String destination, Object payload, Duration messageDelayTime) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, messageDelayTime, null);}public SendReceipt syncSendDelayMessage(String destination, String payload, Duration messageDelayTime) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, messageDelayTime, null);}public SendReceipt syncSendDelayMessage(String destination, byte[] payload, Duration messageDelayTime) {Message<?> message = MessageBuilder.withPayload(payload).build();return syncSendGrpcMessage(destination, message, messageDelayTime, null);}public SendReceipt syncSendDelayMessage(String destination, Message<?> message, Duration messageDelayTime) {return syncSendGrpcMessage(destination, message, messageDelayTime, null);}

syncSendDelayMessage也是通过MessageBuilder构建Message,只是通过syncSendGrpcMessage进行发送时指定了messageDelayTime

asyncSend

    public CompletableFuture<SendReceipt> asyncSend(String destination, Message<?> message, Duration messageDelayTime, String messageGroup, CompletableFuture<SendReceipt> future) {if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {log.error("send request message failed. destination:{}, message is null ", destination);throw new IllegalArgumentException("`message` and `message.payload` cannot be null");}Producer grpcProducer = this.getProducer();try {org.apache.rocketmq.client.apis.message.Message rocketMsg = this.createRocketMQMessage(destination, message, messageDelayTime, messageGroup);future = grpcProducer.sendAsync(rocketMsg);} catch (Exception e) {log.error("send request message failed. destination:{}, message:{} ", destination, message);throw new MessagingException(e.getMessage(), e);}return future;}public CompletableFuture<SendReceipt> asyncSendWithObjectPayload(String destination, Object payload, Duration messageDelayTime, String messageGroup, CompletableFuture<SendReceipt> future) {Message<?> message = MessageBuilder.withPayload(payload).build();return asyncSend(destination, message, messageDelayTime, messageGroup, future);}public CompletableFuture<SendReceipt> asyncSendWithStringPayload(String destination, String payload, Duration messageDelayTime, String messageGroup, CompletableFuture<SendReceipt> future) {Message<?> message = MessageBuilder.withPayload(payload).build();return asyncSend(destination, message, messageDelayTime, messageGroup, future);}public CompletableFuture<SendReceipt> asyncSendWithBytePayload(String destination, byte[] payload, Duration messageDelayTime, String messageGroup, CompletableFuture<SendReceipt> future) {Message<?> message = MessageBuilder.withPayload(payload).build();return asyncSend(destination, message, messageDelayTime, messageGroup, future);}public CompletableFuture<SendReceipt> asyncSendWithMessagePayload(String destination, Message<?> payload, Duration messageDelayTime, String messageGroup, CompletableFuture<SendReceipt> future) {return asyncSend(destination, payload, messageDelayTime, messageGroup, future);}        

asyncSend与syncSendGrpcMessage类似先通过createRocketMQMessage转换为org.apache.rocketmq.client.apis.message.Message,只是最后调用的是grpcProducer.sendAsync来发送;asyncSendWithObjectPayload、asyncSendWithStringPayload、asyncSendWithBytePayload、asyncSendWithMessagePayload最后调用的是asyncSend方法

asyncSendNormalMessage

    public CompletableFuture<SendReceipt> asyncSendNormalMessage(String destination, Object payload, CompletableFuture<SendReceipt> future) {return asyncSendWithObjectPayload(destination, payload, null, null, future);}public CompletableFuture<SendReceipt> asyncSendNormalMessage(String destination, String payload, CompletableFuture<SendReceipt> future) {return asyncSendWithStringPayload(destination, payload, null, null, future);}public CompletableFuture<SendReceipt> asyncSendNormalMessage(String destination, byte[] payload, CompletableFuture<SendReceipt> future) {return asyncSendWithBytePayload(destination, payload, null, null, future);}public CompletableFuture<SendReceipt> asyncSendNormalMessage(String destination, Message<?> payload, CompletableFuture<SendReceipt> future) {return asyncSendWithMessagePayload(destination, payload, null, null, future);}

asyncSendNormalMessage委托给了asyncSendWithObjectPayload、asyncSendWithStringPayload、asyncSendWithBytePayload、asyncSendWithMessagePayload;最后调用的是asyncSend方法

asyncSendFifoMessage

    public CompletableFuture<SendReceipt> asyncSendFifoMessage(String destination, Object payload, String messageGroup, CompletableFuture<SendReceipt> future) {return asyncSendWithObjectPayload(destination, payload, null, messageGroup, future);}public CompletableFuture<SendReceipt> asyncSendFifoMessage(String destination, String payload, String messageGroup, CompletableFuture<SendReceipt> future) {return asyncSendWithStringPayload(destination, payload, null, messageGroup, future);}public CompletableFuture<SendReceipt> asyncSendFifoMessage(String destination, byte[] payload, String messageGroup, CompletableFuture<SendReceipt> future) {return asyncSendWithBytePayload(destination, payload, null, messageGroup, future);}public CompletableFuture<SendReceipt> asyncSendFifoMessage(String destination, Message<?> payload, String messageGroup, CompletableFuture<SendReceipt> future) {return asyncSendWithMessagePayload(destination, payload, null, messageGroup, future);}

asyncSendFifoMessage委托给了asyncSendWithObjectPayload、asyncSendWithStringPayload、asyncSendWithBytePayload、asyncSendWithMessagePayload,只是传递了messageGroup

asyncSendDelayMessage

    public CompletableFuture<SendReceipt> asyncSendDelayMessage(String destination, Object payload, Duration messageDelayTime, CompletableFuture<SendReceipt> future) {return asyncSendWithObjectPayload(destination, payload, messageDelayTime, null, future);}public CompletableFuture<SendReceipt> asyncSendDelayMessage(String destination, String payload, Duration messageDelayTime, CompletableFuture<SendReceipt> future) {return asyncSendWithStringPayload(destination, payload, messageDelayTime, null, future);}public CompletableFuture<SendReceipt> asyncSendDelayMessage(String destination, byte[] payload, Duration messageDelayTime, CompletableFuture<SendReceipt> future) {return asyncSendWithBytePayload(destination, payload, messageDelayTime, null, future);}public CompletableFuture<SendReceipt> asyncSendDelayMessage(String destination, Message<?> payload, Duration messageDelayTime, CompletableFuture<SendReceipt> future) {return asyncSendWithMessagePayload(destination, payload, messageDelayTime, null, future);}

asyncSendDelayMessage委托了asyncSendWithObjectPayload、asyncSendWithStringPayload、asyncSendWithBytePayload、asyncSendWithMessagePayload,只是传递了messageDelayTime

sendMessageInTransaction

    public Pair<SendReceipt, Transaction> sendMessageInTransaction(String destination, Object payload) throws ClientException {Message<?> message = MessageBuilder.withPayload(payload).build();return sendTransactionMessage(destination, message);}public Pair<SendReceipt, Transaction> sendMessageInTransaction(String destination, String payload) throws ClientException {Message<?> message = MessageBuilder.withPayload(payload).build();return sendTransactionMessage(destination, message);}public Pair<SendReceipt, Transaction> sendMessageInTransaction(String destination, byte[] payload) throws ClientException {Message<?> message = MessageBuilder.withPayload(payload).build();return sendTransactionMessage(destination, message);}/*** @param destination formats: `topicName:tags`* @param message     {@link Message} the message to be sent.* @return CompletableFuture<SendReceipt> Asynchronous Task Results*/public Pair<SendReceipt, Transaction> sendTransactionMessage(String destination, Message<?> message) {if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {log.error("send request message failed. destination:{}, message is null ", destination);throw new IllegalArgumentException("`message` and `message.payload` cannot be null");}final SendReceipt sendReceipt;Producer grpcProducer = this.getProducer();org.apache.rocketmq.client.apis.message.Message rocketMsg = this.createRocketMQMessage(destination, message, null, null);final Transaction transaction;try {transaction = grpcProducer.beginTransaction();sendReceipt = grpcProducer.send(rocketMsg, transaction);log.info("Send transaction message successfully, messageId={}", sendReceipt.getMessageId());} catch (ClientException e) {log.error("send request message failed. destination:{}, message:{} ", destination, message);throw new RuntimeException(e);}return new Pair<>(sendReceipt, transaction);}    

sendMessageInTransaction先通过MessageBuilder构建消息,最后调用的是sendTransactionMessage;sendTransactionMessage也是先通过createRocketMQMessage转为org.apache.rocketmq.client.apis.message.Message,最后通过grpcProducer.beginTransaction()、grpcProducer.send(rocketMsg, transaction)来发送事务消息

receive

    public List<MessageView> receive(int maxMessageNum, Duration invisibleDuration) throws ClientException {SimpleConsumer simpleConsumer = this.getSimpleConsumer();return simpleConsumer.receive(maxMessageNum, invisibleDuration);}public CompletableFuture<List<MessageView>> receiveAsync(int maxMessageNum, Duration invisibleDuration) throws ClientException, IOException {SimpleConsumer simpleConsumer = this.getSimpleConsumer();CompletableFuture<List<MessageView>> listCompletableFuture = simpleConsumer.receiveAsync(maxMessageNum, invisibleDuration);simpleConsumer.close();return listCompletableFuture;}

receive通过simpleConsumer.receive来拉取;receiveAsync则是通过simpleConsumer.receiveAsync来拉取

ack

    public void ack(MessageView message) throws ClientException {SimpleConsumer simpleConsumer = this.getSimpleConsumer();simpleConsumer.ack(message);}public CompletableFuture<Void> ackAsync(MessageView messageView) {SimpleConsumer simpleConsumer = this.getSimpleConsumer();return simpleConsumer.ackAsync(messageView);}

ack是通过simpleConsumer.ack来操作;ackAsync是通过simpleConsumer.ackAsync来操作

小结

rocketmq5的RocketMQClientTemplate继承了org.springframework.messaging.core.AbstractMessageSendingTemplate,实现了spring-messaging的MessageSendingOperations接口,同时它自己扩展了如下方法

  • syncSendNormalMessage、syncSendFifoMessage、syncSendDelayMessage
  • asyncSendNormalMessage、asyncSendFifoMessage、asyncSendDelayMessage
  • sendMessageInTransaction
  • receive、receiveAsync
  • ack、ackAsync
    其发送消息底层依赖的是grpcProducer.send、sendAsync、send(rocketMsg, transaction),而消费相关的则是依赖的SimpleConsumer

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

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

相关文章

【C++】模板详解

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

域内攻击手法——AS-REP Roasting攻击和Kerberoasting攻击

一、AS-REP Roasting攻击 1、AS-REP Roasting攻击原理 AS-REP Roasting是一种对用户账户进行离线爆破的攻击方式。但是该攻击方式使用上比较受限&#xff0c;因为其需要用户账户设置不要求Kerberos 预身份验证选项&#xff0c;而该选项默认是没有勾选的。Kerberos 预身份验证…

基于jeecgboot-vue3的Flowable流程仿钉钉流程设计器-发送信息服务处理

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、因为仿钉钉设计器里发送消息处理是一个服务任务&#xff0c;所以要根据这个服务任务进行处理 2、这里目前只对消息进行处理&#xff0c;就是用websocket的发送方式 输入相应的内容&…

最新爆火的开源AI项目 | LivePortrait 本地安装教程

LivePortrait 本地部署教程&#xff0c;强大且开源的可控人像AI视频生成 1&#xff0c;准备工作&#xff0c;本地下载代码并准备环境&#xff0c;运行命令前需安装git 以下操作不要安装在C盘和容量较小的硬盘&#xff0c;可以找个大点的硬盘装哟 2&#xff0c;需要安装FFmp…

Java-- Stream流

感受stream流 代码 package demo1;import javax.naming.Name; import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class StreamDemo1 {public static void main(String[] args) {ArrayList<String> list1 new ArrayList<>();l…

基于深度学习算法,支持再学习功能,不断提升系统精准度的智慧地产开源了。

智慧地产视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。通过计算机视觉和…

Java | Leetcode Java题解之第279题完全平方数

题目&#xff1a; 题解&#xff1a; class Solution {public int numSquares(int n) {if (isPerfectSquare(n)) {return 1;}if (checkAnswer4(n)) {return 4;}for (int i 1; i * i < n; i) {int j n - i * i;if (isPerfectSquare(j)) {return 2;}}return 3;}// 判断是否为…

Spring Security学习笔记(二)Spring Security认证和鉴权

前言&#xff1a;本系列博客基于Spring Boot 2.6.x依赖的Spring Security5.6.x版本 上一篇博客介绍了Spring Security的整体架构&#xff0c;本篇博客要讲的是Spring Security的认证和鉴权两个重要的机制。 UsernamePasswordAuthenticationFilter和BasicAuthenticationFilter是…

Idea 编译项目报错 java: java.lang.OutOfMemoryError:GC overhead limit exceeded

报错 java: java.lang.OutOfMemoryError: WrappedJavaFileObject[org.jetbrains.jps.javac.InputFileObjectpos13979: GC overhead limit exceeded解决 默认是700M&#xff0c;有的时候项目引入的依赖包比较大&#xff0c;可能超过了700M,需要扩大&#xff0c;根据实际情况设…

Dockerfile指令详解和Docker操作命令

1.容器的特点&#xff1a;1&#xff09;自包含&#xff08;包括应用程序及其运行环境&#xff09;&#xff1b;2&#xff09;可移植&#xff1b;3&#xff09;相互隔离&#xff1b;4&#xff09;轻量级。 2.docker成为容器的事实标准在于&#xff1a;1&#xff09;在运行环境上…

开局一个启动器:从零开始入坑ComfyUI

前几天刷某乎的时候看到了一位大佬写的好文&#xff0c;可图 IP-Adapter 模型已开源&#xff0c;更多玩法&#xff0c;更强生态&#xff01; - 知乎 (zhihu.com) 久闻ComfyUI大名&#xff0c;决定试一下。这次打算不走寻常路&#xff0c;不下载现成的一键包了&#xff0c;而是…

ESP32和mDNS学习

目录 mDNS的作用mDNS涉及到的标准文件组播地址IPv4 多播地址IPv6 多播地址预先定义好的组播地址 mDNS调试工具例程mDNS如何开发和使用注册服务查询服务 mDNS的作用 mDNS 是一种组播 UDP 服务&#xff0c;用来提供本地网络服务和主机发现。 你要和设备通信&#xff0c;需要记住…

【计算机网络】静态路由实验

一&#xff1a;实验目的 1&#xff1a;掌握通过静态路由方法实现网络的连通性。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS-C服务器、网线、Windows 2019/2003操作系统的计算机等。 软件&#xff1a;记事本、WireShark、Chrome浏览器等。 三&#xff1a;实验方…

Spark实时(二):StructuredStreaming编程模型

文章目录 StructuredStreaming编程模型 一、基础语义 二、事件时间和延迟数据 三、​​​​​​​容错语义 StructuredStreaming编程模型 一、基础语义 Structured Streaming处理实时数据思想是将实时数据看成一张没有边界的表,数据源源不断的追加到这张表中,这可以让我…

实时捕获数据库变更

1.CDC概述 CDC 的全称是 Change Data Capture &#xff0c;在广义的概念上&#xff0c;只要能捕获数据变更的技术&#xff0c;我们都可以称为 CDC 。我们目前通常描述的CDC 技术主要面向数据库的变更&#xff0c;是一种用于捕获数据库中数据变更的技术&#xff0c;CDC 技术应用…

web网站组成

web网站由四部分组成&#xff1a;浏览器 前端服务器 后端服务器 数据库服务器 流程&#xff1a; 1.浏览器输入网站后&#xff0c;向前端服务器发送请求&#xff0c;前端服务器响应&#xff0c;静态的数据给浏览器。 2.前端代码中script中有url,这个是向后台发送请求的网…

Windows下帆软BI(finebi)单机部署移植(Tomcat)攻略

一、基础环境 操作系统&#xff1a;Windows 10 64bit 帆软BI 版本&#xff1a;V9.0/V10.0 HTTP工具&#xff1a;Tomcat 外置数据库&#xff1a;Oracle 11g 实验内容&#xff1a;将已经部署好的帆软BI从一台电脑移植到另一台电脑 二、前期准备 1、做好外置数据库移植&…

结合创新!小波变换+注意力机制,实现100%分类准确率

小波变换是一种新的变换分析方法&#xff0c;它能有效提取信号的局部特征&#xff0c;但无法完全捕捉数据重要部分。为了解决这个问题&#xff0c;我们引入注意力机制&#xff0c;利用其强化关注重点的优势&#xff0c;将两者结合&#xff0c;做到更全面、深入地挖掘数据特征&a…

【初阶数据结构】9.二叉树(4)

文章目录 5.二叉树算法题5.1 单值二叉树5.2 相同的树5.3 另一棵树的子树5.4 二叉树遍历5.5 二叉树的构建及遍历 6.二叉树选择题 5.二叉树算法题 5.1 单值二叉树 点击链接做题 代码&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* …

昇思25天学习打卡营第22天|CycleGAN图像风格迁移互换

相关知识 CycleGAN 循环生成网络&#xff0c;实现了在没有配对示例的情况下将图像从源域X转换到目标域Y的方法&#xff0c;应用于域迁移&#xff0c;也就是图像风格迁移。上章介绍了可以完成图像翻译任务的Pix2Pix&#xff0c;但是Pix2Pix的数据必须是成对的。CycleGAN中只需…