我是靠谱客的博主 文艺钢笔,最近开发中收集的这篇文章主要介绍【SpringMVC】DispatcherServlet重要组件之一HandlerMapping,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
概括:
作用是根据request找到相应处理器Handler和Interceptors,HandlerMapping接口里只有一个方法:
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
我们也可以自己定义一个HandlerMapping,实现方法。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
按顺序遍历所有的HandlerMapping,找到后立即返回。
配置顺序比如:order越小优先级越高
详情
AbstractHandlerMapping
HandlerMapping的抽象实现,所有HandlerMapping都继承自它。采用模板模式设计了HandlerMapping实现。
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
implements HandlerMapping, Ordered{
....省略...
@Override
protected void initApplicationContext() throws BeansException {
//模板方法,用于子类提供一个添加或者修改Interceptors的入口,目前SpringMVC没有实现
extendInterceptors(this.interceptors);
//将SpringMVC容器及父容器中的所有MappedInterceptor类型Bean添加到mappedInterceptors属性
detectMappedInterceptors(this.mappedInterceptors);
//初始化Interceptor,具体内容其实是将Interceptors属性里所包含的对象按类型添加到mappedInterceptors或者adaptedInterceptors
initInterceptors();
}
protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
mappedInterceptors.addAll(
BeanFactoryUtils.beansOfTypeIncludingAncestors(
getApplicationContext(), MappedInterceptor.class, true, false).values());
}
protected void initInterceptors() {
if (!this.interceptors.isEmpty()) {
for (int i = 0; i < this.interceptors.size(); i++) {
Object interceptor = this.interceptors.get(i);
if (interceptor == null) {
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
}
if (interceptor instanceof MappedInterceptor) {
this.mappedInterceptors.add((MappedInterceptor) interceptor);
}
else {
this.adaptedInterceptors.add(adaptInterceptor(interceptor));
}
}
}
}
}
AbstractHandlerMapping之用
通过getHandler方法来获取处理器Handler和拦截器Interceptor的
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 = getApplicationContext().getBean(handlerName);
}
return getHandlerExecutionChain(handler, request);
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
chain.addInterceptors(getAdaptedInterceptors());
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}
AbstractUrlHandlerMapping系列
AbstractUrlHandlerMapping系列都继承自AbstractUrlHandlerMapping;通过url来进行匹配的。大致原理是将url与对应的Handler保存在一个map中,在getHandlerInternal方法中使用url从map中获取Handler。AbstractUrlHandlerMapping中实现了具体用url从map中获取Handler的过程,而map的初始化则交给了具体的子孙类去完成。
private Object rootHandler;
private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();
@Override
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
Object handler = lookupHandler(lookupPath, request);
if (handler == null) {
// We need to care for the default handler directly, since we need to
// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
Object rawHandler = null;
if ("/".equals(lookupPath)) {
rawHandler = getRootHandler();
}
if (rawHandler == null) {
rawHandler = getDefaultHandler();
}
if (rawHandler != null) {
// Bean name or resolved handler?
if (rawHandler instanceof String) {
String handlerName = (String) rawHandler;
rawHandler = getApplicationContext().getBean(handlerName);
}
validateHandler(rawHandler, request);
handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
}
}
if (handler != null && logger.isDebugEnabled()) {
logger.debug("Mapping [" + lookupPath + "] to " + handler);
}
else if (handler == null && logger.isTraceEnabled()) {
logger.trace("No handler mapping found for [" + lookupPath + "]");
}
return handler;
}
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
// Direct match?
Object handler = this.handlerMap.get(urlPath);
if (handler != null) {
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
return buildPathExposingHandler(handler, urlPath, urlPath, null);
}
// Pattern match?
List<String> matchingPatterns = new ArrayList<String>();
for (String registeredPattern : this.handlerMap.keySet()) {
if (getPathMatcher().match(registeredPattern, urlPath)) {
matchingPatterns.add(registeredPattern);
}
}
String bestPatternMatch = null;
Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
if (!matchingPatterns.isEmpty()) {
Collections.sort(matchingPatterns, patternComparator);
if (logger.isDebugEnabled()) {
logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
}
bestPatternMatch = matchingPatterns.get(0);
}
if (bestPatternMatch != null) {
handler = this.handlerMap.get(bestPatternMatch);
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
validateHandler(handler, request);
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
// There might be multiple 'best patterns', let's make sure we have the correct URI template variables
// for all of them
Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();
for (String matchingPattern : matchingPatterns) {
if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
uriTemplateVariables.putAll(decodedVars);
}
}
if (logger.isDebugEnabled()) {
logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
}
return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
}
// No handler found...
return null;
}
SimpleUrlHandlerMapping
AbstractDetectingUrlHandlerMapping
AbstractHandlerMethodMapping系列
最后
以上就是文艺钢笔为你收集整理的【SpringMVC】DispatcherServlet重要组件之一HandlerMapping的全部内容,希望文章能够帮你解决【SpringMVC】DispatcherServlet重要组件之一HandlerMapping所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复