问题描述
我有一个 spring 应用程序,它使用带有 websockets 的 tomcat.我想在每次 tomcat 创建新线程时使用 DelegatingSecurityContextRunnable 执行,即扭曲 tomcat 线程.有谁知道这是怎么做到的.可以找到问题的原因.此处
也许这可以通过使用 AOP 和一些建议来完成?
在 Spring Boot 中,您可以通过挂钩到 Tomcat 连接器来配置 Wrapper.以这个为例:
@Bean公共 EmbeddedServletContainerFactory servletContainerFactory() {TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {@覆盖公共无效定制(连接器连接器){AbstractProtocol protocolHandler = (AbstractProtocol) connector.getProtocolHandler();任务队列任务队列 = 新任务队列(){@覆盖public boolean offer(Runnable e, long timeout, TimeUnit unit) throws InterruptedException {return super.offer(new MyRunnable(e), timeout, unit);}@覆盖公共布尔报价(Runnable o){返回 super.offer(new MyRunnable(o));}};TaskThreadFactory tf = new TaskThreadFactory("artur-" + "-exec-", false, 0);ThreadPoolExecutor e = new ThreadPoolExecutor(10, 10, 1000, TimeUnit.SECONDS, taskqueue);taskqueue.setParent(e);protocolHandler.setExecutor(e);}});返厂;}
这是我的自定义 Runable(这可以是任何包装器,我没有费心实现你的):
静态类 MyRunnable 实现 Runnable {私人可运行 r;公共 MyRunnable(Runnable r) {这.r = r;}@覆盖公共无效运行(){System.out.println("自定义可运行");运行内部();}无效运行内部(){r.run();}}
这是我的导入:
import java.util.concurrent.TimeUnit;导入 org.apache.catalina.connector.Connector;导入 org.apache.coyote.AbstractProtocol;导入 org.apache.tomcat.util.threads.TaskQueue;导入 org.apache.tomcat.util.threads.TaskThreadFactory;导入 org.apache.tomcat.util.threads.ThreadPoolExecutor;导入 org.springframework.boot.autoconfigure.EnableAutoConfiguration;导入 org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;导入 org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;导入 org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;导入 org.springframework.boot.web.support.SpringBootServletInitializer;导入 org.springframework.context.annotation.Bean;导入 org.springframework.context.annotation.ComponentScan;导入 org.springframework.context.annotation.Configuration;导入 org.springframework.context.annotation.FilterType;导入 org.springframework.context.annotation.PropertySource;
这是做什么的:
Tomcat 连接器自行初始化.您可以设置要使用的执行程序,在这种情况下,Tomcat 将停止创建自己的配置,而是使用您的配置.
通过覆盖队列中的 offer 方法,您有机会将您的 Runnable
包装在任何自定义的 Runnable
中.就我而言,为了进行测试,我只是添加了一个 Sysout
以查看一切是否正常.
我使用的 Threadpool
实现是 tomcat 默认的精确副本(减去属性).这样,行为保持不变,除了任何 Runnable
现在都是您的委托包装器.
当我测试时,我的控制台打印:
自定义运行
我希望这就是您要找的.p>
我使用 spring boot,但这本质上是一个 tomcat 问题,而不是 spring 问题.您可以根据您的具体情况调整解决方案.
-- 阿图尔
I have an spring app which is using tomcat with websockets. I would like to use the DelegatingSecurityContextRunnable to be executed every time when tomcat creates a new thread, i.e. warp the tomcat thread. Does anyone know how this is done. The reason for the question can be found.here
Maybe this can be done with using AOP and some advice?
In Spring boot you can configure a Wrapper by hooking into the Tomcat connector. See this as an example:
@Bean
public EmbeddedServletContainerFactory servletContainerFactory() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
AbstractProtocol protocolHandler = (AbstractProtocol) connector.getProtocolHandler();
TaskQueue taskqueue = new TaskQueue() {
@Override
public boolean offer(Runnable e, long timeout, TimeUnit unit) throws InterruptedException {
return super.offer(new MyRunnable(e), timeout, unit);
}
@Override
public boolean offer(Runnable o) {
return super.offer(new MyRunnable(o));
}
};
TaskThreadFactory tf = new TaskThreadFactory("artur-" + "-exec-", false, 0);
ThreadPoolExecutor e = new ThreadPoolExecutor(10, 10, 1000, TimeUnit.SECONDS, taskqueue);
taskqueue.setParent(e);
protocolHandler.setExecutor(e);
}
});
return factory;
}
And here is my custom Runable (this can be any wrapper, i did not bother implementing exactly yours):
static class MyRunnable implements Runnable {
private Runnable r;
public MyRunnable(Runnable r) {
this.r = r;
}
@Override
public void run() {
System.out.println("Custom runable");
runInner();
}
void runInner() {
r.run();
}
}
And here are my imports:
import java.util.concurrent.TimeUnit;
import org.apache.catalina.connector.Connector;
import org.apache.coyote.AbstractProtocol;
import org.apache.tomcat.util.threads.TaskQueue;
import org.apache.tomcat.util.threads.TaskThreadFactory;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.PropertySource;
What this does:
The Tomcat connector initialises itself. You can set the executor to use, in which case Tomcat will stop creating its own configuration and instead use yours.
By overwriting the offer methods in the queue, you have the chance to wrap your Runnable
in any custom Runnable
. In my case, for testing, I simply added a Sysout
to see that everything is working correctly.
The Threadpool
implementation I used is an exact copy of the tomcat default (minus the properties). This way, behaviour stays the same, except that any Runnable
is now your delegating wrapper.
When I test that, my console prints:
Custom runable
I hope this is what you were looking for.
I use spring boot, but this is essentially a tomcat issue not a spring issue. You can adapt the solution to your specific scenario.
-- Artur
这篇关于每次tomcat创建新线程时如何运行DelegatingSecurityContextRunnable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!