Java 在不访问internet的情况下调用Spring控制器方法
tldr:有没有一种方法可以在不上网的情况下发出内部请求(使用方法的路径) -- 为什么我需要它?我有一个项目,收到了许多事件。由一名控制员决定由谁来处理每一事件。所以我有类似的东西:Java 在不访问internet的情况下调用Spring控制器方法,java,spring,spring-restcontroller,Java,Spring,Spring Restcontroller,tldr:有没有一种方法可以在不上网的情况下发出内部请求(使用方法的路径) -- 为什么我需要它?我有一个项目,收到了许多事件。由一名控制员决定由谁来处理每一事件。所以我有类似的东西: @RestController @请求映射(“/events”) 公共类EventHandlerAPI{ @自动连线 私人事件处理程序事件处理程序; @自动连线 私人EventBHandler EventBHandler; @邮戳(“/a”) public void handleEventA(@RequestBo
@RestController
@请求映射(“/events”)
公共类EventHandlerAPI{
@自动连线
私人事件处理程序事件处理程序;
@自动连线
私人EventBHandler EventBHandler;
@邮戳(“/a”)
public void handleEventA(@RequestBody EventA event){
句柄(id,事件);
}
@邮戳(“/b”)
public void handleEventB(@RequestBody EventB event){
句柄(id,事件);
}
}
我们最近增加了通过队列服务接收事件的支持。它向我们发送有效负载和事件类。我们的决定是让这两个接口都工作(rest和queue)。避免代码重复的解决方案是让控制器选择处理事件的处理程序。现在的代码与此类似:
@配置
公共类EventHandlerQueueConsumer{
@自动连线
私有EventHandlerAPI EventHandlerAPI;
私有映射事件处理程序;
@施工后
public void init(){
/*启动侦听队列*/
报关员();
}
私人无效申报人{
eventHandlers=newhashmap();
put(EventAHandler.class,(EventHandler)eventHandlerAPI::handleEventA);
put(EventBHandler.class,(EventHandler)eventHandlerAPI::handleEventB);
}
私有void onEventReceived(AbstractEvent事件){
EventHandler=eventHandlers.get(event.getClass());
句柄(事件);
}
私有接口事件处理程序{
无效句柄(T事件);
}
}
这段代码可以工作,但它不允许控制器选择谁来处理事件(我们的意图)。这个决定实际上是由地图决定的
我想做的是通过它的请求映射调用控制器方法,而不必访问internet。大概是这样的:
@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内部都使用HttpServletRequest
和HttpServletResponse
:(
有没有一种方法可以在不访问internet的情况下发出内部请求(使用方法的路径)
它们是同一应用程序的类
那就足够容易了
1) 您可以使用restemplate
实用程序类在http(s)://localhost:{port}/API/{path}
上调用自己的API。这是首选方法,因为您将遵循标准MVC模式。比如:
restTemplate.exchange(uri, HttpMethod.POST, httpEntity, ResponseClass.class);
@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;
}
2) 如果您根本不想调用网络连接,那么您可以使用Spring的internal来查找映射/方法映射,或者使用一些反射来构建自定义的连接
在控制器启动时映射。然后,您可以按照模型类中显示的方式将事件/对象从映射传递给方法。比如:
restTemplate.exchange(uri, HttpMethod.POST, httpEntity, ResponseClass.class);
@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;
}
@RequestMapping(“foo”)
公共方法(){
System.out.println(“mapping=“+getMapping(“fooMethod”);//您可以在@PostContract初始化阶段获取所有方法/映射
}
私有字符串getMapping(字符串方法名){
方法方法[]=this.getClass().getMethods();
for(int i=0;i0){
返回映射[mapping.length-1];
}
}
}
返回null;
}
是同一应用程序的EventHandlerQueueConsumer
和EventHandlerAPI
类,还是这两个类位于不同的应用程序中(即不同的微服务)?@MikhailKholodkov他们是同一应用程序的类第二个是想要做的,但是我想知道是否有Spring特性可以做这样的事情,我只能想到点击Spring启动执行器的/mapping
端点(第17条),然后解析响应。它包含您需要的所有信息。但这又是一个过度工程化的解决方案,我仍然建议使用普通的restemplate
call。