1.基本思路
通过uri直接匹配到Controller中的HandlerMethod,
重写 AbstractHandlerMethodMapping
的 registerHandlerMethod()
,将自己的uri
与RequestMappingInfo
放在一个map里,
然后再重写 lookupHandlerMethod()
通过uri直接查询HandlerMethod ,如果没找到就用默认查询策略去寻找就好了。
2.创建自定义MvcRequestMappingHandlerMapping
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;
@Slf4j
public class MvcRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
private static Map<String, RequestMappingInfo> infoMap = new HashMap<>();
@Override
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
try {
// 自定义规则
String finalPath = lookupPath
.replace("//", "/")
.replace(".json", "")
.replace(".jhtml", "");
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = super.getHandlerMethods();
String key = buildKey(finalPath, request.getMethod());
RequestMappingInfo mappingInfo = infoMap.get(key);
HandlerMethod method = handlerMethodMap.get(mappingInfo);
if (method!=null) {
return method;
}
} catch (Exception e) {
log.error("Direct Matching RequestMappingInfo Error. path => " + lookupPath);
}
return super.lookupHandlerMethod(lookupPath, request);
}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
this.setOrder(-1);
}
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
try {
Class<?> handlerType = (handler instanceof String ?
obtainApplicationContext().getType((String) handler) : handler.getClass());
RequestMapping beanMapping = AnnotatedElementUtils.findMergedAnnotation(handlerType, RequestMapping.class);
RequestMapping methodMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
if (beanMapping!=null && methodMapping!=null) {
String bm = beanMapping.value()[0];
String mm = methodMapping.value()[0];
if (!mm.startsWith("/")) {
mm = "/"+mm;
}
RequestMethod[] methods = methodMapping.method();
for (RequestMethod requestMethod : methods) {
String key = buildKey(bm+mm, requestMethod.toString());
infoMap.put(key, mapping);
}
}
} catch (NoSuchBeanDefinitionException e) {
logger.error("Register HandlerMethod Error. ", e);
}
super.registerHandlerMethod(handler, method, mapping);
}
// 自定义uri规则
public String buildKey(String uri, String method) {
if (!uri.startsWith("/")) {
uri = "/"+ uri;
}
uri = uri
.replace("*", "")
.replace("//", "/")
.replace(".json", "")
.replace(".jhtml", "");
if (uri.endsWith("/")) {
uri = uri.substring(0, uri.length()-1);
}
return uri+"#"+method.toUpperCase();
}
}
3. 继承WebMvcConfigurationSupport
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/**
* 应该是 @Configuration 注解,
* 但是用了这个注解他在创建RequestMappingHandlerMapping的时候就不会扫描Web相关资源,
* 扫描Controller这些实在扫描Service,Config这些之后进行的,暂时先用这个控制器注解代替一下
* */
@Controller
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
return new MvcRequestMappingHandlerMapping();
}
}