如何从HttpServlet访问bean的相同实例?

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

我对Spring Framework有点陌生。我有一个用Spring(4.2.1)编写的Web应用程序。我正在尝试使用Micrometer库公开指标,并将使用Prometheus进行抓取。

应用程序的相关结构是这样的:-核心模块(JAR)-Web服务模块(WAR)

我创建了一个PrometheusService类,它是在核心模块中定义的bean。在bean内定义的是PrometheusMeterRegistryCounter

@Service
public class PrometheusService {

    private static PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
    private static Counter newAssetCounter = Counter
            .builder("new_asset_counter")
            .description("count of created assets")
            .tags("region", "na")
            .register(registry);

    public PrometheusService() {
        new JvmMemoryMetrics().bindTo(registry);
        new DiskSpaceMetrics(new File("/")).bindTo(registry);
        new ProcessorMetrics().bindTo(registry);
        new UptimeMetrics().bindTo(registry);
    }

    public static PrometheusMeterRegistry getRegistry() {
        return registry;
    }

    public Counter getNewAssetCounter() {
        return this.newAssetCounter;
    }

}

我创建了MetricsResource,这是一个暴露[/ Https]端点的HttpServlet。尝试@Autowire PrometheusService Bean时,此处始终为null。快速搜索告诉我HttpServlet不是由Spring管理的。如果我想@Autowire,则需要添加如下内容:

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(webApplicationContext);

现在,我能够@Autowire Servlet中的PrometheusService bean。

bean中定义的Counter在核心模块内递增。 MetricsResource doGet方法写入存储在PrometheusMeterRegistry中的度量。

@WebServlet("/metrics")
public class MetricsResource extends HttpServlet  {

    private PrometheusService promService; // @Autowired
    private PrometheusMeterRegistry registry;

    @Override
    public void init() throws ServletException {
        super.init();

//        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(webApplicationContext);

//        promService = (PrometheusService) getServletContext().getAttribute("prometheusService");

//        WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
//        AutowireCapableBeanFactory ctx = context.getAutowireCapableBeanFactory();
//        ctx.autowireBean(this);
    }

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws IOException {
        resp.setStatus(HttpServletResponse.SC_OK);
        resp.setContentType(TextFormat.CONTENT_TYPE_004);

        registry = promService.getRegistry();

        Writer writer = resp.getWriter();
        try {
            registry.scrape(writer);
            writer.flush();
        } finally {
            writer.close();
        }
    }
}

尽管有问题

,是在/ metrics端点处Counter的值始终为0。

无论是@Autowired还是我手动尝试获取bean。

这怎么可能?我的PrometheusService Bean是单例。甚至PrometheusMeterRegistry和Counter也被标记为静态,那么为什么在servlet中得到另一个对象?经过更多搜索后,我发现Spring将为每个容器创建一个单例bean

。所以我假设这里发生的是有两个容器或上下文。主应用程序上下文和servlet上下文。

我尝试过的一些事情:使PrometheusService实现ApplicationContextAware使用实现ApplicationContextAware并返回Bean的ServiceLocator类将上下文参数添加到web.xml在app-context.xml中使用ServletContextAttributeExporter使用WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext())

我继续获得该对象的新实例。我要做的就是能够使用Micrometer创建和公开自定义指标。我的方法有缺陷吗?如何从HttpServlet中访问正确的bean?

Spring dependency injection to other instancehttp://senthadev.com/sharing-spring-container-between-modules-in-a-web-application.htmlSpring dependency injection to other instanceApplicationContext and ServletContext

我对Spring Framework有点陌生。我有一个用Spring(4.2.1)编写的Web应用程序。我正在尝试使用Micrometer库公开指标,并将使用Prometheus进行抓取。相关的...

java spring servlets dependency-injection
1个回答
0
投票

尝试processInjectionBasedOnServletContext(Object target, ServletContext servletContext)

© www.soinside.com 2019 - 2024. All rights reserved.