Spring WebFlux简单应用程序无法使用JSON响应[已关闭]

问题描述 投票:0回答:1

我有一个简单的 Spring Web 应用程序,我尝试返回 JSON 作为响应,但我不知道为什么以及如何返回 JSON 输出。我在这里做错了什么?

package com.restservice.restservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RestserviceApplication {

    public static void main(String[] args) {

        SpringApplication.run(RestserviceApplication.class, args);
    }

}


package com.restservice.restservice;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import javax.print.attribute.standard.Media;
import java.time.Duration;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function;

import static java.time.LocalTime.now;

@RestController
public class MainController {

    @GetMapping(value = "/stocks/{symbol}" ,produces = MediaType.TEXT_EVENT_STREAM_VALUE)
   public Flux prices(@PathVariable("symbol") String symbol) {

    return Flux.interval(Duration.ofSeconds(2))
            .map(stockprice -> new StockPrice(symbol, getRandomStockPrice(),now()));
}


    private static Double getRandomStockPrice() {
       return  ThreadLocalRandom.current().nextDouble(100.0);
    }
}



package com.restservice.restservice;

import java.time.LocalTime;


public class StockPrice {

String symbol;
double randomStockPrice;
LocalTime now;


public StockPrice() {
}


public StockPrice(String symbol, double randomStockPrice, LocalTime now) {
    this.symbol = symbol;
    this.randomStockPrice = randomStockPrice;
    this.now = now;
}
}

如何将 StockPrice 字符串符号、双随机StockPrice、LocalTime 以格式化 json 的形式打印到网络上?

更新

我修复了 StockPrice 和 MainController 类,但现在我收到此错误:

