SpringMVC之url的使用

1.  实践场景

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

<a href="<c:url value='/demo/demo' />">按钮1</a>
<a href="${pageContext.request.contextPath}/demo/demo">按钮2</a>

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

<a href="${s:mvcUrl('DC#demo').build()}">按钮3</a>

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<T, MappingRegistration<T>> registry = new HashMap<T, MappingRegistration<T>>();

	private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();

	private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>();

	private final Map<String, List<HandlerMethod>> nameLookup =
				new ConcurrentHashMap<String, List<HandlerMethod>>();

	private final Map<HandlerMethod, CorsConfiguration> corsLookup =
				new ConcurrentHashMap<HandlerMethod, CorsConfiguration>();

	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源代码分析与实践>一书。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值