springmvc根据请求uri获取handlermapping源码
springmvc根据请求uri获取handlermapping源码
org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
org.springframework.web.servlet.DispatcherServlet#getHandler
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (logger.isTraceEnabled()) { logger.trace("Mapped to " + handler); } else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { logger.debug("Mapped to " + executionChain.getHandler()); } if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); config = (config != null ? config.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
此处定义个三个controller,分别采用springmvc实现controller的三种方式。如下所示。
@Component("/handlercontroller.do") public class HandlerController implements HttpRequestHandler { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("111"); } } @Component("/implController.do") public class ImplController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("实现Controller接口"); return new ModelAndView("index"); } } @Controller public class TestController { /** * 访问普通的字符串,试图解析器会解析成对应的页面 * @return */ @RequestMapping("/str.do") public Object Test(){ return "index"; } /** * 因为返回值是一个对象,所以如果不做特殊处理,则试图解析器无法解析 * 对象嵌套是一个难点 * @param name * @param request * @param response * @return */ @RequestMapping("/model.do") @ResponseBody public Object modeltest(String name, HttpServletRequest request, HttpServletResponse response){ System.out.println("调用了modeltest"); String req_name = request.getParameter("name"); Map hashMap = new HashMap<>(); hashMap.put("key", "value"); return hashMap; } }
现在依次测试
断点:
先访问:http://localhost/model.do
从getHandlerInternal(request)已经获取到handler
第二次测试地址:http://localhost/handlercontroller.do
进行代码跟踪发现程序在遍历三个handleMappings,分别是:RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、RouterFunctionMapping
此时RequestMappingHandlerMapping未空,所以遍历到BeanNameUrlHandlerMapping,因为这次访问的uri的定义方式是实现HttpRequestHandler接口。
此时已经找到了匹配的handler。
第三次访问地址:http://localhost/implController.do
可以看到,与第二次访问所获取handler的对象是同一个。
分类:
三大框架源码分析
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了