当前位置: 首页 > 知识库问答 >
问题:

为什么RESTendpoint会被访问两次,第二次访问是否可以消除?

孟翰藻
2023-03-14

代码“起作用”,因为它返回预期的信息(DemoPOJO对象列表)。但是,如下所示的控制台输出所示,正在对localhost上的REST服务进行两次调用:8080/v2/demopojo。我有一种感觉,第二次调用是对反应编程缺乏了解的结果,但我不知道第二次调用是在这个REST API上进行的,我想消除它,因为当部署“实际的东西”时,冗余很可能是一个性能问题。

在提供的代码中,在localhost:8080/v3/democlient(在DemoClientHandler中实现)上进行调用,然后使用WebClient对象访问localhost:8080/v2/demopojo(在DemoPOJOHandler中实现)上的相应REST服务。

(我已经将代码简化为仅与RESTendpoint/v3/democlient相关联的语句)

2019-09-26 12:30:23.389  INFO 4260 --- [           main] com.test.demo.DemoApplication            : Starting DemoApplication on M7730-LFR with PID 4260 (D:\sandbox\DemoReactive\build\classes\java\main started by LesR in D:\sandbox\DemoReactive)
2019-09-26 12:30:23.391  INFO 4260 --- [           main] com.test.demo.DemoApplication            : No active profile set, falling back to default profiles: default
2019-09-26 12:30:24.570  INFO 4260 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2019-09-26 12:30:24.573  INFO 4260 --- [           main] com.test.demo.DemoApplication            : Started DemoApplication in 1.41 seconds (JVM running for 1.975)
2019-09-26 12:30:28.796  INFO 4260 --- [ctor-http-nio-3] m.n.d.accesslogger.ServiceRequestLogger  : 
    *****  Begin, Access Request Log
    Service request    -> GET @ http://localhost:8080/v3/DemoClient
    Service handled by -> com.test.demo.democlient.DemoClientHandler.getAll()
    *****  End, Access Request Log
2019-09-26 12:30:28.823  INFO 4260 --- [ctor-http-nio-8] m.n.d.accesslogger.ServiceRequestLogger  : 
    *****  Begin, Access Request Log
    Service request    -> GET @ http://localhost:8080/v2/DemoPOJO
    Service handled by -> com.test.demo.demopojo.DemoPOJOHandler.getAll()
    *****  End, Access Request Log
2019-09-26 12:30:28.911  INFO 4260 --- [ctor-http-nio-9] m.n.d.accesslogger.ServiceRequestLogger  : 
    *****  Begin, Access Request Log
    Service request    -> GET @ http://localhost:8080/v2/DemoPOJO
    Service handled by -> com.test.demo.demopojo.DemoPOJOHandler.getAll()
    *****  End, Access Request Log
@Component
public class DemoClientHandler {

    public static final String PATH_VAR_ID = "id";

    @Autowired
    ServiceRequestLogger svcRequestLogger;

    @Autowired
    DemoClient demoClient;

    public Mono<ServerResponse> getAll(ServerRequest request) {
        Flux<DemoPOJO> fluxDemoPOJO = demoClient.getAll();

        svcRequestLogger.logServiceRequest(this.getClass(), "getAll()", request);

        return fluxDemoPOJO.hasElements().flatMap(hasElement -> {
            return hasElement ? ServerResponse.ok()
                                              .contentType(MediaType.APPLICATION_JSON)
                                              .body(fluxDemoPOJO, DemoPOJO.class)
                              : ServerResponse.noContent().build();
        });
    }
}

使用WebClient访问“第一级”REST API...

@Component
public class DemoClient {

    private final WebClient client;

    public DemoClient() {
        client = WebClient.create();
    }

    public Flux<DemoPOJO> getAll() {
        return client.get().uri("http://localhost:8080/v2/DemoPOJO")
                           .accept(MediaType.APPLICATION_JSON)
                           .exchange()
                           .flatMapMany(response -> response.bodyToFlux(DemoPOJO.class));
    }
)

“一级”处理程序...

@Component
public class DemoPOJOHandler {

    @Autowired
    private ServiceRequestLogger svcRequestLogger;

    @Autowired
    private DemoPOJOService service;

    public Mono<ServerResponse> getAll(ServerRequest request) {
        Flux<DemoPOJO> fluxDemoPOJO = service.getAll();

        svcRequestLogger.logServiceRequest(this.getClass(), "getAll()", request);

        return fluxDemoPOJO.hasElements().flatMap(hasElement -> {
            return hasElement ? ServerResponse.ok()
                                              .contentType(MediaType.APPLICATION_JSON)
                                              .body(fluxDemoPOJO, DemoPOJO.class)
                              : ServerResponse.noContent().build();
        });
    }
}

用于第二级(WebClient)REST API的路由器...

@Configuration
public class DemoClientRouter {

    @Bean
    public RouterFunction<ServerResponse> clientRoutes(DemoClientHandler requestHandler) {
        return nest(path("/v3"),
                nest(accept(APPLICATION_JSON),
                        RouterFunctions.route(RequestPredicates.GET("/DemoClient"), requestHandler::getAll)));
    }
}
@Configuration
public class DemoPOJORouter {

