- 适配器出现的原因
-
- 因为Handler的返回是多种的,那么在对用于进行显示响应结果的时候显然不能使用同一种方式进行响应
- 适配器的作用就是根据返回的handler不同进行不同响应结果的适配,采用适配器模式
- HandlerAdapter 接口
-
- SpringMVC 中使用适配器模式来解决不同的 Handler 的执行。根据 Handler 来找到支 持它的 HandlerAdapter,通过 HandlerAdapter 执行这个 Handler 得到 ModelAndView 对 象。
- 接口中的抽象方法
-
- boolean supports(Object handler); 判断是否支持传入的 Handler
- ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) 用来使用 Handler 处理请求
- long getLastModified(HttpServletRequest request, Object handler); 用 来 获 取 资 料 的 Last-Modified 值
- 类结构
-
- SpringMVC提供了四种适配的方式(低版本有五种,已经过时)
- 二)HandlerAdapter 接口下的四种适配器适配的请求
-
- 1.首先在判断支持的handler之前是会先调用的supports()方法,至于这个的方式是在哪里调用的在下面的解析中会解释,现在为了讲清楚每个的适配器的适配具体Hanlder
- 2.AbstractHandlerMethodAdapter适配 器
- supports()方法判断传入的适配器是否是HandlerMethod的实例很明显AbstractHandlerMethodAdapter是用于处理注解方式的适配器
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
- 如果是调用子类实现的supportsInternal的实现方法
protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
- 在返回为true的情况下会调用handleInternal方法
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;//创建视图对象
checkRequest(request);//检查请求的有效性
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);//获取sesion
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);//调用HandlerMethod封装的方法
}
}
else {
// No HttpSession available -> no mutex necessary
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
- 3.HttpRequestHandlerAdapter适配器
- 和上面流程一致判断是HttpRequestHandler的对象
- HttpRequestHandler接口的方法,用于处理实现了此接口的Controller
public interface HttpRequestHandler {
void handle(HttpRequest request, HttpResponse response, HttpContext context)
throws HttpException, IOException;
}
- 1.首先判断传入的Handler是不是HttpRequestHandler接口的实例
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);//实现上还是调用实现类的方法
return null;
}
- 4.SimpleControllerHandlerAdapter适配器
-
- SimpleControllerHandlerAdapter 是 Controller 实现类的适配器类,其本质也是执行 Controller 中的 handleRequest 方法。
- 1.首先执行判断实例对象是否为Controller接口的实现类
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);//强转调用实现类的方法
}
- 5.SimpleServletHandlerAdapter适配器
-
- SimpleServletHandlerAdapter 其实是一个 Servlet 的适配器,其最终执行的方法是 Servlet 的 service 方法
- 1.首先执行判断实例对象是否为Servlet接口的实现类
@Override
public boolean supports(Object handler) {
return (handler instanceof Servlet);
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((Servlet) handler).service(request, response);//调用继承了Servlet的子类的service方法
return null;
}
- 四)适配器初始化和具体响应适配的选择
-
- 1).适配器的初始化在DispatcherServlet前端控制器中
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);//初始化适配器
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
- 2.适配器的初始化分为两种
-
- 下面是初始化是适配器的方法
- 1.在配置文件设置了注解驱动创建的适配器是以下三种
- RequestMappingHandlerAdapter
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
- 存在Map集合中的方式键适配器的全称,值是适配器对象(版本之间存在差异)
- 2.在配置文件内未注册注解驱动
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
//想看在这里打断点
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
OrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
//创建默认的适配器
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
}
}
}
- 2)适配在响应的时候是如何选择的呢?
-
- 在进行响应的时候,适配器的选择要根据Handler的类型进行判断是什么类型就创建什么类型的适配器
- 解析完毕的请求都会到doDispatch方法内进行处理
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
//此方法就是根据handler获取对应的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
- 在getHandlerAdapter方法内调用了适配器的supports方法,这也是上面遗留的问题
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {//调用适配器的supports返方法判断适配器的类型
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
- 总结
-
- 1.适配器分为四种,代表四种不同的适配方式,最常用的就是RequestMappingHandlerAdapter
- 2.在进行进行适配器初始化的时候要分为有没有配置注解驱动,因为没有注解驱动创建的适配器是默认的情况下的适配器不支持注解。
- 3.适配器的使用要根据Handler的类型判断