2024-02-02T13:12:40.219+02:00  INFO 25088 --- [           main] c.r.restservice.RestserviceApplication   : Starting RestserviceApplication using Java 17.0.9 with PID 25088 (C:\dev\my\java\spring_applications\ReactiveSpringBootREST Service2\restservice\target\classes started by meir.yanovich in C:\dev\my\java\spring_applications\ReactiveSpringBootREST Service2\restservice)
2024-02-02T13:12:40.229+02:00  INFO 25088 --- [           main] c.r.restservice.RestserviceApplication   : No active profile set, falling back to 1 default profile: "default"
2024-02-02T13:12:44.473+02:00  INFO 25088 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8002
2024-02-02T13:12:44.490+02:00  INFO 25088 --- [           main] c.r.restservice.RestserviceApplication   : Started RestserviceApplication in 5.178 seconds (process running for 6.052)
2024-02-02T13:12:47.819+02:00 ERROR 25088 --- [ctor-http-nio-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [036f67d2-1] Error [org.springframework.core.codec.CodecException: Type definition error: [simple type, class com.restservice.restservice.StockPrice]] for HTTP GET "/stocks/1", but ServerHttpResponse already committed (200 OK)
2024-02-02T13:12:47.820+02:00 ERROR 25088 --- [ctor-http-nio-2] r.n.http.server.HttpServerOperations     : [036f67d2-1, L:/[0:0:0:0:0:0:0:1]:8002 - R:/[0:0:0:0:0:0:0:1]:58573] Error finishing response. Closing connection

    org.springframework.core.codec.CodecException: Type definition error: [simple type, class com.restservice.restservice.StockPrice]
        at org.springframework.http.codec.json.AbstractJackson2Encoder.encodeValue(AbstractJackson2Encoder.java:256) ~[spring-web-6.1.3.jar:6.1.3]
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
    Error has been observed at the following site(s):
        *__checkpoint ⇢ Handler com.restservice.restservice.MainController#prices(String) [DispatcherHandler]
        *__checkpoint ⇢ HTTP GET "/stocks/1" [ExceptionHandlingWebHandler]
    Original Stack Trace:
            at org.springframework.http.codec.json.AbstractJackson2Encoder.encodeValue(AbstractJackson2Encoder.java:256) ~[spring-web-6.1.3.jar:6.1.3]
            at org.springframework.http.codec.ServerSentEventHttpMessageWriter.lambda$encodeEvent$1(ServerSentEventHttpMessageWriter.java:176) ~[spring-web-6.1.3.jar:6.1.3]
            at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:46) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.Flux.subscribe(Flux.java:8777) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:260) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:79) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.Flux.subscribe(Flux.java:8777) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:452) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:251) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[reactor-core-3.6.2.jar:3.6.2]
            at org.springframework.http.server.reactive.ChannelSendOperator$WriteBarrier.emitCachedSignals(ChannelSendOperator.java:312) ~[spring-web-6.1.3.jar:6.1.3]
            at org.springframework.http.server.reactive.ChannelSendOperator$WriteBarrier.request(ChannelSendOperator.java:283) ~[spring-web-6.1.3.jar:6.1.3]
            at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:164) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:236) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:92) ~[reactor-core-3.6.2.jar:3.6.2]
            at org.springframework.http.server.reactive.ChannelSendOperator$WriteBarrier.subscribe(ChannelSendOperator.java:358) ~[spring-web-6.1.3.jar:6.1.3]
            at reactor.core.publisher.FluxSource.subscribe(FluxSource.java:71) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.Flux.subscribe(Flux.java:8777) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.netty.channel.MonoSendMany.subscribe(MonoSendMany.java:102) ~[reactor-netty-core-1.1.15.jar:1.1.15]
            at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:241) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:204) ~[reactor-core-3.6.2.jar:3.6.2]
            at reactor.netty.FutureMono$FutureSubscription.operationComplete(FutureMono.java:196) ~[reactor-netty-core-1.1.15.jar:1.1.15]
            at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:583) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:559) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:636) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:625) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:105) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.internal.PromiseNotificationUtil.trySuccess(PromiseNotificationUtil.java:48) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.ChannelOutboundBuffer.safeSuccess(ChannelOutboundBuffer.java:726) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.ChannelOutboundBuffer.remove(ChannelOutboundBuffer.java:281) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.ChannelOutboundBuffer.removeBytes(ChannelOutboundBuffer.java:361) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.socket.nio.NioSocketChannel.doWrite(NioSocketChannel.java:421) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:931) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.flush0(AbstractNioChannel.java:355) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:895) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.DefaultChannelPipeline$HeadContext.flush(DefaultChannelPipeline.java:1372) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:935) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:921) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:907) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.flush(CombinedChannelDuplexHandler.java:531) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.ChannelOutboundHandlerAdapter.flush(ChannelOutboundHandlerAdapter.java:125) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.CombinedChannelDuplexHandler.flush(CombinedChannelDuplexHandler.java:356) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:937) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:921) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:907) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.ChannelDuplexHandler.flush(ChannelDuplexHandler.java:127) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:937) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:957) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.AbstractChannelHandlerContext$WriteTask.run(AbstractChannelHandlerContext.java:1263) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569) ~[netty-transport-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.105.Final.jar:4.1.105.Final]
            at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]
    Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.restservice.restservice.StockPrice and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
        at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1308) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:414) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:53) ~[jackson-databind-2.15.3.jar:2.15.3]
        at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:30) ~[jackson-databind-2.15.3.jar:2.15.3]
java json spring-boot spring-webflux
1个回答
2
投票

您刚刚调用了构造。你必须吸收构造函数中传入的值。您必须在

randomStockPrice
类内创建一个变量符号
StockPrice
。然后你需要将构造函数中的值设置为等于它们

像这样:

public class StockPrice {
    String symbol;
    double randomStockPrice;
    LocalTime now;

    public StockPrice() {
    }


    public StockPrice(String symbol, double randomStockPrice, LocalTime now) {
        this.symbol = symbol;
        this.randomStockPrice = randomStockPrice;
        this.now = now;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.