简介
在Spring MVC中,HandlerMapping
是一个非常重要的组件,它负责将请求分发给对应的处理器。AbstractUrlHandlerMapping
是HandlerMapping
的一个实现类,它通过URL映射规则来确定请求应该由哪个处理器来处理。本文将详细介绍AbstractUrlHandlerMapping
的源码实现,并提供两个示例说明。
AbstractUrlHandlerMapping源码解读
AbstractUrlHandlerMapping
是HandlerMapping
的一个抽象实现类,它提供了一些通用的方法和属性,如urlMap
、order
、pathMatcher
等。以下是AbstractUrlHandlerMapping
的源码实现。
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
private Map<String, Object> urlMap = new LinkedHashMap<>();
private UrlPathHelper urlPathHelper = new UrlPathHelper();
private PathMatcher pathMatcher = new AntPathMatcher();
private boolean useTrailingSlashMatch = true;
private boolean lazyInitHandlers = false;
public void setUrlMap(Map<String, ?> urlMap) {
this.urlMap = new LinkedHashMap<>(urlMap);
}
public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
this.urlPathHelper = (urlPathHelper != null ? urlPathHelper : new UrlPathHelper());
}
public void setPathMatcher(PathMatcher pathMatcher) {
this.pathMatcher = (pathMatcher != null ? pathMatcher : new AntPathMatcher());
}
public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) {
this.useTrailingSlashMatch = useTrailingSlashMatch;
}
public void setLazyInitHandlers(boolean lazyInitHandlers) {
this.lazyInitHandlers = lazyInitHandlers;
}
@Override
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
handler = getDefaultHandler();
}
return handler;
}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
Object handler = this.urlMap.get(urlPath);
if (handler == null) {
handler = lookupHandler(urlPath, request.getMethod());
}
return handler;
}
protected Object lookupHandler(String urlPath, String httpMethod) throws Exception {
List<Object> matchingHandlers = new ArrayList<>();
for (Map.Entry<String, Object> entry : this.urlMap.entrySet()) {
String mappedPath = entry.getKey();
Object handler = entry.getValue();
if (this.pathMatcher.match(mappedPath, urlPath)) {
if (handler instanceof String) {
handler = getApplicationContext().getBean((String) handler);
}
matchingHandlers.add(handler);
}
}
if (!matchingHandlers.isEmpty()) {
if (matchingHandlers.size() > 1) {
matchingHandlers = sortMatchingHandlers(matchingHandlers, urlPath, httpMethod);
}
return matchingHandlers.get(0);
}
return null;
}
protected List<Object> sortMatchingHandlers(List<Object> matchingHandlers, String lookupPath, String httpMethod) {
if (matchingHandlers.size() > 1) {
Comparator<Object> comparator = new RequestMappingInfoHandlerMethodMappingNamingComparator(this.pathMatcher, lookupPath);
if (this.order != null) {
comparator = new OrderComparator().compare(comparator, this.order);
}
if (this.useTrailingSlashMatch) {
comparator = new TrailingSlashHandlerMappingComparator(lookupPath).compare(comparator, null);
}
Collections.sort(matchingHandlers, comparator);
}
return matchingHandlers;
}
}
在上面的源码中,我们可以看到AbstractUrlHandlerMapping
定义了一些属性和方法,如urlMap
、urlPathHelper
、pathMatcher
、useTrailingSlashMatch
、lazyInitHandlers
等。其中,urlMap
是一个Map
对象,用于存储URL映射规则和对应的处理器;urlPathHelper
是一个UrlPathHelper
对象,用于获取请求的URL路径;pathMatcher
是一个PathMatcher
对象,用于匹配URL路径和映射规则;useTrailingSlashMatch
表示是否使用尾部斜杠匹配;lazyInitHandlers
表示是否延迟初始化处理器。
在getHandlerInternal()
方法中,我们可以看到AbstractUrlHandlerMapping
使用urlPathHelper
获取请求的URL路径,并调用lookupHandler()
方法查找对应的处理器。如果找不到对应的处理器,则返回默认的处理器。
在lookupHandler()
方法中,我们可以看到AbstractUrlHandlerMapping
首先从urlMap
中查找是否有对应的处理器,如果没有,则调用lookupHandler(String urlPath, String httpMethod)
方法查找对应的处理器。在lookupHandler(String urlPath, String httpMethod)
方法中,AbstractUrlHandlerMapping
遍历urlMap
中的所有映射规则,使用pathMatcher
匹配URL路径和映射规则,找到匹配的处理器后,将其添加到matchingHandlers
列表中。如果matchingHandlers
列表不为空,则调用sortMatchingHandlers()
方法对处理器进行排序,并返回第一个处理器。
示例1:使用AbstractUrlHandlerMapping处理HTTP GET请求
以下是一个使用AbstractUrlHandlerMapping
处理HTTP GET请求的示例。
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView("hello");
modelAndView.addObject("message", "Hello, World!");
return modelAndView;
}
}
public class HelloHandlerMapping extends AbstractUrlHandlerMapping {
public HelloHandlerMapping() {
setUrlMap(Collections.singletonMap("/hello", new HelloController()));
setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
public class HelloWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(HelloHandlerMapping.class);
context.setServletContext(servletContext);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
在上面的示例中,我们首先定义了一个HelloController
类,它实现了Controller
接口,并在handleRequest()
方法中返回一个ModelAndView
对象。然后,我们定义了一个HelloHandlerMapping
类,它继承了AbstractUrlHandlerMapping
类,并在构造函数中使用setUrlMap()
方法设置了URL映射规则和对应的处理器。最后,我们定义了一个HelloWebApplicationInitializer
类,它实现了WebApplicationInitializer
接口,并在onStartup()
方法中注册了HelloHandlerMapping
类和DispatcherServlet
。
示例2:使用AbstractUrlHandlerMapping处理HTTP POST请求
以下是另一个使用AbstractUrlHandlerMapping
处理HTTP POST请求的示例。
public class CalculatorController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
int a = Integer.parseInt(request.getParameter("a"));
int b = Integer.parseInt(request.getParameter("b"));
int result = a + b;
ModelAndView modelAndView = new ModelAndView("result");
modelAndView.addObject("result", result);
return modelAndView;
}
}
public class CalculatorHandlerMapping extends AbstractUrlHandlerMapping {
public CalculatorHandlerMapping() {
setUrlMap(Collections.singletonMap("/calculator", new CalculatorController()));
setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
public class CalculatorWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(CalculatorHandlerMapping.class);
context.setServletContext(servletContext);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
在上面的示例中,我们首先定义了一个CalculatorController
类,它实现了Controller
接口,并在handleRequest()
方法中获取请求参数a
和b
,计算结果后返回一个ModelAndView
对象。然后,我们定义了一个CalculatorHandlerMapping
类,它继承了AbstractUrlHandlerMapping
类,并在构造函数中使用setUrlMap()
方法设置了URL映射规则和对应的处理器。最后,我们定义了一个CalculatorWebApplicationInitializer
类,它实现了WebApplicationInitializer
接口,并在onStartup()
方法中注册了CalculatorHandlerMapping
类和DispatcherServlet
。
总结
本文详细介绍了AbstractUrlHandlerMapping
的源码实现,并提供了两个示例说明。我们首先介绍了AbstractUrlHandlerMapping
的属性和方法,如urlMap
、urlPathHelper
、pathMatcher
、useTrailingSlashMatch
、lazyInitHandlers
等。然后,我们提供了一个使用AbstractUrlHandlerMapping
处理HTTP GET请求的示例和一个使用AbstractUrlHandlerMapping
处理HTTP POST请求的示例。通过本文的介绍,我们可以了解到如何在Spring MVC应用程序中使用AbstractUrlHandlerMapping
来分发请求。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringMVC源码解读之HandlerMapping – AbstractUrlHandlerMapping系列request分发 - Python技术站