优化Spring RequestMapping

1.基本思路

通过uri直接匹配到Controller中的HandlerMethod,
重写 AbstractHandlerMethodMappingregisterHandlerMethod(),将自己的uriRequestMappingInfo放在一个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 infoMap = new HashMap<>();

    @Override
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {

        try {
            // 自定义规则
            String finalPath = lookupPath
                    .replace("//", "/")
                    .replace(".json", "")
                    .replace(".jhtml", "");

            Map 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();
    }
}

你可能感兴趣的:(优化Spring RequestMapping)