一、springmvc启动加载流程
1、引入spring-web.jar包时,在这个包的META-INF/services/javax.servlet.ServletContainerInitializer文件中定义的加载类SpringServletContainerInitializer,提供给springmvc实现初始化的操作。
2、在SpringServletContainerInitializer类中,通过@HandlesTypes来引入WebApplicationInitializer。
3、自己自定义的启动类只要继承了WebApplicationInitializer类并实现了onStartUp方法,那么servlet容器在启动的时候就会拿到自己自定义的启动类,并开始启动。
**启动原理:**servlet容器在初始化的时候会加载到SpringServletContainerInitializer类,然后这个类中通过@HandlesTypes来引入WebApplicationInitializer子类,然后回调传递ServletContext上下文,此处使用的是模板方法。
springmvc是如何来替代web.xml的?核心就是使用的SpringServletContainerInitializer类。
二、拦截器与过滤器区别
相同点:
拦截器和过滤器都是基于Aop实现,能够对请求执行之前和之后实现拦截。
不同点:
过滤器是基于Servlet容器实现,对Web请求之前和之后实现拦截
拦截器不需要依赖于Servlet、不仅可以实现Web请求进行拦截,还有对其他方法拦截等。
过滤器比拦截器先执行,拦截器封装的方法比过滤器拦截使用起来更加简单。
应用场景:
拦截器:权限控制、日志打印、参数验证、会话信息。
过滤器:编码转换、跨域解决、xss攻击。
三、DispatcherServlet底层源码分析

1.执行doDispatch;
2.调用getHandler方法获取请求目标的方法 也就是 请求url映射路径对应的控制层具体的方法;
handlerMappings的作用查找控制器位置,比如xml和注解方式;
3.调用getHandlerAdapter获取控制层适配器 RequestMappingHandlerAdapter;
4.执行拦截器前置方法 preHandle() 如果返回为true的话;
5.执行实际请求目标方法 返回modeAndView对象;
6.执行拦截器PostHandle()方法;
7.设置渲染视图层内容;
8.执行拦截器afterCompletion方法;
四、SpringMVC控制对象初始化流程
1、HttpServletBean类的init() 方法
2、FrameworkServlet类的initServletBean() 方法 → initWebApplicationContext()
3、DispatcherServlet类的onRefresh() 方法 → initStrategies()方法
java
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);//初始化上传文件解析器(或者是多部分请求解析器)
initLocaleResolver(context);//初始化本地化解析器
initThemeResolver(context);//初始化主题解析器
initHandlerMappings(context);//初始化处理器映射器
initHandlerAdapters(context);//初始化处理器适配器
initHandlerExceptionResolvers(context);//初始化处理器异常解析器
initRequestToViewNameTranslator(context);//初始化请求到视图名翻译器
initViewResolvers(context);//初始化视图解析器
initFlashMapManager(context);//初始化重定向数据管理器
}
五、SpringMVC中的适配器
**适配器模式:**将一个系统的接口转换成另外一种形式,从而使原来不能直接调用的接口变得可以调用。使用适配器可以针对不容的handler类型找到不同的适配器来实现执行目标方法。
SpringMVC中有以下几种适配器:
1、继承Controller方式所使用的适配器:SimpleControllerHandlerAdapter
2、 HTTP请求处理器适配器:HttpRequestHandlerAdapter
3、注解方式(@Controller)的处理器适配器:RequestMappingHandlerAdapter
适配器模式应用场景
-
Mybatis多种日志框架的整合(logback、log4j)
-
SpringMVC适配器模式
-
新老版本的兼容问题
适配器模式源码分析
java
1.使用getHandlerAdapter获取对应的hanlder的具体HandlerAdapter
2.HandlerAdapter接口有如下的子 c处理请求适配器
2.1继承Controller方式所使用的适配器:SimpleControllerHandlerAdapter
2.2 HTTP请求处理器适配器:HttpRequestHandlerAdapter
2.3注解方式(@Controller)的处理器适配器:RequestMappingHandlerAdapter
如果不采用适配器的话 :
If(hanlder instanceof Controller){
// 执行Controller适配器
}
If(hanlder instanceof HttpControler){
// 执行我们的HttpController
}
If(hanlder instanceof ServletControler){
// 执行我们的HttpController
}
If(hanlder instanceof AnnotationControler){
// 执行我们的AnnotationController
}
六、SpringMvc异步实现方式
异步支持需要注意的两个地方
* 1、config类中开启异步@EnableAsync
* 2、初始化类中 dynamic.setAsyncSupported(true);//开启springmvc异步
1、第一种方式:直接在接口上添加@Async注解来实现
java
@Async
public String getMember(){
try {
System.out.println("2、业务处理开始,线程名称"+Thread.currentThread().getContextClassLoader());
Thread.sleep(3000);
System.out.println("3、业务处理完毕,线程名称"+Thread.currentThread().getContextClassLoader());
}catch (Exception e){
e.printStackTrace();
}
return "member";
}
2、第二种方式:使用Callable类的方式
java
/**
* 异步支持需要注意的两个地方
* 1、config类中开启异步@EnableAsync
* 2、初始化类中 dynamic.setAsyncSupported(true);//开启springmvc异步
* Callable这种方式也是需要等业务线程处理完毕后,才会返回给客户端,为了避免等待时间,可以在客户端写一个定时器来查询处理结果
*/
@RequestMapping("/asyncMember")
@ResponseBody
public Callable<String> asyncMember(){
Callable<String> callable = new Callable<String>() {
public String call() throws Exception {
//耗时的时间都可以放在这个里面去处理
String member = memberService.getMember();
return member;
}
};
return callable;
}