18
18
19
19
package org .springdoc .webflux .api ;
20
20
21
+ import java .lang .annotation .Annotation ;
22
+ import java .lang .reflect .Method ;
23
+ import java .util .ArrayList ;
24
+ import java .util .Arrays ;
25
+ import java .util .HashSet ;
21
26
import java .util .LinkedHashMap ;
22
27
import java .util .List ;
23
28
import java .util .Map ;
30
35
import io .swagger .v3 .core .util .Yaml ;
31
36
import io .swagger .v3 .oas .annotations .Operation ;
32
37
import io .swagger .v3 .oas .models .OpenAPI ;
38
+ import org .apache .commons .lang3 .ArrayUtils ;
39
+ import org .apache .commons .lang3 .StringUtils ;
40
+ import org .slf4j .Logger ;
41
+ import org .slf4j .LoggerFactory ;
33
42
import org .springdoc .api .AbstractOpenApiResource ;
34
43
import org .springdoc .core .AbstractRequestBuilder ;
35
44
import org .springdoc .core .GenericResponseBuilder ;
38
47
import org .springdoc .core .SpringDocConfigProperties ;
39
48
import org .springdoc .core .customizers .OpenApiCustomiser ;
40
49
import org .springdoc .core .customizers .OperationCustomizer ;
50
+ import org .springdoc .webflux .annotations .RouterOperation ;
51
+ import org .springdoc .webflux .annotations .RouterOperations ;
41
52
import reactor .core .publisher .Mono ;
42
53
43
54
import org .springframework .beans .factory .annotation .Autowired ;
44
55
import org .springframework .beans .factory .annotation .Value ;
56
+ import org .springframework .beans .factory .config .BeanDefinition ;
57
+ import org .springframework .beans .factory .config .ConfigurableListableBeanFactory ;
58
+ import org .springframework .context .ApplicationContext ;
59
+ import org .springframework .core .type .StandardMethodMetadata ;
45
60
import org .springframework .http .MediaType ;
46
61
import org .springframework .http .server .reactive .ServerHttpRequest ;
62
+ import org .springframework .util .CollectionUtils ;
47
63
import org .springframework .web .bind .annotation .GetMapping ;
48
64
import org .springframework .web .bind .annotation .RequestMethod ;
49
65
import org .springframework .web .bind .annotation .RestController ;
50
66
import org .springframework .web .method .HandlerMethod ;
67
+ import org .springframework .web .reactive .HandlerMapping ;
68
+ import org .springframework .web .reactive .function .server .RouterFunction ;
51
69
import org .springframework .web .reactive .result .condition .PatternsRequestCondition ;
52
70
import org .springframework .web .reactive .result .method .RequestMappingInfo ;
53
71
import org .springframework .web .reactive .result .method .RequestMappingInfoHandlerMapping ;
62
80
@ RestController
63
81
public class OpenApiResource extends AbstractOpenApiResource {
64
82
83
+ private static final Logger LOGGER = LoggerFactory .getLogger (OpenApiResource .class );
84
+
65
85
private final RequestMappingInfoHandlerMapping requestMappingHandlerMapping ;
66
86
87
+ @ Autowired
88
+ private List <HandlerMapping > handlerMappings ;
89
+
67
90
public OpenApiResource (String groupName , OpenAPIBuilder openAPIBuilder , AbstractRequestBuilder requestBuilder ,
68
91
GenericResponseBuilder responseBuilder , OperationBuilder operationParser ,
69
92
RequestMappingInfoHandlerMapping requestMappingHandlerMapping ,
@@ -79,7 +102,7 @@ public OpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder req
79
102
RequestMappingInfoHandlerMapping requestMappingHandlerMapping ,
80
103
Optional <List <OperationCustomizer >> operationCustomizers ,
81
104
Optional <List <OpenApiCustomiser >> openApiCustomisers , SpringDocConfigProperties springDocConfigProperties ) {
82
- super (DEFAULT_GROUP_NAME , openAPIBuilder , requestBuilder , responseBuilder , operationParser ,operationCustomizers , openApiCustomisers , springDocConfigProperties );
105
+ super (DEFAULT_GROUP_NAME , openAPIBuilder , requestBuilder , responseBuilder , operationParser , operationCustomizers , openApiCustomisers , springDocConfigProperties );
83
106
this .requestMappingHandlerMapping = requestMappingHandlerMapping ;
84
107
}
85
108
@@ -123,6 +146,51 @@ protected void getPaths(Map<String, Object> restControllers) {
123
146
}
124
147
}
125
148
}
149
+
150
+ ApplicationContext applicationContext = (ApplicationContext ) requestMappingHandlerMapping .getApplicationContext ();
151
+ Map <String , RouterFunction > routerBeans = applicationContext .getBeansOfType (RouterFunction .class );
152
+
153
+ for (Map .Entry <String , RouterFunction > entry : routerBeans .entrySet ()) {
154
+ List <RouterOperation > routerOperationList = new ArrayList <>();
155
+ RouterOperations routerOperations = applicationContext .findAnnotationOnBean (entry .getKey (), RouterOperations .class );
156
+ if (routerOperations == null ) {
157
+ RouterOperation routerOperation = applicationContext .findAnnotationOnBean (entry .getKey (), RouterOperation .class );
158
+ routerOperationList .add (routerOperation );
159
+ }
160
+ else
161
+ routerOperationList .addAll (Arrays .asList (routerOperations .value ()));
162
+
163
+ if (!CollectionUtils .isEmpty (routerOperationList )) {
164
+ for (RouterOperation routerOperation : routerOperationList ) {
165
+ if (!Void .class .equals (routerOperation .beanClass ())) {
166
+ Object handlerBean = applicationContext .getBean (routerOperation .beanClass ());
167
+ HandlerMethod handlerMethod = null ;
168
+ if (StringUtils .isNotBlank (routerOperation .beanMethod ())) {
169
+ try {
170
+ if (ArrayUtils .isEmpty (routerOperation .parameterTypes ())) {
171
+ Optional <Method > methodOptional = Arrays .stream (handlerBean .getClass ().getDeclaredMethods ())
172
+ .filter (method1 -> routerOperation .beanMethod ().equals (method1 .getName ()) && method1 .getParameters ().length == 0 )
173
+ .findAny ();
174
+ if (!methodOptional .isPresent ())
175
+ methodOptional = Arrays .stream (handlerBean .getClass ().getDeclaredMethods ())
176
+ .filter (method1 -> routerOperation .beanMethod ().equals (method1 .getName ()))
177
+ .findAny ();
178
+ if (methodOptional .isPresent ())
179
+ handlerMethod = new HandlerMethod (handlerBean , methodOptional .get ());
180
+ }
181
+ else
182
+ handlerMethod = new HandlerMethod (handlerBean , routerOperation .beanMethod (), routerOperation .parameterTypes ());
183
+ }
184
+ catch (NoSuchMethodException e ) {
185
+ LOGGER .error (e .getMessage ());
186
+ }
187
+ if (handlerMethod != null )
188
+ calculatePath (handlerMethod , routerOperation .path (), new HashSet <>(Arrays .asList (routerOperation .method ())));
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
126
194
}
127
195
128
196
protected void calculateServerUrl (ServerHttpRequest serverHttpRequest , String apiDocsUrl ) {
@@ -131,4 +199,23 @@ protected void calculateServerUrl(ServerHttpRequest serverHttpRequest, String ap
131
199
openAPIBuilder .setServerBaseUrl (serverBaseUrl );
132
200
}
133
201
202
+ public List <String > getBeansWithAnnotation (ConfigurableListableBeanFactory factory , Class <? extends Annotation > type ) {
203
+
204
+ List <String > result = new ArrayList <>();
205
+
206
+ for (String name : factory .getBeanDefinitionNames ()) {
207
+ BeanDefinition bd = factory .getBeanDefinition (name );
208
+
209
+ if (bd .getSource () instanceof StandardMethodMetadata ) {
210
+ StandardMethodMetadata metadata = (StandardMethodMetadata ) bd .getSource ();
211
+
212
+ Map <String , Object > attributes = metadata .getAnnotationAttributes (type .getName ());
213
+ if (null == attributes ) {
214
+ continue ;
215
+ }
216
+ }
217
+ }
218
+
219
+ return result ;
220
+ }
134
221
}
0 commit comments