xiejun
2024-11-01 80b6cbfc9c861469146318d0b3dd5f8b8b525b8a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu 卢春梦 (596392912@qq.com)
 */
package org.springblade.core.cloud.version;
 
import feign.MethodMetadata;
import org.springblade.core.cloud.annotation.ApiVersion;
import org.springblade.core.cloud.annotation.UrlVersion;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.convert.ConversionService;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
 
/**
 * 支持 blade-boot 的 版本 处理
 *
 * @see org.springblade.core.cloud.annotation.UrlVersion
 * @see org.springblade.core.cloud.annotation.ApiVersion
 * @author L.cm
 */
public class BladeSpringMvcContract extends SpringMvcContract {
 
    public BladeSpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors, ConversionService conversionService) {
        super(annotatedParameterProcessors, conversionService);
    }
 
    @Override
    protected void processAnnotationOnMethod(MethodMetadata data, Annotation methodAnnotation, Method method) {
        if (RequestMapping.class.isInstance(methodAnnotation) || methodAnnotation.annotationType().isAnnotationPresent(RequestMapping.class)) {
            Class<?> targetType = method.getDeclaringClass();
            // url 上的版本,优先获取方法上的版本
            UrlVersion urlVersion = AnnotatedElementUtils.findMergedAnnotation(method, UrlVersion.class);
            // 再次尝试类上的版本
            if (urlVersion == null || StringUtil.isBlank(urlVersion.value())) {
                urlVersion = AnnotatedElementUtils.findMergedAnnotation(targetType, UrlVersion.class);
            }
            if (urlVersion != null && StringUtil.isNotBlank(urlVersion.value())) {
                String versionUrl = "/" + urlVersion.value();
                data.template().uri(versionUrl);
            }
 
            // 注意:在父类之前 添加 url版本,在父类之后,处理 Media Types 版本
            super.processAnnotationOnMethod(data, methodAnnotation, method);
 
            // 处理 Media Types 版本信息
            ApiVersion apiVersion = AnnotatedElementUtils.findMergedAnnotation(method, ApiVersion.class);
            // 再次尝试类上的版本
            if (apiVersion == null || StringUtil.isBlank(apiVersion.value())) {
                apiVersion = AnnotatedElementUtils.findMergedAnnotation(targetType, ApiVersion.class);
            }
            if (apiVersion != null && StringUtil.isNotBlank(apiVersion.value())) {
                BladeMediaType bladeMediaType = new BladeMediaType(apiVersion.value());
                data.template().header(HttpHeaders.ACCEPT, bladeMediaType.toString());
            }
        }
    }
 
    /**
     * 参考:https://gist.github.com/rmfish/0ed59a9af6c05157be2a60c9acea2a10
     * @param annotations 注解
     * @param paramIndex 参数索引
     * @return 是否 http 注解
     */
    @Override
    protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {
        boolean httpAnnotation = super.processAnnotationsOnParameter(data, annotations, paramIndex);
        // 在 springMvc 中如果是 Get 请求且参数中是对象 没有声明为@RequestBody 则默认为 Param
        if (!httpAnnotation && StringPool.GET.equals(data.template().method().toUpperCase())) {
            for (Annotation parameterAnnotation : annotations) {
                if (!(parameterAnnotation instanceof RequestBody)) {
                    return false;
                }
            }
            data.queryMapIndex(paramIndex);
            return true;
        }
        return httpAnnotation;
    }
}