Some important maven dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.43.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
netty server:
@Component
@Order(value = 0)
@Async
public class UdpServer implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(UdpServer.class);
@Value("${udp.port:8896}")
private int udpPort;
@Autowired
UdpServerHandler udpServerHandler;
private EventLoopGroup eventLoopGroup;
@Override
public void run(String... args) {
eventLoopGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.option(ChannelOption.SO_REUSEADDR,true)
.handler(udpServerHandler);
logger.info("udp server start udp port: ",udpPort);
ChannelFuture cf2 = bootstrap.bind(udpPort).sync();
cf2.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}
}
@PreDestroy
public void closeUdp(){
logger.info("udp server closed");
eventLoopGroup.shutdownGracefully();
}
}
UdpServerHandler:
@Component
@SuppressWarnings("all")
public class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private Logger logger = LoggerFactory.getLogger(UdpServerHandler.class);
@Autowired
UdpService udpService;
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
try {
Channel channel = ctx.channel();
SocketAddress socketAddress = channel.remoteAddress();
if (socketAddress != null){
String channelKey = socketAddress.toString();
logger.info("channel :{} connected", channelKey);
}
}catch (Exception e){
e.printStackTrace();
}
super.channelActive(ctx);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket datagramPacket) {
try {
String sender = datagramPacket.sender().toString();
logger.info(sender);
}catch (Exception e){
e.printStackTrace();
}
try {
udpService.solveData(ctx, datagramPacket);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String channelKey = ctx.channel().remoteAddress().toString();
logger.info("channel :{} closed", channelKey);
super.channelInactive(ctx);
}
}
Rabbitmq config:
@Configuration
public class RabbitConfig {
@Value("${spring.rabbitmq.host}")
private String host;
@Value("${spring.rabbitmq.port}")
private int port;
@Value("${spring.rabbitmq.username}")
private String username;
@Value("${spring.rabbitmq.password}")
private String password;
@Value("${spring.rabbitmq.virtual-host}")
private String virtualHost;
@Autowired
DownlinkUdpConfig downlinkUdpConfig;
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host, port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
return connectionFactory;
}
@Bean
@Primary
@Scope("prototype")
Encoder multipartFormEncoder() {
return new SpringFormEncoder();
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(connectionFactory());
}
@Bean
public Queue DownlinkQueue() {
Map<String, Object> arguments=new HashMap<>(3);
arguments.put("x-dead-letter-exchange", downlinkUdpConfig.getDeadExchange());
arguments.put("x-dead-letter-routing-key", downlinkUdpConfig.getDeadRoutingKey());
arguments.put("x-message-ttl",downlinkUdpConfig.getxMessageTtl());
return new Queue(downlinkUdpConfig.getQueue(), true,false,false,arguments);
}
@Bean
public DirectExchange DownlinkExchange() {
return new DirectExchange(downlinkUdpConfig.getExchange());
}
@Bean
public Binding bindingDownlinkQueue() {
return BindingBuilder.bind(DownlinkQueue()).to(DownlinkExchange()).with(downlinkUdpConfig.getRoutingKey());
}
@Bean
public Queue DownlinkDeadQueue(){
return new Queue(downlinkUdpConfig.getDeadQueue(),true);
}
@Bean
public DirectExchange DownlinkDeadExchange(){
return new DirectExchange(downlinkUdpConfig.getDeadExchange(),true,false);
}
@Bean
public Binding bindingDownlinkDead(){
return BindingBuilder.bind(DownlinkDeadQueue()).to(DownlinkDeadExchange()).with(downlinkUdpConfig.getDeadRoutingKey());
}
}
DownlinkUdpListener:
@Component
public class DownlinkUdpListener {
Logger logger = LoggerFactory.getLogger(this.getClass());
@RabbitListener(queues = "downlink_udp_queue")
public void process(Channel channel, Message message) {
//1.get message from rabbitMq
String rabbitMessage = new String(message.getBody());
logger.info("get result from rabbitMq is:{}", rabbitMessage);
//1.1 ack get message
try {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (IOException e) {
logger.info("ack error, message is:{}", rabbitMessage);
}
}
}
The problem now is that I have no consumers in the downlink_udp_queue queue on the rabbitmq management interface. I suspect that the SimpleChannelInboundHandler of UdpServerHandler causes @RabbitListener to not take effect.