Servlet3 可编程式注册web组件

Servlet3 可编程式注册web组件

为了增强可插拔性,servlet3在servletContext中增加新的方法,支持编程方式申明和注册servlet、filter、listener组件。ServletContext定义一组方法,servlet使用其与servlet容器进行通讯。举例:获取文件MIME类型,分发请求或写日志文件等。
我们可以通过调用ServletContextListener#contextInitializedServletContainerInitializer#onStartup方法,实现动态注册组件。

ServletContext注册方法汇总

方法描述方法
通过addXXX()方法注册组件。右边每个方法有多个重载形式。每个重载方法需要组件name参数(listener方法除外)以及类名或类类型或组件实例。servlet方法返回ServletRegistration.Dynamic,Filter返回FilterRegistration.Dynamic,listener返回void,返回Registration对象可以实现进一步配置。 `addServlet(…) addFilter(…) addListener(…)`
通过createXXX()方法创建实例。我们需要提供类类型作为参数给每个方法。这些方法可能在调用上面addXXX方法之前被调用。`createServlet(…) createFilter(…) createListener(…)`
通过 `getXXXRegistration()`获取Registration对象,不使用listener。如果servlet/fliter没有在web.xml或注解中注册,调用将在`ServletContextListener#contextInitialized`中抛出`UnsupportedOperationException`异常。`getServletRegistration(…) getFilterRegistration(…)`

编程式配置组件场景

这个特性让框架设计者在启动阶段可以加载特定的web组件,而无需最终用户手工在应用端提供相同的配置。如spring使用 ServletContainerInitializer,开发者使用框架仅需要增加框架jar依赖并创建相应的pojo(使用框架特定的注解或实现一些接口)。

我们也可以通过驻留在框架jar中的ServletContextListener来实现,但缺点是,如果应用的web.xml文件中已经配置metadata-complete="true"用于提升性能,则不能实现正确加载。设置该标志会引起容器不去扫描jar中的注解。因此ServletContainerInitializer(spi)是更标准的方式。

我们应该仅使用ServletContextListener#contextInitialized实现应用级别的可编程配置。基于一些动态参数,选择性决定插入/注册那些web组件。

示例

通过ServletContextListener#contextInitialized动态注册servlet,假设一个servlet应用需要根据不同的地理位置加载不同的servlet。

1.DefaultAppController servlet代码。

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



public class DefaultAppController extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.getWriter().println("DefaultAppController");
    }
} 

2.OffshoreAppController servlet代码。

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

public class OffshoreAppController extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("OffshoreAppController");
    }
}

3.AppContextListener 动态加载servlet。

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebListener;
import java.util.Locale;

@WebListener
public class AppContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent event) {
        Locale locale = Locale.getDefault();
        ServletRegistration.Dynamic registration = event.getServletContext()
                .addServlet("appController", locale.getISO3Country().equals("USA") ?
                        DefaultAppController.class : OffshoreAppController.class);
        registration.addMapping("/app/");

    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值