该文章为原创(转载请注明出处):如何不通过@Controller编码方式批量裸露内网接口 - 简书 (jianshu.com)

实在业务场景

心愿在原有根底上裸露内网接口,且不心愿应用nginx做转发
例如api/xxx/lan/yyy定义为内网接口
然而现有接口为service/xxx/yyy 服务调用接口

须要达成目标
主动将原有的 service/xxx/yyy 裸露为 api/xxx/lan/yyy,且不影响原有性能
例如:原有接口

@Controller@RequestMapping("/service")public class ServiceController {    @PostMapping("/xxx/yyy")    public Object yyy(@RequestBody Object body) {    }}

计划一(繁琐耗时,不好保护)

手动形式调用

@Controller@RequestMapping("/api")public class ApiLanController {    @Autowired    private ServiceController serviceController;    @PostMapping("/xxx/lan/yyy")    public Object yyy(@RequestBody Object body) {        serviceController.yyy(body);    }}

计划二

主动依据原有接口,裸露新接口

package xxx;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.boot.context.properties.bind.Bindable;import org.springframework.boot.context.properties.bind.Binder;import org.springframework.core.env.Environment;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import java.util.HashMap;import java.util.Map;import java.util.Set;import static java.util.Collections.emptySet;class ForwardingRequestMapping implements BeanPostProcessor {        private final Set<String> paths;        public ForwardingRequestMapping(Environment environment) {            paths = Binder.get(environment).bind("xxx.mapping-lan-forwarding", Bindable.setOf(String.class)).orElse(emptySet());        }        private static RequestMappingInfo buildNewRequestMappingInfo(RequestMappingInfo info, RequestMappingInfo.BuilderConfiguration config) {            RequestMappingInfo.Builder builder = RequestMappingInfo                    .paths(changePatterns(info.getPatternsCondition().getPatterns().toArray(new String[0])))                    .methods(info.getMethodsCondition().getMethods().toArray(new RequestMethod[0]))                    .params(info.getParamsCondition().getExpressions().stream().map(Object::toString).toArray(String[]::new))                    .headers(info.getHeadersCondition().getExpressions().stream().map(Object::toString).toArray(String[]::new))                    .consumes(info.getConsumesCondition().getExpressions().stream().map(Object::toString).toArray(String[]::new))                    .produces(info.getProducesCondition().getExpressions().stream().map(Object::toString).toArray(String[]::new))                    .mappingName(info.getName());            builder.customCondition(info.getCustomCondition());            return builder.options(config).build();        }        private static String[] changePatterns(String[] patterns) {            String[] newPatterns = new String[patterns.length];            for (int i = 0, patternsLength = patterns.length; i < patternsLength; i++) {                // serviceController service/xxx/yyy 裸露为 api/xxx/lan/yyy//                newPatterns[i] =             }            return newPatterns;        }        public static RequestMappingInfo.BuilderConfiguration builderConfiguration(RequestMappingHandlerMapping mapping) {            RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();            config.setUrlPathHelper(mapping.getUrlPathHelper());            config.setPathMatcher(mapping.getPathMatcher());            config.setSuffixPatternMatch(mapping.useSuffixPatternMatch());            config.setTrailingSlashMatch(mapping.useTrailingSlashMatch());            config.setRegisteredSuffixPatternMatch(mapping.useRegisteredSuffixPatternMatch());            config.setContentNegotiationManager(mapping.getContentNegotiationManager());            return config;        }        @Override        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {            if (bean instanceof RequestMappingHandlerMapping) {                RequestMappingHandlerMapping mapping = ((RequestMappingHandlerMapping) bean);                Map<RequestMappingInfo, HandlerMethod> newMap = new HashMap<>();                RequestMappingInfo.BuilderConfiguration config = builderConfiguration(mapping);                mapping.getHandlerMethods().forEach((info, handleMethod) -> {                    for (String pattern : info.getPatternsCondition().getPatterns()) {                        if (paths.contains(pattern)) {                            RequestMappingInfo newInfo = buildNewRequestMappingInfo(info, config);                            newMap.put(newInfo, handleMethod);                        }                    }                });                // 注册新的映射规定                newMap.forEach((mappingInfo, handleMethod) -> mapping.registerMapping(mappingInfo, handleMethod.getBean(), handleMethod.getMethod()));            }            return bean;        }    }

最终成果

新增配置,主动将service/xxx/yyy依据规定裸露为新的api/xxx/lan/yyy

xxx.mapping-lan-forwarding:    - service/xxx/yyy

前端拜访api/xxx/lan/yyy申请,申请会反射调用到service/xxx/yyy对应的Controller的办法

该文章为原创(转载请注明出处):如何不通过@Controller编码方式批量裸露内网接口 - 简书 (jianshu.com)