Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring mvc SpringBoot Undertow:如何分派到工作线程_Spring Mvc_Spring Boot_Worker_Undertow - Fatal编程技术网

Spring mvc SpringBoot Undertow:如何分派到工作线程

Spring mvc SpringBoot Undertow:如何分派到工作线程,spring-mvc,spring-boot,worker,undertow,Spring Mvc,Spring Boot,Worker,Undertow,我目前正在研究springboot,但(对我来说)不太清楚如何将传入的http请求发送到工作线程以阻止操作处理 查看TowerEmbeddedServletContainer.class下的类,它看起来不可能有这种行为,因为唯一的HttpHandler是ServletHandler,它允许@Controller配置 private Undertow createUndertowServer() { try { HttpHandler servletHandler = th

我目前正在研究springboot,但(对我来说)不太清楚如何将传入的http请求发送到工作线程以阻止操作处理

查看TowerEmbeddedServletContainer.class下的类,它看起来不可能有这种行为,因为唯一的HttpHandler是ServletHandler,它允许@Controller配置

private Undertow createUndertowServer() {
    try {
        HttpHandler servletHandler = this.manager.start();
        this.builder.setHandler(getContextHandler(servletHandler));
        return this.builder.build();
    }
    catch (ServletException ex) {
        throw new EmbeddedServletContainerException(
                "Unable to start embdedded Undertow", ex);
    }
}

private HttpHandler getContextHandler(HttpHandler servletHandler) {
    if (StringUtils.isEmpty(this.contextPath)) {
        return servletHandler;
    }
    return Handlers.path().addPrefixPath(this.contextPath, servletHandler);

}
默认情况下,在undertow中,所有请求都由IO线程处理,以进行非阻塞操作。 这是否意味着每个@Controller执行都将由一个非阻塞线程处理?或者有没有一种解决方案可以从IO-THREAD或WORKER-THREAD中选择

我试图编写一个变通方法,但这段代码非常糟糕,也许有人有更好的解决方案:

BlockingHandler.class

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BlockingHandler {

    String contextPath() default "/";

}
public class UndertowInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        configurableApplicationContext.addBeanFactoryPostProcessor(new UndertowHandlerPostProcessor());
    }

}
public class UndertowHandlerPostProcessor implements BeanDefinitionRegistryPostProcessor {


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(BlockingHandler.class));
        for (BeanDefinition beanDefinition : scanner.findCandidateComponents("org.me.lah")){

            try{
                Class clazz = Class.forName(beanDefinition.getBeanClassName());
                beanDefinitionRegistry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);
            } catch (ClassNotFoundException e) {
                throw new BeanCreationException(format("Unable to create bean %s", beanDefinition.getBeanClassName()), e);
            }
        }
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        //no need to post process defined bean
    }
}
public class UndertowEmbeddedServletContainerFactory extends  AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
        DeploymentManager manager = createDeploymentManager(initializers);
        int port = getPort();
        if (port == 0) {
            port = SocketUtils.findAvailableTcpPort(40000);
        }
        Undertow.Builder builder = createBuilder(port);

        Map<String, Object> handlers = applicationContext.getBeansWithAnnotation(BlockingHandler.class);
        return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(),
            port, port >= 0, handlers);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

...
public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager,
                                        String contextPath, int port, boolean autoStart, Map<String, Object> handlers) {
    this.builder = builder;
    this.manager = manager;
    this.contextPath = contextPath;
    this.port = port;
    this.autoStart = autoStart;
    this.handlers = handlers;
}

private Undertow createUndertowServer() {
    try {
        HttpHandler servletHandler = this.manager.start();
        String path = this.contextPath.isEmpty() ? "/" : this.contextPath;
        PathHandler pathHandler = Handlers.path().addPrefixPath(path, servletHandler);
        for(Entry<String, Object> entry : handlers.entrySet()){
            Annotation annotation = entry.getValue().getClass().getDeclaredAnnotation(BlockingHandler.class);
            System.out.println(((BlockingHandler) annotation).contextPath());
            pathHandler.addPrefixPath(((BlockingHandler) annotation).contextPath(), (HttpHandler) entry.getValue());
        }

        this.builder.setHandler(pathHandler);
        return this.builder.build();
    }
    catch (ServletException ex) {
        throw new EmbeddedServletContainerException(
                "Unable to start embdedded Undertow", ex);
    }
}
初始值设定项下的类

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BlockingHandler {

    String contextPath() default "/";

}
public class UndertowInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        configurableApplicationContext.addBeanFactoryPostProcessor(new UndertowHandlerPostProcessor());
    }

}
public class UndertowHandlerPostProcessor implements BeanDefinitionRegistryPostProcessor {


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(BlockingHandler.class));
        for (BeanDefinition beanDefinition : scanner.findCandidateComponents("org.me.lah")){

            try{
                Class clazz = Class.forName(beanDefinition.getBeanClassName());
                beanDefinitionRegistry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);
            } catch (ClassNotFoundException e) {
                throw new BeanCreationException(format("Unable to create bean %s", beanDefinition.getBeanClassName()), e);
            }
        }
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        //no need to post process defined bean
    }
}
public class UndertowEmbeddedServletContainerFactory extends  AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
        DeploymentManager manager = createDeploymentManager(initializers);
        int port = getPort();
        if (port == 0) {
            port = SocketUtils.findAvailableTcpPort(40000);
        }
        Undertow.Builder builder = createBuilder(port);

        Map<String, Object> handlers = applicationContext.getBeansWithAnnotation(BlockingHandler.class);
        return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(),
            port, port >= 0, handlers);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

