Commit a2aff61fe3ccbdaa2745868c1334a579bec519f2
1 parent
b2ebdd73
整合阿里云RocketMQ SDK
Showing
14 changed files
with
960 additions
and
1352 deletions
pom.xml
@@ -60,17 +60,6 @@ | @@ -60,17 +60,6 @@ | ||
60 | <artifactId>spring-boot-starter</artifactId> | 60 | <artifactId>spring-boot-starter</artifactId> |
61 | </dependency> | 61 | </dependency> |
62 | <dependency> | 62 | <dependency> |
63 | - <groupId>org.apache.rocketmq</groupId> | ||
64 | - <artifactId>rocketmq-client</artifactId> | ||
65 | - <version>${rocketmq-version}</version> | ||
66 | - <exclusions> | ||
67 | - <exclusion> | ||
68 | - <groupId>org.slf4j</groupId> | ||
69 | - <artifactId>slf4j-api</artifactId> | ||
70 | - </exclusion> | ||
71 | - </exclusions> | ||
72 | - </dependency> | ||
73 | - <dependency> | ||
74 | <groupId>com.aliyun.openservices</groupId> | 63 | <groupId>com.aliyun.openservices</groupId> |
75 | <artifactId>ons-client</artifactId> | 64 | <artifactId>ons-client</artifactId> |
76 | <version>1.7.2.Final</version> | 65 | <version>1.7.2.Final</version> |
src/main/java/org/apache/rocketmq/spring/starter/AliyunRocketMQAutoConfiguration.java
@@ -22,13 +22,12 @@ import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerCon | @@ -22,13 +22,12 @@ import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerCon | ||
22 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_MODE; | 22 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_MODE; |
23 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_THREAD_MAX; | 23 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_CONSUME_THREAD_MAX; |
24 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_MESSAGE_MODEL; | 24 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_MESSAGE_MODEL; |
25 | -import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_NAMESERVER; | ||
26 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_OBJECT_MAPPER; | 25 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_OBJECT_MAPPER; |
27 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_LISTENER; | 26 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_LISTENER; |
28 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_TEMPLATE; | 27 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_ROCKETMQ_TEMPLATE; |
29 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_EXPRESS; | 28 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_EXPRESS; |
30 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_TYPE; | 29 | import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_SELECTOR_TYPE; |
31 | -import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.PROP_TOPIC; | 30 | +import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.*; |
32 | 31 | ||
33 | import java.util.Map; | 32 | import java.util.Map; |
34 | import java.util.Objects; | 33 | import java.util.Objects; |
@@ -39,7 +38,6 @@ import javax.annotation.Resource; | @@ -39,7 +38,6 @@ import javax.annotation.Resource; | ||
39 | 38 | ||
40 | import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | 39 | import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; |
41 | import org.apache.rocketmq.spring.starter.core.AliyunRocketMQListenerContainer; | 40 | import org.apache.rocketmq.spring.starter.core.AliyunRocketMQListenerContainer; |
42 | -import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
43 | import org.apache.rocketmq.spring.starter.core.RocketMQListener; | 41 | import org.apache.rocketmq.spring.starter.core.RocketMQListener; |
44 | import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | 42 | import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; |
45 | import org.springframework.aop.support.AopUtils; | 43 | import org.springframework.aop.support.AopUtils; |
@@ -72,7 +70,6 @@ import lombok.extern.slf4j.Slf4j; | @@ -72,7 +70,6 @@ import lombok.extern.slf4j.Slf4j; | ||
72 | 70 | ||
73 | @Configuration | 71 | @Configuration |
74 | @EnableConfigurationProperties(RocketMQProperties.class) | 72 | @EnableConfigurationProperties(RocketMQProperties.class) |
75 | -@ConditionalOnProperty(name = "spring.rocketmq.aliyun",havingValue="true") | ||
76 | @Order | 73 | @Order |
77 | @Slf4j | 74 | @Slf4j |
78 | public class AliyunRocketMQAutoConfiguration { | 75 | public class AliyunRocketMQAutoConfiguration { |
@@ -80,23 +77,27 @@ public class AliyunRocketMQAutoConfiguration { | @@ -80,23 +77,27 @@ public class AliyunRocketMQAutoConfiguration { | ||
80 | @Bean | 77 | @Bean |
81 | @ConditionalOnClass(Producer.class) | 78 | @ConditionalOnClass(Producer.class) |
82 | @ConditionalOnMissingBean(Producer.class) | 79 | @ConditionalOnMissingBean(Producer.class) |
83 | - @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"}) | 80 | + @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"environmentPrefix", "producer.group"}) |
84 | public Producer mqProducer(RocketMQProperties rocketMQProperties) { | 81 | public Producer mqProducer(RocketMQProperties rocketMQProperties) { |
85 | 82 | ||
86 | RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); | 83 | RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); |
87 | String groupName = producerConfig.getGroup(); | 84 | String groupName = producerConfig.getGroup(); |
88 | Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null"); | 85 | Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null"); |
89 | String accessKey = rocketMQProperties.getAccessKey(); | 86 | String accessKey = rocketMQProperties.getAccessKey(); |
90 | - Assert.hasText(accessKey, "[spring.rocketmq.producer.accessKey] must not be null"); | 87 | + Assert.hasText(accessKey, "[spring.rocketmq.accessKey] must not be null"); |
91 | String secretKey = rocketMQProperties.getSecretKey(); | 88 | String secretKey = rocketMQProperties.getSecretKey(); |
92 | - Assert.hasText(secretKey, "[spring.rocketmq.producer.secretKey] must not be null"); | 89 | + Assert.hasText(secretKey, "[spring.rocketmq.secretKey] must not be null"); |
90 | + String onsAddr = rocketMQProperties.getOnsAddr(); | ||
91 | + Assert.hasText(secretKey, "[spring.rocketmq.onsAddr] must not be null"); | ||
92 | + String environmentPrefix = rocketMQProperties.getEnvironmentPrefix(); | ||
93 | + Assert.hasText(secretKey, "[spring.rocketmq.environmentPrefix] must not be null"); | ||
93 | 94 | ||
94 | Properties producerProperties = new Properties(); | 95 | Properties producerProperties = new Properties(); |
95 | - producerProperties.setProperty(PropertyKeyConst.ProducerId, "PID_"+groupName); | 96 | + //生成者ProducerId添加前缀:PID_+环境标识_+groupName |
97 | + producerProperties.setProperty(PropertyKeyConst.ProducerId, "PID_"+environmentPrefix+"_"+groupName); | ||
96 | producerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); | 98 | producerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); |
97 | producerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); | 99 | producerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); |
98 | - producerProperties.setProperty(PropertyKeyConst.ONSAddr, rocketMQProperties.getNameServer()); | ||
99 | - | 100 | + producerProperties.setProperty(PropertyKeyConst.ONSAddr, onsAddr); |
100 | Producer producer = ONSFactory.createProducer(producerProperties); | 101 | Producer producer = ONSFactory.createProducer(producerProperties); |
101 | return producer; | 102 | return producer; |
102 | } | 103 | } |
@@ -111,12 +112,13 @@ public class AliyunRocketMQAutoConfiguration { | @@ -111,12 +112,13 @@ public class AliyunRocketMQAutoConfiguration { | ||
111 | @Bean(destroyMethod = "destroy") | 112 | @Bean(destroyMethod = "destroy") |
112 | @ConditionalOnBean(Producer.class) | 113 | @ConditionalOnBean(Producer.class) |
113 | @ConditionalOnMissingBean(name = "rocketMQTemplate") | 114 | @ConditionalOnMissingBean(name = "rocketMQTemplate") |
114 | - public RocketMQTemplate rocketMQTemplate(Producer mqProducer, | 115 | + public RocketMQTemplate rocketMQTemplate(Producer mqProducer,RocketMQProperties rocketMQProperties, |
115 | @Autowired(required = false) | 116 | @Autowired(required = false) |
116 | @Qualifier("rocketMQMessageObjectMapper") | 117 | @Qualifier("rocketMQMessageObjectMapper") |
117 | ObjectMapper objectMapper) { | 118 | ObjectMapper objectMapper) { |
118 | RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); | 119 | RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); |
119 | rocketMQTemplate.setAliyunProducer(mqProducer); | 120 | rocketMQTemplate.setAliyunProducer(mqProducer); |
121 | + rocketMQTemplate.setEnvironmentPrefix(rocketMQProperties.getEnvironmentPrefix()); | ||
120 | if (Objects.nonNull(objectMapper)) { | 122 | if (Objects.nonNull(objectMapper)) { |
121 | rocketMQTemplate.setObjectMapper(objectMapper); | 123 | rocketMQTemplate.setObjectMapper(objectMapper); |
122 | } | 124 | } |
@@ -176,10 +178,11 @@ public class AliyunRocketMQAutoConfiguration { | @@ -176,10 +178,11 @@ public class AliyunRocketMQAutoConfiguration { | ||
176 | RocketMQListener rocketMQListener = (RocketMQListener) bean; | 178 | RocketMQListener rocketMQListener = (RocketMQListener) bean; |
177 | RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); | 179 | RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); |
178 | BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(AliyunRocketMQListenerContainer.class); | 180 | BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(AliyunRocketMQListenerContainer.class); |
179 | - beanBuilder.addPropertyValue(PROP_NAMESERVER, rocketMQProperties.getNameServer()); | ||
180 | - beanBuilder.addPropertyValue(PROP_TOPIC, environment.resolvePlaceholders(annotation.topic())); | 181 | + beanBuilder.addPropertyValue(PROP_ONS_Addr, rocketMQProperties.getOnsAddr()); |
182 | + beanBuilder.addPropertyValue(PROP_TOPIC, rocketMQProperties.getEnvironmentPrefix()+"_"+environment.resolvePlaceholders(annotation.topic())); | ||
181 | 183 | ||
182 | - beanBuilder.addPropertyValue(PROP_CONSUMER_GROUP, environment.resolvePlaceholders(annotation.consumerGroup())); | 184 | + //消费者ConsumerId添加前缀:PID_+环境标识_+groupName |
185 | + beanBuilder.addPropertyValue(PROP_CONSUMER_GROUP, "CID_"+rocketMQProperties.getEnvironmentPrefix()+"_"+environment.resolvePlaceholders(annotation.consumerGroup())); | ||
183 | beanBuilder.addPropertyValue(PROP_CONSUME_MODE, annotation.consumeMode()); | 186 | beanBuilder.addPropertyValue(PROP_CONSUME_MODE, annotation.consumeMode()); |
184 | beanBuilder.addPropertyValue(PROP_CONSUME_THREAD_MAX, annotation.consumeThreadMax()); | 187 | beanBuilder.addPropertyValue(PROP_CONSUME_THREAD_MAX, annotation.consumeThreadMax()); |
185 | beanBuilder.addPropertyValue(PROP_MESSAGE_MODEL, annotation.messageModel()); | 188 | beanBuilder.addPropertyValue(PROP_MESSAGE_MODEL, annotation.messageModel()); |
@@ -187,13 +190,14 @@ public class AliyunRocketMQAutoConfiguration { | @@ -187,13 +190,14 @@ public class AliyunRocketMQAutoConfiguration { | ||
187 | beanBuilder.addPropertyValue(PROP_SELECTOR_TYPE, annotation.selectorType()); | 190 | beanBuilder.addPropertyValue(PROP_SELECTOR_TYPE, annotation.selectorType()); |
188 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_LISTENER, rocketMQListener); | 191 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_LISTENER, rocketMQListener); |
189 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_TEMPLATE, rocketMQTemplate); | 192 | beanBuilder.addPropertyValue(PROP_ROCKETMQ_TEMPLATE, rocketMQTemplate); |
193 | + beanBuilder.addPropertyValue(PROP_ENVIRONMENT_PREFIX, rocketMQProperties.getEnvironmentPrefix()); | ||
190 | if (Objects.nonNull(objectMapper)) { | 194 | if (Objects.nonNull(objectMapper)) { |
191 | beanBuilder.addPropertyValue(PROP_OBJECT_MAPPER, objectMapper); | 195 | beanBuilder.addPropertyValue(PROP_OBJECT_MAPPER, objectMapper); |
192 | } | 196 | } |
193 | beanBuilder.setDestroyMethodName(METHOD_DESTROY); | 197 | beanBuilder.setDestroyMethodName(METHOD_DESTROY); |
194 | //增加阿里云key | 198 | //增加阿里云key |
195 | - beanBuilder.addPropertyValue("accessKey", rocketMQProperties.getAccessKey()); | ||
196 | - beanBuilder.addPropertyValue("secretKey", rocketMQProperties.getSecretKey()); | 199 | + beanBuilder.addPropertyValue(PROP_ACCESS_KEY, rocketMQProperties.getAccessKey()); |
200 | + beanBuilder.addPropertyValue(PROP_SECRET_KEY, rocketMQProperties.getSecretKey()); | ||
197 | 201 | ||
198 | String containerBeanName = String.format("%s_%s", AliyunRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); | 202 | String containerBeanName = String.format("%s_%s", AliyunRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); |
199 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); | 203 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); |
src/main/java/org/apache/rocketmq/spring/starter/RocketMQAutoConfiguration.java deleted
1 | -/* | ||
2 | - * Licensed to the Apache Software Foundation (ASF) under one or more | ||
3 | - * contributor license agreements. See the NOTICE file distributed with | ||
4 | - * this work for additional information regarding copyright ownership. | ||
5 | - * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
6 | - * (the "License"); you may not use this file except in compliance with | ||
7 | - * the License. You may obtain a copy of the License at | ||
8 | - * | ||
9 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | - * | ||
11 | - * Unless required by applicable law or agreed to in writing, software | ||
12 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | - * See the License for the specific language governing permissions and | ||
15 | - * limitations under the License. | ||
16 | - */ | ||
17 | - | ||
18 | -package org.apache.rocketmq.spring.starter; | ||
19 | - | ||
20 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
21 | -import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | ||
22 | -import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
23 | -import org.apache.rocketmq.spring.starter.core.RocketMQListener; | ||
24 | -import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | ||
25 | -import java.util.Map; | ||
26 | -import java.util.Objects; | ||
27 | -import java.util.concurrent.atomic.AtomicLong; | ||
28 | -import javax.annotation.Resource; | ||
29 | -import lombok.extern.slf4j.Slf4j; | ||
30 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
31 | -import org.apache.rocketmq.client.impl.MQClientAPIImpl; | ||
32 | -import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
33 | -import org.springframework.aop.support.AopUtils; | ||
34 | -import org.springframework.beans.BeansException; | ||
35 | -import org.springframework.beans.factory.InitializingBean; | ||
36 | -import org.springframework.beans.factory.annotation.Autowired; | ||
37 | -import org.springframework.beans.factory.annotation.Qualifier; | ||
38 | -import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
39 | -import org.springframework.beans.factory.support.DefaultListableBeanFactory; | ||
40 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
41 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
42 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
43 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
44 | -import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
45 | -import org.springframework.context.ApplicationContext; | ||
46 | -import org.springframework.context.ApplicationContextAware; | ||
47 | -import org.springframework.context.ConfigurableApplicationContext; | ||
48 | -import org.springframework.context.annotation.Bean; | ||
49 | -import org.springframework.context.annotation.Configuration; | ||
50 | -import org.springframework.core.annotation.Order; | ||
51 | -import org.springframework.core.env.StandardEnvironment; | ||
52 | -import org.springframework.util.Assert; | ||
53 | - | ||
54 | -import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.*; | ||
55 | - | ||
56 | -@Configuration | ||
57 | -@ConditionalOnProperty(name = "spring.rocketmq.aliyun",havingValue="false") | ||
58 | -@EnableConfigurationProperties(RocketMQProperties.class) | ||
59 | -@ConditionalOnClass(MQClientAPIImpl.class) | ||
60 | -@Order | ||
61 | -@Slf4j | ||
62 | -public class RocketMQAutoConfiguration { | ||
63 | - | ||
64 | - @Bean | ||
65 | - @ConditionalOnClass(DefaultMQProducer.class) | ||
66 | - @ConditionalOnMissingBean(DefaultMQProducer.class) | ||
67 | - @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"}) | ||
68 | - public DefaultMQProducer mqProducer(RocketMQProperties rocketMQProperties) { | ||
69 | - | ||
70 | - RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); | ||
71 | - String groupName = producerConfig.getGroup(); | ||
72 | - Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null"); | ||
73 | - | ||
74 | - DefaultMQProducer producer = new DefaultMQProducer(producerConfig.getGroup()); | ||
75 | - producer.setNamesrvAddr(rocketMQProperties.getNameServer()); | ||
76 | - producer.setSendMsgTimeout(producerConfig.getSendMsgTimeout()); | ||
77 | - producer.setRetryTimesWhenSendFailed(producerConfig.getRetryTimesWhenSendFailed()); | ||
78 | - producer.setRetryTimesWhenSendAsyncFailed(producerConfig.getRetryTimesWhenSendAsyncFailed()); | ||
79 | - producer.setMaxMessageSize(producerConfig.getMaxMessageSize()); | ||
80 | - producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMsgBodyOverHowmuch()); | ||
81 | - producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryAnotherBrokerWhenNotStoreOk()); | ||
82 | - | ||
83 | - return producer; | ||
84 | - } | ||
85 | - | ||
86 | - @Bean | ||
87 | - @ConditionalOnClass(ObjectMapper.class) | ||
88 | - @ConditionalOnMissingBean(name = "rocketMQMessageObjectMapper") | ||
89 | - public ObjectMapper rocketMQMessageObjectMapper() { | ||
90 | - return new ObjectMapper(); | ||
91 | - } | ||
92 | - | ||
93 | - @Bean(destroyMethod = "destroy") | ||
94 | - @ConditionalOnBean(DefaultMQProducer.class) | ||
95 | - @ConditionalOnMissingBean(name = "rocketMQTemplate") | ||
96 | - public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, | ||
97 | - @Autowired(required = false) | ||
98 | - @Qualifier("rocketMQMessageObjectMapper") | ||
99 | - ObjectMapper objectMapper) { | ||
100 | - RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); | ||
101 | - rocketMQTemplate.setDefaultProducer(mqProducer); | ||
102 | - if (Objects.nonNull(objectMapper)) { | ||
103 | - rocketMQTemplate.setObjectMapper(objectMapper); | ||
104 | - } | ||
105 | - | ||
106 | - return rocketMQTemplate; | ||
107 | - } | ||
108 | - | ||
109 | - @Configuration | ||
110 | - @ConditionalOnClass(DefaultMQPushConsumer.class) | ||
111 | - @EnableConfigurationProperties(RocketMQProperties.class) | ||
112 | - @ConditionalOnProperty(prefix = "spring.rocketmq", value = "nameServer") | ||
113 | - @Order | ||
114 | - public static class ListenerContainerConfiguration implements ApplicationContextAware, InitializingBean { | ||
115 | - private ConfigurableApplicationContext applicationContext; | ||
116 | - | ||
117 | - private AtomicLong counter = new AtomicLong(0); | ||
118 | - | ||
119 | - @Resource | ||
120 | - private StandardEnvironment environment; | ||
121 | - | ||
122 | - @Resource | ||
123 | - private RocketMQProperties rocketMQProperties; | ||
124 | - | ||
125 | - private ObjectMapper objectMapper; | ||
126 | - | ||
127 | - @Autowired | ||
128 | - private RocketMQTemplate rocketMQTemplate; | ||
129 | - | ||
130 | - public ListenerContainerConfiguration() { | ||
131 | - } | ||
132 | - | ||
133 | - @Autowired(required = false) | ||
134 | - public ListenerContainerConfiguration( | ||
135 | - @Qualifier("rocketMQMessageObjectMapper") ObjectMapper objectMapper) { | ||
136 | - this.objectMapper = objectMapper; | ||
137 | - } | ||
138 | - | ||
139 | - @Override | ||
140 | - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | ||
141 | - this.applicationContext = (ConfigurableApplicationContext) applicationContext; | ||
142 | - } | ||
143 | - | ||
144 | - @Override | ||
145 | - public void afterPropertiesSet() { | ||
146 | - Map<String, Object> beans = this.applicationContext.getBeansWithAnnotation(RocketMQMessageListener.class); | ||
147 | - | ||
148 | - if (Objects.nonNull(beans)) { | ||
149 | - beans.forEach(this::registerContainer); | ||
150 | - } | ||
151 | - } | ||
152 | - | ||
153 | - private void registerContainer(String beanName, Object bean) { | ||
154 | - Class<?> clazz = AopUtils.getTargetClass(bean); | ||
155 | - | ||
156 | - if (!RocketMQListener.class.isAssignableFrom(bean.getClass())) { | ||
157 | - throw new IllegalStateException(clazz + " is not instance of " + RocketMQListener.class.getName()); | ||
158 | - } | ||
159 | - | ||
160 | - RocketMQListener rocketMQListener = (RocketMQListener) bean; | ||
161 | - RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); | ||
162 | - BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultRocketMQListenerContainer.class); | ||
163 | - beanBuilder.addPropertyValue(PROP_NAMESERVER, rocketMQProperties.getNameServer()); | ||
164 | - beanBuilder.addPropertyValue(PROP_TOPIC, environment.resolvePlaceholders(annotation.topic())); | ||
165 | - | ||
166 | - beanBuilder.addPropertyValue(PROP_CONSUMER_GROUP, environment.resolvePlaceholders(annotation.consumerGroup())); | ||
167 | - beanBuilder.addPropertyValue(PROP_CONSUME_MODE, annotation.consumeMode()); | ||
168 | - beanBuilder.addPropertyValue(PROP_CONSUME_THREAD_MAX, annotation.consumeThreadMax()); | ||
169 | - beanBuilder.addPropertyValue(PROP_MESSAGE_MODEL, annotation.messageModel()); | ||
170 | - beanBuilder.addPropertyValue(PROP_SELECTOR_EXPRESS, environment.resolvePlaceholders(annotation.selectorExpress())); | ||
171 | - beanBuilder.addPropertyValue(PROP_SELECTOR_TYPE, annotation.selectorType()); | ||
172 | - beanBuilder.addPropertyValue(PROP_ROCKETMQ_LISTENER, rocketMQListener); | ||
173 | - beanBuilder.addPropertyValue(PROP_ROCKETMQ_TEMPLATE, rocketMQTemplate); | ||
174 | - if (Objects.nonNull(objectMapper)) { | ||
175 | - beanBuilder.addPropertyValue(PROP_OBJECT_MAPPER, objectMapper); | ||
176 | - } | ||
177 | - beanBuilder.setDestroyMethodName(METHOD_DESTROY); | ||
178 | - | ||
179 | - String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); | ||
180 | - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory(); | ||
181 | - beanFactory.registerBeanDefinition(containerBeanName, beanBuilder.getBeanDefinition()); | ||
182 | - | ||
183 | - DefaultRocketMQListenerContainer container = beanFactory.getBean(containerBeanName, DefaultRocketMQListenerContainer.class); | ||
184 | - | ||
185 | - if (!container.isStarted()) { | ||
186 | - try { | ||
187 | - container.start(); | ||
188 | - } catch (Exception e) { | ||
189 | - log.error("started container failed. {}", container, e); | ||
190 | - throw new RuntimeException(e); | ||
191 | - } | ||
192 | - } | ||
193 | - | ||
194 | - log.info("register rocketMQ listener to container, listenerBeanName:{}, containerBeanName:{}", beanName, containerBeanName); | ||
195 | - } | ||
196 | - } | ||
197 | -} |
src/main/java/org/apache/rocketmq/spring/starter/RocketMQProperties.java
@@ -24,22 +24,25 @@ import org.springframework.boot.context.properties.ConfigurationProperties; | @@ -24,22 +24,25 @@ import org.springframework.boot.context.properties.ConfigurationProperties; | ||
24 | @ConfigurationProperties(prefix = "spring.rocketmq") | 24 | @ConfigurationProperties(prefix = "spring.rocketmq") |
25 | @Data | 25 | @Data |
26 | public class RocketMQProperties { | 26 | public class RocketMQProperties { |
27 | - | ||
28 | - /** | ||
29 | - * name server for rocketMQ, formats: `host:port;host:port` | 27 | + /** |
28 | + * 环境前缀 | ||
29 | + */ | ||
30 | + private String environmentPrefix; | ||
31 | + /** | ||
32 | + * 消息队列服务接入点 | ||
30 | */ | 33 | */ |
31 | - private String nameServer; | 34 | + private String onsAddr; |
32 | 35 | ||
33 | - private Producer producer; | ||
34 | - /** | ||
35 | - * 阿里云分配的accesskey | 36 | + /** |
37 | + * AccessKey, 用于标识、校验用户身份 | ||
36 | */ | 38 | */ |
37 | private String accessKey; | 39 | private String accessKey; |
38 | /** | 40 | /** |
39 | - * 阿里云分配的secretKey | 41 | + * SecretKey, 用于标识、校验用户身份 |
40 | */ | 42 | */ |
41 | private String secretKey; | 43 | private String secretKey; |
42 | 44 | ||
45 | + private Producer producer; | ||
43 | @Data | 46 | @Data |
44 | public static class Producer { | 47 | public static class Producer { |
45 | 48 |
src/main/java/org/apache/rocketmq/spring/starter/annotation/RocketMQMessageListener.java
@@ -17,15 +17,17 @@ | @@ -17,15 +17,17 @@ | ||
17 | 17 | ||
18 | package org.apache.rocketmq.spring.starter.annotation; | 18 | package org.apache.rocketmq.spring.starter.annotation; |
19 | 19 | ||
20 | -import org.apache.rocketmq.common.filter.ExpressionType; | ||
21 | -import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
22 | -import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
23 | import java.lang.annotation.Documented; | 20 | import java.lang.annotation.Documented; |
24 | import java.lang.annotation.ElementType; | 21 | import java.lang.annotation.ElementType; |
25 | import java.lang.annotation.Retention; | 22 | import java.lang.annotation.Retention; |
26 | import java.lang.annotation.RetentionPolicy; | 23 | import java.lang.annotation.RetentionPolicy; |
27 | import java.lang.annotation.Target; | 24 | import java.lang.annotation.Target; |
28 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | 25 | + |
26 | +import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
27 | +import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
28 | + | ||
29 | +import com.aliyun.openservices.ons.api.ExpressionType; | ||
30 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; | ||
29 | 31 | ||
30 | @Target(ElementType.TYPE) | 32 | @Target(ElementType.TYPE) |
31 | @Retention(RetentionPolicy.RUNTIME) | 33 | @Retention(RetentionPolicy.RUNTIME) |
src/main/java/org/apache/rocketmq/spring/starter/core/AliyunRocketMQListenerContainer.java
@@ -25,38 +25,39 @@ import java.util.List; | @@ -25,38 +25,39 @@ import java.util.List; | ||
25 | import java.util.Objects; | 25 | import java.util.Objects; |
26 | import java.util.Properties; | 26 | import java.util.Properties; |
27 | 27 | ||
28 | -import org.apache.commons.lang3.StringUtils; | ||
29 | -import org.apache.commons.lang3.exception.ExceptionUtils; | ||
30 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
31 | -import org.apache.rocketmq.client.consumer.MessageSelector; | ||
32 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; | ||
33 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
34 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
35 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
36 | -import org.apache.rocketmq.client.exception.MQClientException; | ||
37 | -import org.apache.rocketmq.common.message.MessageExt; | ||
38 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
39 | import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | 28 | import org.apache.rocketmq.spring.starter.enums.ConsumeMode; |
40 | import org.apache.rocketmq.spring.starter.enums.SelectorType; | 29 | import org.apache.rocketmq.spring.starter.enums.SelectorType; |
41 | import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; | 30 | import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; |
42 | import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; | 31 | import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; |
32 | +import org.apache.rocketmq.spring.starter.utils.ExceptionUtil; | ||
43 | import org.apache.rocketmq.spring.starter.utils.IPUtil; | 33 | import org.apache.rocketmq.spring.starter.utils.IPUtil; |
44 | import org.springframework.beans.factory.InitializingBean; | 34 | import org.springframework.beans.factory.InitializingBean; |
45 | import org.springframework.util.Assert; | 35 | import org.springframework.util.Assert; |
36 | +import org.springframework.util.StringUtils; | ||
46 | 37 | ||
47 | import com.aliyun.openservices.ons.api.Action; | 38 | import com.aliyun.openservices.ons.api.Action; |
48 | import com.aliyun.openservices.ons.api.ConsumeContext; | 39 | import com.aliyun.openservices.ons.api.ConsumeContext; |
49 | import com.aliyun.openservices.ons.api.Consumer; | 40 | import com.aliyun.openservices.ons.api.Consumer; |
50 | import com.aliyun.openservices.ons.api.Message; | 41 | import com.aliyun.openservices.ons.api.Message; |
51 | import com.aliyun.openservices.ons.api.MessageListener; | 42 | import com.aliyun.openservices.ons.api.MessageListener; |
43 | +import com.aliyun.openservices.ons.api.MessageSelector; | ||
52 | import com.aliyun.openservices.ons.api.ONSFactory; | 44 | import com.aliyun.openservices.ons.api.ONSFactory; |
53 | import com.aliyun.openservices.ons.api.PropertyKeyConst; | 45 | import com.aliyun.openservices.ons.api.PropertyKeyConst; |
54 | import com.aliyun.openservices.ons.api.batch.BatchConsumer; | 46 | import com.aliyun.openservices.ons.api.batch.BatchConsumer; |
55 | -import com.aliyun.openservices.ons.api.bean.BatchConsumerBean; | 47 | +import com.aliyun.openservices.ons.api.batch.BatchMessageListener; |
48 | +import com.aliyun.openservices.ons.api.order.ConsumeOrderContext; | ||
56 | import com.aliyun.openservices.ons.api.order.MessageOrderListener; | 49 | import com.aliyun.openservices.ons.api.order.MessageOrderListener; |
50 | +import com.aliyun.openservices.ons.api.order.OrderAction; | ||
57 | import com.aliyun.openservices.ons.api.order.OrderConsumer; | 51 | import com.aliyun.openservices.ons.api.order.OrderConsumer; |
52 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
53 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
54 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
55 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
56 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.client.exception.MQClientException; | ||
57 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.message.MessageExt; | ||
58 | +import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel; | ||
58 | import com.fasterxml.jackson.databind.ObjectMapper; | 59 | import com.fasterxml.jackson.databind.ObjectMapper; |
59 | - | 60 | +import static org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainerConstants.*; |
60 | import lombok.Getter; | 61 | import lombok.Getter; |
61 | import lombok.Setter; | 62 | import lombok.Setter; |
62 | import lombok.extern.slf4j.Slf4j; | 63 | import lombok.extern.slf4j.Slf4j; |
@@ -77,23 +78,13 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -77,23 +78,13 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
77 | 78 | ||
78 | @Setter | 79 | @Setter |
79 | @Getter | 80 | @Getter |
80 | - private long suspendCurrentQueueTimeMillis = 1000; | ||
81 | - | 81 | + private String consumerGroup; |
82 | /** | 82 | /** |
83 | - * Message consume retry strategy<br> -1,no retry,put into DLQ directly<br> 0,broker control retry frequency<br> | ||
84 | - * >0,client control retry frequency | 83 | + * 消息队列服务接入点 |
85 | */ | 84 | */ |
86 | @Setter | 85 | @Setter |
87 | @Getter | 86 | @Getter |
88 | - private int delayLevelWhenNextConsume = 0; | ||
89 | - | ||
90 | - @Setter | ||
91 | - @Getter | ||
92 | - private String consumerGroup; | ||
93 | - | ||
94 | - @Setter | ||
95 | - @Getter | ||
96 | - private String nameServer; | 87 | + private String onsAddr; |
97 | 88 | ||
98 | @Setter | 89 | @Setter |
99 | @Getter | 90 | @Getter |
@@ -141,6 +132,11 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -141,6 +132,11 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
141 | private BatchConsumer batchConsumer; | 132 | private BatchConsumer batchConsumer; |
142 | 133 | ||
143 | private Class messageType; | 134 | private Class messageType; |
135 | + /** | ||
136 | + * 环境前缀 | ||
137 | + */ | ||
138 | + @Setter | ||
139 | + private String environmentPrefix; | ||
144 | 140 | ||
145 | @Setter | 141 | @Setter |
146 | private RocketMQTemplate rocketMQTemplate; | 142 | private RocketMQTemplate rocketMQTemplate; |
@@ -180,66 +176,62 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -180,66 +176,62 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
180 | 176 | ||
181 | @SuppressWarnings("unchecked") | 177 | @SuppressWarnings("unchecked") |
182 | public Action consume(final Message message, final ConsumeContext context){ | 178 | public Action consume(final Message message, final ConsumeContext context){ |
183 | - for (MessageExt messageExt : msgs) { | ||
184 | - Date consumeBeginTime = new Date(); | ||
185 | - log.debug("received msg: {}", messageExt); | ||
186 | - try { | ||
187 | - long now = System.currentTimeMillis(); | ||
188 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
189 | - long costTime = System.currentTimeMillis() - now; | ||
190 | - log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
191 | - } catch (Exception e) { | ||
192 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
193 | - context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); | ||
194 | - if(messageExt.getTopic().equals("DATA_COLLECTION_TOPIC") && "ConsumeMsgFailed".equals(messageExt.getTags())){ | ||
195 | - log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
196 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
197 | - } | ||
198 | - if(e instanceof ConvertMsgException){ | ||
199 | - log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
200 | - //消息消费失败,发送失败消息 | ||
201 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
202 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
203 | - } | ||
204 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
205 | - return ConsumeConcurrentlyStatus.RECONSUME_LATER; | 179 | + Date consumeBeginTime = new Date(); |
180 | + log.debug("received msg: {}", message); | ||
181 | + try { | ||
182 | + long now = consumeBeginTime.getTime(); | ||
183 | + rocketMQListener.onMessage(doConvertMessage(message)); | ||
184 | + long costTime = System.currentTimeMillis() - now; | ||
185 | + log.debug("consume {} cost: {} ms", message.getMsgID(), costTime); | ||
186 | + } catch (Exception e) { | ||
187 | + log.warn("consume message failed. message:{}", message, e); | ||
188 | + if(message.getTopic().equals(environmentPrefix+"_"+CONSUMEFAILED_TOPIC) && CONSUMEFAILED_TAG.equals(message.getTag())){ | ||
189 | + log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
190 | + return Action.CommitMessage; | ||
191 | + } | ||
192 | + if(e instanceof ConvertMsgException){ | ||
193 | + log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
194 | + //消息消费失败,发送失败消息 | ||
195 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
196 | + return Action.CommitMessage; | ||
206 | } | 197 | } |
198 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
199 | + return Action.ReconsumeLater; | ||
207 | } | 200 | } |
208 | - | ||
209 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | 201 | + |
202 | + return Action.CommitMessage; | ||
210 | } | 203 | } |
211 | /** | 204 | /** |
212 | * 发送消息消费失败消息 | 205 | * 发送消息消费失败消息 |
213 | - * @param messageExt | 206 | + * @param message |
214 | * @param e | 207 | * @param e |
215 | * 2018年3月22日 zhaowg | 208 | * 2018年3月22日 zhaowg |
216 | */ | 209 | */ |
217 | - private void sendConsumeMsgFailed(MessageExt messageExt, Exception e,Date consumeBeginTime) { | 210 | + private void sendConsumeMsgFailed(Message message, Exception e,Date consumeBeginTime) { |
218 | log.info("消费消息失败,开始发送消费失败MQ"); | 211 | log.info("消费消息失败,开始发送消费失败MQ"); |
219 | - String topic = "DATA_COLLECTION_TOPIC"; | ||
220 | - String tag = "ConsumeMsgFailed"; | 212 | + String topic = environmentPrefix+"_"+CONSUMEFAILED_TOPIC; |
213 | + String tag = CONSUMEFAILED_TAG; | ||
221 | try{ | 214 | try{ |
222 | Date consumeEndTime = new Date(); | 215 | Date consumeEndTime = new Date(); |
223 | - String destination = topic+":"+tag; | ||
224 | ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | 216 | ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); |
225 | consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | 217 | consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); |
226 | consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | 218 | consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); |
227 | consumeFailedMsgVO.setConsumeGroup(consumerGroup); | 219 | consumeFailedMsgVO.setConsumeGroup(consumerGroup); |
228 | consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | 220 | consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); |
229 | if(e!=null){ | 221 | if(e!=null){ |
230 | - String errMsg = ExceptionUtils.getStackTrace(e); | ||
231 | - if(StringUtils.isNotBlank(errMsg)){ | 222 | + String errMsg = ExceptionUtil.getTrace(e); |
223 | + if(!StringUtils.isEmpty(errMsg)){ | ||
232 | //最多保存1024个字符 | 224 | //最多保存1024个字符 |
233 | consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | 225 | consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); |
234 | } | 226 | } |
235 | } | 227 | } |
236 | - consumeFailedMsgVO.setMsg(new String(messageExt.getBody())); | ||
237 | - consumeFailedMsgVO.setMsgId(messageExt.getMsgId()); | ||
238 | - consumeFailedMsgVO.setMsgKeys(messageExt.getKeys()); | ||
239 | - consumeFailedMsgVO.setReconsumeTimes(messageExt.getReconsumeTimes()); | ||
240 | - consumeFailedMsgVO.setTag(messageExt.getTags()); | ||
241 | - consumeFailedMsgVO.setTopic(messageExt.getTopic()); | ||
242 | - rocketMQTemplate.sendOneWay(destination, consumeFailedMsgVO); | 228 | + consumeFailedMsgVO.setMsg(new String(message.getBody())); |
229 | + consumeFailedMsgVO.setMsgId(message.getMsgID()); | ||
230 | + consumeFailedMsgVO.setMsgKeys(message.getKey()); | ||
231 | + consumeFailedMsgVO.setReconsumeTimes(message.getReconsumeTimes()); | ||
232 | + consumeFailedMsgVO.setTag(message.getTag()); | ||
233 | + consumeFailedMsgVO.setTopic(message.getTopic()); | ||
234 | + rocketMQTemplate.sendOneWay(topic, tag, consumeFailedMsgVO); | ||
243 | log.info("发送消息消费失败MQ成功"); | 235 | log.info("发送消息消费失败MQ成功"); |
244 | }catch(Exception e1){ | 236 | }catch(Exception e1){ |
245 | log.info("发送消息消费失败MQ异常",e); | 237 | log.info("发送消息消费失败MQ异常",e); |
@@ -250,50 +242,103 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -250,50 +242,103 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
250 | 242 | ||
251 | public class DefaultMessageListenerOrderly implements MessageOrderListener { | 243 | public class DefaultMessageListenerOrderly implements MessageOrderListener { |
252 | 244 | ||
253 | - @SuppressWarnings("unchecked") | ||
254 | - public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { | ||
255 | - for (MessageExt messageExt : msgs) { | ||
256 | - log.debug("received msg: {}", messageExt); | ||
257 | - try { | ||
258 | - long now = System.currentTimeMillis(); | ||
259 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
260 | - long costTime = System.currentTimeMillis() - now; | ||
261 | - log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
262 | - } catch (Exception e) { | ||
263 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
264 | - context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); | ||
265 | - return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; | ||
266 | - } | 245 | + @Override |
246 | + public OrderAction consume(Message message, ConsumeOrderContext context) { | ||
247 | + log.debug("received msg: {}", message); | ||
248 | + try { | ||
249 | + long now = System.currentTimeMillis(); | ||
250 | + rocketMQListener.onMessage(doConvertMessage(message)); | ||
251 | + long costTime = System.currentTimeMillis() - now; | ||
252 | + log.info("consume {} cost: {} ms", message.getMsgID(), costTime); | ||
253 | + } catch (Exception e) { | ||
254 | + log.warn("consume message failed. message:{}", message, e); | ||
255 | + return OrderAction.Suspend; | ||
267 | } | 256 | } |
268 | - | ||
269 | - return ConsumeOrderlyStatus.SUCCESS; | ||
270 | - } | 257 | + return OrderAction.Success; |
258 | + } | ||
259 | + } | ||
260 | + | ||
261 | + public class DefaultMessageListenerBatchs implements BatchMessageListener{ | ||
262 | + | ||
263 | + @Override | ||
264 | + public Action consume(List<Message> messages, ConsumeContext context) { | ||
265 | + for (Message message : messages) { | ||
266 | + Date consumeBeginTime = new Date(); | ||
267 | + log.debug("received msg: {}", message); | ||
268 | + try { | ||
269 | + long now = consumeBeginTime.getTime(); | ||
270 | + rocketMQListener.onMessage(doConvertMessage(message)); | ||
271 | + long costTime = System.currentTimeMillis() - now; | ||
272 | + log.debug("consume {} cost: {} ms", message.getMsgID(), costTime); | ||
273 | + } catch (Exception e) { | ||
274 | + log.warn("consume message failed. message:{}", message, e); | ||
275 | + if(message.getTopic().equals(environmentPrefix+"_"+CONSUMEFAILED_TOPIC) && CONSUMEFAILED_TAG.equals(message.getTag())){ | ||
276 | + log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
277 | + continue; | ||
278 | + } | ||
279 | + if(e instanceof ConvertMsgException){ | ||
280 | + log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
281 | + //消息消费失败,发送失败消息 | ||
282 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
283 | + continue; | ||
284 | + } | ||
285 | + this.sendConsumeMsgFailed(message,e,consumeBeginTime); | ||
286 | + return Action.ReconsumeLater; | ||
287 | + } | ||
288 | + } | ||
289 | + return Action.CommitMessage; | ||
290 | + } | ||
291 | + | ||
292 | + /** | ||
293 | + * 发送消息消费失败消息 | ||
294 | + * @param message | ||
295 | + * @param e | ||
296 | + * 2018年3月22日 zhaowg | ||
297 | + */ | ||
298 | + private void sendConsumeMsgFailed(Message message, Exception e,Date consumeBeginTime) { | ||
299 | + log.info("消费消息失败,开始发送消费失败MQ"); | ||
300 | + String topic = environmentPrefix+"_"+CONSUMEFAILED_TOPIC; | ||
301 | + String tag = CONSUMEFAILED_TAG; | ||
302 | + try{ | ||
303 | + Date consumeEndTime = new Date(); | ||
304 | + ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | ||
305 | + consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | ||
306 | + consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | ||
307 | + consumeFailedMsgVO.setConsumeGroup(consumerGroup); | ||
308 | + consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | ||
309 | + if(e!=null){ | ||
310 | + String errMsg = ExceptionUtil.getTrace(e); | ||
311 | + if(!StringUtils.isEmpty(errMsg)){ | ||
312 | + //最多保存1024个字符 | ||
313 | + consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | ||
314 | + } | ||
315 | + } | ||
316 | + consumeFailedMsgVO.setMsg(new String(message.getBody())); | ||
317 | + consumeFailedMsgVO.setMsgId(message.getMsgID()); | ||
318 | + consumeFailedMsgVO.setMsgKeys(message.getKey()); | ||
319 | + consumeFailedMsgVO.setReconsumeTimes(message.getReconsumeTimes()); | ||
320 | + consumeFailedMsgVO.setTag(message.getTag()); | ||
321 | + consumeFailedMsgVO.setTopic(message.getTopic()); | ||
322 | + rocketMQTemplate.sendOneWay(topic, tag, consumeFailedMsgVO); | ||
323 | + log.info("发送消息消费失败MQ成功"); | ||
324 | + }catch(Exception e1){ | ||
325 | + log.info("发送消息消费失败MQ异常",e); | ||
326 | + } | ||
327 | + | ||
328 | + } | ||
271 | } | 329 | } |
272 | - | ||
273 | @Override | 330 | @Override |
274 | public void afterPropertiesSet() throws Exception { | 331 | public void afterPropertiesSet() throws Exception { |
275 | start(); | 332 | start(); |
276 | } | 333 | } |
277 | 334 | ||
278 | - @Override | ||
279 | - public String toString() { | ||
280 | - return "DefaultRocketMQListenerContainer{" + | ||
281 | - "consumerGroup='" + consumerGroup + '\'' + | ||
282 | - ", nameServer='" + nameServer + '\'' + | ||
283 | - ", topic='" + topic + '\'' + | ||
284 | - ", consumeMode=" + consumeMode + | ||
285 | - ", selectorType=" + selectorType + | ||
286 | - ", selectorExpress='" + selectorExpress + '\'' + | ||
287 | - ", messageModel=" + messageModel + | ||
288 | - '}'; | ||
289 | - } | ||
290 | 335 | ||
291 | @SuppressWarnings("unchecked") | 336 | @SuppressWarnings("unchecked") |
292 | - private Object doConvertMessage(MessageExt messageExt) { | ||
293 | - if (Objects.equals(messageType, MessageExt.class)) { | ||
294 | - return messageExt; | 337 | + private Object doConvertMessage(Message message) { |
338 | + if (Objects.equals(messageType, Message.class)) { | ||
339 | + return message; | ||
295 | } else { | 340 | } else { |
296 | - String str = new String(messageExt.getBody(), Charset.forName(charset)); | 341 | + String str = new String(message.getBody(), Charset.forName(charset)); |
297 | if (Objects.equals(messageType, String.class)) { | 342 | if (Objects.equals(messageType, String.class)) { |
298 | return str; | 343 | return str; |
299 | } else { | 344 | } else { |
@@ -335,72 +380,45 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | @@ -335,72 +380,45 @@ public class AliyunRocketMQListenerContainer implements InitializingBean, Rocket | ||
335 | 380 | ||
336 | Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); | 381 | Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); |
337 | Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); | 382 | Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); |
338 | - Assert.notNull(nameServer, "Property 'nameServer' is required"); | 383 | + Assert.notNull(onsAddr, "Property 'nameServer' is required"); |
339 | Assert.notNull(topic, "Property 'topic' is required"); | 384 | Assert.notNull(topic, "Property 'topic' is required"); |
340 | 385 | ||
341 | Properties consumerProperties = new Properties(); | 386 | Properties consumerProperties = new Properties(); |
342 | - consumerProperties.setProperty(PropertyKeyConst.ConsumerId, "CID_"+consumerGroup); | 387 | + consumerProperties.setProperty(PropertyKeyConst.ConsumerId, consumerGroup); |
343 | consumerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); | 388 | consumerProperties.setProperty(PropertyKeyConst.AccessKey, accessKey); |
344 | consumerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); | 389 | consumerProperties.setProperty(PropertyKeyConst.SecretKey, secretKey); |
345 | - consumerProperties.setProperty(PropertyKeyConst.ONSAddr, nameServer); | 390 | + consumerProperties.setProperty(PropertyKeyConst.ONSAddr, onsAddr); |
346 | consumerProperties.setProperty(PropertyKeyConst.ConsumeThreadNums, consumeThreadMax+""); | 391 | consumerProperties.setProperty(PropertyKeyConst.ConsumeThreadNums, consumeThreadMax+""); |
347 | consumerProperties.setProperty(PropertyKeyConst.MessageModel, messageModel.getModeCN()); | 392 | consumerProperties.setProperty(PropertyKeyConst.MessageModel, messageModel.getModeCN()); |
348 | - //判断是否为批量消费者 | ||
349 | - boolean isBatchConsume = false; | ||
350 | //允许用户自己设置该consumer的一些配置 | 393 | //允许用户自己设置该consumer的一些配置 |
351 | - DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer(); | ||
352 | - if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { | ||
353 | - ((RocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(defaultMQPushConsumer); | ||
354 | - isBatchConsume = defaultMQPushConsumer.getConsumeMessageBatchMaxSize()>1; | 394 | + if (rocketMQListener instanceof AliyunRocketMQPushConsumerLifecycleListener) { |
395 | + ((AliyunRocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumerProperties); | ||
355 | } | 396 | } |
356 | - | ||
357 | switch (consumeMode) { | 397 | switch (consumeMode) { |
358 | case ORDERLY://顺序消息 | 398 | case ORDERLY://顺序消息 |
359 | orderConsumer = ONSFactory.createOrderedConsumer(consumerProperties); | 399 | orderConsumer = ONSFactory.createOrderedConsumer(consumerProperties); |
360 | if(selectorType == SelectorType.TAG){ | 400 | if(selectorType == SelectorType.TAG){ |
361 | orderConsumer.subscribe(topic, selectorExpress, new DefaultMessageListenerOrderly()); | 401 | orderConsumer.subscribe(topic, selectorExpress, new DefaultMessageListenerOrderly()); |
362 | }else if(selectorType == SelectorType.SQL92){ | 402 | }else if(selectorType == SelectorType.SQL92){ |
363 | - orderConsumer.subscribe(topic, com.aliyun.openservices.ons.api.MessageSelector.bySql(selectorExpress), new DefaultMessageListenerOrderly()); | 403 | + orderConsumer.subscribe(topic, MessageSelector.bySql(selectorExpress), new DefaultMessageListenerOrderly()); |
364 | } | 404 | } |
365 | break; | 405 | break; |
366 | case CONCURRENTLY://普通消息 | 406 | case CONCURRENTLY://普通消息 |
367 | - if(isBatchConsume){ | ||
368 | - //批量消息 | ||
369 | - | ||
370 | - } | ||
371 | - | ||
372 | consumer = ONSFactory.createConsumer(consumerProperties); | 407 | consumer = ONSFactory.createConsumer(consumerProperties); |
373 | if(selectorType == SelectorType.TAG){ | 408 | if(selectorType == SelectorType.TAG){ |
374 | consumer.subscribe(topic, selectorExpress, new DefaultMessageListenerConcurrently()); | 409 | consumer.subscribe(topic, selectorExpress, new DefaultMessageListenerConcurrently()); |
375 | }else if(selectorType == SelectorType.SQL92){ | 410 | }else if(selectorType == SelectorType.SQL92){ |
376 | - consumer.subscribe(topic, com.aliyun.openservices.ons.api.MessageSelector.bySql(selectorExpress), new DefaultMessageListenerConcurrently()); | 411 | + consumer.subscribe(topic, MessageSelector.bySql(selectorExpress), new DefaultMessageListenerConcurrently()); |
377 | } | 412 | } |
378 | break; | 413 | break; |
414 | + case BATCH://批量消息 | ||
415 | + batchConsumer = ONSFactory.createBatchConsumer(consumerProperties); | ||
416 | + batchConsumer.subscribe(topic, selectorExpress, new DefaultMessageListenerBatchs()); | ||
417 | + break; | ||
379 | default: | 418 | default: |
380 | throw new IllegalArgumentException("Property 'consumeMode' was wrong."); | 419 | throw new IllegalArgumentException("Property 'consumeMode' was wrong."); |
381 | } | 420 | } |
382 | 421 | ||
383 | - | ||
384 | - | ||
385 | - | ||
386 | - | ||
387 | - consumer.subscribe(MqConfig.TOPIC, MqConfig.TAG, new MessageListenerImpl()); | ||
388 | - consumer.start(); | ||
389 | - | ||
390 | - switch (selectorType) { | ||
391 | - case TAG: | ||
392 | - consumer.subscribe(topic, selectorExpress); | ||
393 | - break; | ||
394 | - case SQL92: | ||
395 | - consumer.subscribe(topic, MessageSelector.bySql(selectorExpress)); | ||
396 | - break; | ||
397 | - default: | ||
398 | - throw new IllegalArgumentException("Property 'selectorType' was wrong."); | ||
399 | - } | ||
400 | - | ||
401 | - | ||
402 | - | ||
403 | - | ||
404 | } | 422 | } |
405 | 423 | ||
406 | } | 424 | } |
src/main/java/org/apache/rocketmq/spring/starter/core/RocketMQPushConsumerLifecycleListener.java renamed to src/main/java/org/apache/rocketmq/spring/starter/core/AliyunRocketMQPushConsumerLifecycleListener.java
@@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
17 | 17 | ||
18 | package org.apache.rocketmq.spring.starter.core; | 18 | package org.apache.rocketmq.spring.starter.core; |
19 | 19 | ||
20 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | 20 | +import java.util.Properties; |
21 | 21 | ||
22 | -public interface RocketMQPushConsumerLifecycleListener extends RocketMQConsumerLifecycleListener<DefaultMQPushConsumer> { | 22 | +public interface AliyunRocketMQPushConsumerLifecycleListener extends RocketMQConsumerLifecycleListener<Properties> { |
23 | } | 23 | } |
src/main/java/org/apache/rocketmq/spring/starter/core/DefaultRocketMQListenerContainer.java
1 | -/* | ||
2 | - * Licensed to the Apache Software Foundation (ASF) under one or more | ||
3 | - * contributor license agreements. See the NOTICE file distributed with | ||
4 | - * this work for additional information regarding copyright ownership. | ||
5 | - * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
6 | - * (the "License"); you may not use this file except in compliance with | ||
7 | - * the License. You may obtain a copy of the License at | ||
8 | - * | ||
9 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | - * | ||
11 | - * Unless required by applicable law or agreed to in writing, software | ||
12 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | - * See the License for the specific language governing permissions and | ||
15 | - * limitations under the License. | ||
16 | - */ | ||
17 | - | ||
18 | -package org.apache.rocketmq.spring.starter.core; | ||
19 | - | ||
20 | -import java.lang.reflect.ParameterizedType; | ||
21 | -import java.lang.reflect.Type; | ||
22 | -import java.nio.charset.Charset; | ||
23 | -import java.util.Date; | ||
24 | -import java.util.List; | ||
25 | -import java.util.Objects; | ||
26 | - | ||
27 | -import org.apache.commons.lang3.StringUtils; | ||
28 | -import org.apache.commons.lang3.exception.ExceptionUtils; | ||
29 | -import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
30 | -import org.apache.rocketmq.client.consumer.MessageSelector; | ||
31 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; | ||
32 | -import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
33 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
34 | -import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
35 | -import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; | ||
36 | -import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; | ||
37 | -import org.apache.rocketmq.client.exception.MQClientException; | ||
38 | -import org.apache.rocketmq.common.message.MessageExt; | ||
39 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
40 | -import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
41 | -import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
42 | -import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; | ||
43 | -import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; | ||
44 | -import org.apache.rocketmq.spring.starter.utils.IPUtil; | ||
45 | -import org.springframework.beans.factory.InitializingBean; | ||
46 | -import org.springframework.util.Assert; | ||
47 | - | ||
48 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
49 | - | ||
50 | -import lombok.Getter; | ||
51 | -import lombok.Setter; | ||
52 | -import lombok.extern.slf4j.Slf4j; | ||
53 | - | ||
54 | -@SuppressWarnings("WeakerAccess") | ||
55 | -@Slf4j | ||
56 | -public class DefaultRocketMQListenerContainer implements InitializingBean, RocketMQListenerContainer { | ||
57 | - | ||
58 | - @Setter | ||
59 | - @Getter | ||
60 | - private long suspendCurrentQueueTimeMillis = 1000; | ||
61 | - | ||
62 | - /** | ||
63 | - * Message consume retry strategy<br> -1,no retry,put into DLQ directly<br> 0,broker control retry frequency<br> | ||
64 | - * >0,client control retry frequency | ||
65 | - */ | ||
66 | - @Setter | ||
67 | - @Getter | ||
68 | - private int delayLevelWhenNextConsume = 0; | ||
69 | - | ||
70 | - @Setter | ||
71 | - @Getter | ||
72 | - private String consumerGroup; | ||
73 | - | ||
74 | - @Setter | ||
75 | - @Getter | ||
76 | - private String nameServer; | ||
77 | - | ||
78 | - @Setter | ||
79 | - @Getter | ||
80 | - private String topic; | ||
81 | - | ||
82 | - @Setter | ||
83 | - @Getter | ||
84 | - private ConsumeMode consumeMode = ConsumeMode.CONCURRENTLY; | ||
85 | - | ||
86 | - @Setter | ||
87 | - @Getter | ||
88 | - private SelectorType selectorType = SelectorType.TAG; | ||
89 | - | ||
90 | - @Setter | ||
91 | - @Getter | ||
92 | - private String selectorExpress = "*"; | ||
93 | - | ||
94 | - @Setter | ||
95 | - @Getter | ||
96 | - private MessageModel messageModel = MessageModel.CLUSTERING; | ||
97 | - | ||
98 | - @Setter | ||
99 | - @Getter | ||
100 | - private int consumeThreadMax = 64; | ||
101 | - | ||
102 | - @Getter | ||
103 | - @Setter | ||
104 | - private String charset = "UTF-8"; | ||
105 | - | ||
106 | - @Setter | ||
107 | - @Getter | ||
108 | - private ObjectMapper objectMapper = new ObjectMapper(); | ||
109 | - | ||
110 | - @Setter | ||
111 | - @Getter | ||
112 | - private boolean started; | ||
113 | - | ||
114 | - @Setter | ||
115 | - private RocketMQListener rocketMQListener; | ||
116 | - | ||
117 | - private DefaultMQPushConsumer consumer; | ||
118 | - | ||
119 | - private Class messageType; | ||
120 | - | ||
121 | - @Setter | ||
122 | - private RocketMQTemplate rocketMQTemplate; | ||
123 | - | ||
124 | - public void setupMessageListener(RocketMQListener rocketMQListener) { | ||
125 | - this.rocketMQListener = rocketMQListener; | ||
126 | - } | ||
127 | - | ||
128 | - @Override | ||
129 | - public void destroy() { | ||
130 | - this.setStarted(false); | ||
131 | - if (Objects.nonNull(consumer)) { | ||
132 | - consumer.shutdown(); | ||
133 | - } | ||
134 | - log.info("container destroyed, {}", this.toString()); | ||
135 | - } | ||
136 | - | ||
137 | - public synchronized void start() throws MQClientException { | ||
138 | - | ||
139 | - if (this.isStarted()) { | ||
140 | - throw new IllegalStateException("container already started. " + this.toString()); | ||
141 | - } | ||
142 | - | ||
143 | - initRocketMQPushConsumer(); | ||
144 | - | ||
145 | - // parse message type | ||
146 | - this.messageType = getMessageType(); | ||
147 | - log.debug("msgType: {}", messageType.getName()); | ||
148 | - | ||
149 | - consumer.start(); | ||
150 | - this.setStarted(true); | ||
151 | - | ||
152 | - log.info("started container: {}", this.toString()); | ||
153 | - } | ||
154 | - | ||
155 | - public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { | ||
156 | - | ||
157 | - @SuppressWarnings("unchecked") | ||
158 | - public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { | ||
159 | - for (MessageExt messageExt : msgs) { | ||
160 | - Date consumeBeginTime = new Date(); | ||
161 | - log.debug("received msg: {}", messageExt); | ||
162 | - try { | ||
163 | - long now = System.currentTimeMillis(); | ||
164 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
165 | - long costTime = System.currentTimeMillis() - now; | ||
166 | - log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
167 | - } catch (Exception e) { | ||
168 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
169 | - context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); | ||
170 | - if(messageExt.getTopic().equals("DATA_COLLECTION_TOPIC") && "ConsumeMsgFailed".equals(messageExt.getTags())){ | ||
171 | - log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
172 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
173 | - } | ||
174 | - if(e instanceof ConvertMsgException){ | ||
175 | - log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
176 | - //消息消费失败,发送失败消息 | ||
177 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
178 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
179 | - } | ||
180 | - this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
181 | - return ConsumeConcurrentlyStatus.RECONSUME_LATER; | ||
182 | - } | ||
183 | - } | ||
184 | - | ||
185 | - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
186 | - } | ||
187 | - /** | ||
188 | - * 发送消息消费失败消息 | ||
189 | - * @param messageExt | ||
190 | - * @param e | ||
191 | - * 2018年3月22日 zhaowg | ||
192 | - */ | ||
193 | - private void sendConsumeMsgFailed(MessageExt messageExt, Exception e,Date consumeBeginTime) { | ||
194 | - log.info("消费消息失败,开始发送消费失败MQ"); | ||
195 | - String topic = "DATA_COLLECTION_TOPIC"; | ||
196 | - String tag = "ConsumeMsgFailed"; | ||
197 | - try{ | ||
198 | - Date consumeEndTime = new Date(); | ||
199 | - String destination = topic+":"+tag; | ||
200 | - ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | ||
201 | - consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | ||
202 | - consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | ||
203 | - consumeFailedMsgVO.setConsumeGroup(consumerGroup); | ||
204 | - consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | ||
205 | - if(e!=null){ | ||
206 | - String errMsg = ExceptionUtils.getStackTrace(e); | ||
207 | - if(StringUtils.isNotBlank(errMsg)){ | ||
208 | - //最多保存1024个字符 | ||
209 | - consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | ||
210 | - } | ||
211 | - } | ||
212 | - consumeFailedMsgVO.setMsg(new String(messageExt.getBody())); | ||
213 | - consumeFailedMsgVO.setMsgId(messageExt.getMsgId()); | ||
214 | - consumeFailedMsgVO.setMsgKeys(messageExt.getKeys()); | ||
215 | - consumeFailedMsgVO.setReconsumeTimes(messageExt.getReconsumeTimes()); | ||
216 | - consumeFailedMsgVO.setTag(messageExt.getTags()); | ||
217 | - consumeFailedMsgVO.setTopic(messageExt.getTopic()); | ||
218 | - rocketMQTemplate.sendOneWay(destination, consumeFailedMsgVO); | ||
219 | - log.info("发送消息消费失败MQ成功"); | ||
220 | - }catch(Exception e1){ | ||
221 | - log.info("发送消息消费失败MQ异常",e); | ||
222 | - } | ||
223 | - | ||
224 | - } | ||
225 | - } | ||
226 | - | ||
227 | - public class DefaultMessageListenerOrderly implements MessageListenerOrderly { | ||
228 | - | ||
229 | - @SuppressWarnings("unchecked") | ||
230 | - public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { | ||
231 | - for (MessageExt messageExt : msgs) { | ||
232 | - log.debug("received msg: {}", messageExt); | ||
233 | - try { | ||
234 | - long now = System.currentTimeMillis(); | ||
235 | - rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
236 | - long costTime = System.currentTimeMillis() - now; | ||
237 | - log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
238 | - } catch (Exception e) { | ||
239 | - log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
240 | - context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); | ||
241 | - return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; | ||
242 | - } | ||
243 | - } | ||
244 | - | ||
245 | - return ConsumeOrderlyStatus.SUCCESS; | ||
246 | - } | ||
247 | - } | ||
248 | - | ||
249 | - @Override | ||
250 | - public void afterPropertiesSet() throws Exception { | ||
251 | - start(); | ||
252 | - } | ||
253 | - | ||
254 | - @Override | ||
255 | - public String toString() { | ||
256 | - return "DefaultRocketMQListenerContainer{" + | ||
257 | - "consumerGroup='" + consumerGroup + '\'' + | ||
258 | - ", nameServer='" + nameServer + '\'' + | ||
259 | - ", topic='" + topic + '\'' + | ||
260 | - ", consumeMode=" + consumeMode + | ||
261 | - ", selectorType=" + selectorType + | ||
262 | - ", selectorExpress='" + selectorExpress + '\'' + | ||
263 | - ", messageModel=" + messageModel + | ||
264 | - '}'; | ||
265 | - } | ||
266 | - | ||
267 | - @SuppressWarnings("unchecked") | ||
268 | - private Object doConvertMessage(MessageExt messageExt) { | ||
269 | - if (Objects.equals(messageType, MessageExt.class)) { | ||
270 | - return messageExt; | ||
271 | - } else { | ||
272 | - String str = new String(messageExt.getBody(), Charset.forName(charset)); | ||
273 | - if (Objects.equals(messageType, String.class)) { | ||
274 | - return str; | ||
275 | - } else { | ||
276 | - // if msgType not string, use objectMapper change it. | ||
277 | - try { | ||
278 | - return objectMapper.readValue(str, messageType); | ||
279 | - } catch (Exception e) { | ||
280 | - log.info("convert failed. str:{}, msgType:{}", str, messageType); | ||
281 | - throw new ConvertMsgException("cannot convert message to " + messageType, e); | ||
282 | - } | ||
283 | - } | ||
284 | - } | ||
285 | - } | ||
286 | - | ||
287 | - private Class getMessageType() { | ||
288 | - Type[] interfaces = rocketMQListener.getClass().getGenericInterfaces(); | ||
289 | - if (Objects.nonNull(interfaces)) { | ||
290 | - for (Type type : interfaces) { | ||
291 | - if (type instanceof ParameterizedType) { | ||
292 | - ParameterizedType parameterizedType = (ParameterizedType) type; | ||
293 | - if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) { | ||
294 | - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); | ||
295 | - if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { | ||
296 | - return (Class) actualTypeArguments[0]; | ||
297 | - } else { | ||
298 | - return Object.class; | ||
299 | - } | ||
300 | - } | ||
301 | - } | ||
302 | - } | ||
303 | - | ||
304 | - return Object.class; | ||
305 | - } else { | ||
306 | - return Object.class; | ||
307 | - } | ||
308 | - } | ||
309 | - | ||
310 | - private void initRocketMQPushConsumer() throws MQClientException { | ||
311 | - | ||
312 | - Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); | ||
313 | - Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); | ||
314 | - Assert.notNull(nameServer, "Property 'nameServer' is required"); | ||
315 | - Assert.notNull(topic, "Property 'topic' is required"); | ||
316 | - | ||
317 | - consumer = new DefaultMQPushConsumer(consumerGroup); | ||
318 | - consumer.setNamesrvAddr(nameServer); | ||
319 | - consumer.setConsumeThreadMax(consumeThreadMax); | ||
320 | - if (consumeThreadMax < consumer.getConsumeThreadMin()) { | ||
321 | - consumer.setConsumeThreadMin(consumeThreadMax); | ||
322 | - } | ||
323 | - | ||
324 | - consumer.setMessageModel(messageModel); | ||
325 | - | ||
326 | - switch (selectorType) { | ||
327 | - case TAG: | ||
328 | - consumer.subscribe(topic, selectorExpress); | ||
329 | - break; | ||
330 | - case SQL92: | ||
331 | - consumer.subscribe(topic, MessageSelector.bySql(selectorExpress)); | ||
332 | - break; | ||
333 | - default: | ||
334 | - throw new IllegalArgumentException("Property 'selectorType' was wrong."); | ||
335 | - } | ||
336 | - | ||
337 | - switch (consumeMode) { | ||
338 | - case ORDERLY: | ||
339 | - consumer.setMessageListener(new DefaultMessageListenerOrderly()); | ||
340 | - break; | ||
341 | - case CONCURRENTLY: | ||
342 | - consumer.setMessageListener(new DefaultMessageListenerConcurrently()); | ||
343 | - break; | ||
344 | - default: | ||
345 | - throw new IllegalArgumentException("Property 'consumeMode' was wrong."); | ||
346 | - } | ||
347 | - | ||
348 | - // provide an entryway to custom setting RocketMQ consumer | ||
349 | - if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { | ||
350 | - ((RocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumer); | ||
351 | - } | ||
352 | - | ||
353 | - } | ||
354 | - | ||
355 | -} | 1 | +///* |
2 | +// * Licensed to the Apache Software Foundation (ASF) under one or more | ||
3 | +// * contributor license agreements. See the NOTICE file distributed with | ||
4 | +// * this work for additional information regarding copyright ownership. | ||
5 | +// * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
6 | +// * (the "License"); you may not use this file except in compliance with | ||
7 | +// * the License. You may obtain a copy of the License at | ||
8 | +// * | ||
9 | +// * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +// * | ||
11 | +// * Unless required by applicable law or agreed to in writing, software | ||
12 | +// * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +// * See the License for the specific language governing permissions and | ||
15 | +// * limitations under the License. | ||
16 | +// */ | ||
17 | +// | ||
18 | +//package org.apache.rocketmq.spring.starter.core; | ||
19 | +// | ||
20 | +//import java.lang.reflect.ParameterizedType; | ||
21 | +//import java.lang.reflect.Type; | ||
22 | +//import java.nio.charset.Charset; | ||
23 | +//import java.util.Date; | ||
24 | +//import java.util.List; | ||
25 | +//import java.util.Objects; | ||
26 | +// | ||
27 | +//import org.apache.commons.lang3.StringUtils; | ||
28 | +//import org.apache.commons.lang3.exception.ExceptionUtils; | ||
29 | +//import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; | ||
30 | +//import org.apache.rocketmq.client.consumer.MessageSelector; | ||
31 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; | ||
32 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; | ||
33 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; | ||
34 | +//import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; | ||
35 | +//import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; | ||
36 | +//import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; | ||
37 | +//import org.apache.rocketmq.client.exception.MQClientException; | ||
38 | +//import org.apache.rocketmq.common.message.MessageExt; | ||
39 | +//import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
40 | +//import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
41 | +//import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
42 | +//import org.apache.rocketmq.spring.starter.exception.ConvertMsgException; | ||
43 | +//import org.apache.rocketmq.spring.starter.msgvo.ConsumeFailedMsgVO; | ||
44 | +//import org.apache.rocketmq.spring.starter.utils.IPUtil; | ||
45 | +//import org.springframework.beans.factory.InitializingBean; | ||
46 | +//import org.springframework.util.Assert; | ||
47 | +// | ||
48 | +//import com.fasterxml.jackson.databind.ObjectMapper; | ||
49 | +// | ||
50 | +//import lombok.Getter; | ||
51 | +//import lombok.Setter; | ||
52 | +//import lombok.extern.slf4j.Slf4j; | ||
53 | +// | ||
54 | +//@SuppressWarnings("WeakerAccess") | ||
55 | +//@Slf4j | ||
56 | +//public class DefaultRocketMQListenerContainer implements InitializingBean, RocketMQListenerContainer { | ||
57 | +// | ||
58 | +// @Setter | ||
59 | +// @Getter | ||
60 | +// private long suspendCurrentQueueTimeMillis = 1000; | ||
61 | +// | ||
62 | +// /** | ||
63 | +// * Message consume retry strategy<br> -1,no retry,put into DLQ directly<br> 0,broker control retry frequency<br> | ||
64 | +// * >0,client control retry frequency | ||
65 | +// */ | ||
66 | +// @Setter | ||
67 | +// @Getter | ||
68 | +// private int delayLevelWhenNextConsume = 0; | ||
69 | +// | ||
70 | +// @Setter | ||
71 | +// @Getter | ||
72 | +// private String consumerGroup; | ||
73 | +// | ||
74 | +// @Setter | ||
75 | +// @Getter | ||
76 | +// private String nameServer; | ||
77 | +// | ||
78 | +// @Setter | ||
79 | +// @Getter | ||
80 | +// private String topic; | ||
81 | +// | ||
82 | +// @Setter | ||
83 | +// @Getter | ||
84 | +// private ConsumeMode consumeMode = ConsumeMode.CONCURRENTLY; | ||
85 | +// | ||
86 | +// @Setter | ||
87 | +// @Getter | ||
88 | +// private SelectorType selectorType = SelectorType.TAG; | ||
89 | +// | ||
90 | +// @Setter | ||
91 | +// @Getter | ||
92 | +// private String selectorExpress = "*"; | ||
93 | +// | ||
94 | +// @Setter | ||
95 | +// @Getter | ||
96 | +// private MessageModel messageModel = MessageModel.CLUSTERING; | ||
97 | +// | ||
98 | +// @Setter | ||
99 | +// @Getter | ||
100 | +// private int consumeThreadMax = 64; | ||
101 | +// | ||
102 | +// @Getter | ||
103 | +// @Setter | ||
104 | +// private String charset = "UTF-8"; | ||
105 | +// | ||
106 | +// @Setter | ||
107 | +// @Getter | ||
108 | +// private ObjectMapper objectMapper = new ObjectMapper(); | ||
109 | +// | ||
110 | +// @Setter | ||
111 | +// @Getter | ||
112 | +// private boolean started; | ||
113 | +// | ||
114 | +// @Setter | ||
115 | +// private RocketMQListener rocketMQListener; | ||
116 | +// | ||
117 | +// private DefaultMQPushConsumer consumer; | ||
118 | +// | ||
119 | +// private Class messageType; | ||
120 | +// | ||
121 | +// @Setter | ||
122 | +// private RocketMQTemplate rocketMQTemplate; | ||
123 | +// | ||
124 | +// public void setupMessageListener(RocketMQListener rocketMQListener) { | ||
125 | +// this.rocketMQListener = rocketMQListener; | ||
126 | +// } | ||
127 | +// | ||
128 | +// @Override | ||
129 | +// public void destroy() { | ||
130 | +// this.setStarted(false); | ||
131 | +// if (Objects.nonNull(consumer)) { | ||
132 | +// consumer.shutdown(); | ||
133 | +// } | ||
134 | +// log.info("container destroyed, {}", this.toString()); | ||
135 | +// } | ||
136 | +// | ||
137 | +// public synchronized void start() throws MQClientException { | ||
138 | +// | ||
139 | +// if (this.isStarted()) { | ||
140 | +// throw new IllegalStateException("container already started. " + this.toString()); | ||
141 | +// } | ||
142 | +// | ||
143 | +// initRocketMQPushConsumer(); | ||
144 | +// | ||
145 | +// // parse message type | ||
146 | +// this.messageType = getMessageType(); | ||
147 | +// log.debug("msgType: {}", messageType.getName()); | ||
148 | +// | ||
149 | +// consumer.start(); | ||
150 | +// this.setStarted(true); | ||
151 | +// | ||
152 | +// log.info("started container: {}", this.toString()); | ||
153 | +// } | ||
154 | +// | ||
155 | +// public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { | ||
156 | +// | ||
157 | +// @SuppressWarnings("unchecked") | ||
158 | +// public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { | ||
159 | +// for (MessageExt messageExt : msgs) { | ||
160 | +// Date consumeBeginTime = new Date(); | ||
161 | +// log.debug("received msg: {}", messageExt); | ||
162 | +// try { | ||
163 | +// long now = System.currentTimeMillis(); | ||
164 | +// rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
165 | +// long costTime = System.currentTimeMillis() - now; | ||
166 | +// log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
167 | +// } catch (Exception e) { | ||
168 | +// log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
169 | +// context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); | ||
170 | +// if(messageExt.getTopic().equals("DATA_COLLECTION_TOPIC") && "ConsumeMsgFailed".equals(messageExt.getTags())){ | ||
171 | +// log.error("消费失败的消息为“保存消费失败日志消息”,不需要记录日志,不需要重新消费,直接返回成功"); | ||
172 | +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
173 | +// } | ||
174 | +// if(e instanceof ConvertMsgException){ | ||
175 | +// log.error("消费失败的原因为转换对象失败,需要记录日志,不需要重新消费,返回消费成功"); | ||
176 | +// //消息消费失败,发送失败消息 | ||
177 | +// this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
178 | +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
179 | +// } | ||
180 | +// this.sendConsumeMsgFailed(messageExt,e,consumeBeginTime); | ||
181 | +// return ConsumeConcurrentlyStatus.RECONSUME_LATER; | ||
182 | +// } | ||
183 | +// } | ||
184 | +// | ||
185 | +// return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; | ||
186 | +// } | ||
187 | +// /** | ||
188 | +// * 发送消息消费失败消息 | ||
189 | +// * @param messageExt | ||
190 | +// * @param e | ||
191 | +// * 2018年3月22日 zhaowg | ||
192 | +// */ | ||
193 | +// private void sendConsumeMsgFailed(MessageExt messageExt, Exception e,Date consumeBeginTime) { | ||
194 | +// log.info("消费消息失败,开始发送消费失败MQ"); | ||
195 | +// String topic = "DATA_COLLECTION_TOPIC"; | ||
196 | +// String tag = "ConsumeMsgFailed"; | ||
197 | +// try{ | ||
198 | +// Date consumeEndTime = new Date(); | ||
199 | +// String destination = topic+":"+tag; | ||
200 | +// ConsumeFailedMsgVO consumeFailedMsgVO = new ConsumeFailedMsgVO(); | ||
201 | +// consumeFailedMsgVO.setConsumeBeginTime(consumeBeginTime); | ||
202 | +// consumeFailedMsgVO.setConsumeEndTime(consumeEndTime); | ||
203 | +// consumeFailedMsgVO.setConsumeGroup(consumerGroup); | ||
204 | +// consumeFailedMsgVO.setConsumeIp(IPUtil.getLocalHost()); | ||
205 | +// if(e!=null){ | ||
206 | +// String errMsg = ExceptionUtils.getStackTrace(e); | ||
207 | +// if(StringUtils.isNotBlank(errMsg)){ | ||
208 | +// //最多保存1024个字符 | ||
209 | +// consumeFailedMsgVO.setCunsumerErrMsg(errMsg.substring(0, 1024)); | ||
210 | +// } | ||
211 | +// } | ||
212 | +// consumeFailedMsgVO.setMsg(new String(messageExt.getBody())); | ||
213 | +// consumeFailedMsgVO.setMsgId(messageExt.getMsgId()); | ||
214 | +// consumeFailedMsgVO.setMsgKeys(messageExt.getKeys()); | ||
215 | +// consumeFailedMsgVO.setReconsumeTimes(messageExt.getReconsumeTimes()); | ||
216 | +// consumeFailedMsgVO.setTag(messageExt.getTags()); | ||
217 | +// consumeFailedMsgVO.setTopic(messageExt.getTopic()); | ||
218 | +// rocketMQTemplate.sendOneWay(destination, consumeFailedMsgVO); | ||
219 | +// log.info("发送消息消费失败MQ成功"); | ||
220 | +// }catch(Exception e1){ | ||
221 | +// log.info("发送消息消费失败MQ异常",e); | ||
222 | +// } | ||
223 | +// | ||
224 | +// } | ||
225 | +// } | ||
226 | +// | ||
227 | +// public class DefaultMessageListenerOrderly implements MessageListenerOrderly { | ||
228 | +// | ||
229 | +// @SuppressWarnings("unchecked") | ||
230 | +// public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) { | ||
231 | +// for (MessageExt messageExt : msgs) { | ||
232 | +// log.debug("received msg: {}", messageExt); | ||
233 | +// try { | ||
234 | +// long now = System.currentTimeMillis(); | ||
235 | +// rocketMQListener.onMessage(doConvertMessage(messageExt)); | ||
236 | +// long costTime = System.currentTimeMillis() - now; | ||
237 | +// log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); | ||
238 | +// } catch (Exception e) { | ||
239 | +// log.warn("consume message failed. messageExt:{}", messageExt, e); | ||
240 | +// context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); | ||
241 | +// return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; | ||
242 | +// } | ||
243 | +// } | ||
244 | +// | ||
245 | +// return ConsumeOrderlyStatus.SUCCESS; | ||
246 | +// } | ||
247 | +// } | ||
248 | +// | ||
249 | +// @Override | ||
250 | +// public void afterPropertiesSet() throws Exception { | ||
251 | +// start(); | ||
252 | +// } | ||
253 | +// | ||
254 | +// @Override | ||
255 | +// public String toString() { | ||
256 | +// return "DefaultRocketMQListenerContainer{" + | ||
257 | +// "consumerGroup='" + consumerGroup + '\'' + | ||
258 | +// ", nameServer='" + nameServer + '\'' + | ||
259 | +// ", topic='" + topic + '\'' + | ||
260 | +// ", consumeMode=" + consumeMode + | ||
261 | +// ", selectorType=" + selectorType + | ||
262 | +// ", selectorExpress='" + selectorExpress + '\'' + | ||
263 | +// ", messageModel=" + messageModel + | ||
264 | +// '}'; | ||
265 | +// } | ||
266 | +// | ||
267 | +// @SuppressWarnings("unchecked") | ||
268 | +// private Object doConvertMessage(MessageExt messageExt) { | ||
269 | +// if (Objects.equals(messageType, MessageExt.class)) { | ||
270 | +// return messageExt; | ||
271 | +// } else { | ||
272 | +// String str = new String(messageExt.getBody(), Charset.forName(charset)); | ||
273 | +// if (Objects.equals(messageType, String.class)) { | ||
274 | +// return str; | ||
275 | +// } else { | ||
276 | +// // if msgType not string, use objectMapper change it. | ||
277 | +// try { | ||
278 | +// return objectMapper.readValue(str, messageType); | ||
279 | +// } catch (Exception e) { | ||
280 | +// log.info("convert failed. str:{}, msgType:{}", str, messageType); | ||
281 | +// throw new ConvertMsgException("cannot convert message to " + messageType, e); | ||
282 | +// } | ||
283 | +// } | ||
284 | +// } | ||
285 | +// } | ||
286 | +// | ||
287 | +// private Class getMessageType() { | ||
288 | +// Type[] interfaces = rocketMQListener.getClass().getGenericInterfaces(); | ||
289 | +// if (Objects.nonNull(interfaces)) { | ||
290 | +// for (Type type : interfaces) { | ||
291 | +// if (type instanceof ParameterizedType) { | ||
292 | +// ParameterizedType parameterizedType = (ParameterizedType) type; | ||
293 | +// if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) { | ||
294 | +// Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); | ||
295 | +// if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { | ||
296 | +// return (Class) actualTypeArguments[0]; | ||
297 | +// } else { | ||
298 | +// return Object.class; | ||
299 | +// } | ||
300 | +// } | ||
301 | +// } | ||
302 | +// } | ||
303 | +// | ||
304 | +// return Object.class; | ||
305 | +// } else { | ||
306 | +// return Object.class; | ||
307 | +// } | ||
308 | +// } | ||
309 | +// | ||
310 | +// private void initRocketMQPushConsumer() throws MQClientException { | ||
311 | +// | ||
312 | +// Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); | ||
313 | +// Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); | ||
314 | +// Assert.notNull(nameServer, "Property 'nameServer' is required"); | ||
315 | +// Assert.notNull(topic, "Property 'topic' is required"); | ||
316 | +// | ||
317 | +// consumer = new DefaultMQPushConsumer(consumerGroup); | ||
318 | +// consumer.setNamesrvAddr(nameServer); | ||
319 | +// consumer.setConsumeThreadMax(consumeThreadMax); | ||
320 | +// if (consumeThreadMax < consumer.getConsumeThreadMin()) { | ||
321 | +// consumer.setConsumeThreadMin(consumeThreadMax); | ||
322 | +// } | ||
323 | +// | ||
324 | +// consumer.setMessageModel(messageModel); | ||
325 | +// | ||
326 | +// switch (selectorType) { | ||
327 | +// case TAG: | ||
328 | +// consumer.subscribe(topic, selectorExpress); | ||
329 | +// break; | ||
330 | +// case SQL92: | ||
331 | +// consumer.subscribe(topic, MessageSelector.bySql(selectorExpress)); | ||
332 | +// break; | ||
333 | +// default: | ||
334 | +// throw new IllegalArgumentException("Property 'selectorType' was wrong."); | ||
335 | +// } | ||
336 | +// | ||
337 | +// switch (consumeMode) { | ||
338 | +// case ORDERLY: | ||
339 | +// consumer.setMessageListener(new DefaultMessageListenerOrderly()); | ||
340 | +// break; | ||
341 | +// case CONCURRENTLY: | ||
342 | +// consumer.setMessageListener(new DefaultMessageListenerConcurrently()); | ||
343 | +// break; | ||
344 | +// default: | ||
345 | +// throw new IllegalArgumentException("Property 'consumeMode' was wrong."); | ||
346 | +// } | ||
347 | +// | ||
348 | +// // provide an entryway to custom setting RocketMQ consumer | ||
349 | +// if (rocketMQListener instanceof AliyunRocketMQPushConsumerLifecycleListener) { | ||
350 | +// ((AliyunRocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumer); | ||
351 | +// } | ||
352 | +// | ||
353 | +// } | ||
354 | +// | ||
355 | +//} |
src/main/java/org/apache/rocketmq/spring/starter/core/DefaultRocketMQListenerContainerConstants.java
@@ -32,6 +32,20 @@ public final class DefaultRocketMQListenerContainerConstants { | @@ -32,6 +32,20 @@ public final class DefaultRocketMQListenerContainerConstants { | ||
32 | public static final String PROP_ROCKETMQ_LISTENER = "rocketMQListener"; | 32 | public static final String PROP_ROCKETMQ_LISTENER = "rocketMQListener"; |
33 | public static final String PROP_OBJECT_MAPPER = "objectMapper"; | 33 | public static final String PROP_OBJECT_MAPPER = "objectMapper"; |
34 | public static final String METHOD_DESTROY = "destroy"; | 34 | public static final String METHOD_DESTROY = "destroy"; |
35 | - /**生产者 add zwg*/ | ||
36 | - public static final String PROP_ROCKETMQ_TEMPLATE = "rocketMQTemplate"; | 35 | + public static final String PROP_ROCKETMQ_TEMPLATE = "rocketMQTemplate"; |
36 | + public static final String PROP_ONS_Addr = "onsAddr"; | ||
37 | + public static final String PROP_ACCESS_KEY = "accessKey"; | ||
38 | + public static final String PROP_SECRET_KEY = "secretKey"; | ||
39 | + /** | ||
40 | + * 环境前缀 | ||
41 | + */ | ||
42 | + public static final String PROP_ENVIRONMENT_PREFIX = "environmentPrefix"; | ||
43 | + /** | ||
44 | + * 消息消费失败发送的主题 | ||
45 | + */ | ||
46 | + public final static String CONSUMEFAILED_TOPIC = "ZTEITS_RNT_CLOUD"; | ||
47 | + /** | ||
48 | + * 消息消费失败发送的tag | ||
49 | + */ | ||
50 | + public final static String CONSUMEFAILED_TAG = "ConsumeMsgFailed"; | ||
37 | } | 51 | } |
src/main/java/org/apache/rocketmq/spring/starter/core/RocketMQTemplate.java
@@ -17,54 +17,30 @@ | @@ -17,54 +17,30 @@ | ||
17 | 17 | ||
18 | package org.apache.rocketmq.spring.starter.core; | 18 | package org.apache.rocketmq.spring.starter.core; |
19 | 19 | ||
20 | -import com.aliyun.openservices.ons.api.MessageAccessor; | ||
21 | -import com.aliyun.openservices.ons.api.OnExceptionContext; | ||
22 | -import com.aliyun.openservices.ons.api.Producer; | ||
23 | -import com.aliyun.openservices.ons.api.PropertyKeyConst; | ||
24 | -import com.aliyun.openservices.ons.api.exception.ONSClientException; | ||
25 | -import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.message.MessageExt; | ||
26 | -import com.fasterxml.jackson.core.JsonProcessingException; | ||
27 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
28 | import java.nio.charset.Charset; | 20 | import java.nio.charset.Charset; |
29 | -import java.util.Iterator; | ||
30 | import java.util.Map; | 21 | import java.util.Map; |
31 | -import java.util.Objects; | ||
32 | -import java.util.Properties; | ||
33 | import java.util.Map.Entry; | 22 | import java.util.Map.Entry; |
23 | +import java.util.Objects; | ||
34 | 24 | ||
35 | -import lombok.Getter; | ||
36 | -import lombok.Setter; | ||
37 | -import lombok.extern.slf4j.Slf4j; | ||
38 | -import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
39 | -import org.apache.rocketmq.client.producer.MessageQueueSelector; | ||
40 | -import org.apache.rocketmq.client.producer.SendCallback; | ||
41 | -import org.apache.rocketmq.client.producer.SendResult; | ||
42 | -import org.apache.rocketmq.client.producer.SendStatus; | ||
43 | -import org.apache.rocketmq.client.producer.selector.SelectMessageQueueByHash; | ||
44 | -import org.apache.rocketmq.common.message.MessageConst; | ||
45 | -import org.apache.rocketmq.common.message.MessageQueue; | ||
46 | import org.springframework.beans.factory.DisposableBean; | 25 | import org.springframework.beans.factory.DisposableBean; |
47 | import org.springframework.beans.factory.InitializingBean; | 26 | import org.springframework.beans.factory.InitializingBean; |
48 | -import org.springframework.messaging.Message; | ||
49 | -import org.springframework.messaging.MessageHeaders; | ||
50 | import org.springframework.messaging.MessagingException; | 27 | import org.springframework.messaging.MessagingException; |
51 | -import org.springframework.messaging.core.AbstractMessageSendingTemplate; | ||
52 | -import org.springframework.messaging.core.MessagePostProcessor; | ||
53 | -import org.springframework.messaging.support.MessageBuilder; | ||
54 | -import org.springframework.util.Assert; | ||
55 | -import org.springframework.util.MimeTypeUtils; | ||
56 | -import org.springframework.util.StringUtils; | ||
57 | 28 | ||
58 | -@SuppressWarnings({"WeakerAccess", "unused"}) | 29 | +import com.aliyun.openservices.ons.api.Message; |
30 | +import com.aliyun.openservices.ons.api.Producer; | ||
31 | +import com.aliyun.openservices.ons.api.SendCallback; | ||
32 | +import com.aliyun.openservices.ons.api.SendResult; | ||
33 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
34 | + | ||
35 | +import lombok.Getter; | ||
36 | +import lombok.Setter; | ||
37 | +import lombok.extern.slf4j.Slf4j; | ||
38 | + | ||
59 | @Slf4j | 39 | @Slf4j |
60 | -public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> implements InitializingBean, DisposableBean { | 40 | +public class RocketMQTemplate implements InitializingBean, DisposableBean { |
61 | 41 | ||
62 | @Getter | 42 | @Getter |
63 | @Setter | 43 | @Setter |
64 | - private DefaultMQProducer defaultProducer; | ||
65 | - | ||
66 | - @Getter | ||
67 | - @Setter | ||
68 | private Producer aliyunProducer; | 44 | private Producer aliyunProducer; |
69 | 45 | ||
70 | @Setter | 46 | @Setter |
@@ -74,479 +50,252 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> imp | @@ -74,479 +50,252 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> imp | ||
74 | @Getter | 50 | @Getter |
75 | @Setter | 51 | @Setter |
76 | private String charset = "UTF-8"; | 52 | private String charset = "UTF-8"; |
77 | - | ||
78 | - @Getter | 53 | + |
54 | + /** | ||
55 | + * 环境前缀 | ||
56 | + */ | ||
79 | @Setter | 57 | @Setter |
80 | - private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash(); | 58 | + private String environmentPrefix; |
81 | 59 | ||
82 | /** | 60 | /** |
83 | - * <p> Send message in synchronous mode. This method returns only when the sending procedure totally completes. | ||
84 | - * Reliable synchronous transmission is used in extensive scenes, such as important notification messages, SMS | ||
85 | - * notification, SMS marketing system, etc.. </p> | ||
86 | - * | ||
87 | - * <strong>Warn:</strong> this method has internal retry-mechanism, that is, internal implementation will retry | ||
88 | - * {@link DefaultMQProducer#getRetryTimesWhenSendFailed} times before claiming failure. As a result, multiple | ||
89 | - * messages may potentially delivered to broker(s). It's up to the application developers to resolve potential | ||
90 | - * duplication issue. | ||
91 | - * | ||
92 | - * @param destination formats: `topicName:tags` | ||
93 | - * @param message {@link org.springframework.messaging.Message} | 61 | + * 同步发送消息 |
62 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
63 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
64 | + * @param key 业务主键 | ||
65 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
66 | + * @param userProperties 添加用户自定义属性键值对; 该键值对在消费消费时可被获取.也可用于做SQL属性过滤 | ||
67 | + * @param startDeliverTime 设置消息的定时投递时间(绝对时间),最大延迟时间为7天. | ||
68 | + * </p> | ||
69 | + * <ol> | ||
70 | + * <li>延迟投递: 延迟3s投递, 设置为: System.currentTimeMillis() + 3000;</li> | ||
71 | + * <li>定时投递: 2016-02-01 11:30:00投递, 设置为: new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-02-01 11:30:00").getTime()</li> | ||
72 | + * </ol> | ||
94 | * @return {@link SendResult} | 73 | * @return {@link SendResult} |
74 | + * 2018年3月23日 zhaowg | ||
95 | */ | 75 | */ |
96 | - public SendResult syncSend(String destination, Message<?> message) { | ||
97 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
98 | - log.info("syncSend failed. destination:{}, message is null ", destination); | ||
99 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | 76 | + public SendResult syncSend(String topic,String tag,String keys,Object payload,Map<String, String> userProperties,Long startDeliverTime) { |
77 | + if (Objects.isNull(topic) || Objects.isNull(payload)) { | ||
78 | + log.info("同步消息发送失败,主题和消息不能为空"); | ||
79 | + throw new IllegalArgumentException("同步消息发送失败,主题和消息不能为空"); | ||
100 | } | 80 | } |
101 | 81 | ||
102 | try { | 82 | try { |
103 | - SendResult sendResult = new SendResult(); | ||
104 | - long now = System.currentTimeMillis(); | ||
105 | - if(aliyunProducer != null){ | ||
106 | - //阿里云发送 | ||
107 | - com.aliyun.openservices.ons.api.Message aliyunMsg = convertToAliyunRocketMsg(destination,message); | ||
108 | - com.aliyun.openservices.ons.api.SendResult aliyunSendResult = aliyunProducer.send(aliyunMsg); | ||
109 | - sendResult = convertAliyunSendResult(aliyunSendResult); | ||
110 | - }else if(defaultProducer != null){ | ||
111 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
112 | - sendResult = defaultProducer.send(rocketMsg); | ||
113 | - }else{ | ||
114 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | ||
115 | - } | 83 | + long now = System.currentTimeMillis(); |
84 | + | ||
85 | + Message rocketMsg = new Message(environmentPrefix+"_"+topic, tag, keys, convertToRocketMsg(payload)); | ||
86 | + if(userProperties!=null && !userProperties.isEmpty()){ | ||
87 | + for (Entry<String, String> userProp : userProperties.entrySet()) { | ||
88 | + rocketMsg.putUserProperties(userProp.getKey(), userProp.getValue()); | ||
89 | + } | ||
90 | + } | ||
91 | + if(startDeliverTime!=null){ | ||
92 | + //设置定时发送时间 | ||
93 | + rocketMsg.setStartDeliverTime(startDeliverTime); | ||
94 | + } | ||
95 | + //阿里云发送 | ||
96 | + SendResult sendResult = aliyunProducer.send(rocketMsg); | ||
116 | long costTime = System.currentTimeMillis() - now; | 97 | long costTime = System.currentTimeMillis() - now; |
117 | - log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); | 98 | + log.debug("发送消息耗时: {} ms, msgId:{}", costTime, sendResult.getMessageId()); |
118 | return sendResult; | 99 | return sendResult; |
119 | } catch (Exception e) { | 100 | } catch (Exception e) { |
120 | - log.info("syncSend failed. destination:{}, message:{} ", destination, message); | 101 | + log.info("同步发送失败. topic:{}, message:{} ", topic, payload); |
121 | throw new MessagingException(e.getMessage(), e); | 102 | throw new MessagingException(e.getMessage(), e); |
122 | } | 103 | } |
123 | } | 104 | } |
124 | 105 | ||
125 | /** | 106 | /** |
126 | - * Same to {@link #syncSend(String, Message)}. | ||
127 | - * | ||
128 | - * @param destination formats: `topicName:tags` | ||
129 | - * @param payload the Object to use as payload | 107 | + * Same to {@link #syncSend(String, String, String, Object, Map, Long)}. |
108 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
109 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
110 | + * @param key 业务主键 | ||
111 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
130 | * @return {@link SendResult} | 112 | * @return {@link SendResult} |
113 | + * 2018年3月23日 zhaowg | ||
131 | */ | 114 | */ |
132 | - public SendResult syncSend(String destination, Object payload) { | ||
133 | - Message<?> message = this.doConvert(payload, null, null); | ||
134 | - return syncSend(destination, message); | 115 | + public SendResult syncSend(String topic,String tag,String keys, Object payload) { |
116 | + return syncSend(topic, tag, keys, payload, null, null); | ||
135 | } | 117 | } |
136 | - | ||
137 | - | ||
138 | - /** | ||
139 | - * Same to {@link #syncSend(String, Message)} with send orderly with hashKey by specified. | ||
140 | - * | ||
141 | - * @param destination formats: `topicName:tags` | ||
142 | - * @param message {@link org.springframework.messaging.Message} | ||
143 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | ||
144 | - * @return {@link SendResult} | ||
145 | - */ | ||
146 | - /*public SendResult syncSendOrderly(String destination, Message<?> message, String hashKey) { | ||
147 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
148 | - log.info("syncSendOrderly failed. destination:{}, message is null ", destination); | ||
149 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | ||
150 | - } | ||
151 | - | ||
152 | - try { | ||
153 | - long now = System.currentTimeMillis(); | ||
154 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
155 | - //TODO | ||
156 | - throw new RuntimeException("暂时未整合阿里云Producer,不要使用"); | ||
157 | -// SendResult sendResult = producer.send(rocketMsg, messageQueueSelector, hashKey, timeout); | ||
158 | -// long costTime = System.currentTimeMillis() - now; | ||
159 | -// log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); | ||
160 | -// return sendResult; | ||
161 | - } catch (Exception e) { | ||
162 | - log.info("syncSendOrderly failed. destination:{}, message:{} ", destination, message); | ||
163 | - throw new MessagingException(e.getMessage(), e); | ||
164 | - } | ||
165 | - }*/ | ||
166 | - | ||
167 | - | ||
168 | /** | 118 | /** |
169 | - * Same to {@link #syncSend(String, Object)} with send orderly with hashKey by specified. | ||
170 | - * | ||
171 | - * @param destination formats: `topicName:tags` | ||
172 | - * @param payload the Object to use as payload | ||
173 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | 119 | + * Same to {@link #syncSend(String, String, String, Object)}. |
120 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
121 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
122 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
174 | * @return {@link SendResult} | 123 | * @return {@link SendResult} |
124 | + * 2018年3月23日 zhaowg | ||
175 | */ | 125 | */ |
176 | -// public SendResult syncSendOrderly(String destination, Object payload, String hashKey) { | ||
177 | -// Message<?> message = this.doConvert(payload, null, null); | ||
178 | -// return syncSendOrderly(destination, message, hashKey); | ||
179 | -// } | 126 | + public SendResult syncSend(String topic,String tag, Object payload) { |
127 | + return syncSend(topic, tag,null, payload); | ||
128 | + } | ||
180 | 129 | ||
181 | /** | 130 | /** |
182 | - * 将公共的sendCallBack转换为阿里云的sendCallBack | ||
183 | - * @param sendCallback | ||
184 | - * @return | 131 | + * 异步发送消息 |
132 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
133 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
134 | + * @param key 业务主键 | ||
135 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
136 | + * @param userProperties 添加用户自定义属性键值对; 该键值对在消费消费时可被获取.也可用于做SQL属性过滤 | ||
137 | + * @param startDeliverTime 设置消息的定时投递时间(绝对时间),最大延迟时间为7天. | ||
138 | + * </p> | ||
139 | + * <ol> | ||
140 | + * <li>延迟投递: 延迟3s投递, 设置为: System.currentTimeMillis() + 3000;</li> | ||
141 | + * <li>定时投递: 2016-02-01 11:30:00投递, 设置为: new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-02-01 11:30:00").getTime()</li> | ||
142 | + * </ol> | ||
143 | + * @param sendCallback 发送完成要执行的回调函数 | ||
185 | * 2018年3月23日 zhaowg | 144 | * 2018年3月23日 zhaowg |
186 | */ | 145 | */ |
187 | - private com.aliyun.openservices.ons.api.SendCallback aliyunSendCallBackConvert(final SendCallback sendCallback) { | ||
188 | - com.aliyun.openservices.ons.api.SendCallback aliyunSendCallBack = new com.aliyun.openservices.ons.api.SendCallback() { | ||
189 | - | ||
190 | - @Override | ||
191 | - public void onSuccess(com.aliyun.openservices.ons.api.SendResult sendResult) { | ||
192 | - sendCallback.onSuccess(convertAliyunSendResult(sendResult)); | ||
193 | - } | ||
194 | - | ||
195 | - @Override | ||
196 | - public void onException(OnExceptionContext context) { | ||
197 | - sendCallback.onException(context.getException()); | ||
198 | - } | ||
199 | - }; | ||
200 | - return aliyunSendCallBack; | ||
201 | - } | ||
202 | - /** | ||
203 | - * <p> Send message to broker asynchronously. asynchronous transmission is generally used in response time sensitive | ||
204 | - * business scenarios. </p> | ||
205 | - * | ||
206 | - * This method returns immediately. On sending completion, <code>sendCallback</code> will be executed. | ||
207 | - * | ||
208 | - * Similar to {@link #syncSend(String, Object)}, internal implementation would potentially retry up to {@link | ||
209 | - * DefaultMQProducer#getRetryTimesWhenSendAsyncFailed} times before claiming sending failure, which may yield | ||
210 | - * message duplication and application developers are the one to resolve this potential issue. | ||
211 | - * | ||
212 | - * @param destination formats: `topicName:tags` | ||
213 | - * @param message {@link org.springframework.messaging.Message} | ||
214 | - * @param sendCallback {@link SendCallback} | ||
215 | - */ | ||
216 | - public void asyncSend(String destination, Message<?> message, SendCallback sendCallback) { | ||
217 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
218 | - log.info("asyncSend failed. destination:{}, message is null ", destination); | ||
219 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | 146 | + public void asyncSend(String topic,String tag,String keys,Object payload,Map<String, String> userProperties, |
147 | + Long startDeliverTime,SendCallback sendCallback) { | ||
148 | + if (Objects.isNull(topic) || Objects.isNull(payload)) { | ||
149 | + log.info("异步消息发送失败,主题和消息不能为空"); | ||
150 | + throw new IllegalArgumentException("异步消息发送失败,主题和消息不能为空"); | ||
220 | } | 151 | } |
221 | - | ||
222 | try { | 152 | try { |
223 | - if(aliyunProducer != null){ | ||
224 | - com.aliyun.openservices.ons.api.Message aliyunMsg = this.convertToAliyunRocketMsg(destination, message); | ||
225 | - aliyunProducer.sendAsync(aliyunMsg, aliyunSendCallBackConvert(sendCallback)); | ||
226 | - }else if(defaultProducer != null){ | ||
227 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
228 | - defaultProducer.send(rocketMsg, sendCallback); | ||
229 | - }else{ | ||
230 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | 153 | + long now = System.currentTimeMillis(); |
154 | + | ||
155 | + Message rocketMsg = new Message(environmentPrefix+"_"+topic, tag, keys, convertToRocketMsg(payload)); | ||
156 | + if(userProperties!=null && !userProperties.isEmpty()){ | ||
157 | + for (Entry<String, String> userProp : userProperties.entrySet()) { | ||
158 | + rocketMsg.putUserProperties(userProp.getKey(), userProp.getValue()); | ||
159 | + } | ||
160 | + } | ||
161 | + if(startDeliverTime!=null){ | ||
162 | + //设置定时发送时间 | ||
163 | + rocketMsg.setStartDeliverTime(startDeliverTime); | ||
231 | } | 164 | } |
165 | + //阿里云发送 | ||
166 | + aliyunProducer.sendAsync(rocketMsg, sendCallback); | ||
167 | + long costTime = System.currentTimeMillis() - now; | ||
168 | + log.debug("发送消息耗时: {} ms", costTime); | ||
232 | } catch (Exception e) { | 169 | } catch (Exception e) { |
233 | - log.info("asyncSend failed. destination:{}, message:{} ", destination, message); | 170 | + log.info("异步发送失败. topic:{}, message:{} ", topic, payload); |
234 | throw new MessagingException(e.getMessage(), e); | 171 | throw new MessagingException(e.getMessage(), e); |
235 | } | 172 | } |
236 | } | 173 | } |
237 | - | ||
238 | - /** | ||
239 | - * Same to {@link #asyncSend(String, Message, SendCallback)}. | ||
240 | - * | ||
241 | - * @param destination formats: `topicName:tags` | ||
242 | - * @param payload the Object to use as payload | ||
243 | - * @param sendCallback {@link SendCallback} | 174 | + /** |
175 | + * Same to {@link #asyncSend(String, String, String, Object, Map, Long, SendCallback)}. | ||
176 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
177 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
178 | + * @param key 业务主键 | ||
179 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
180 | + * @param sendCallback 发送完成要执行的回调函数 | ||
181 | + * @return {@link SendResult} | ||
182 | + * 2018年3月23日 zhaowg | ||
244 | */ | 183 | */ |
245 | - public void asyncSend(String destination, Object payload, SendCallback sendCallback) { | ||
246 | - Message<?> message = this.doConvert(payload, null, null); | ||
247 | - asyncSend(destination, message, sendCallback); | 184 | + public void asyncSend(String topic,String tag,String keys, Object payload,SendCallback sendCallback) { |
185 | + asyncSend(topic, tag, keys, payload, null, null,sendCallback); | ||
248 | } | 186 | } |
249 | - | ||
250 | - | ||
251 | /** | 187 | /** |
252 | - * Same to {@link #asyncSend(String, Message, SendCallback)} with send orderly with hashKey by specified. | ||
253 | - * | ||
254 | - * @param destination formats: `topicName:tags` | ||
255 | - * @param message {@link org.springframework.messaging.Message} | ||
256 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | ||
257 | - * @param sendCallback {@link SendCallback} | ||
258 | - */ | ||
259 | -// public void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback) { | ||
260 | -// if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
261 | -// log.info("asyncSendOrderly failed. destination:{}, message is null ", destination); | ||
262 | -// throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | ||
263 | -// } | ||
264 | -// | ||
265 | -// try { | ||
266 | -// org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
267 | -// //TODO zwg | ||
268 | -// throw new RuntimeException("暂时未整合阿里云Producer,不要使用"); | ||
269 | -// //producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); | ||
270 | -// } catch (Exception e) { | ||
271 | -// log.info("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); | ||
272 | -// throw new MessagingException(e.getMessage(), e); | ||
273 | -// } | ||
274 | -// } | ||
275 | - | ||
276 | - /** | ||
277 | - * Same to {@link #asyncSendOrderly(String, Message, String, SendCallback)}. | ||
278 | - * | ||
279 | - * @param destination formats: `topicName:tags` | ||
280 | - * @param payload the Object to use as payload | ||
281 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | ||
282 | - * @param sendCallback {@link SendCallback} | 188 | + * Same to {@link #asyncSend(String, String, String, Object,SendCallback)}. |
189 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
190 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
191 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
192 | + * @param sendCallback 发送完成要执行的回调函数 | ||
193 | + * @return {@link SendResult} | ||
194 | + * 2018年3月23日 zhaowg | ||
283 | */ | 195 | */ |
284 | -// public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback) { | ||
285 | -// Message<?> message = this.doConvert(payload, null, null); | ||
286 | -// asyncSendOrderly(destination, message, hashKey, sendCallback); | ||
287 | -// } | ||
288 | - | 196 | + public void asyncSend(String topic,String tag, Object payload,SendCallback sendCallback) { |
197 | + asyncSend(topic, tag,null, payload,sendCallback); | ||
198 | + } | ||
289 | /** | 199 | /** |
290 | - * Similar to <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP</a>, this method won't wait for | ||
291 | - * acknowledgement from broker before return. Obviously, it has maximums throughput yet potentials of message loss. | ||
292 | - * | ||
293 | - * One-way transmission is used for cases requiring moderate reliability, such as log collection. | ||
294 | - * | ||
295 | - * @param destination formats: `topicName:tags` | ||
296 | - * @param message {@link org.springframework.messaging.Message} | 200 | + * 服务器不应答,无法保证消息是否成功到达服务器 |
201 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
202 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
203 | + * @param key 业务主键 | ||
204 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
205 | + * @param userProperties 添加用户自定义属性键值对; 该键值对在消费消费时可被获取.也可用于做SQL属性过滤 | ||
206 | + * @param startDeliverTime 设置消息的定时投递时间(绝对时间),最大延迟时间为7天. | ||
207 | + * </p> | ||
208 | + * <ol> | ||
209 | + * <li>延迟投递: 延迟3s投递, 设置为: System.currentTimeMillis() + 3000;</li> | ||
210 | + * <li>定时投递: 2016-02-01 11:30:00投递, 设置为: new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-02-01 11:30:00").getTime()</li> | ||
211 | + * </ol> | ||
212 | + * 2018年3月23日 zhaowg | ||
297 | */ | 213 | */ |
298 | - public void sendOneWay(String destination, Message<?> message) { | ||
299 | - if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
300 | - log.info("sendOneWay failed. destination:{}, message is null ", destination); | ||
301 | - throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | 214 | + public void sendOneWay(String topic,String tag,String keys,Object payload,Map<String, String> userProperties, |
215 | + Long startDeliverTime) { | ||
216 | + if (Objects.isNull(topic) || Objects.isNull(payload)) { | ||
217 | + log.info("sendOneWay消息发送失败,主题和消息不能为空"); | ||
218 | + throw new IllegalArgumentException("sendOneWay消息发送失败,主题和消息不能为空"); | ||
302 | } | 219 | } |
303 | - | ||
304 | try { | 220 | try { |
305 | - if(aliyunProducer !=null){ | ||
306 | - //阿里云环境 | ||
307 | - com.aliyun.openservices.ons.api.Message aliyunMsg = convertToAliyunRocketMsg(destination, message); | ||
308 | - aliyunProducer.sendOneway(aliyunMsg); | ||
309 | - }else if(defaultProducer != null){ | ||
310 | - org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
311 | - defaultProducer.sendOneway(rocketMsg); | ||
312 | - }else{ | ||
313 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | ||
314 | - } | 221 | + long now = System.currentTimeMillis(); |
315 | 222 | ||
223 | + Message rocketMsg = new Message(environmentPrefix+"_"+topic, tag, keys, convertToRocketMsg(payload)); | ||
224 | + if(userProperties!=null && !userProperties.isEmpty()){ | ||
225 | + for (Entry<String, String> userProp : userProperties.entrySet()) { | ||
226 | + rocketMsg.putUserProperties(userProp.getKey(), userProp.getValue()); | ||
227 | + } | ||
228 | + } | ||
229 | + if(startDeliverTime!=null){ | ||
230 | + //设置定时发送时间 | ||
231 | + rocketMsg.setStartDeliverTime(startDeliverTime); | ||
232 | + } | ||
233 | + //阿里云发送 | ||
234 | + aliyunProducer.sendOneway(rocketMsg); | ||
235 | + long costTime = System.currentTimeMillis() - now; | ||
236 | + log.debug("发送消息耗时: {} ms", costTime); | ||
316 | } catch (Exception e) { | 237 | } catch (Exception e) { |
317 | - log.info("sendOneWay failed. destination:{}, message:{} ", destination, message); | 238 | + log.info("sendOneWay发送失败. topic:{}, message:{} ", topic, payload); |
318 | throw new MessagingException(e.getMessage(), e); | 239 | throw new MessagingException(e.getMessage(), e); |
319 | } | 240 | } |
320 | } | 241 | } |
321 | - | ||
322 | - /** | ||
323 | - * Same to {@link #sendOneWay(String, Message)} | ||
324 | - * | ||
325 | - * @param destination formats: `topicName:tags` | ||
326 | - * @param payload the Object to use as payload | 242 | + /** |
243 | + * Same to {@link #sendOneWay(String, String, String, Object, Map, Long)}. | ||
244 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
245 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
246 | + * @param key 业务主键 | ||
247 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
248 | + * 2018年3月23日 zhaowg | ||
327 | */ | 249 | */ |
328 | - public void sendOneWay(String destination, Object payload) { | ||
329 | - Message<?> message = this.doConvert(payload, null, null); | ||
330 | - sendOneWay(destination, message); | 250 | + public void sendOneWay(String topic,String tag,String keys, Object payload) { |
251 | + sendOneWay(topic, tag, keys, payload, null, null); | ||
331 | } | 252 | } |
332 | - | ||
333 | /** | 253 | /** |
334 | - * Same to {@link #sendOneWay(String, Message)} with send orderly with hashKey by specified. | ||
335 | - * | ||
336 | - * @param destination formats: `topicName:tags` | ||
337 | - * @param message {@link org.springframework.messaging.Message} | ||
338 | - * @param hashKey use this key to select queue. for example: orderId, productId ... | 254 | + * Same to {@link #sendOneWay(String, String, String, Object)}. |
255 | + * @param topic 消息主题, 最长不超过255个字符; 由a-z, A-Z, 0-9, 以及中划线"-"和下划线"_"构成. | ||
256 | + * @param tag 消息标签, 请使用合法标识符, 尽量简短且见名知意 | ||
257 | + * @param payload 消息体, 消息体长度默认不超过4M, 具体请参阅集群部署文档描述. | ||
258 | + * 2018年3月23日 zhaowg | ||
339 | */ | 259 | */ |
340 | -// public void sendOneWayOrderly(String destination, Message<?> message, String hashKey) { | ||
341 | -// if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { | ||
342 | -// log.info("sendOneWayOrderly failed. destination:{}, message is null ", destination); | ||
343 | -// throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); | ||
344 | -// } | ||
345 | -// | ||
346 | -// try { | ||
347 | -// //TODO zwg | ||
348 | -// throw new RuntimeException("暂时未整合阿里云Producer,不要使用"); | ||
349 | -// //org.apache.rocketmq.common.message.Message rocketMsg = convertToRocketMsg(destination, message); | ||
350 | -// //producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); | ||
351 | -// } catch (Exception e) { | ||
352 | -// log.info("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); | ||
353 | -// throw new MessagingException(e.getMessage(), e); | ||
354 | -// } | ||
355 | -// } | 260 | + public void sendOneWay(String topic,String tag, Object payload) { |
261 | + sendOneWay(topic, tag,null, payload); | ||
262 | + } | ||
356 | 263 | ||
357 | - /** | ||
358 | - * Same to {@link #sendOneWayOrderly(String, Message, String)} | ||
359 | - * | ||
360 | - * @param destination formats: `topicName:tags` | ||
361 | - * @param payload the Object to use as payload | ||
362 | - */ | ||
363 | -// public void sendOneWayOrderly(String destination, Object payload, String hashKey) { | ||
364 | -// Message<?> message = this.doConvert(payload, null, null); | ||
365 | -// sendOneWayOrderly(destination, message, hashKey); | ||
366 | -// } | ||
367 | - | ||
368 | @Override | 264 | @Override |
369 | public void afterPropertiesSet() throws Exception { | 265 | public void afterPropertiesSet() throws Exception { |
370 | if(aliyunProducer != null){ | 266 | if(aliyunProducer != null){ |
371 | - log.info("开始启动阿里云环境生产者"); | 267 | + log.info("开始启动阿里云[环境标识:"+environmentPrefix+"]生产者"); |
372 | aliyunProducer.start(); | 268 | aliyunProducer.start(); |
373 | - }else if(defaultProducer != null){ | ||
374 | - log.info("开始启动非阿里云环境生产者"); | ||
375 | - defaultProducer.start(); | ||
376 | - }else{ | ||
377 | - throw new RuntimeException("product为空,请检查配置文件是否配置:spring.rocketmq.aliyun,且值为true或false"); | ||
378 | } | 269 | } |
379 | } | 270 | } |
380 | 271 | ||
381 | - protected void doSend(String destination, Message<?> message) { | ||
382 | - SendResult sendResult = syncSend(destination, message); | ||
383 | - log.debug("send message to `{}` finished. result:{}", destination, sendResult); | ||
384 | - } | ||
385 | /** | 272 | /** |
386 | - * 转换阿里云返回对象 | ||
387 | - * @param aliyunSendResult | 273 | + * 转换对象为字节 |
274 | + * @param msgObj | ||
388 | * @return | 275 | * @return |
389 | * 2018年3月23日 zhaowg | 276 | * 2018年3月23日 zhaowg |
390 | */ | 277 | */ |
391 | - private SendResult convertAliyunSendResult(com.aliyun.openservices.ons.api.SendResult aliyunSendResult) { | ||
392 | - SendResult sendResult = new SendResult(); | ||
393 | - sendResult.setMsgId(aliyunSendResult.getMessageId()); | ||
394 | - MessageQueue messageQueue = new MessageQueue(aliyunSendResult.getTopic(), null, 0); | ||
395 | - sendResult.setMessageQueue(messageQueue); | ||
396 | - sendResult.setSendStatus(SendStatus.SEND_OK); | ||
397 | - return sendResult; | ||
398 | - } | ||
399 | - /** | ||
400 | - * 转换为阿里云发送的消息对象 | ||
401 | - * @param destination formats: `topicName:tags` | ||
402 | - * @param message {@link org.springframework.messaging.Message} | ||
403 | - * @return | ||
404 | - * 2018年3月23日 zhaowg | ||
405 | - */ | ||
406 | - private com.aliyun.openservices.ons.api.Message convertToAliyunRocketMsg(String destination, Message<?> message) { | ||
407 | - Object payloadObj = message.getPayload(); | ||
408 | - byte[] payloads; | ||
409 | - | ||
410 | - if (payloadObj instanceof String) { | ||
411 | - payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); | ||
412 | - } else { | ||
413 | - try { | ||
414 | - String jsonObj = this.objectMapper.writeValueAsString(payloadObj); | ||
415 | - payloads = jsonObj.getBytes(Charset.forName(charset)); | ||
416 | - } catch (Exception e) { | ||
417 | - throw new RuntimeException("convert to RocketMQ message failed.", e); | ||
418 | - } | ||
419 | - } | ||
420 | - | ||
421 | - String[] tempArr = destination.split(":", 2); | ||
422 | - String topic = tempArr[0]; | ||
423 | - String tags = ""; | ||
424 | - if (tempArr.length > 1) { | ||
425 | - tags = tempArr[1]; | ||
426 | - } | ||
427 | - | ||
428 | - com.aliyun.openservices.ons.api.Message rocketMsg = new com.aliyun.openservices.ons.api.Message(topic, tags, payloads); | ||
429 | - | ||
430 | - MessageHeaders headers = message.getHeaders(); | ||
431 | - if (Objects.nonNull(headers) && !headers.isEmpty()) { | ||
432 | - Object keys = headers.get(MessageConst.PROPERTY_KEYS); | ||
433 | - if (!StringUtils.isEmpty(keys)) { // if headers has 'KEYS', set rocketMQ message key | ||
434 | - rocketMsg.setKey(keys.toString()); | ||
435 | - } | ||
436 | - | ||
437 | - headers.entrySet().stream() | ||
438 | - .filter(entry -> !Objects.equals(entry.getKey(), MessageConst.PROPERTY_KEYS) | ||
439 | - && !Objects.equals(entry.getKey(), "FLAG") | ||
440 | - && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "KEYS", "FLAG", "WAIT_STORE_MSG_OK" | ||
441 | - .forEach(entry -> { | ||
442 | - rocketMsg.putUserProperties("USERS_" + entry.getKey(), String.valueOf(entry.getValue())); // add other properties with prefix "USERS_" | ||
443 | - }); | ||
444 | - | ||
445 | - } | ||
446 | - | ||
447 | - return rocketMsg; | ||
448 | - } | ||
449 | - /** | ||
450 | - * Convert spring message to rocketMQ message | ||
451 | - * | ||
452 | - * @param destination formats: `topicName:tags` | ||
453 | - * @param message {@link org.springframework.messaging.Message} | ||
454 | - * @return instance of {@link org.apache.rocketmq.common.message.Message} | ||
455 | - */ | ||
456 | - private org.apache.rocketmq.common.message.Message convertToRocketMsg(String destination, Message<?> message) { | ||
457 | - Object payloadObj = message.getPayload(); | 278 | + private byte[] convertToRocketMsg(Object msgObj) { |
458 | byte[] payloads; | 279 | byte[] payloads; |
459 | 280 | ||
460 | - if (payloadObj instanceof String) { | ||
461 | - payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); | 281 | + if (msgObj instanceof String) { |
282 | + payloads = ((String) msgObj).getBytes(Charset.forName(charset)); | ||
462 | } else { | 283 | } else { |
463 | try { | 284 | try { |
464 | - String jsonObj = this.objectMapper.writeValueAsString(payloadObj); | 285 | + String jsonObj = this.objectMapper.writeValueAsString(msgObj); |
465 | payloads = jsonObj.getBytes(Charset.forName(charset)); | 286 | payloads = jsonObj.getBytes(Charset.forName(charset)); |
466 | } catch (Exception e) { | 287 | } catch (Exception e) { |
467 | throw new RuntimeException("convert to RocketMQ message failed.", e); | 288 | throw new RuntimeException("convert to RocketMQ message failed.", e); |
468 | } | 289 | } |
469 | } | 290 | } |
470 | - | ||
471 | - String[] tempArr = destination.split(":", 2); | ||
472 | - String topic = tempArr[0]; | ||
473 | - String tags = ""; | ||
474 | - if (tempArr.length > 1) { | ||
475 | - tags = tempArr[1]; | ||
476 | - } | ||
477 | - | ||
478 | - org.apache.rocketmq.common.message.Message rocketMsg = new org.apache.rocketmq.common.message.Message(topic, tags, payloads); | ||
479 | - | ||
480 | - MessageHeaders headers = message.getHeaders(); | ||
481 | - if (Objects.nonNull(headers) && !headers.isEmpty()) { | ||
482 | - Object keys = headers.get(MessageConst.PROPERTY_KEYS); | ||
483 | - if (!StringUtils.isEmpty(keys)) { // if headers has 'KEYS', set rocketMQ message key | ||
484 | - rocketMsg.setKeys(keys.toString()); | ||
485 | - } | ||
486 | - | ||
487 | - // set rocketMQ message flag | ||
488 | - Object flagObj = headers.getOrDefault("FLAG", "0"); | ||
489 | - int flag = 0; | ||
490 | - try { | ||
491 | - flag = Integer.parseInt(flagObj.toString()); | ||
492 | - } catch (NumberFormatException e) { | ||
493 | - // ignore | ||
494 | - log.info("flag must be integer, flagObj:{}", flagObj); | ||
495 | - } | ||
496 | - rocketMsg.setFlag(flag); | ||
497 | - | ||
498 | - // set rocketMQ message waitStoreMsgOkObj | ||
499 | - Object waitStoreMsgOkObj = headers.getOrDefault("WAIT_STORE_MSG_OK", "true"); | ||
500 | - boolean waitStoreMsgOK = Boolean.TRUE.equals(waitStoreMsgOkObj); | ||
501 | - rocketMsg.setWaitStoreMsgOK(waitStoreMsgOK); | ||
502 | - | ||
503 | - headers.entrySet().stream() | ||
504 | - .filter(entry -> !Objects.equals(entry.getKey(), MessageConst.PROPERTY_KEYS) | ||
505 | - && !Objects.equals(entry.getKey(), "FLAG") | ||
506 | - && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "KEYS", "FLAG", "WAIT_STORE_MSG_OK" | ||
507 | - .forEach(entry -> { | ||
508 | - rocketMsg.putUserProperty("USERS_" + entry.getKey(), String.valueOf(entry.getValue())); // add other properties with prefix "USERS_" | ||
509 | - }); | ||
510 | - | ||
511 | - } | ||
512 | - | ||
513 | - return rocketMsg; | 291 | + return payloads; |
514 | } | 292 | } |
515 | 293 | ||
516 | - @Override | ||
517 | - protected Message<?> doConvert(Object payload, Map<String, Object> headers, MessagePostProcessor postProcessor) { | ||
518 | - String content; | ||
519 | - if (payload instanceof String) { | ||
520 | - content = (String) payload; | ||
521 | - } else { | ||
522 | - // if payload not as string, use objectMapper change it. | ||
523 | - try { | ||
524 | - content = objectMapper.writeValueAsString(payload); | ||
525 | - } catch (JsonProcessingException e) { | ||
526 | - log.info("convert payload to String failed. payload:{}", payload); | ||
527 | - throw new RuntimeException("convert to payload to String failed.", e); | ||
528 | - } | ||
529 | - } | ||
530 | - | ||
531 | - MessageBuilder<?> builder = MessageBuilder.withPayload(content); | ||
532 | - if (headers != null) { | ||
533 | - builder.copyHeaders(headers); | ||
534 | - } | ||
535 | - builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN); | ||
536 | - | ||
537 | - Message<?> message = builder.build(); | ||
538 | - if (postProcessor != null) { | ||
539 | - message = postProcessor.postProcessMessage(message); | ||
540 | - } | ||
541 | - return message; | ||
542 | - } | ||
543 | 294 | ||
544 | @Override | 295 | @Override |
545 | public void destroy() { | 296 | public void destroy() { |
546 | - if (Objects.nonNull(defaultProducer)) { | ||
547 | - defaultProducer.shutdown(); | ||
548 | - } | ||
549 | if(Objects.nonNull(aliyunProducer)){ | 297 | if(Objects.nonNull(aliyunProducer)){ |
298 | + log.info("开始关闭阿里云[环境标识:"+environmentPrefix+"]生产者"); | ||
550 | aliyunProducer.shutdown(); | 299 | aliyunProducer.shutdown(); |
551 | } | 300 | } |
552 | } | 301 | } |
src/main/java/org/apache/rocketmq/spring/starter/enums/ConsumeMode.java
@@ -19,12 +19,17 @@ package org.apache.rocketmq.spring.starter.enums; | @@ -19,12 +19,17 @@ package org.apache.rocketmq.spring.starter.enums; | ||
19 | 19 | ||
20 | public enum ConsumeMode { | 20 | public enum ConsumeMode { |
21 | /** | 21 | /** |
22 | - * receive asynchronously delivered messages concurrently | 22 | + * 同时接收异步发送的消息 |
23 | */ | 23 | */ |
24 | CONCURRENTLY, | 24 | CONCURRENTLY, |
25 | 25 | ||
26 | /** | 26 | /** |
27 | - * receive asynchronously delivered messages orderly. one queue, one thread | 27 | + * 顺序接收消息,一个队列,一个线程 |
28 | */ | 28 | */ |
29 | - ORDERLY | 29 | + ORDERLY, |
30 | + | ||
31 | + /** | ||
32 | + * 批量接收发送的消息,允许自定义范围为[1, 32], 实际消费数量可能小于该值 | ||
33 | + */ | ||
34 | + BATCH | ||
30 | } | 35 | } |
src/main/java/org/apache/rocketmq/spring/starter/enums/SelectorType.java
@@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
17 | 17 | ||
18 | package org.apache.rocketmq.spring.starter.enums; | 18 | package org.apache.rocketmq.spring.starter.enums; |
19 | 19 | ||
20 | -import org.apache.rocketmq.common.filter.ExpressionType; | 20 | +import com.aliyun.openservices.ons.api.ExpressionType; |
21 | 21 | ||
22 | public enum SelectorType { | 22 | public enum SelectorType { |
23 | 23 |
src/main/java/org/apache/rocketmq/spring/starter/utils/ExceptionUtil.java
0 → 100644
1 | +package org.apache.rocketmq.spring.starter.utils; | ||
2 | + | ||
3 | +import java.io.PrintWriter; | ||
4 | +import java.io.StringWriter; | ||
5 | + | ||
6 | +public class ExceptionUtil { | ||
7 | + | ||
8 | + public static String getTrace(Throwable t) { | ||
9 | + StringBuffer buffer = new StringBuffer(); | ||
10 | + if(t==null){ | ||
11 | + return ""; | ||
12 | + } | ||
13 | + StringWriter stringWriter = new StringWriter(); | ||
14 | + PrintWriter writer = new PrintWriter(stringWriter); | ||
15 | + t.printStackTrace(writer); | ||
16 | + //设置堆栈信息 | ||
17 | + buffer.append("堆栈信息为:" + stringWriter.getBuffer().toString()); | ||
18 | + return buffer.toString(); | ||
19 | + } | ||
20 | + | ||
21 | +} |
src/test/java/org/apache/rocketmq/spring/starter/RocketMQAutoConfigurationTests.java
1 | -/* | ||
2 | - * Licensed to the Apache Software Foundation (ASF) under one or more | ||
3 | - * contributor license agreements. See the NOTICE file distributed with | ||
4 | - * this work for additional information regarding copyright ownership. | ||
5 | - * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
6 | - * (the "License"); you may not use this file except in compliance with | ||
7 | - * the License. You may obtain a copy of the License at | ||
8 | - * | ||
9 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | - * | ||
11 | - * Unless required by applicable law or agreed to in writing, software | ||
12 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | - * See the License for the specific language governing permissions and | ||
15 | - * limitations under the License. | ||
16 | - */ | ||
17 | - | ||
18 | -package org.apache.rocketmq.spring.starter; | ||
19 | - | ||
20 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
21 | -import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | ||
22 | -import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
23 | -import org.apache.rocketmq.spring.starter.core.RocketMQListener; | ||
24 | -import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | ||
25 | -import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
26 | -import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
27 | -import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
28 | -import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
29 | -import org.junit.After; | ||
30 | -import org.junit.Test; | ||
31 | -import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
32 | -import org.springframework.boot.test.util.EnvironmentTestUtils; | ||
33 | -import org.springframework.context.annotation.AnnotationConfigApplicationContext; | ||
34 | - | ||
35 | -import static org.assertj.core.api.Assertions.assertThat; | ||
36 | - | ||
37 | -public class RocketMQAutoConfigurationTests { | ||
38 | - | ||
39 | - private static final String TEST_CONSUMER_GROUP = "my_consumer"; | ||
40 | - | ||
41 | - private static final String TEST_TOPIC = "test-topic"; | ||
42 | - | ||
43 | - private AnnotationConfigApplicationContext context; | ||
44 | - | ||
45 | - @Test | ||
46 | - public void rocketMQTemplate() { | ||
47 | - | ||
48 | - load("spring.rocketmq.nameServer=127.0.0.1:9876", | ||
49 | - "spring.rocketmq.producer.group=my_group", | ||
50 | - "spring.rocketmq.producer.send-msg-timeout=30000", | ||
51 | - "spring.rocketmq.producer.retry-times-when-send-async-failed=1", | ||
52 | - "spring.rocketmq.producer.compress-msg-body-over-howmuch=1024", | ||
53 | - "spring.rocketmq.producer.max-message-size=10240", | ||
54 | - "spring.rocketmq.producer.retry-another-broker-when-not-store-ok=true", | ||
55 | - "spring.rocketmq.producer.retry-times-when-send-failed=1"); | ||
56 | - | ||
57 | - assertThat(this.context.containsBean("rocketMQMessageObjectMapper")).isTrue(); | ||
58 | - assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
59 | - assertThat(this.context.containsBean("rocketMQTemplate")).isTrue(); | ||
60 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
61 | - | ||
62 | - RocketMQTemplate rocketMQTemplate = this.context.getBean(RocketMQTemplate.class); | ||
63 | - ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
64 | - assertThat(rocketMQTemplate.getObjectMapper()).isEqualTo(objectMapper); | ||
65 | - | ||
66 | - DefaultMQProducer defaultMQProducer = rocketMQTemplate.getProducer(); | ||
67 | - | ||
68 | - assertThat(defaultMQProducer.getNamesrvAddr()).isEqualTo("127.0.0.1:9876"); | ||
69 | - assertThat(defaultMQProducer.getProducerGroup()).isEqualTo("my_group"); | ||
70 | - assertThat(defaultMQProducer.getSendMsgTimeout()).isEqualTo(30000); | ||
71 | - assertThat(defaultMQProducer.getRetryTimesWhenSendAsyncFailed()).isEqualTo(1); | ||
72 | - assertThat(defaultMQProducer.getCompressMsgBodyOverHowmuch()).isEqualTo(1024); | ||
73 | - assertThat(defaultMQProducer.getMaxMessageSize()).isEqualTo(10240); | ||
74 | - assertThat(defaultMQProducer.isRetryAnotherBrokerWhenNotStoreOK()).isTrue(); | ||
75 | - assertThat(defaultMQProducer.getRetryTimesWhenSendFailed()).isEqualTo(1); | ||
76 | - } | ||
77 | - | ||
78 | - @Test | ||
79 | - public void enableProducer() { | ||
80 | - load(); | ||
81 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
82 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
83 | - closeContext(); | ||
84 | - | ||
85 | - load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
86 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
87 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
88 | - closeContext(); | ||
89 | - | ||
90 | - load("spring.rocketmq.producer.group=my_group"); | ||
91 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
92 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
93 | - closeContext(); | ||
94 | - | ||
95 | - load("spring.rocketmq.nameServer=127.0.0.1:9876", "spring.rocketmq.producer.group=my_group"); | ||
96 | - assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
97 | - assertThat(this.context.containsBean("rocketMQTemplate")).isEqualTo(true); | ||
98 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
99 | - } | ||
100 | - | ||
101 | - @Test | ||
102 | - public void enableConsumer() { | ||
103 | - load(); | ||
104 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
105 | - closeContext(); | ||
106 | - | ||
107 | - load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
108 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
109 | - closeContext(); | ||
110 | - | ||
111 | - load(false); | ||
112 | - this.context.registerBeanDefinition("myListener", | ||
113 | - BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
114 | - this.context.refresh(); | ||
115 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
116 | - closeContext(); | ||
117 | - | ||
118 | - load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
119 | - this.context.registerBeanDefinition("myListener", | ||
120 | - BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
121 | - this.context.refresh(); | ||
122 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
123 | - assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
124 | - assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
125 | - assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
126 | - | ||
127 | - } | ||
128 | - | ||
129 | - @Test | ||
130 | - public void listenerContainer() { | ||
131 | - load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
132 | - BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(MyListener.class); | ||
133 | - this.context.registerBeanDefinition("myListener", beanBuilder.getBeanDefinition()); | ||
134 | - this.context.refresh(); | ||
135 | - | ||
136 | - assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
137 | - assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
138 | - | ||
139 | - DefaultRocketMQListenerContainer listenerContainer = | ||
140 | - this.context.getBean(DefaultRocketMQListenerContainer.class.getName() + "_1", | ||
141 | - DefaultRocketMQListenerContainer.class); | ||
142 | - ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
143 | - assertThat(listenerContainer.getObjectMapper()).isEqualTo(objectMapper); | ||
144 | - assertThat(listenerContainer.getConsumeMode()).isEqualTo(ConsumeMode.CONCURRENTLY); | ||
145 | - assertThat(listenerContainer.getSelectorType()).isEqualTo(SelectorType.TAG); | ||
146 | - assertThat(listenerContainer.getSelectorExpress()).isEqualTo("*"); | ||
147 | - assertThat(listenerContainer.getConsumerGroup()).isEqualTo(TEST_CONSUMER_GROUP); | ||
148 | - assertThat(listenerContainer.getTopic()).isEqualTo(TEST_TOPIC); | ||
149 | - assertThat(listenerContainer.getNameServer()).isEqualTo("127.0.0.1:9876"); | ||
150 | - assertThat(listenerContainer.getMessageModel()).isEqualTo(MessageModel.CLUSTERING); | ||
151 | - assertThat(listenerContainer.getConsumeThreadMax()).isEqualTo(1); | ||
152 | - } | ||
153 | - | ||
154 | - @After | ||
155 | - public void closeContext() { | ||
156 | - if (this.context != null) { | ||
157 | - this.context.close(); | ||
158 | - } | ||
159 | - } | ||
160 | - | ||
161 | - @RocketMQMessageListener(consumerGroup = TEST_CONSUMER_GROUP, topic = TEST_TOPIC, consumeThreadMax = 1) | ||
162 | - private static class MyListener implements RocketMQListener<String> { | ||
163 | - | ||
164 | - @Override | ||
165 | - public void onMessage(String message) { | ||
166 | - System.out.println(message); | ||
167 | - } | ||
168 | - } | ||
169 | - | ||
170 | - private void load(boolean refresh, String... environment) { | ||
171 | - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
172 | - ctx.register(RocketMQAutoConfiguration.class); | ||
173 | - EnvironmentTestUtils.addEnvironment(ctx, environment); | ||
174 | - if (refresh) { | ||
175 | - ctx.refresh(); | ||
176 | - } | ||
177 | - this.context = ctx; | ||
178 | - } | ||
179 | - | ||
180 | - private void load(String... environment) { | ||
181 | - load(true, environment); | ||
182 | - } | ||
183 | -} | ||
184 | - | 1 | +///* |
2 | +// * Licensed to the Apache Software Foundation (ASF) under one or more | ||
3 | +// * contributor license agreements. See the NOTICE file distributed with | ||
4 | +// * this work for additional information regarding copyright ownership. | ||
5 | +// * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
6 | +// * (the "License"); you may not use this file except in compliance with | ||
7 | +// * the License. You may obtain a copy of the License at | ||
8 | +// * | ||
9 | +// * http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +// * | ||
11 | +// * Unless required by applicable law or agreed to in writing, software | ||
12 | +// * distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +// * See the License for the specific language governing permissions and | ||
15 | +// * limitations under the License. | ||
16 | +// */ | ||
17 | +// | ||
18 | +//package org.apache.rocketmq.spring.starter; | ||
19 | +// | ||
20 | +//import com.fasterxml.jackson.databind.ObjectMapper; | ||
21 | +//import org.apache.rocketmq.spring.starter.annotation.RocketMQMessageListener; | ||
22 | +//import org.apache.rocketmq.spring.starter.core.DefaultRocketMQListenerContainer; | ||
23 | +//import org.apache.rocketmq.spring.starter.core.RocketMQListener; | ||
24 | +//import org.apache.rocketmq.spring.starter.core.RocketMQTemplate; | ||
25 | +//import org.apache.rocketmq.spring.starter.enums.ConsumeMode; | ||
26 | +//import org.apache.rocketmq.spring.starter.enums.SelectorType; | ||
27 | +//import org.apache.rocketmq.client.producer.DefaultMQProducer; | ||
28 | +//import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; | ||
29 | +//import org.junit.After; | ||
30 | +//import org.junit.Test; | ||
31 | +//import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
32 | +//import org.springframework.boot.test.util.EnvironmentTestUtils; | ||
33 | +//import org.springframework.context.annotation.AnnotationConfigApplicationContext; | ||
34 | +// | ||
35 | +//import static org.assertj.core.api.Assertions.assertThat; | ||
36 | +// | ||
37 | +//public class RocketMQAutoConfigurationTests { | ||
38 | +// | ||
39 | +// private static final String TEST_CONSUMER_GROUP = "my_consumer"; | ||
40 | +// | ||
41 | +// private static final String TEST_TOPIC = "test-topic"; | ||
42 | +// | ||
43 | +// private AnnotationConfigApplicationContext context; | ||
44 | +// | ||
45 | +// @Test | ||
46 | +// public void rocketMQTemplate() { | ||
47 | +// | ||
48 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876", | ||
49 | +// "spring.rocketmq.producer.group=my_group", | ||
50 | +// "spring.rocketmq.producer.send-msg-timeout=30000", | ||
51 | +// "spring.rocketmq.producer.retry-times-when-send-async-failed=1", | ||
52 | +// "spring.rocketmq.producer.compress-msg-body-over-howmuch=1024", | ||
53 | +// "spring.rocketmq.producer.max-message-size=10240", | ||
54 | +// "spring.rocketmq.producer.retry-another-broker-when-not-store-ok=true", | ||
55 | +// "spring.rocketmq.producer.retry-times-when-send-failed=1"); | ||
56 | +// | ||
57 | +// assertThat(this.context.containsBean("rocketMQMessageObjectMapper")).isTrue(); | ||
58 | +// assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
59 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isTrue(); | ||
60 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
61 | +// | ||
62 | +// RocketMQTemplate rocketMQTemplate = this.context.getBean(RocketMQTemplate.class); | ||
63 | +// ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
64 | +// assertThat(rocketMQTemplate.getObjectMapper()).isEqualTo(objectMapper); | ||
65 | +// | ||
66 | +// DefaultMQProducer defaultMQProducer = rocketMQTemplate.getProducer(); | ||
67 | +// | ||
68 | +// assertThat(defaultMQProducer.getNamesrvAddr()).isEqualTo("127.0.0.1:9876"); | ||
69 | +// assertThat(defaultMQProducer.getProducerGroup()).isEqualTo("my_group"); | ||
70 | +// assertThat(defaultMQProducer.getSendMsgTimeout()).isEqualTo(30000); | ||
71 | +// assertThat(defaultMQProducer.getRetryTimesWhenSendAsyncFailed()).isEqualTo(1); | ||
72 | +// assertThat(defaultMQProducer.getCompressMsgBodyOverHowmuch()).isEqualTo(1024); | ||
73 | +// assertThat(defaultMQProducer.getMaxMessageSize()).isEqualTo(10240); | ||
74 | +// assertThat(defaultMQProducer.isRetryAnotherBrokerWhenNotStoreOK()).isTrue(); | ||
75 | +// assertThat(defaultMQProducer.getRetryTimesWhenSendFailed()).isEqualTo(1); | ||
76 | +// } | ||
77 | +// | ||
78 | +// @Test | ||
79 | +// public void enableProducer() { | ||
80 | +// load(); | ||
81 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
82 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
83 | +// closeContext(); | ||
84 | +// | ||
85 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
86 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
87 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
88 | +// closeContext(); | ||
89 | +// | ||
90 | +// load("spring.rocketmq.producer.group=my_group"); | ||
91 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
92 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
93 | +// closeContext(); | ||
94 | +// | ||
95 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876", "spring.rocketmq.producer.group=my_group"); | ||
96 | +// assertThat(this.context.containsBean("mqProducer")).isTrue(); | ||
97 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isEqualTo(true); | ||
98 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
99 | +// } | ||
100 | +// | ||
101 | +// @Test | ||
102 | +// public void enableConsumer() { | ||
103 | +// load(); | ||
104 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
105 | +// closeContext(); | ||
106 | +// | ||
107 | +// load("spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
108 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
109 | +// closeContext(); | ||
110 | +// | ||
111 | +// load(false); | ||
112 | +// this.context.registerBeanDefinition("myListener", | ||
113 | +// BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
114 | +// this.context.refresh(); | ||
115 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isEmpty(); | ||
116 | +// closeContext(); | ||
117 | +// | ||
118 | +// load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
119 | +// this.context.registerBeanDefinition("myListener", | ||
120 | +// BeanDefinitionBuilder.rootBeanDefinition(MyListener.class).getBeanDefinition()); | ||
121 | +// this.context.refresh(); | ||
122 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
123 | +// assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
124 | +// assertThat(this.context.containsBean("mqProducer")).isFalse(); | ||
125 | +// assertThat(this.context.containsBean("rocketMQTemplate")).isFalse(); | ||
126 | +// | ||
127 | +// } | ||
128 | +// | ||
129 | +// @Test | ||
130 | +// public void listenerContainer() { | ||
131 | +// load(false, "spring.rocketmq.nameServer=127.0.0.1:9876"); | ||
132 | +// BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder.rootBeanDefinition(MyListener.class); | ||
133 | +// this.context.registerBeanDefinition("myListener", beanBuilder.getBeanDefinition()); | ||
134 | +// this.context.refresh(); | ||
135 | +// | ||
136 | +// assertThat(this.context.getBeansOfType(DefaultRocketMQListenerContainer.class)).isNotEmpty(); | ||
137 | +// assertThat(this.context.containsBean(DefaultRocketMQListenerContainer.class.getName() + "_1")).isTrue(); | ||
138 | +// | ||
139 | +// DefaultRocketMQListenerContainer listenerContainer = | ||
140 | +// this.context.getBean(DefaultRocketMQListenerContainer.class.getName() + "_1", | ||
141 | +// DefaultRocketMQListenerContainer.class); | ||
142 | +// ObjectMapper objectMapper = this.context.getBean("rocketMQMessageObjectMapper", ObjectMapper.class); | ||
143 | +// assertThat(listenerContainer.getObjectMapper()).isEqualTo(objectMapper); | ||
144 | +// assertThat(listenerContainer.getConsumeMode()).isEqualTo(ConsumeMode.CONCURRENTLY); | ||
145 | +// assertThat(listenerContainer.getSelectorType()).isEqualTo(SelectorType.TAG); | ||
146 | +// assertThat(listenerContainer.getSelectorExpress()).isEqualTo("*"); | ||
147 | +// assertThat(listenerContainer.getConsumerGroup()).isEqualTo(TEST_CONSUMER_GROUP); | ||
148 | +// assertThat(listenerContainer.getTopic()).isEqualTo(TEST_TOPIC); | ||
149 | +// assertThat(listenerContainer.getNameServer()).isEqualTo("127.0.0.1:9876"); | ||
150 | +// assertThat(listenerContainer.getMessageModel()).isEqualTo(MessageModel.CLUSTERING); | ||
151 | +// assertThat(listenerContainer.getConsumeThreadMax()).isEqualTo(1); | ||
152 | +// } | ||
153 | +// | ||
154 | +// @After | ||
155 | +// public void closeContext() { | ||
156 | +// if (this.context != null) { | ||
157 | +// this.context.close(); | ||
158 | +// } | ||
159 | +// } | ||
160 | +// | ||
161 | +// @RocketMQMessageListener(consumerGroup = TEST_CONSUMER_GROUP, topic = TEST_TOPIC, consumeThreadMax = 1) | ||
162 | +// private static class MyListener implements RocketMQListener<String> { | ||
163 | +// | ||
164 | +// @Override | ||
165 | +// public void onMessage(String message) { | ||
166 | +// System.out.println(message); | ||
167 | +// } | ||
168 | +// } | ||
169 | +// | ||
170 | +// private void load(boolean refresh, String... environment) { | ||
171 | +// AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); | ||
172 | +// ctx.register(RocketMQAutoConfiguration.class); | ||
173 | +// EnvironmentTestUtils.addEnvironment(ctx, environment); | ||
174 | +// if (refresh) { | ||
175 | +// ctx.refresh(); | ||
176 | +// } | ||
177 | +// this.context = ctx; | ||
178 | +// } | ||
179 | +// | ||
180 | +// private void load(String... environment) { | ||
181 | +// load(true, environment); | ||
182 | +// } | ||
183 | +//} | ||
184 | +// |