【记】SpringMVC 面试题总结

1.什么是SpringMVC?

SpringMVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model、View、Controller分离,将Web层进行职责解耦,把复杂的Web应用分成逻辑清晰的几个部分,简化开发,减少出错,方便组内开发人员之间的配合

2.SpringMVC的执行流程是什么样的?

  1. 浏览器发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet先对请求进行一个简单判断(是简单请求还是Multipart请求),然后DispatcherServlet遍历每一个处理器映射器HandlerMapping,将请求交给每一个HandlerMapping进行匹配
  3. HandlerMapping接收请求后,对请求进行解析,然后根据解析结果,寻找对应的处理器Handler对象及处理器拦截器HandlerInterceptor,最后将其包装成处理器执行链HandlerExecutionChain对象返还给DispatcherServlet
  4. DispatcherServlet根据HandlerExcutionChain对象中的Handler寻找与之对应的处理器适配器HandlerAdapter对象,同时执行了HandlerExecutionChain中的拦截器前端方法(preHandler())
  5. 找到对应的HandlerAdapter之后,执行对应的处理器Handler
  6. Handler执行完毕之后,返还ModelAndView对象给对应的HandlerAdapter,HandlerAdapter再将其返还给DispatcherServlet
  7. DispatcherServlet接收ModelAndView对象之后,先调用HandlerExcutionChain中的拦截器后端方法(postHandler()),之后遍历所有的视图解析器ViewResolver,匹配ModelAndView对象
  8. 匹配成功后,ViewResolver将视图名称域响应目标定位对象进行绑定,形成视图View对象返还给DispatcherServlet
  9. DispatcherServlet根据View对象调用对应的渲染方法,对其进行渲染(合并数据Model、结合View对象中的响应目标定位对象准备响应对象Response、结合合并的数据Model和Response对象形成最终的响应视图)
  10. DispatcherServelt渲染好View对象之后,执行HandlerExcutionChain的afterCompletion方法,进行最终响应
DispatcherServlet extends FrameworkServlet extends HttpServletBean extends HttpServlet

enum HttpMethod{
	GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
}

class FrameworkServlet{
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res){
		HttpMethod httpMethod=HttpMethod.resolve(req.getMethod());
		if(httpMethod==HttpMethod.PATCH || httpMethod==null){
			processRequest(req,res);
		}else{
			super.serrvice(req,res);
		}
		...
	}
	
	protected final void processRequest(req,res){
		...
		try{
			doService(req,rest);
		}catch...
	}
	
	protected abstract void doService(req,res){
		throws Exception;
	}
}

class DispatcherServlet{
	@Override
	protected void doService(req,res){
		...
		try{
			//分发
			doDispatch(req,res);
		}finally{
			...
		}
	}
	
	protected void doDispatch(req,res){
		HttpServletRequest processRequest=req;
		HandlerExecutionChain mappedHandler=null;
		boolean multpartRequestParsed=false;
		...
		try{
			ModelAndView mv=null;
			...
			try{
				//检查请求是否是二进制请求
				processedRequest=chekMultipart(req);
				multipartRequestParsed=(processedRequest!=req);
				
				//根据请求获取Handler
				mappedHandler=getHandler(processedRequest);
				//Handler为空判断
				if(mappedHandler == null){
					noHandlerFound(processedRequest,res);
					return;
				}
				
				//根据Handler获取HandlerAdapter
				HandlerAdapter ha=getHandlerAdapter(mappedHandler.getHandler());
				
				String method=req.getMethod();
				...
				
				//执行拦截器
				if(!mappedHandler.applyPreHandler(processedRequest,res)){
					return;
				}
				
				//执行Hanlder
				mv=ha.handle(processedRequest,res,mappedHandler.getHandler());
			}
		}
	}
	
	//获取Handler
	//handlerMappings来自于jar包中的DispatcherServlet.properties
	@Nullable
	private List<HandlerMapping> handlerMappings;
	@Nullable
	protected HandlerExecutionChain getHandler(req){
		if(this.handlerMappings!=null){
			//遍历HandlerMapping
			//因为有不同方式注册的Handler,所以存在多个HandlerMapping
			//可以通过@Controller注册
			//也可以通过@WebServlet+extends HttpServlet注册
			//还可以通过@Component+implements Controller注册
			for(HandlerMapping hm:this.handlerMappings){
				...
				//将获取Handler,并将其封装到HandlerExecutionChain
				HandlerExecutionChain handler=hm.getHandler(req);
				if(handler!=null){
					return handler;
				}
			}
		}
		return null;
	}
	
	//获取HandlerAdapter
	//handlerAdapters的值来自于jar包中的DispatcherServlet.properties
	@Nullable
	private List<HandlerAdapter> handlerAdapters;
	protected HandlerAdapter getHandlerAdapter(Object handler){
		if(this.handlerAdapters!=null){
			//遍历HandlerAdapter
			//因为有不同方式注册的Handler,所以存在多个HandlerAdapter
			for(HandlerAdapter ha:this.handlerAdapters){
				...
				//匹配Handler
				if(ha.support(handler){
					return ha;
				}
			}
		}
	}
}

//执行Handler
//执行mappedHandler.getHandler()
class HandlerExecutionChain{
	...
	//
	public Object getHandler(){
		return this.handler;
	}
}

//执行Handler
//执行ha.handle(processedRequest,res,mappedHandler.getHandler())

//如果自定义的Handler是通过implements Controller注册的话
//则强制转换成Controller接口,向下转型执行自定义的Handler中的方法
class SimpleControllerHanderAdapter{
	...
	@Override
	@Nullable
	public ModelAndView handle(req,res,Object handler){
		return ((Controller)handler).test(req,res);
	}
}

//如果自定义的Handler是通过@Controller注册的话
class AbstractHandlerMethodAdapter{
	@Override
	@Nullable
	public final ModelAndView(req,res,Object handler){
		return handlerInternal(req,res,(HandlerMethod)handler);
	}
}
class RequestMappingHandlerAdapter{
	@Override
	protected ModelAndView handlerInternal(req,res,HandlerMethod handlerMethod){
		ModelAndView mav;
		checkRequest(req);
		...
		else{
			mav=invokeHandlerMethod(req,res,handlerMethod);
		}
	}
	
	@Nullable
	protected ModelAndView invokeHandlerMethod(req,res,handlerMethod){
		...
	}
}

3.SpringMVC有哪些重要的组件?

  1. 前端控制器DispatcherServlet:相当于转发器
  2. 处理器映射器HandlerMapping:根据请求url查找对应的处理器Handler
  3. 处理器执行链HandlerExecutionChain:处理器执行链
  4. 处理器适配器HandlerAdapter:处理器Handler需要遵循的规范
  5. 具体的处理器Handler:程序员开发的具体处理器(Controller类)
  6. 视图解析器ViewResolver:对视图View进行解析
  7. 具体的视图View:程序员开发的具体视图(如jsp、pdf等)

为什么SpringMVC底层通过反射获取Handler的单元方法?

  1. DispatcherServlet不能使用new
  2. 通过@Controller获取的Handler不是Servlet子类,所以不能转发和重定向
  3. 只能使用反射
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值