Skip to content
This repository was archived by the owner on Dec 4, 2025. It is now read-only.

Commit 3ed7a6c

Browse files
authored
Merge pull request #810 from shalousun/master
feat: Supports generating descriptions for OpenAPI HTTP error statuses like 404, 500, etc.
2 parents ac56941 + a4d9669 commit 3ed7a6c

12 files changed

+573
-40
lines changed

src/main/java/com/ly/doc/builder/openapi/AbstractOpenApiBuilder.java

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ public void setComponentKey(String componentKey) {
9090
*/
9191
abstract Map<String, Object> buildResponsesBody(ApiConfig apiConfig, ApiMethodDoc apiMethodDoc);
9292

93+
/**
94+
* Build request parameters
95+
*
96+
* @param apiMethodDoc API data for the method
97+
*/
98+
abstract List<Map<String, Object>> buildParameters(ApiMethodDoc apiMethodDoc);
99+
100+
abstract Map<String, Object> getStringParams(ApiParam apiParam, boolean hasItems);
101+
102+
103+
/**
104+
* component schema
105+
*
106+
* @param apiSchema API schema
107+
* @return component schema Map
108+
*/
109+
abstract public Map<String, Object> buildComponentsSchema(ApiSchema<ApiDoc> apiSchema);
110+
93111
protected static final Map<String, String> STRING_COMPONENT = new HashMap<>();
94112

95113
static {
@@ -281,14 +299,6 @@ public static Map<String, Object> buildExampleData(ApiMethodDoc apiMethodDoc, bo
281299

282300
}
283301

284-
/**
285-
* Build request parameters
286-
*
287-
* @param apiMethodDoc API data for the method
288-
*/
289-
abstract List<Map<String, Object>> buildParameters(ApiMethodDoc apiMethodDoc);
290-
291-
abstract Map<String, Object> getStringParams(ApiParam apiParam, boolean hasItems);
292302

293303
/**
294304
* If it is a get request or @PathVariable set the request parameters
@@ -352,18 +362,40 @@ public static Map<String, Object> buildParametersSchema(ApiReqParam header) {
352362
* @return response info
353363
*/
354364
public Map<String, Object> buildResponses(ApiConfig apiConfig, ApiMethodDoc apiMethodDoc, List<ApiExceptionStatus> apiExceptionStatuses) {
355-
Map<String, Object> response = new HashMap<>(10);
365+
Map<String, Object> response = new LinkedHashMap<>(8);
356366
response.put("200", buildResponsesBody(apiConfig, apiMethodDoc));
367+
if (CollectionUtil.isNotEmpty(apiExceptionStatuses)) {
368+
for (ApiExceptionStatus apiExceptionStatus : apiExceptionStatuses) {
369+
response.put(apiExceptionStatus.getStatus(), buildEexcetionResponsesBody(apiConfig, apiExceptionStatus));
370+
}
371+
}
357372
return response;
358373
}
359374

360-
/**
361-
* component schema
362-
*
363-
* @param apiDocs List of ApiDoc
364-
* @return component schema Map
365-
*/
366-
abstract public Map<String, Object> buildComponentsSchema(List<ApiDoc> apiDocs);
375+
public Map<String, Object> buildEexcetionResponsesBody(ApiConfig apiConfig, ApiExceptionStatus apiExceptionStatus) {
376+
Map<String, Object> responseBody = new HashMap<>(8);
377+
responseBody.put("description", apiExceptionStatus.getDesc());
378+
Map<String, Object> content = new HashMap<>(8);
379+
Map<String, Object> mediaTypeContent = new HashMap<>(8);
380+
Map<String, Object> schema = new HashMap<>(8);
381+
String responseRef = componentKey + OpenApiSchemaUtil.getClassNameFromParams(apiExceptionStatus.getExceptionResponseParams());
382+
if (CollectionUtil.isNotEmpty(apiExceptionStatus.getExceptionResponseParams())) {
383+
schema.put("$ref", responseRef);
384+
}
385+
mediaTypeContent.put("schema", schema);
386+
if (OPENAPI_3_COMPONENT_KRY.equals(componentKey) && apiConfig.isResponseExample()) {
387+
Map<String, Object> json = new HashMap<>(8);
388+
Map<String, Object> jsonData = new HashMap<>(8);
389+
jsonData.put("summary", "response example");
390+
jsonData.put("value", apiExceptionStatus.getResponseUsage());
391+
json.put("json", jsonData);
392+
mediaTypeContent.put("examples", json);
393+
}
394+
content.put("*/*", mediaTypeContent);
395+
responseBody.put("content", content);
396+
return responseBody;
397+
}
398+
367399

368400
/**
369401
* component schema properties
@@ -483,13 +515,13 @@ private Map<String, Object> buildPropertiesData(ApiParam apiParam, Map<String, O
483515
* This method iterates through all API documentation entries to extract request and response parameter information,
484516
* and organizes them into OpenAPI component schemas.
485517
*
486-
* @param apiDocs List of API documentation, containing multiple API method descriptions.
518+
* @param apiSchema The API documentation schema.
487519
* @return Returns a map containing all component schemas.
488520
*/
489-
public Map<String, Object> buildComponentData(List<ApiDoc> apiDocs) {
521+
public Map<String, Object> buildComponentData(ApiSchema<ApiDoc> apiSchema) {
490522
Map<String, Object> component = new HashMap<>(16);
491523
component.put(DocGlobalConstants.DEFAULT_PRIMITIVE, STRING_COMPONENT);
492-
apiDocs.forEach(
524+
apiSchema.getApiDatas().forEach(
493525
a -> {
494526
List<ApiMethodDoc> apiMethodDocs = a.getList();
495527
apiMethodDocs.forEach(
@@ -507,6 +539,14 @@ public Map<String, Object> buildComponentData(List<ApiDoc> apiDocs) {
507539
);
508540
}
509541
);
542+
// excption response components
543+
if (Objects.nonNull(apiSchema.getApiExceptionStatuses())) {
544+
apiSchema.getApiExceptionStatuses().forEach(e -> {
545+
List<ApiParam> responseParams = e.getExceptionResponseParams();
546+
String responseSchemaName = OpenApiSchemaUtil.getClassNameFromParams(e.getExceptionResponseParams());
547+
component.put(responseSchemaName, buildProperties(responseParams, component, true));
548+
});
549+
}
510550
component.remove(OpenApiSchemaUtil.NO_BODY_PARAM);
511551
return component;
512552
}
@@ -528,9 +568,4 @@ public ApiSchema<ApiDoc> getOpenApiDocs(ApiConfig config, JavaProjectBuilder pro
528568
Objects.requireNonNull(docBuildTemplate, "doc build template is null");
529569
return docBuildTemplate.getApiData(configBuilder);
530570
}
531-
532-
public static Map<String, Object> buildErrorStatusResponse(ApiConfig apiConfig, List<ApiExceptionStatus> apiExceptionStatuses) {
533-
// TODO
534-
return null;
535-
}
536571
}

src/main/java/com/ly/doc/builder/openapi/OpenApiBuilder.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public void openApiCreate(ApiConfig config, ApiSchema<ApiDoc> apiSchema) {
8888
Set<OpenApiTag> tags = new HashSet<>();
8989
json.put("tags", tags);
9090
json.put("paths", buildPaths(config, apiSchema, tags));
91-
json.put("components", buildComponentsSchema(apiSchema.getApiDatas()));
91+
json.put("components", buildComponentsSchema(apiSchema));
9292

9393
String filePath = config.getOutPath();
9494
filePath = filePath + DocGlobalConstants.OPEN_API_JSON;
@@ -195,6 +195,7 @@ public Map<String, Object> buildResponsesBody(ApiConfig apiConfig, ApiMethodDoc
195195
return responseBody;
196196
}
197197

198+
198199
@Override
199200
List<Map<String, Object>> buildParameters(ApiMethodDoc apiMethodDoc) {
200201
Map<String, Object> parameters;
@@ -279,9 +280,9 @@ Map<String, Object> getStringParams(ApiParam apiParam, boolean hasItems) {
279280
}
280281

281282
@Override
282-
public Map<String, Object> buildComponentsSchema(List<ApiDoc> apiDocs) {
283+
public Map<String, Object> buildComponentsSchema(ApiSchema<ApiDoc> apiSchema) {
283284
Map<String, Object> schemas = new HashMap<>(4);
284-
schemas.put("schemas", buildComponentData(apiDocs));
285+
schemas.put("schemas", buildComponentData(apiSchema));
285286
return schemas;
286287
}
287288
}

src/main/java/com/ly/doc/builder/openapi/SwaggerBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public void openApiCreate(ApiConfig config, ApiSchema<ApiDoc> apiSchema) {
9090
Set<OpenApiTag> tags = new HashSet<>();
9191
json.put("tags", tags);
9292
json.put("paths", buildPaths(config, apiSchema, tags));
93-
json.put("definitions", buildComponentsSchema(apiSchema.getApiDatas()));
93+
json.put("definitions", buildComponentsSchema(apiSchema));
9494

9595
String filePath = config.getOutPath();
9696
filePath = filePath + DocGlobalConstants.OPEN_API_JSON;
@@ -271,8 +271,8 @@ Map<String, Object> getStringParams(ApiParam apiParam, boolean hasItems) {
271271
}
272272

273273
@Override
274-
public Map<String, Object> buildComponentsSchema(List<ApiDoc> apiDocs) {
275-
return buildComponentData(apiDocs);
274+
public Map<String, Object> buildComponentsSchema(ApiSchema<ApiDoc> apiSchema) {
275+
return buildComponentData(apiSchema);
276276
}
277277

278278
}

src/main/java/com/ly/doc/constants/SpringMvcAnnotations.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,9 @@ public interface SpringMvcAnnotations {
6060
String SERVER_ENDPOINT = "ServerEndpoint";
6161

6262
String REST_CONTROLLER_ADVICE = "RestControllerAdvice";
63+
64+
String EXCEPTION_HANDLER = "ExceptionHandler";
65+
66+
String RESPONSE_STATUS = "ResponseStatus";
67+
6368
}

src/main/java/com/ly/doc/model/ApiConfig.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,17 @@ public class ApiConfig {
406406
*/
407407
private JMeter jmeter;
408408

409+
/**
410+
* Flag to include default HTTP status codes
411+
* This field controls whether a default set of HTTP status codes should be included in HTTP responses.
412+
* If set to true, a standard set of HTTP status codes (e.g., 200 OK, 404 Not Found) will be automatically
413+
* added when handling HTTP responses. If set to false, these status codes will not be automatically added,
414+
* requiring manual specification of desired status codes.
415+
* The default value is false to avoid unnecessary resource usage where not required.
416+
* @since 3.0.5
417+
*/
418+
private boolean addDefaultHttpStatuses;
419+
409420
public static ApiConfig getInstance() {
410421
return instance;
411422
}
@@ -1071,4 +1082,12 @@ public JMeter getJmeter() {
10711082
public void setJmeter(JMeter jmeter) {
10721083
this.jmeter = jmeter;
10731084
}
1085+
1086+
public boolean isAddDefaultHttpStatuses() {
1087+
return addDefaultHttpStatuses;
1088+
}
1089+
1090+
public void setAddDefaultHttpStatuses(boolean addDefaultHttpStatuses) {
1091+
this.addDefaultHttpStatuses = addDefaultHttpStatuses;
1092+
}
10741093
}

src/main/java/com/ly/doc/model/ApiExceptionStatus.java

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,93 @@
2121

2222
package com.ly.doc.model;
2323

24+
import org.jetbrains.annotations.NotNull;
25+
2426
import java.util.List;
27+
import java.util.Objects;
2528

2629
/**
2730
* @author yu.sun on 2024/6/9
2831
* @since 3.0.5
2932
*/
30-
public class ApiExceptionStatus {
33+
public class ApiExceptionStatus implements Comparable<ApiExceptionStatus> {
3134
private String status;
35+
36+
private String author;
37+
38+
private String desc;
39+
40+
private String detail;
41+
42+
private String responseUsage;
3243
/**
3344
* http exception response params
3445
*/
3546
private List<ApiParam> exceptionResponseParams;
3647

48+
public static ApiExceptionStatus of() {
49+
return new ApiExceptionStatus();
50+
}
51+
3752
public String getStatus() {
3853
return status;
3954
}
4055

41-
public void setStatus(String status) {
56+
public ApiExceptionStatus setStatus(String status) {
4257
this.status = status;
58+
return this;
4359
}
4460

4561
public List<ApiParam> getExceptionResponseParams() {
4662
return exceptionResponseParams;
4763
}
4864

49-
public void setExceptionResponseParams(List<ApiParam> exceptionResponseParams) {
65+
public ApiExceptionStatus setExceptionResponseParams(List<ApiParam> exceptionResponseParams) {
5066
this.exceptionResponseParams = exceptionResponseParams;
67+
return this;
68+
}
69+
70+
public String getAuthor() {
71+
return author;
72+
}
73+
74+
public ApiExceptionStatus setAuthor(String author) {
75+
this.author = author;
76+
return this;
77+
}
78+
79+
public String getDesc() {
80+
return desc;
81+
}
82+
83+
public ApiExceptionStatus setDesc(String desc) {
84+
this.desc = desc;
85+
return this;
86+
}
87+
88+
public String getDetail() {
89+
return detail;
90+
}
91+
92+
public ApiExceptionStatus setDetail(String detail) {
93+
this.detail = detail;
94+
return this;
95+
}
96+
97+
public String getResponseUsage() {
98+
return responseUsage;
99+
}
100+
101+
public ApiExceptionStatus setResponseUsage(String responseUsage) {
102+
this.responseUsage = responseUsage;
103+
return this;
104+
}
105+
106+
@Override
107+
public int compareTo(@NotNull ApiExceptionStatus o) {
108+
if (Objects.nonNull(o.getDesc())) {
109+
return status.compareTo(o.status);
110+
}
111+
return 0;
51112
}
52113
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (C) 2018-2024 smart-doc
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
package com.ly.doc.model;
22+
23+
/**
24+
* @author yu.sun on 2024/6/9
25+
* @since 3.0.5
26+
*/
27+
public class ExceptionAdviceMethod{
28+
29+
private String status;
30+
31+
private boolean exceptionHandlerMethod;
32+
33+
public static ExceptionAdviceMethod builder(){
34+
return new ExceptionAdviceMethod();
35+
}
36+
37+
public String getStatus() {
38+
return status;
39+
}
40+
41+
public ExceptionAdviceMethod setStatus(String status) {
42+
this.status = status;
43+
return this;
44+
}
45+
46+
public boolean isExceptionHandlerMethod() {
47+
return exceptionHandlerMethod;
48+
}
49+
50+
public ExceptionAdviceMethod setExceptionHandlerMethod(boolean exceptionHandlerMethod) {
51+
this.exceptionHandlerMethod = exceptionHandlerMethod;
52+
return this;
53+
}
54+
}

0 commit comments

Comments
 (0)