Servlet本质就是一个接口,提供了WEB应用的业务开发规范。没有main方法,不能独立运行,因此必须把它部署到Servlet容器中,由容器来实例化并调用 Servlet。
Tomcat其实是Web服务器和Servlet容器的结合体.
Web服务器:监听端口,对外提供WEB远程访问功能;将主机上的资源映射为可供外界访问的URL。----------------资源映射,静态的
Servlet容器:管理容器中的Servlet,接收WEB服务器的请求,分发至对应的Servlet处理相应的业务逻辑。------业务处理,动态的
spring-web 提供了核心 HTTP 集成,包括一些便捷的 servlet 过滤器, Spring HTTP 调用,用于集成其它 web 框架的基础结构以及技术(Hessian,Burlap)。spring-webmvc 是 Spring MVC 的一个实现。spriing-webmvc 依赖于 spring-web,这样包含它就会间接地添加 spring-web。不必显示添加 spring-web。如果你不使用 Spring MVC ,但想要借助其它 Spring 支持的 web 相关技术的优势,那么你只需依赖 spring-web 。
SpringMVC:本质是对Servlet的封装(请求分发、参数解析、相应处理),核心DispatcherServlet最终继承自HttpServlet。
Spring容器是管理service和dao的
SpringMVC容器是管理controller对象的
xml形式Spring整合SpringMVC
web.xml、spring.xml、spring-mvc.xml
web.xml配置样例
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--spring资源上下文定义,在指定路径加载pring的xml配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<!--监听器-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!--过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Springmvc的核心控制器,DispatcherServlet请求分发器-->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--初始化参数
contextConfigLocation 配置springmvc的xml配置文件, 指定路径
也可以不配置: 会自动去WEB-INF去找一个名字叫做 springmvc-servlet.xml 的文件
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--启动时加载servlet :
当web服务器 启动时就会创建servlet(会自动调用servlet的构造函数及init()方法)
-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--配置DispatcherServlet映射通常会为springmvc映射的路径为:除了.jsp的请求都会被匹配所有的请求都会匹配:
springmvc01/user/getUser.jsp ?*.do 、*.action url结尾以.do或者.action的请求会匹配/request/*
要进行约定 将jsp放在/views/ 所有的servlet请求都用/request/
-->
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
关键配置:
org.springframework.web.context.ContextLoaderListener------监听tomcat启动事件
classpath:spring.xml-----------------------------------------------------指定spring的配置
classpath:spring-mvc.xml----------------------------------------------指定springmvc的配置
Tomcat整体结构
Tomcat整体启动流程
catalina.sh中可以看到:set MAINCLASS=org.apache.catalina.startup.Bootstrap
Bootstrap通过反射实例化Catalina,并调用其load(),start()方法
Init
Start
添加StandardHost时,会为其添加一个HostConfig的监听器(识别上下文)
添加StandardContext时,会为其添加一个ContextConfig的监听器(解析上下文中的web.xml)
StandardHost启动时发布时间触发HostConfig的lifecycleEvent(LifecycleEvent event)方法,最终执行,应用部署任务。
Server.xml样例
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="/testweb" docBase="testweb.war" reloadbale="true"/>
<Context path="/testweb1" docBase="testweb.war" reloadable="true"/>
</Host>
appBase指定了Web应用部署的基础目录
Tomcat通过HostConfig完成该目录下Web应用的自动部署
Context节点说明:
path:指定访问该Web应用的URL入口(context-path)
docBase:指定Web应用的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性的相对路径。
reloadable:如果这个属性设为true,tomcat服务器在运行状态下会监视在WEB-INF/classes和 WEB-INF/lib目录下class文件的改动,如果监测到有class文件被更新的,服务器会自动重新加载 Web应用。
HostConfig:
// Deploy XML descriptors from configBase(server.xml文件描述符的方式部署)
deployDescriptors(configBase, configBase.list());
// Deploy WARs(war包的方式部署)
deployWARs(appBase, filteredAppPaths);
// Deploy expanded folders(文件夹的方式部署)
deployDirectories(appBase, filteredAppPaths);
StandardContext在启动时会通知所有listener它的启动状态,而StandardContext有一个默认listener是ContextConfig,所以会调用到HostConfig的lifecycleEvent方法
ContextConfig
configureStart()
webConfig()----该方法会解析web.xml
XML形式Root容器启动
关键配置
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
关键代码
StandardContext
--->listenerStart()
--->listener.contextInitialized(event)
ContextLoaderListener
--->contextInitialized(ServletContextEvent sce)
--->initWebApplicationContext(event.getServletContext())
--->context = createWebApplicationContext(servletContext)--------创建父容器
--->configureAndRefreshWebApplicationContext(cwac, servletContext)---刷新启动父容器
--->wac.refresh()
XML形式Web容器启动
关键配置
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
关键代码
StandardContext
loadOnStartup
Collect "load on startup" servlets that need to be initialized(收集load-on-startup>=0的servlet)
wrapper.load()----加载收集到的需要初始化的servlet
StandardWrapper
loadServlet()
servlet = (Servlet) instanceManager.newInstance(servletClass)-----实例化servlet
initServlet(servlet)----------------------------------------------初始化servlet
servlet.init(facade)----------------------------------------------初始化servlet
HttpServletBean
(DispatcherServlet extends FrameworkServlet;
FrameworkServlet extends HttpServletBean implements ApplicationContextAware)
init()
--->initServletBean()
FrameworkServlet
initServletBean()
--->this.webApplicationContext = this.initWebApplicationContext()
--->wac = this.createWebApplicationContext(rootContext)---实例化子容器
--->wac.setParent(parent)---子父容器关系建立
--->configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac)
--->wac.refresh()
--->onRefresh(wac)------------------------初始化DispatcherServlet相关配置
DispatcherServlet
onRefresh(ApplicationContext context)
--->initStrategies(context)
注解式容器启动(SPI)
/META- INF/service/javax.servlet.ServletContainerInitializer
org.springframework.web.SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer
{
实例化实现WebApplicationInitializer接口的非抽象类,
并initializer.onStartup(servletContext)
内部实现类都是抽象的,我们必须添加一个自定义实现类
}
关键抽象类
AbstractContextLoaderInitializer(父容器)
AbstractDispatcherServletInitializer(子容器)
AbstractAnnotationConfigDispatcherServletInitializer(对上述两类提供支持)