聊一聊適配器模式在Spring框架中的應(yīng)用
一、什么是適配器模式
適配器模式(Adapter Pattern)是一種結(jié)構(gòu)型設(shè)計模式,它允許不兼容的接口之間能夠協(xié)同工作。在Spring框架中,適配器模式被廣泛應(yīng)用,特別是在Spring MVC的請求處理機制中。
適配器模式主要分為兩種:
- 類適配器:通過繼承來實現(xiàn)適配
- 對象適配器:通過組合來實現(xiàn)適配
Spring主要采用的是對象適配器模式,因為它更靈活且符合組合優(yōu)于繼承的原則。
二、Spring MVC中的HandlerAdapter
Spring MVC中,處理器(Handler)可以有多種形式:
- 基于注解的@Controller
- 實現(xiàn)Controller接口的類
- 實現(xiàn)HttpRequestHandler接口的類
- 其他自定義處理器
這些處理器的接口各不相同,DispatcherServlet如果直接與這些處理器交互,會導致代碼高度耦合且難以維護。HandlerAdapter的出現(xiàn)解決了這個問題,它提供了一個統(tǒng)一的接口,使得DispatcherServlet可以用統(tǒng)一的方式調(diào)用各種處理器。
HandlerAdapter源碼:
public interface HandlerAdapter {
boolean supports(Object handler);
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
long getLastModified(HttpServletRequest request, Object handler);
}
- supports():判斷是否支持給定的處理器
- handle():實際處理請求并返回ModelAndView
- getLastModified():獲取資源的最后修改時間(用于緩存)
三、Spring中主要HandlerAdapter實現(xiàn)
31. RequestMappingHandlerAdapter
這是處理基于注解的控制器(@Controller)的適配器,也是最常用的適配器。
使用示例:
@Controller
public class UserController {
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id, Model model) {
User user = userService.getUserById(id);
model.addAttribute("user", user);
return "userDetail";
}
}
RequestMappingHandlerAdapter源碼分析:
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
// 支持的方法參數(shù)解析器
private List<HandlerMethodArgumentResolver> argumentResolvers;
// 支持的方法返回值處理器
private List<HandlerMethodReturnValueHandler> returnValueHandlers;
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
// 1. 準備處理請求
checkRequest(request);
// 2. 執(zhí)行處理器方法
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
// 3. 處理結(jié)果并返回ModelAndView
// ... 詳細處理邏輯
}
}
處理流程:
- 通過supports()確認支持該處理器
- 解析方法參數(shù)(使用argumentResolvers)
- 解析@PathVariable
- 注入Model參數(shù)
- 調(diào)用目標方法
- 處理返回值(使用returnValueHandlers)
- 處理String類型的視圖名
- 處理Model屬性
3.2 SimpleControllerHandlerAdapter
這是處理實現(xiàn)了Controller接口的傳統(tǒng)控制器的適配器。
使用示例:
public class LegacyUserController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
Long id = Long.parseLong(request.getParameter("id"));
User user = userService.getUserById(id);
return new ModelAndView("userDetail", "user", user);
}
}
SimpleControllerHandlerAdapter的源碼分析:
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
3.3 HttpRequestHandlerAdapter
這是處理HttpRequestHandler接口實現(xiàn)的適配器,通常用于處理HTTP請求的原始形式。
使用示例:
public class ResourceHttpRequestHandler implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 直接操作response輸出資源
Path path = Paths.get("static", request.getPathInfo());
Files.copy(path, response.getOutputStream());
}
}
HttpRequestHandlerAdapter的源碼分析:
public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
@Override
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}
}
四、HandlerAdapter的注冊與使用流程
4.1 初始化過程
在Spring MVC中,HandlerAdapter通常通過WebMvcConfigurer配置:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureHandlerAdapters(HandlerAdapterRegistry registry) {
registry.addAdapter(new RequestMappingHandlerAdapter());
registry.addAdapter(new SimpleControllerHandlerAdapter());
registry.addAdapter(new HttpRequestHandlerAdapter());
}
}
4.2 DispatcherServlet的處理流程
讓我們看看DispatcherServlet如何利用HandlerAdapter處理請求:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1. 獲取處理器
HandlerExecutionChain mappedHandler = getHandler(request);
// 2. 獲取適配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 執(zhí)行前置攔截器
if (!mappedHandler.applyPreHandle(request, response)) {
return;
}
// 4. 實際處理請求
ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());
// 5. 應(yīng)用默認視圖名
applyDefaultViewName(request, mv);
// 6. 執(zhí)行后置攔截器
mappedHandler.applyPostHandle(request, response, mv);
// 7. 處理結(jié)果
processDispatchResult(request, response, mappedHandler, mv, dispatchException);
}
getHandlerAdapter()方法的實現(xiàn):
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
throw new ServletException("No adapter for handler [" + handler + "]");
}
圖片