OSGi环境下如何动态增删Web上下文内的Servlet?
Great question! Let’s tackle this for your OSGi environment, since dynamic Servlet management in embedded containers can be tricky depending on your choice of server.
First off, Undertow was built with flexibility front and center, and it natively supports adding/removing Servlets to an existing context out of the box. It fully implements the Servlet 3.0+ dynamic registration API, and its OSGi-friendly design makes it easy to integrate with bundle-based deployments.
How Undertow Enables Dynamic Servlet CRUD
Undertow uses a DeploymentManager to handle web application deployments, and once a context is deployed, you can directly access its ServletContext to register or unregister Servlets at runtime. No need for hacks or custom extensions—this functionality is baked into its core.
Step-by-Step Implementation Example
Initializing Undertow in OSGi
First, set up your Undertow server and deploy a base context (you’d typically wrap this in an OSGi component or activator):
import io.undertow.servlet.api.DeploymentManager; import io.undertow.servlet.api.ServletDeploymentInfo; import io.undertow.servlet.Servlets; import io.undertow.Undertow; // Define your base web context ServletDeploymentInfo deploymentInfo = Servlets.deployment() .setContextPath("/my-osgi-app") .setDeploymentName("my-osgi-app.war"); // Deploy the context via Undertow's container DeploymentManager manager = Servlets.defaultContainer().addDeployment(deploymentInfo); manager.deploy(); // Start the Undertow server Undertow server = Undertow.builder() .addHttpListener(8080, "0.0.0.0") .setHandler(manager.start()) .build(); server.start();
Dynamically Adding a Servlet
Once the server is running, grab the ServletContext from the deployment manager and register your Servlet:
// Get the active ServletContext ServletContext servletContext = manager.getDeployment().getServletContext(); // Create your Servlet instance (could also come from an OSGi service) MyDynamicServlet dynamicServlet = new MyDynamicServlet(); // Register and map the Servlet ServletRegistration.Dynamic registration = servletContext.addServlet("MyDynamicServlet", dynamicServlet); registration.addMapping("/dynamic/*"); registration.setLoadOnStartup(1); // Optional: load immediately
Dynamically Removing a Servlet
To remove a Servlet at runtime, fetch its registration and unregister it:
ServletRegistration registration = servletContext.getServletRegistration("MyDynamicServlet"); if (registration != null) { registration.unregister(); }
OSGi Service Integration (Declarative Services)
To make this truly OSGi-native, use Declarative Services (DS) to automatically register/unregister Servlets when they’re published as OSGi services:
import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import javax.servlet.Servlet; import javax.servlet.ServletRegistration; @Component public class ServletDynamicRegistrar { private DeploymentManager deploymentManager; // Inject the pre-configured DeploymentManager via OSGi DS @Reference public void setDeploymentManager(DeploymentManager manager) { this.deploymentManager = manager; } // Listen for Servlet services being added @Reference( service = Servlet.class, cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC ) public void addServlet(Servlet servlet, java.util.Map<String, Object> serviceProps) { String servletName = (String) serviceProps.get("servlet.name"); String urlPattern = (String) serviceProps.get("servlet.url.pattern"); if (servletName == null || urlPattern == null) { return; // Skip invalid services } ServletContext context = deploymentManager.getDeployment().getServletContext(); ServletRegistration.Dynamic registration = context.addServlet(servletName, servlet); registration.addMapping(urlPattern); } // Listen for Servlet services being removed public void removeServlet(Servlet servlet, java.util.Map<String, Object> serviceProps) { String servletName = (String) serviceProps.get("servlet.name"); if (servletName == null) { return; } ServletContext context = deploymentManager.getDeployment().getServletContext(); ServletRegistration registration = context.getServletRegistration(servletName); if (registration != null) { registration.unregister(); } } }
If you want a solution that’s purpose-built for OSGi, Pax Web is an excellent choice. It’s an OSGi Http Service implementation that supports Jetty, Tomcat, and Undertow as underlying containers—and it natively handles dynamic Servlet deployment via OSGi services.
Why Pax Web is a Great Fit for OSGi
Pax Web abstracts away the container-specific details. Instead of writing custom code to manage Servlets, you just publish your Servlet as an OSGi service with specific properties, and Pax Web automatically deploys it to the web context. When the service is unregistered, it removes the Servlet automatically.
Simplified Dynamic Deployment with Pax Web
Here’s how easy it is to deploy a dynamic Servlet with Pax Web using DS:
import org.osgi.service.component.annotations.Component; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component( property = { "osgi.http.servlet.name=MyPaxServlet", "osgi.http.servlet.pattern=/pax-dynamic/*", "osgi.http.context.path=/my-osgi-app" // Optional: bind to a specific context } ) public class MyPaxServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.getWriter().write("Hello from Pax Web dynamic Servlet!"); } }
That’s it—no manual registration code needed. Pax Web handles all the dynamic lifecycle management for you.
- Jetty: As you noted, Jetty doesn’t natively support dynamic Servlet CRUD on existing contexts without extra work. You’d need to use
MutableServletContextHandleror build custom extensions to enable this, which adds complexity. - Undertow: Native support for dynamic Servlet operations via standard Servlet API and its own deployment model, making it a solid choice for embedded OSGi deployments.
- Pax Web: The most OSGi-native option, leveraging OSGi service lifecycle to handle dynamic Servlet deployment automatically—ideal if you want to align with OSGi best practices.
内容的提问来源于stack exchange,提问作者Martin

