1. 程式人生 > >Servlet3.0——註冊web元件

Servlet3.0——註冊web元件

一、Servlet容器啟動時會掃描當前應用中每一個jar包中的在META-INF/services/javax.servlet.ServletContainerInitializer檔案(該檔案沒有後綴名)中配置的ServletContainerInitializer的實現類,javax.servlet.ServletContainerInitializer檔案的內容就是ServletContainerInitializer實現類的全類名,啟動時會執行這些實現類的onStartUp方法,可以通過@HandlesTypes傳入一些感興趣的型別,在onStartUp方法中做一些操作。一個jar包中只能有一個javax.servlet.ServletContainerInitializer配置檔案,一個javax.servlet.ServletContainerInitializer配置檔案中只能配置一個ServletContainerInitializer實現類。

ServletContainerInitializer實現類:

@HandlesTypes({HelloServiceInterface.class})
public class MyServletContainerInitializer implements ServletContainerInitializer{

	@Override
	public void onStartup(Set<Class<?>> set, ServletContext context) throws ServletException {
		System.out.println("感興趣的類:");
		for (Class<?> clazz : set) {
			System.out.println(">>>>>>" + clazz);
		}
	}

}

onStartUp方法的入參:

    set是@HandlesTypes中傳入的介面或者類的所有子介面或者子類(不包含該介面或該類本身);context是web專案的servlet上下文,一個web專案對應一個ServletContext,通過ServletContext可以來註冊web元件,比如第三方的filter元件(由於第三方的元件並不是我們寫的,我們無法通過@WebServlet、@WebFilter、@WebListener來標註使其攔截相應的請求,這個時候就需要在ServletContainerInitializer中通過ServletContext來註冊了)

javax.servlet.ServletContainerInitializer配置檔案內容:

com.bdm.servlet.MyServletContainerInitializer

javax.servlet.ServletContainerInitializer配置檔案的目錄:

此時在專案啟動時可以看到後臺日誌中打印出:

二、使用ServletContext註冊web元件

UserServlet.java:

public class UserServlet extends HttpServlet{

	private static final long serialVersionUID = -5343785314009218808L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.getWriter().write("tomcat...");
	}
}

UserFilter.java:

public class UserFilter implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("UserFilter...doFilter...");
		chain.doFilter(arg0, arg1);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}

UserListener.java:只要實現了ServletContextListener介面就可以監聽到ServletContext(Servlet容器)的建立和銷燬

public class UserListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent event) {
		System.out.println("UserListener...contextDestroyed...");
	}

	@Override
	public void contextInitialized(ServletContextEvent event) {
		System.out.println("UserListener...contextInitialized...");
	}

}

註冊web元件:

@HandlesTypes({HelloServiceInterface.class})
public class MyServletContainerInitializer implements ServletContainerInitializer{

	@Override
	public void onStartup(Set<Class<?>> set, ServletContext context) throws ServletException {
		
		ServletRegistration.Dynamic userServlet = context.addServlet("userServlet", new UserServlet());
		userServlet.addMapping("/user");
		
		FilterRegistration.Dynamic filter = context.addFilter("userFilter", UserFilter.class);
		filter.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true, "userServlet");
		filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
		
		context.addListener(UserListener.class);
	}

}

context.addServlet()註冊servlet元件,context.addFilter()註冊filter元件,這兩個元件都需要配置對映路徑,其中filter還可以配置攔截哪些servlet;context.addListener()註冊listener,listener在tomcat啟動時就會呼叫其中的邏輯;

servlet、filter、listener這些元件的註冊必須在tomcat容器啟動的時候,有兩處可以進行這些元件的註冊,一個就是上面的例子(通過ServletContainerInitializer中的ServletContext來註冊),還有一個地方可以註冊,就是在ServletContextListener的實現類中獲取到ServletContext,然後通過ServletContext註冊其他的listener、filter、servlet:

@WebListener
public class UserListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent event) {
		System.out.println("UserListener...contextDestroyed...");
	}

	@Override
	public void contextInitialized(ServletContextEvent event) {
		ServletContext servletContext = event.getServletContext();
		Dynamic addServlet = servletContext.addServlet("userServlet", UserServlet.class);
		addServlet.addMapping("/user");
		javax.servlet.FilterRegistration.Dynamic addFilter = servletContext.addFilter("userFilter", UserFilter.class);
		addFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
	}

}
public class UserListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent event) {
		System.out.println("UserListener...contextDestroyed...");
	}

	@Override
	public void contextInitialized(ServletContextEvent event) {
		ServletContext servletContext = event.getServletContext();
		Dynamic addServlet = servletContext.addServlet("userServlet", UserServlet.class);
		addServlet.addMapping("/user");
		javax.servlet.FilterRegistration.Dynamic addFilter = servletContext.addFilter("userFilter", UserFilter.class);
		addFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
	}

}


此處的UserLisener需要使用@WebListener註解的方式註冊,而不可以在ServletContainerInitializer中註冊,不知道什麼原因?