...
public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager,
                                        String contextPath, int port, boolean autoStart, Map<String, Object> handlers) {
    this.builder = builder;
    this.manager = manager;
    this.contextPath = contextPath;
    this.port = port;
    this.autoStart = autoStart;
    this.handlers = handlers;
}

private Undertow createUndertowServer() {
    try {
        HttpHandler servletHandler = this.manager.start();
        String path = this.contextPath.isEmpty() ? "/" : this.contextPath;
        PathHandler pathHandler = Handlers.path().addPrefixPath(path, servletHandler);
        for(Entry<String, Object> entry : handlers.entrySet()){
            Annotation annotation = entry.getValue().getClass().getDeclaredAnnotation(BlockingHandler.class);
            System.out.println(((BlockingHandler) annotation).contextPath());
            pathHandler.addPrefixPath(((BlockingHandler) annotation).contextPath(), (HttpHandler) entry.getValue());
        }

        this.builder.setHandler(pathHandler);
        return this.builder.build();
    }
    catch (ServletException ex) {
        throw new EmbeddedServletContainerException(
                "Unable to start embdedded Undertow", ex);
    }
}
重写UndertowEmbeddedServletContainerFactory.class

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BlockingHandler {

    String contextPath() default "/";

}
public class UndertowInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        configurableApplicationContext.addBeanFactoryPostProcessor(new UndertowHandlerPostProcessor());
    }

}
public class UndertowHandlerPostProcessor implements BeanDefinitionRegistryPostProcessor {


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(BlockingHandler.class));
        for (BeanDefinition beanDefinition : scanner.findCandidateComponents("org.me.lah")){

            try{
                Class clazz = Class.forName(beanDefinition.getBeanClassName());
                beanDefinitionRegistry.registerBeanDefinition(clazz.getSimpleName(), beanDefinition);
            } catch (ClassNotFoundException e) {
                throw new BeanCreationException(format("Unable to create bean %s", beanDefinition.getBeanClassName()), e);
            }
        }
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        //no need to post process defined bean
    }
}
public class UndertowEmbeddedServletContainerFactory extends  AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware, ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
        DeploymentManager manager = createDeploymentManager(initializers);
        int port = getPort();
        if (port == 0) {
            port = SocketUtils.findAvailableTcpPort(40000);
        }
        Undertow.Builder builder = createBuilder(port);

        Map<String, Object> handlers = applicationContext.getBeansWithAnnotation(BlockingHandler.class);
        return new UndertowEmbeddedServletContainer(builder, manager, getContextPath(),
            port, port >= 0, handlers);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

...
public UndertowEmbeddedServletContainer(Builder builder, DeploymentManager manager,
                                        String contextPath, int port, boolean autoStart, Map<String, Object> handlers) {
    this.builder = builder;
    this.manager = manager;
    this.contextPath = contextPath;
    this.port = port;
    this.autoStart = autoStart;
    this.handlers = handlers;
}

private Undertow createUndertowServer() {
    try {
        HttpHandler servletHandler = this.manager.start();
        String path = this.contextPath.isEmpty() ? "/" : this.contextPath;
        PathHandler pathHandler = Handlers.path().addPrefixPath(path, servletHandler);
        for(Entry<String, Object> entry : handlers.entrySet()){
            Annotation annotation = entry.getValue().getClass().getDeclaredAnnotation(BlockingHandler.class);
            System.out.println(((BlockingHandler) annotation).contextPath());
            pathHandler.addPrefixPath(((BlockingHandler) annotation).contextPath(), (HttpHandler) entry.getValue());
        }

        this.builder.setHandler(pathHandler);
        return this.builder.build();
    }
    catch (ServletException ex) {
        throw new EmbeddedServletContainerException(
                "Unable to start embdedded Undertow", ex);
    }
}
最终创建一个分派到工作线程的HttpHandler

@BlockingHandler(contextPath = "/blocking/test")
public class DatabaseHandler implements HttpHandler {

    @Autowired
    private EchoService echoService;

    @Override
    public void handleRequest(HttpServerExchange httpServerExchange) throws Exception {
        if(httpServerExchange.isInIoThread()){
            httpServerExchange.dispatch();
        }

        echoService.getMessage("my message");
    }
}

正如你所看到的,我的“解决方案”非常繁重,我非常感谢任何能简化它的帮助


谢谢你

你什么都不用做

Spring Boot的默认下拖配置在Spring MVC的
DispatcherServlet
前面使用下拖。这个处理程序


如果在
@Controller
中放置断点,您将看到它在名为
XNIO-1 task-n
的线程上被调用,该线程是工作线程(IO线程名为
XNIO-1 I/O-n
)。

您无需执行任何操作

Spring Boot的默认下拖配置在Spring MVC的
DispatcherServlet
前面使用下拖。这个处理程序

如果在
@Controller
中放置断点,您将看到它在名为
XNIO-1 task-n
的线程上被调用,该线程是工作线程(IO线程名为
XNIO-1 I/O-n