    @Bean
    public RouterFunction<ServerResponse> demoPOJORoute(DemoPOJOHandler requestHandler) {
        return nest(path("/v2"),
                nest(accept(APPLICATION_JSON),
                        RouterFunctions.route(RequestPredicates.GET("/DemoPOJO"), requestHandler::getAll)));
    }
}
@Component
public class DemoPOJOService {

    @Autowired
    private DemoPOJORepo demoPOJORepo;

    public Flux<DemoPOJO> getAll() {
        return Flux.fromArray(demoPOJORepo.getAll());
    }
}
@Component
public class DemoPOJORepo {

    private static final int NUM_OBJS = 5;

    private static DemoPOJORepo demoRepo = null;

    private Map<Integer, DemoPOJO> demoPOJOMap;

    private DemoPOJORepo() {
        initMap();
    }

    public static DemoPOJORepo getInstance() {
        if (demoRepo == null) {
            demoRepo = new DemoPOJORepo();
        }
        return demoRepo;
    }

    public DemoPOJO[] getAll() {
        return demoPOJOMap.values().toArray(new DemoPOJO[demoPOJOMap.size()]);
    }

    private void initMap() {
        demoPOJOMap = new TreeMap<Integer, DemoPOJO>();

        for (int ndx = 1; ndx < (NUM_OBJS + 1); ndx++) {
            demoPOJOMap.put(ndx, new DemoPOJO(ndx, "foo_" + ndx, ndx + 100));
        }
    }
}

日志(SLF4J/(logback*)客户端对应用程序日志的REST服务访问...

@Component
public class ServiceRequestLogger {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    public void logServiceRequest(Class serviceHandler, String serviceMethod, ServerRequest request) {
        logger.info(buildLogMessage(serviceHandler, serviceMethod, request));
    }

    private String buildLogMessage(Class serviceHandler, String serviceMethod, ServerRequest request) {
        StringBuilder logMessage = new StringBuilder();

        /* <housekeeping code to build message to log */
        return logMessage.toString();
    }
}

暂时还没有答案

 类似资料:
  • 这是第二次尝试,通过修改的演示代码,希望能更好地说明这个问题。代码已经被剥离,除去了所有的元素,除了那些演示正在遇到的问题的元素。 添加注意:一些额外的测试做了,结果张贴作为一个答案(副扩展这篇文章)。这可能是“预期的行为”,但我仍在努力理解“为什么”。 代码“起作用”,因为它返回预期的信息(字符串或字符串列表)。但是,当使用WebClient访问返回流量的RESTendpoint(localho

  • 本文向大家介绍请问tcp握手为什么两次不可以?为什么不用四次?相关面试题,主要包含被问及请问tcp握手为什么两次不可以?为什么不用四次?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 两次不可以:tcp是全双工通信,两次握手只能确定单向数据链路是可以通信的,并不能保证反向的通信正常 不用四次: 本来握手应该和挥手一样都是需要确认两个方向都能联通的,本来模型应该是: 1.客户端发送syn0给

  • 本小节会创建我们的第一个 Django 工程以及第一个应用,接下来的所有示例将会在这个工程基础上进行演示。 1. 创建第一个Django应用程序 在创建第一个 Django 应用程序之前,我们需要使用 pyenv 工具创建相应的虚拟环境,操作如下: 新建一个统一的目录,用于存放 Django 工程代码: [root@server ~]# mkdir django-manual [root@serv

  • 我写简单的脚本使用诱变库,其中计数文件夹中的音频文件量和文件夹的整个音频播放时间(包括子文件夹的音频文件)。 经过一些测试,我发现我的脚本访问了一些文件夹两次。通常这些目录是另一个子文件夹中的子文件夹。结果它打印了这样的结果: 但实际上,如果将所有音频曲目移动到一个文件夹中,并在该测试文件夹上运行脚本,则会显示不同的结果: 实际上,测试文件夹中的音频曲目数量是885。我用命令检查了它,那么为什么o

  • 问题内容: 是否有一个(独立的!)Java API,它将XML- RPC接口包装到bugzilla?我不想为此编写自己的api,而且我实际上找不到能够做到这一点(而且只能做到这一点)的库。 更新: 我正在寻找 只用Java编写的类似http://oss.dbc.dk/bugzproxy/的东西 问题答案: 我知道这是一个有点老的话题,但是有相同问题的人很可能会在这里落下来。我想分享一篇博客文章,我

  • 问题内容: 我有一个简单的AJAX表单,该表单可以在提交时正常运行。但是,如果我随后将新数据输入相同的表单(而不刷新页面),则它将提交两次表单。如果我第三次这样做,那么它将第三次提交表单,依此类推。为什么这样做呢?这是我的代码: 问题答案: 即使我在开发AJAX登录表单时也遇到了同样的问题。搜寻了几个小时后,我找到了解决方案。希望这对您有所帮助。 基本上,您必须在ajax请求完成后 取消绑定 表单