SpringMVC之url的使用

1.  实践场景

通常情况下。在jsp页面给标签加链接,会直接给出一个具体的URL。例1:

按钮1
按钮2

然而,SpringMVC4还提供了另外一种方式,可以通过Controller类名的大写字符+“#”+方法名,获得路径。例2:

按钮3

2. 代码分析

例1是我们绝大部分人的操作。这里不再细讲。

例2是SpringMVC给我们的提供的一个方便操作。需要用到这个标签。

<%@ taglib prefix="s" uri="http://www.springframework.org/tags" %>

标签里面定义了一个方法:mvcUrl。映射到MvcUriComponentsBuilder.MethodArgumentBuilder.fromMappingName 。方法的作用很简单。首先获得Spring中的RequestMappingInfoHandlerMapping实体类,接着拿到父类的内部类AbstractHandlerMethodMapping.MappingRegistry。MappingRegistry里面有多个map,用来保存URL和Handler的对应关系。当前需要用到的是nameLookup。里面保存的是name和handlerMethos的对应关系,name的获取规则是 类名的大写字母+“#”+方法名。spring4.2之前的版本,用的是MultiValueMap,这个是一Key多Value的Map集合。spring4.2之后,做了代码优化,使用 ConcurrentHashMap用来提高效率。

// org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry
class MappingRegistry {

	private final Map> registry = new HashMap>();

	private final Map mappingLookup = new LinkedHashMap();

	private final MultiValueMap urlLookup = new LinkedMultiValueMap();

	private final Map> nameLookup =
				new ConcurrentHashMap>();

	private final Map corsLookup =
				new ConcurrentHashMap();

	private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
}

使用nameLookUp解析输入的字符串,获得对应的handlerMethod,拼装handlerMethod中controller和method的requestMapping中的值然后输出。具体操作是通过MvcUriComponentsBuilder中内部类MethodArgumentBuilder的bulid()调用外部类的 fromMethodInternal 方法。详见代码:

//org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.MethodArgumentBuilder#build
public String build() {
	return fromMethodInternal(this.baseUrl, this.controllerType, this.method,
					this.argumentValues).build(false).encode().toUriString();
		}
//org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder#fromMethodInternal
private static UriComponentsBuilder fromMethodInternal(UriComponentsBuilder baseUrl,
			Class controllerType, Method method, Object... args) {

	baseUrl = getBaseUrlToUse(baseUrl);
	String typePath = getTypeRequestMapping(controllerType);
	String methodPath = getMethodRequestMapping(method);
	String path = pathMatcher.combine(typePath, methodPath);
	baseUrl.path(path);
	UriComponents uriComponents = applyContributors(baseUrl, method, args);
	return UriComponentsBuilder.newInstance().uriComponents(uriComponents);
}

3. 优缺点分析

下面详细分析一下当前使用例2的优缺点。

优点

          1.前端页面显示路径与@RequestMapping注解解耦。可以随意更改类名和方法的@RequestMapping注解。只要保证类名和方法名不修改即可

      2.springMVC4.2以后,为了提高nameMap的使用效率,将nameMap的实现方式,从MultiValueMap改成ConcurrentHashMap。使用并发响应速度大大提高。

缺点

          1. 使用不方便,需要手动写类大写和方法名

          2. 响应速度慢。需要从NameMap中获得。如果项目较大,方法较多并且页面中的链接较多。会降低响应速度。

          3. 需要将前端页面URL和类名的@RequestMapping解耦的地方不多,可用性不高。

综上所述,需要结合项目的实际情况,综合考虑使用。推荐使用例1的俩种方法。

SpringMVC使用版本:4.2.4

本文参考<看透SpringMVC源代码分析与实践>一书。

你可能感兴趣的:(JAVA,SpringMVC)