Java 在reactor Mono.defer调用上未更新时间戳

Java 在reactor Mono.defer调用上未更新时间戳,java,spring,spring-boot,reactive-programming,project-reactor,Java,Spring,Spring Boot,Reactive Programming,Project Reactor,我有一个服务,它提供数据库中所有当前股票符号的汇率列表。 调用非常简单,当调用服务的rates()方法时,将以以下类的形式给出一个随机速率: public class Rate { private final long timestamp = Instant.now().toEpochMilli(); private String symbol; private final double rate = (Math.random() * 100).toBigDecimal().setS

我有一个服务,它提供数据库中所有当前股票符号的汇率列表。 调用非常简单,当调用服务的
rates()
方法时,将以以下类的形式给出一个随机速率:

public class Rate {
  private final long timestamp = Instant.now().toEpochMilli();
  private String symbol;
  private final double rate = (Math.random() * 100).toBigDecimal().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

  // getters and setters
}
服务方法的实现是:

public Flux<Rate> rates() {
  return service.findAll();
}
公共流量率(){
return service.findAll();
}
我有一个反应式WebSocketHandler,看起来像这样:

@Service
public class MyHandler implements WebSocketHandler {

    private final ObjectMapper objectMapper;
    private final RateService service;
    private final ApplicationProperties applicationProperties;

    public MyHandler(ObjectMapper objectMapper, RateService service, ApplicationProperties applicationProperties) {
        this.objectMapper = objectMapper;
        this.service = service;
        this.applicationProperties = applicationProperties;
    }

    @Override
    public Mono<Void> handle(WebSocketSession session) {
        return session.send(
                Mono.defer(() -> service.rates().collectList())
                        .repeat()
                        .delayElements(Duration.ofSeconds(applicationProperties.getInterval()))
                        .map(value -> {
                            try {
                                return objectMapper.writeValueAsString(value);
                            } catch (JsonProcessingException e) {
                                return null;
                            }
                        })
                        .map(session::textMessage)
        );
    }
}
@服务
公共类MyHandler实现WebSocketHandler{
私有最终ObjectMapper ObjectMapper;
私人最终收费服务;
私有最终应用程序属性应用程序属性;
公共MyHandler(ObjectMapper ObjectMapper、RateService服务、ApplicationProperties ApplicationProperties){
this.objectMapper=objectMapper;
服务=服务;
this.applicationProperties=applicationProperties;
}
@凌驾
公共单声道句柄(WebSocketSession会话){
返回会话.send(
Mono.defer(()->service.rates().collectList())
.重复
.delayElements(持续时间.of秒(applicationProperties.getInterval())
.map(值->{
试一试{
返回objectMapper.writeValueAsString(值);
}捕获(JsonProcessingException e){
返回null;
}
})
.map(会话::文本消息)
);
}
}
当我通过客户端连接到WebSocket时,我每5秒就会得到一个速率列表,这很好。我唯一的问题是
timestamp
属性每5秒就有一个完全相同的时间戳。所以我通过WebSocket的第一个响应是这样的:
[{“timestamp”:“2018-10-08T09:52:51.387Z”,“symbol”:“GOOG”,“rate”:33.91}]
,第二个响应是
[{“timestamp”:“2018-10-08T09:52:51.387Z”,“symbol”:“GOOG”,“rate”:51.43}
。所以速率改变了,但时间戳没有改变


但是,我可以通过重写
rate
字段的getter来解决这个问题,但我不希望在该层中解决它。我只希望getter返回值而不进行任何操作。

几乎正确,为了理解,请运行下面的内容,有一些东西放错了位置,我建议您从查看使用
'Creating Rate'发出的时间戳开始。

在创建列表之前,重复、重复、重复,因此在将其发送到客户端之前创建并存储该列表,因此如果延迟创建过程而不是发送过程,则速率将每5秒创建一次并发出

public class MyHandler  {

    private final ObjectMapper objectMapper = new ObjectMapper();

    public Flux<String> handle() {
        return Mono.defer(() -> rates().delayElements(Duration.ofSeconds(5)).collectList())
                .repeat()
                .map(value -> {
                    try {
                        return objectMapper.writeValueAsString(value);
                    } catch (JsonProcessingException e) {
                        return null;
                    }
                });
    }

    private Flux<Rate> rates() {
        return Flux.just(new Rate("a"), new Rate("b"), new Rate("c"));
    }

    public static void main(String[] args) {
        new MyHandler().handle()
                .subscribe(str -> System.out.println(str + ", time now - " + Instant.now().toEpochMilli()));
        try {
            Thread.sleep(60_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static class Rate {
        private final long timestamp;
        private String symbol;
        private final double rate;

        public Rate(String symbol) {
            this.symbol = symbol;
            timestamp = Instant.now().toEpochMilli();
            rate  = new BigDecimal(Math.random() * 100).setScale(2, RoundingMode.HALF_UP).doubleValue();
            System.out.println("Creating Rate " + timestamp);
        }
        // getters and setters

        public long getTimestamp() {
            return timestamp;
        }
        public String getSymbol() {
            return symbol;
        }
        public void setSymbol(String symbol) {
            this.symbol = symbol;
        }
        public double getRate() {
            return rate;
        }
    }
}
公共类MyHandler{
私有最终ObjectMapper ObjectMapper=新ObjectMapper();
公共流量句柄(){
返回Mono.defer(()->rates().delayElements(持续时间为秒(5)).collectList())
.重复
.map(值->{
试一试{
返回objectMapper.writeValueAsString(值);
}捕获(JsonProcessingException e){
返回null;
}
});
}
私人流量率(){
收益流量。刚刚(新利率(“a”)、新利率(“b”)、新利率(“c”);
}
公共静态void main(字符串[]args){
新建MyHandler().handle()
.subscribe(str->System.out.println(str+”,time now-“+Instant.now().toEpochMilli());
试一试{
睡眠(60_000);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
静态课率{
私有最终长时间戳;
私有字符串符号;
私人最终双倍费率;
公共费率(字符串符号){
这个符号=符号;
timestamp=Instant.now().toEpochMilli();
rate=新的BigDecimal(Math.random()*100).setScale(2,舍入模式.HALF_UP).doubleValue();
System.out.println(“创建速率”+时间戳);
}
//接球手和接球手
公共长getTimestamp(){
返回时间戳;
}
公共字符串getSymbol(){
返回符号;
}
公共无效集合符号(字符串符号){
这个符号=符号;
}
公共双速率(){
回报率;
}
}
}

几乎正确,为了理解,请运行下面的内容,有一些东西放错了位置,我建议您从查看
'Creating Rate'
发出的时间戳开始

在创建列表之前,重复、重复、重复,因此在将其发送到客户端之前创建并存储该列表,因此如果延迟创建过程而不是发送过程,则速率将每5秒创建一次并发出

public class MyHandler  {

    private final ObjectMapper objectMapper = new ObjectMapper();

    public Flux<String> handle() {
        return Mono.defer(() -> rates().delayElements(Duration.ofSeconds(5)).collectList())
                .repeat()
                .map(value -> {
                    try {
                        return objectMapper.writeValueAsString(value);
                    } catch (JsonProcessingException e) {
                        return null;
                    }
                });
    }

    private Flux<Rate> rates() {
        return Flux.just(new Rate("a"), new Rate("b"), new Rate("c"));
    }

    public static void main(String[] args) {
        new MyHandler().handle()
                .subscribe(str -> System.out.println(str + ", time now - " + Instant.now().toEpochMilli()));
        try {
            Thread.sleep(60_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static class Rate {
        private final long timestamp;
        private String symbol;
        private final double rate;

        public Rate(String symbol) {
            this.symbol = symbol;
            timestamp = Instant.now().toEpochMilli();
            rate  = new BigDecimal(Math.random() * 100).setScale(2, RoundingMode.HALF_UP).doubleValue();
            System.out.println("Creating Rate " + timestamp);
        }
        // getters and setters

        public long getTimestamp() {
            return timestamp;
        }
        public String getSymbol() {
            return symbol;
        }
        public void setSymbol(String symbol) {
            this.symbol = symbol;
        }
        public double getRate() {
            return rate;
        }
    }
}
公共类MyHandler{
私有最终ObjectMapper ObjectMapper=新ObjectMapper();
公共流量句柄(){
返回Mono.defer(()->rates().delayElements(持续时间为秒(5)).collectList())
.重复
.map(值->{
试一试{
返回objectMapper.writeValueAsString(值);
}捕获(JsonProcessingException e){
返回null;
}
});
}
私人流量率(){
收益流量。刚刚(新利率(“a”)、新利率(“b”)、新利率(“c”);
}
公共静态void main(字符串[]args){
新建MyHandler().handle()
.subscribe(str->System.out.println(str+”,time now-“+Instant.now().toEpochMilli());
试一试{
睡眠(60_000);
}捕捉(中断异常e){
e、 printStackTrace();