1.MVC是什么?
M是Model,V是View,C是Controller。
View很好理解,就是用户面对的视图。
Model可以理解成业务层和持久层。
Controller接收用户输入的请求数据,调用Model,返回View。
2.SpringMVC处理请求的流程
要点:
1 DispatcherServlet:称为中央调度器。在Tomcat服务器启动时,会解析web.xml文件,实例化DispatcherServlet对象。在DispatcherServlet对象的的init()方法中,根据指定的bean.xml文件,创建spring容器,创建controller,service,dao等bean对象。
2 关于子父容器的概念:DispatcherServlet对象创建时会在对象内部创建一个spring容器。如果我们有多个DispatcherServlet对象呢?理所当然会有多个spring容器,每个spring容器归属于独立的DispatcherServlet对象。但如果这样的话,多个spring容器内会存在冗余的对象。这样是对资源的浪费,能否有一种解决办法能解决冗余。答案肯定是有的,就是创建一个父容器,子容器共享父容器内的对象。利用ContextLoaderListener实现。ContextLoaderListener监听器在Tomcat启动时读取contextConfigLocation对应的路径创建一个父容器。之后我们创建的DispatcherServlet内的容器会通过setParent()方法自动设置父子关系,框架内部实现。事实上多个DispatcherServlet其实也没什么用处,一个其实够用了。如果只有一个DispatcherServlet那么也没有必要有父子容器。
3 DispatcherServlet如何工作的?DispatcherServlet在创建时需要指定他将要识别的uri,可以用通配符*。如"*
StringHttpMessageConverter String text/plain, */* MappingJackson2HttpMessageConverter Object application/json, application/*+json AllEncompassingFormHttpMessageConverter Map > application/x-www-form-urlencoded, multipart/form-data SourceHttpMessageConverter Source application/xml, text/xml, application/*+xml
6.控制器的异常处理
1.模块内局部异常处理。在处理器类中定义某方法,使用@ExceptionHandler注解(value=异常类.class)表示,当处理器类中的任意处理器抛出对应异常就会执行异常处理方法。
2.全局异常处理。定义一个异常处理类,用@ControllerAdvice标识,类中所有方法都用@ExceptionHandler注解标识。
7.拦截器interceptor
1.如何定义拦截器?
1.1实现HandlerInterceptor接口。接口中定义了三个方法,preHandler,postHandler,afterCompletion。
preHandler表示在handler执行前执行,通常用来做一些预处理,如认证,安全等,preHandler返回值是Boolean类型的,只有返回true时才会执行handler方法,返回false当前请求就被截断了。
postHandler表示在handler执行之后执行,可以对handler处理的ModelAndView做二次处理。
afterCompletion只有在preHandler方法返回true才会执行。
1.2声明拦截器,配置拦截路径
2.多个拦截器的执行顺序?
按照拦截器定义的顺序 preHandler1->preHandler2...->handler...->postHandler2->postHandler1...->afterCompletion2->afterCompletion1。
preHandler返回false之后后面的操作直接中断。
afterCompletion根据preHandler的返回结果来判断是否执行的,返回true就执行,false就不执行。
8.java配置springmvc
定义一个类实现WebMvcConfigurer接口用@Configuration标识,重写里面的方法即可。
9.DispatcherServlet底层是一个Servlet,继承了frameworkServlet。
frameworkServlet继承HttpServletBean。 HttpServletBean继承HttpServlet。HttpServlet继承GenericServlet。GenericServlet继承Servlet。
9.DispatcherServlet初始化的过程
1.DispatcherServlet是一个Servlet,符合Servlet生命周期。创建DispatcherServlet时首先调用init方法初始化。HttpServletBean对init方法进行了重写,DispatcherServlet执行的init其实是继承而来的。在HttpServletBean的init中继续调用frameworkServlet的initServletBean方法。在initServletBean中调用initWebApplication方法初始化容器。在initWebApplication中调用createWebApplicationContext通过反射创建容器,然后onFresh刷新容器,调用initStrategies进行组件的初始化,最后将容器放入全局作用域。
因为DIspatcherServlet继承了上面全部方法,所以在DispatcherServlet初始化时会执行一遍这些方法
10.DispatcherServlet调用服务的过程
Servlet处理服务的方法是service方法。当然DispatcherServlet也不例外。调用service方法处理请求,然后调用doService方法,最终调用doDispatch方法处理请求。
DispatcherServlet的doDispatcher原码。看注释!
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
//处理执行链对象
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
//调用HandlerMapping找到对应的handler对象封装成执行链对象并返回
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
this.noHandlerFound(processedRequest, response);
return;
}
//获取可执行该handler的HandlerAdapter实现类对象
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
//执行拦截器的preHandler方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//真正执行handler方法。这一步其实做了非常多工作。
//HandlerAdaptr帮我们从请求中获取参数,String转成参数类型。
//将java对象放入响应体等等操作。
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
this.applyDefaultViewName(processedRequest, mv);
//执行postHandler方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
//最后是对视图的处理和判断mv中是否有异常,有就进行异常处理和afterCompletion方法的执行。
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
11.springmvc处理服务的最终流程
1.用户请求到达,DispatcherServlet进行捕获
2.根据uri发给HandlerMapping处理,没找到就报404。
3.找到了的话HandlerMapping就把handler和拦截器集合和索引封装起来给DispatcherServlet返回一个HandlerExceuctionChain。
4.DispatcherServlet调用HandlerAdapter找到合适的,能处理这个handler的HandlerAdapter实现类。
5.得到这个HandlerAdapter实现类之后,开始执行拦截器preHandler方法。(正向)
6.handlerAdapter提取request中的请求参数并将string转换成java对象或类型,赋值到handler方法的形参上,接着执行真正handler方法。HTTPMessageConverter实现类对返回值进行消息转换。
7.返回一个ModelAndView对象给DispatcherServlet。
8.执行postHandler方法(反向)
9.渲染视图。判断ModelAndView中是否有异常,处理异常。执行afterCompletion方法(反向)。
10返回视图,返回数据。



