【Spring】内嵌Tomcat调试Mvc

菜瓜:今天听到个名词“父子容器”,百度了一下,感觉概念有点空洞,这是什么核武器?

水稻:你说的是SpringMvc和Spring吧,其实只是一个概念而已,用来将两个容器做隔离,起到解耦的作用,其中子容器可以拿到父容器的bean,父容器拿不到子容器的。但是SpringBoot出来之后这个概念基本就被淡化掉,没有太大意义,SpringBoot中只有一个容器了。

菜瓜:能不能给个demo?

水稻:可以。由于现在SpringBoot已经大行其道,Mvc你可能接触的少,甚至没接触过。

早些年启动一个Mvc项目费老鼻子劲了,要配置各种Xml文件(Web.xml,spring.xml,spring-dispather.xml),然后开发完的项目要打成War包发到Tomcat容器中

现在可以直接引入Tomcat包,用main方法直接调起。为了调试方便,我就演示一个Pom引入Tomcat的例子

①启动类

package com.vip.qc.mvc; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleListener; import org.apache.catalina.startup.Tomcat; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** * 参考: * https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet * <p> * 嵌入tomcat,由Tomcat发起对Spring容器的初始化调用过程 * <p> * - 启动过程 * * - Servlet规范,Servlet容器在启动之后会SPI加载META-INF/services目录下的实现类并调用其onStartup方法 * * - Spring遵循规范实现了ServletContainerInitializer接口。该接口在执行时会收集WebApplicationInitializer接口实现类并循环调用其onStartup方法 * * - 其中AbstractDispatcherServletInitializer * * * - 将spring上下文放入ContextLoaderListener监听器,该监听会发起对refresh方法的调用 * * * - 注册dispatcherServlet,后续会由tomcat调用HttpServletBean的init方法,完成子容器的refresh调用 * * * * @author QuCheng on 2020/6/28. */ public class SpringWebStart { public static void main(String[] args) { Tomcat tomcat = new Tomcat(); try {
// 此处需要取一个目录 Context context
= tomcat.addContext("http://www.likecs.com/", System.getProperty("java.io.tmp")); context.addLifecycleListener((LifecycleListener) Class.forName(tomcat.getHost().getConfigClass()).newInstance()); tomcat.setPort(8081); tomcat.start(); tomcat.getServer().await(); } catch (LifecycleException | ClassNotFoundException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } } static class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { private final static String PACKAGE_PATH = "com.vip.qc.mvc.controller"; private final static String PACKAGE_PATH_CHILD = "com.vip.qc.mvc.service"; @Override protected String[] getServletMappings() { return new String[]{"http://www.likecs.com/"}; } @Override protected Class<?>[] getRootConfigClasses() { // spring 父容器 return new Class[]{AppConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { // servlet 子容器 return new Class[]{ServletConfig.class}; } @Configuration @ComponentScan(value = PACKAGE_PATH_CHILD, excludeFilters = @ComponentScan.Filter(classes = Controller.class)) static class AppConfig { } @Configuration @ComponentScan(value = PACKAGE_PATH, includeFilters = @ComponentScan.Filter(classes = Controller.class)) static class ServletConfig { } } } 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpszjg.html