无需上网即可调用Spring控制器方法

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

tldr:有没有办法在不上网的情况下发出内部请求(使用方法的路径)?

--

我为什么需要它?我有一个接收很多活动的项目。谁将处理每个事件的决定由财务主任做出。所以我有类似的东西:

@RestController
@RequestMapping("/events")
public class EventHandlerAPI {

    @Autowired 
    private EventAHandler eventAhandler;
    @Autowired 
    private EventBHandler eventBhandler;

    @PostMapping("/a")
    public void handleEventA(@RequestBody EventA event) {
       eventAhandler.handle(id, event);
    }

    @PostMapping("/b")
    public void handleEventB(@RequestBody EventB event) {
       eventBhandler.handle(id, event);
    }

}

我们最近添加了通过队列服务接收事件的支持。它向我们发送有效载荷和事件类。我们的决定是让两个接口都工作(休息和队列)。避免代码重复的解决方案是让Controller选择哪个处理程序来处理事件。现在的代码与此类似:

@Configuration
public class EventHandlerQueueConsumer {

    @Autowired 
    private EventHandlerAPI eventHandlerAPI;

    private Map<Class, EventHandler> eventHandlers;

    @PostConstruct 
    public void init() { 
        /* start listen queue */ 
        declareEventHandlers();
    }

    private void declareEventHandlers() {
        eventHandlers = new HashMap<>();
        eventHandlers.put(EventAHandler.class, (EventHandler<EventAHandler>) eventHandlerAPI::handleEventA);
        eventHandlers.put(EventBHandler.class, (EventHandler<EventBHandler>) eventHandlerAPI::handleEventB);
    }

   private void onEventReceived(AbstractEvent event) {
       EventHandler eventHandler = eventHandlers.get(event.getClass());
       eventHandler.handle(event);
   }

    private interface EventHandler<T extends AbstractEvent> {
        void handle(T event);
    }

}

此代码有效,但它不会让控制器选择谁来处理事件(我们的意图)。该决定实际上是由地图决定的。

我想做的是通过它的请求映射来调用控制器方法,而无需访问互联网。像这样的东西:

@Configuration
public class EventHandlerQueueConsumer {

    // MADE UP CLASS TO SHOW WHAT I WANT
    @Autowired
    private ControllerInkover controllerInvoker;

    @PostConstruct 
    public void init() { /* start listen queue */ }

   private void onEventReceived(AbstractEvent event) {
       controllerInvoker.post(event.getPath(), new Object[] { event });
   }

}

这种方式更清晰,让控制器做出所有决定。

我研究了很多,但没有找到实现它的方法。调试spring,我发现他如何在DispatcherServlet之后路由请求,但所有spring内部使用HttpServletRequestHttpServletResponse :(

有没有办法在不上网的情况下发出内部请求(使用方法的路径)?

java spring spring-restcontroller
1个回答
2
投票

它们是同一应用程序的类

那应该很容易。

1)您可以使用http(s)://localhost:{port}/api/{path}实用程序类在RestTemplate上调用自己的API。这是首选方式,因为您将遵循标准MVC模式。就像是:

restTemplate.exchange(uri, HttpMethod.POST, httpEntity, ResponseClass.class);

2)如果你根本不想调用网络连接,那么你可以使用Spring的内部来查找映射/方法映射,或者在控制器启动时使用一些反射来构建自定义映射。然后,您可以按照模型类中显示的方式将事件/对象传递给地图中的方法。就像是:

@RequestMapping("foo")
 public void fooMethod() {
    System.out.println("mapping = " + getMapping("fooMethod")); // you can get all methods/mapping in @PostContruct initialization phase
 }

 private String getMapping(String methodName) {
    Method methods[] = this.getClass().getMethods();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName() == methodName) {
            String mapping[] = methods[i].getAnnotation(RequestMapping.class).value();
            if (mapping.length > 0) {
                return mapping[mapping.length - 1];
            }
        }
    }
    return null;
}
© www.soinside.com 2019 - 2024. All rights reserved.