如何使用 Spring Boot 注册辅助 servlet?

Posted

技术标签:

【中文标题】如何使用 Spring Boot 注册辅助 servlet?【英文标题】:How can I register a secondary servlet with Spring Boot? 【发布时间】:2014-01-21 19:46:41 【问题描述】:

我需要在我的应用程序中注册一个额外的 servlet。但是使用 Spring Boot 及其 Java Config,我不能只在 web.xml 文件中添加 servlet 映射。

如何添加额外的 servlet?

【问题讨论】:

我刚刚提出了这个问题,但是如果您不介意,除了提供的 DispatcherServlet 之外,添加其他 Servlet 的目的是什么?你可以使用多个控制器和任何你想要的 url/路径 @aerox 已经很多年了……我不记得当时的用例了。也许是利用 DropWizard 指标导出器 servlet,因为它提供了一种可视化已收集的指标的方法。 SpringBoot 后来将其合并到执行器端点本身中。 (而 Micrometer.io 更好地解决了这个问题) 【参考方案1】:

也可以使用ServletRegistrationBean

@Bean
public ServletRegistrationBean servletRegistrationBean()
    return new ServletRegistrationBean(new FooServlet(),"/someOtherUrl/*");

我最终选择了这条路。

【讨论】:

如何在ServletRegistrationBean中添加多个servlet? @sakura 您不能添加多个 servlet。您是指多个网址吗? @sakura 为什么要使用同一个注册 bean 注册多个 servlet?只需创建多个注册 bean。 @MiladNaseri 实际上我有多个 servlet 过滤器,并且想在不同的 URL 上使用 ServletRegistrationBean 配置这些过滤器。或者在不同的唯一 url 上配置相同的 servlet,而不仅仅是所有 url。无论如何,我想这是我在 cmets 中问这个问题时的要求。我最终在所有网址上应用了该过滤器。 @Milad:感谢您指出这一点。你应该给这个作为官方答案,然后我会给你一个点【参考方案2】:

Just add a bean for the servlet。它将被映射到/beanName/

@Bean
public Servlet foo() 
    return new FooServlet();

【讨论】:

请注意,如果您真的希望它映射到/something/* 而不是/something/,则需要使用ServletRegistrationBean 这对我不起作用。在这个答案中起作用的是 ServletRegistrationBean:***.com/a/20939923/3165190 @peterh sn-p 是最简单的;我更新了旧链接。 @chrylis 谢谢,很高兴看到!【参考方案3】:

您可以在Application类中使用不同的ServletRegistrationBean注册多个不同的servlet,例如@Bean,您可以注册一个servlet有多个servlet映射;

   @Bean
   public ServletRegistrationBean axisServletRegistrationBean() 
      ServletRegistrationBean registration = new ServletRegistrationBean(new AxisServlet(), "/services/*");
      registration.addUrlMappings("*.jws");
      return registration;
   

   @Bean
   public ServletRegistrationBean adminServletRegistrationBean() 
      return new ServletRegistrationBean(new AdminServlet(), "/servlet/AdminServlet");
   

【讨论】:

【参考方案4】:

我们也可以通过如下方式注册Servlet:

@Configuration
public class ConfigureWeb implements ServletContextInitializer, EmbeddedServletContainerCustomizer 

  @Override
  public void onStartup(ServletContext servletContext) throws ServletException 
      registerServlet(servletContext);
  

  private void registerServlet(ServletContext servletContext) 
      log.debug("register Servlet");
      ServletRegistration.Dynamic serviceServlet = servletContext.addServlet("ServiceConnect", new ServiceServlet());

      serviceServlet.addMapping("/api/ServiceConnect/*");
      serviceServlet.setAsyncSupported(true);
      serviceServlet.setLoadOnStartup(2);
  

【讨论】:

【参考方案5】:

如果您使用的是嵌入式服务器,您可以使用@WebServlet 注释您的 servlet 类:

@WebServlet(urlPatterns = "/example")
public class ExampleServlet extends HttpServlet

来自@WebServlet:

用于声明 servlet 的注解。

此注解在部署时由容器处理,并且 在指定 URL 上提供的相应 servlet 模式。

并在基类上启用@ServletComponentScan

@ServletComponentScan
@EntityScan(basePackageClasses =  ExampleApp.class, Jsr310JpaConverters.class )
@SpringBootApplication
public class ExampleApp 

请注意@ServletComponentScan 仅适用于嵌入式服务器:

启用对 Servlet 组件(过滤器、servlet 和 听众)。仅在使用嵌入式 Web 时执行扫描 服务器。

更多信息:The @ServletComponentScan Annotation in Spring Boot

【讨论】:

【参考方案6】:

这种方式对我有用,有一个名为 WS01455501EndpointFor89 的 servlet

@Bean
public ServletRegistrationBean<WS01455501EndpointFor89> servletRegistrationBeanAlt(ApplicationContext context) 
    ServletRegistrationBean<WS01455501EndpointFor89> servletRegistrationBean = new ServletRegistrationBean<>(new WS01455501EndpointFor89(),
            "/WS01455501Endpoint");
    servletRegistrationBean.setLoadOnStartup(1);
    return servletRegistrationBean;

【讨论】:

【参考方案7】:

在 BeanDefinitionRegistryPostProcessor 中也可用

package bj;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@SpringBootApplication
class App implements BeanDefinitionRegistryPostProcessor 
    public static void main(String[] args) 
        SpringApplication.run(App.class, args);
    

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException 
        registry.registerBeanDefinition("myServlet", new RootBeanDefinition(ServletRegistrationBean.class,
                () -> new ServletRegistrationBean<>(new HttpServlet() 
                    @Override
                    protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException 
                        resp.getWriter().write("hello world");
                    
                , "/foo/*")));
    

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
    

【讨论】:

以上是关于如何使用 Spring Boot 注册辅助 servlet?的主要内容,如果未能解决你的问题,请参考以下文章

如何从使用 Spring Cloud Eureka 服务器注册的 Spring Boot 应用程序中公开 Prometheus 指标

Spring-boot 为辅助 SSL 侦听器配置 client-auth=need

Spring Boot + WebSocket 实时消息推送

Spring Boot MyBatis代码自动生成和辅助插件

在 Spring Boot 中,如何在每次测试之前重置指标注册表?

如何在Spring Boot中运行时注册bean?