springmvc
Servlet继承关系
Servlet
接口有五个方法需要实现,比较重要的方法是service
方法每次请求都会进入这个方法GenericServlet
抽象类对Servlet
接口中的部分方法做了默认实现,用户自定义的Servlet
只需要继承GenericServlet
类就行了HttpServlet
类继承GenericServlet
重写了servlet
方法,方法的主要逻辑是区分http请求的请求方式HttpServletBean
:被spring管理的servlet,实现了EnvironmentAware
接口可以获取应用程序的环境变量和系统环境变量。主要作用是初始化环境系统然后让FrameworkServlet
拿到springWeb容器(servlet关联spring容器)FrameworkServlet
:实现了ApplicationContextAware
接口,关联项目的spring容器DispatcherServlet
:核心
servlet
继承关系
HandlerMethod
DispathcerServlet
包含几个重要的属性:
List<HandlerMapping> handlerMappings;
List<HandlerAdapter> handlerAdapters
1、Controller
spring的controller有多种,最常见的一种是使用@Controller
注解的类,还有一种是直接实现Controller
接口。每一种controller都有一个对应的RequestMapping去处理(建立url和method的映射关系,请求进来后根据url反射调用method)
@Controller
@SpringBootApplication
public class TestMvcComponents2 {
@ResponseBody
@RequestMapping(value = "/method1", method = RequestMethod.GET)
public String controllerMethod1() {
return "method1...";
}
@ResponseBody
@RequestMapping(value = "/method2", method = RequestMethod.GET)
public String controllerMethod2() {
return "method2...";
}
public static void main(String[] args) throws NoSuchFieldException {
ConfigurableApplicationContext ac = SpringApplication.run(TestMvcComponents2.class, args);
Map<String, HandlerMapping> handlerMappingMap = ac.getBeansOfType(HandlerMapping.class);
// MappingRegistry是一个map包含所有的HandlerMethod
RequestMappingHandlerMapping handlerMapping = (RequestMappingHandlerMapping)
handlerMappingMap.get("requestMappingHandlerMapping");
System.out.println(handlerMapping);
}
}
2、HandlerMapping
springmvc
中的控制器有多种实现方式,可以通过注解、继承Controller
接口等方式实现,所以对应的HandlerMapping
也有多种
RequestMappingHandlerMapping
是用来处理加了@Controller
的控制器的。加了@RequestMapping
注解的方法会被封装为HandlerMethod
,URL
地址作为map的key
,url
对应的handlerMethod
作为value
放入mappingRegistry
中。
3、HandlerMethod
加了@RequestMapping
注解的方法会被封装为HandlerMethod
当请求进来是spring会根据url调用对应的HandlerMethod。
4、handlerAdapter
adapter.handle(req, res, handleMethod)
HandlerMethod
有多种,加@RequestMapping
只是其中一种方式。调用不同的HandlerAdapter
需要使用不同的方法,adapter
对外提供了一个名字为handler
的API
可以适配(调用)不同的HandlerMethod
。
HandlerAdapter
1、参数解析器
@ResponseBody
@RequestMapping(value = "/s", method = RequestMethod.GET)
// GET http://localhost:8080/s?wd1=java&wd=python
public String controllerMethod3(@RequestParam("wd") String queryString) {
// 查询字符串为: python
return "查询字符串为: " + queryString;
}
spring框架反射调用controllerMethod3
方法时是如何给queryString
参数赋值的?通过参数解析器,所有的参数解析器都继承HandlerMethodArgumentResolver
接口。
@RequestParam
的解析器为RequestParamMethodArgumentResolver
,解析器的原理就是从request中获取值并返回
其他
onStartup
@HandlesTypes
ServletContext
来自tomcat
,添加servlet
// org.springframework.web.SpringServletContainerInitializer#onStartup
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer{
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses){
// webAppInitializerClasses包含所有实现了WebApplicationInitializer接口的类
// ~
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
容器初始化
RootApplicatoinContext
使用的事件通知的方式,触发fresh
(如果没有给根容器传)
WebApplicationContext
在HttpServlet
的init
调用后触发fresh
子容器作为DisaptcherServlet
构造方法的属性,传递给FrameworkServlet
HttpServlet#init --> FrameworkServlet#onfresh.........