Java 如何向Spring Boot注册辅助servlet?

Java 如何向Spring Boot注册辅助servlet?,java,spring,spring-boot,Java,Spring,Spring Boot,我需要在应用程序中注册一个额外的servlet。然而,使用SpringBoot及其Java配置,我不能只在web.xml文件中添加servlet映射 如何添加其他servlet?。它将被映射到/{beanName}/ @Bean public Servlet foo() { return new FooServlet(); } 还提供了ServletRegistrationBean @Bean public ServletRegistrationBean servletRegistra

我需要在应用程序中注册一个额外的servlet。然而,使用SpringBoot及其Java配置,我不能只在
web.xml
文件中添加servlet映射

如何添加其他servlet?

。它将被映射到
/{beanName}/

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

还提供了
ServletRegistrationBean

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

这就是我选择的路径。

您可以在应用程序类中使用不同的ServletRegistrationBean(如@Bean)注册多个不同的servlet,并且可以注册一个具有多个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");
   }

我们还可以按照以下方式注册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);
  }
}

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

@WebServlet(urlPatterns = "/example")
public class ExampleServlet extends HttpServlet
发件人:

用于声明servlet的注释

容器在部署时处理此批注,并且 相应的servlet在指定的URL上可用 模式

并在基类上启用
@ServletComponentScan

@ServletComponentScan
@EntityScan(basePackageClasses = { ExampleApp.class, Jsr310JpaConverters.class })
@SpringBootApplication
public class ExampleApp 
请注意,仅适用于嵌入式服务器:

启用对Servlet组件(筛选器、Servlet和 听众)。扫描仅在使用嵌入式web时执行 服务器


更多信息:

也可在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) {
    }
}
包bj;
导入org.springframework.beans.BeansException;
导入org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
导入org.springframework.beans.factory.support.BeanDefinitionRegistry;
导入org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
导入org.springframework.beans.factory.support.RootBean定义;
导入org.springframework.boot.SpringApplication;
导入org.springframework.boot.autoconfigure.springboot应用程序;
导入org.springframework.boot.web.servlet.ServletRegistrationBean;
导入javax.servlet.http.HttpServlet;
导入javax.servlet.http.HttpServletRequest;
导入javax.servlet.http.HttpServletResponse;
导入java.io.IOException;
@SpringBoot应用程序
类应用程序实现BeanDefinitionRegistryPostProcessor{
公共静态void main(字符串[]args){
SpringApplication.run(App.class,args);
}
@凌驾
公共无效后处理BeanDefinitionRegistry(BeanDefinitionRegistry注册表)引发BeanException{
registry.registerBeanDefinition(“myServlet”),新的RootBeanDefinition(ServletRegistrationBean.class,
()->新的ServletRegistrationBean(新的HttpServlet(){
@凌驾
受保护的无效服务(HttpServletRequest-req、HttpServletResponse-resp)引发IOException{
resp.getWriter()编写(“hello world”);
}
},“/foo/*”);
}
@凌驾
public void后处理beanFactory(ConfigurableListableBeanFactory beanFactory){
}
}

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

@Bean
public ServletRegistrationBean<WS01455501EndpointFor89> servletRegistrationBeanAlt(ApplicationContext context) {
    ServletRegistrationBean<WS01455501EndpointFor89> servletRegistrationBean = new ServletRegistrationBean<>(new WS01455501EndpointFor89(),
            "/WS01455501Endpoint");
    servletRegistrationBean.setLoadOnStartup(1);
    return servletRegistrationBean;
}
@Bean
公共ServletRegistrationBean servletRegistrationBeanAlt(应用程序上下文上下文){
ServletRegistrationBean ServletRegistrationBean=新的ServletRegistrationBean(新的WS01455501EndpointFor89(),
“/WS01455501Endpoint”);
servletRegistrationBean.setLoadOnStartup(1);
返回servletRegistrationBean;
}

如何在ServletRegistrationBean中添加多个servlet?@sakura您不能添加多个servlet。你是说多个URL吗?@sakura为什么要使用同一个注册bean注册多个servlet?只需创建多个注册bean。@MiladNaseri实际上我有多个servlet过滤器,并希望在不同的URL上使用ServletRegistrationBean配置这些过滤器。或者在不同的唯一URL上配置相同的servlet,而不仅仅是在所有URL上。无论如何,我想这是我在评论中提出这个问题时的要求。最后我在所有URL上应用了这个过滤器。@Mild:谢谢你指出这一点。你应该给出这个正式答案,然后我会给你一点提示,如果你真的想把它映射到
/something/*
而不是
/something/
,你需要使用
ServletRegistrationBean
。这对我来说不起作用。这个答案中的ServletRegistrationBean起了作用:@peterh代码片段尽可能的琐碎;我更新了陈旧的链接。@chrylis谢谢,很高兴见到你!我刚才提出了这个问题,但是如果您不介意的话,除了提供的DispatcherServlet之外,添加其他Servlet的目的是什么?无论如何,您都可以使用多个控制器和任意url/路径want@aerox已经很多年了。。。我记不起当时的用例了。也许是利用DropWizard metric exporter servlet,因为它提供了一种可视化已收集的度量的方法。SpringBoot后来将其整合到执行器端点本身中。(千分尺.io更能解决这个问题)