SpringBoot对所有PUT、DELETE接口追加POST请求方式

背景

产品在某个项目进行私有化交付的时候,遇到WAF拦截PUT、DELETE请求的场景,只能将现有接口的请求方式修改为POST请求方式。

考虑到产品经过了多年的沉淀,涉及到的接口很多,手动修改可能存在改漏的情况。另外,基于标准的Restful接口定义规范,不同的业务动作应该通过请求方式进行区分。

所有,想通过底层架构优化的方式,在应用服务启动时,对定义为PUT和DELETE请求方式的接口,追加POST请求方式,具体实现代码如下:

通过RequestMappingHandlerMapping修改RequestMappingInfo接口定义

public class CustomRequestMappingHandler extends RequestMappingHandlerMapping {

    private static final String DATA_FRAME_PACKAGE_FOR_CN = "cn.xxx";

    private static final String DATA_FRAME_PACKAGE_FOR_COM = "com.xxx";

    private static final List<RequestMethod> REQUEST_METHODS = Arrays.asList(RequestMethod.PUT, RequestMethod.DELETE);

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        // 对包路径为com.xxx、cn.xxx进行处理
        // 仅处理web层接口,不处理feign接口
        if ((StringUtils.startsWithIgnoreCase(handlerType.getName(), DATA_FRAME_PACKAGE_FOR_CN)
                || StringUtils.startsWithIgnoreCase(handlerType.getName(), DATA_FRAME_PACKAGE_FOR_COM))
                && AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class)
                && !AnnotatedElementUtils.hasAnnotation(handlerType, FeignClient.class)) {
            // 从父类方法获取接口定义
            RequestMappingInfo requestMappingInfo = super.getMappingForMethod(method, handlerType);
            // 匹配PUT、DELETE请求接口
            if (CollectionUtils.containsAny(requestMappingInfo.getMethodsCondition().getMethods(), REQUEST_METHODS)
                    && !requestMappingInfo.getMethodsCondition().getMethods().contains(RequestMethod.POST)) {
                // 获取原始请求方法
                Set<RequestMethod> methods = requestMappingInfo.getMethodsCondition().getMethods();
                // 添加POST方法
                methods.add(RequestMethod.POST);
                // 创建新的RequestMappingInfo
                return RequestMappingInfo.paths().build().combine(requestMappingInfo);
            }
        }
        return super.getMappingForMethod(method, handlerType);
    }

}

注册自定义的RequestMappingHandlerMapping

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "custom.openapi.registration-post-method.enabled", havingValue = "true", matchIfMissing = true)
public class WebMvcConfig implements WebMvcRegistrations {
    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandler();
        handlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return handlerMapping;
    }
}

通过Swagger查看原有的DELETE接口定义:
image

追加POST请求方式后的POST接口定义:
image

posted @ 2025-04-16 15:27  codest  阅读(110)  评论(0)    收藏  举报