20210422技术分享

技术分享

消息队列的使用

业务场景

需要实现文件导出功能,由于ribbon的接口时间限制,故采用异步的方式进行文件导出。

实现逻辑

接口的主流程不执行数据的操作,将数据的查询和封装操作进行异步处理(时间主要消耗在这一部分)。
rabbitmq实现方式,将数据导出操作的消息推送到队列,然后等待消息被消费即可。最终消费者异步进行数据导出操作,并将结果以邮件的形式发送给用户。

demo

生产者

配置ConnectFactory RabbitTemplate

 @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host,port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setPublisherConfirms(true);
        return connectionFactory;
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    //必须是prototype类型
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        return template;
    }

交换机的配置可以再配置文件中配置也可以手动在rabbitmq web控制台配置
生产者可以配置相应的回调,得注意rabbittemplate需要是原型模式

 public void sendMsg(String content) {
        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
        //把消息放入ROUTINGKEY_A对应的队列当中去,对应的是队列A
        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_A, RabbitmqConfig.ROUTINGKEY_A, content, correlationId);
    }

消费者

监听相应的队列即可@RabbitListener
同时在消费者方法中也可以进行手动确认(需要开启手动确认的配置不然报错)

    @RabbitListener(queues = RabbitmqConfig.QUEUE_A)
    public void customer(String msg) throws InterruptedException {
        log.info("消费的消息:{}",msg);
        log.info("开始数据处理。。。。。。。");
        Thread.sleep(5000);
        log.info("处理完毕");
        log.info("发送邮件");
    }

    @RabbitListener(queues = RabbitmqConfig.QUEUE_A)
    public void customerAck(String msg, Message message, Channel channel) throws IOException {
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
    }
   

参数校验

问题

一般在代码中存在大量的if判断来校验参数的合法性,增加代码复杂度同时又不利于阅读,其实可以通过注解的方式对字段进行校验。

使用

常用

@notEmpty 字段不能为null和空
@pattern 正则校验字符串

定义controller层的参数校验异常统一处理

@RestControllerAdvice
public class ControllerAdvice {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public List<ObjectError> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        // 从异常对象中拿到ObjectError对象
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        return allErrors ;

    }
}

java8中的流和lambda表达式

@Slf4j
public class StreamTest {
    @Test
    public void streamTest(){
        List<String> list = this.list();
        List<List<String>> lists = this.listFlat();
        log.info("所有元素处理前{}",list);
        List<String> collect = list.stream().map(
                e -> {
                    e = e + "1";
                    return e;
                }
        ).collect(Collectors.toList());
        log.info("所有元素处理后{}",collect);
        log.info("原有结构{}",lists);
        List<String> collect1 = lists.stream().flatMap(List::stream).collect(Collectors.toList());
        log.info("现有结构{}",collect1);
    }

    public List<String> list(){
        ArrayList<String> messageDtos = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            messageDtos.add(String.valueOf(i)) ;
        }
        return messageDtos ;
    }
    public List<List<String>> listFlat(){
        ArrayList<List<String>> lists = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            lists.add(this.list());

        }
        return lists ;
    }
}

optional.ofnullable().ifpresent()可以避免操作对象产生空指针的问题

上一篇:今年五一,你买到票了吗?


下一篇:maven将依赖打入jar包中