如何使用 SpringBoot 注册辅助 servlet?

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

如何添加其他 servlet?

74319 次浏览

只需为 servlet 添加一个 bean,它就会被映射到 /{beanName}/

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

另外还有 ServletRegistrationBean

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

结果我选择了这条路。

您可以用不同的 ServletRegistrationBean 注册多个不同的 servlet,比如在 Application 类中注册@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");
}

我们还可以通过以下方式注册 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

来自 @ WebServlet:

用于声明 servlet 的注释。

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

并在基类上启用 @ServletComponentScan:

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

请注意,@ ServletComponent 扫描只能在嵌入式服务器上运行:

启用对 Servlet 组件(筛选器、 Servlet 和 扫描只在使用嵌入式网页时进行 服务器。

更多信息: Spring 引导中的@ServletComponent 扫描注释

在 BeanDefinition itionRegistryPostProcessor 中也可以找到

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) {
}
}

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

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