SpringMVC项目中获取所有URL到Controller Method的映射

import com.google.common.collect.Lists;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @date 2021-05-06
 */
@Component
public class TestInitializer implements ApplicationContextAware, InitializingBean {

    // 一个方法可以对应多个uri
    public static Map<String,List<String>> methodUriMap = new HashMap();

    // 一个uri也可以对应多个方法,不过这里不支持,只支持一个uri对应一个方法
    public static Map<String,String> uriMethodMap = new HashMap();

    @Override
    public void afterPropertiesSet() throws Exception {

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, HandlerMapping.class, true, false);
        List<HandlerMapping> handlerMappingList = matchingBeans.values().stream().filter(handlerMapping -> handlerMapping instanceof RequestMappingHandlerMapping).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(handlerMappingList)) {
            RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) handlerMappingList.get(0);
            Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
            for (Map.Entry<RequestMappingInfo, HandlerMethod> requestMappingInfoHandlerMethodEntry : handlerMethods.entrySet()) {
                RequestMappingInfo requestMappingInfo = requestMappingInfoHandlerMethodEntry.getKey();
                HandlerMethod mappingInfoValue = requestMappingInfoHandlerMethodEntry.getValue();

                RequestMethodsRequestCondition methodCondition = requestMappingInfo.getMethodsCondition();
                Set<String> requestTypes = new HashSet<>();
                if(!CollectionUtils.isEmpty(methodCondition.getMethods())){
                    // get、post、PUT... 配置(没有配置的说明都支持)
                    requestTypes = methodCondition.getMethods().stream().map(RequestMethod::name).collect(Collectors.toSet());
                }
                PatternsRequestCondition patternsCondition = requestMappingInfo.getPatternsCondition();
                if(CollectionUtils.isEmpty(patternsCondition.getPatterns())) {
                    continue;
                }
                // 完整的uri配置(有可能是这种 /api/project/audit/ip/{projectName}/{env} )
                Set<String> requestUrls = patternsCondition.getPatterns();

                // @RequestMapping 里面配置 params、headers、produces、consumes导致存在多个相同uri#method的,遇到直接忽略;这里只支持一个uri对应一个方法
                List<String> uriList = Lists.newArrayList();
                for(String requestUrl:requestUrls){
                    if(CollectionUtils.isEmpty(requestTypes)) {
                        // 说明 get、post、PUT... 都支持
                        for(RequestMethod requestMethod:RequestMethod.values()){
                            String uriIdentity = requestUrl+"#"+ requestMethod.name();
                            if(uriMethodMap.containsKey(uriIdentity)){
                                // 配置 params、headers、produces、consumes导致存在多个相同uri#method的,遇到直接忽略;这里只支持一个uri对应一个方法
                                String tempMethodIdentity = uriMethodMap.get(uriIdentity);
                                List<String> tempUriList = methodUriMap.get(tempMethodIdentity);
                                tempUriList.remove(uriIdentity);
                                if(CollectionUtils.isEmpty(tempUriList)){
                                    methodUriMap.remove(tempMethodIdentity);
                                }
                                uriMethodMap.remove(uriIdentity);
                            }else{
                                uriList.add(uriIdentity);
                            }
                        }
                    }else{
                        requestTypes.forEach(requestType -> {
                            String uriIdentity = requestUrl+"#"+ requestType;
                            if(uriMethodMap.containsKey(uriIdentity)){
                                //  配置 params、headers、produces、consumes导致存在多个相同uri#method的,遇到直接忽略;这里只支持一个uri对应一个方法
                                String tempMethodIdentity = uriMethodMap.get(uriIdentity);
                                List<String> tempUriList = methodUriMap.get(tempMethodIdentity);
                                tempUriList.remove(uriIdentity);
                                if(CollectionUtils.isEmpty(tempUriList)){
                                    methodUriMap.remove(tempMethodIdentity);
                                }
                                uriMethodMap.remove(uriIdentity);
                            }else{
                                uriList.add(uriIdentity);
                            }
                        });
                    }
                }
                if(CollectionUtils.isEmpty(uriList)){
                    continue;
                }

                String controllerName = mappingInfoValue.getBeanType().toString();
                String requestMethodName = mappingInfoValue.getMethod().getName();
                Class<?>[] methodParamTypes = mappingInfoValue.getMethod().getParameterTypes();
                StringBuilder methodIdentity = new StringBuilder(controllerName).append(".").append(requestMethodName);
                methodIdentity.append("(");
                for(Class<?> methodParamType:methodParamTypes){
                    methodIdentity.append(methodParamType.getName());
                }
                methodIdentity.append(")");

                // 存入map
                methodUriMap.put(methodIdentity.toString(),uriList);
                uriList.forEach(uri-> uriMethodMap.put(uri,methodIdentity.toString()));
            }
        }
    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值