Spring Boot 和 Swagger 文本/html 响应映射

Posted

技术标签:

【中文标题】Spring Boot 和 Swagger 文本/html 响应映射【英文标题】:Spring Boot and Swagger text/html response mapping 【发布时间】:2019-08-06 19:50:56 【问题描述】:

我有一个非常简单的 java spring boot + swagger 项目。

仅出于测试目的,我创建了两个映射类:Names.java 和 NamesContainer.java

public class Names 

@XmlAttribute(name="ref")
@ApiModelProperty(notes = "The auto-generated version of the product...")
private String key;

@XmlValue
@ApiModelProperty(notes = "The auto-generated version of the product...")
private String name;....-> rest of the class(Default constuctor and getters and setters)

...........

    @XmlRootElement(name="root")
public class NamesContainer 

    @XmlElement(name="listNames")
    @ApiModelProperty(notes = "The auto-generated version of the product")
    private List<Names> listNames;....-> rest of the class(Default constuctor and getters and setters)

对于响应,我使用一种@Get 方法:

    @RequestMapping(method = RequestMethod.GET, value = "/api/javainuse")
    @ApiOperation(value = "Get a scheduled process by id.",notes = "This is note ;)",response = NamesContainer.class,code = HttpURLConnection.HTTP_OK, produces="text/html")
    @ApiResponses(value = @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "set in case of success. Returns the requested scheduled process",  response = NamesContainer.class))

    public NamesContainer sayHello() 

        Map<String, String> mapNames = new HashMap<String, String>();
        mapNames.put("Name1", "Docnho");
        mapNames.put("Name2", "Silvia");
        mapNames.put("Name3", "Pepa");
        mapNames.put("Name4", "Mima");
        mapNames.put("Name5", "Mohamed");

        List<Names> listNames = new ArrayList<Names>();

    for(Map.Entry<String, String> entryName : mapNames.entrySet())
    
        listNames.add(new Names(entryName.getKey(), entryName.getValue()));
    

    NamesContainer container = new NamesContainer(listNames);


    return container;

如果我使用 produces="application/json"produces="application/xml",结果如预期:

但如果我尝试使用 produces="text/html"

响应与预期不符:

响应正文是;

<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Fri Mar 15 18:43:55 EET 2019</div><div>There was an unexpected error (type=Not Acceptable, status=406).</div><div>Could not find acceptable representation</div></body></html> 

问题是是否可以映射我现有的对象 NamesContainer.java 以生成 HTML 响应以及如何做到这一点?

【问题讨论】:

花了一些时间,这可能很有用github.com/springfox/springfox/issues/1180 【参考方案1】:

没有办法(目前还没有办法)将 POJO 字段映射到带有注释的 html。

Instread 可以使用 Spring 提出的开箱即用的其他方式将 POJO(模型)绑定到 html:Thymleaf temlates、Freemarker templates 和 JSP 页面。

以下是其中一种可能的解决方案的示例:

    使用 html Thymleaf 模板创建 HTML 页面。例如table.html 视图:

<body>
    <table>
    <tr>
        <th>Key</th>
        <th>Name</th>
    </tr>
    <tr th:each="mapEnty: $mapNames">
        <td th:text="$mapEnty.key" />
        <td th:text="$mapEnty.value" />
    </tr>
    </table>
</body>
    在 Spring @Controller 中为“text/html”内容类型创建 @RequestMapping,填写模型并返回“表格”视图。例如:
    @GetMapping(value = "/api/javainuse", produces = MediaType.TEXT_HTML_VALUE)
    public String table(Model model) 
        Map<String, String> mapNames = new HashMap<String, String>();
        ...
        model.addAttribute("mapNames", mapNames);
        return "table";
    

【讨论】:

【参考方案2】:

您的 Pojo 可能需要更明确的映射/注释来生成 HTML。我假设您正在寻找类似

<table>
  <tr>
    <th>Name1</th>
    <th>Name2</th>
    <th>Name3</th>
    <th>Name4</th>
  </tr>
  <tr>
    <td>Peppa</td>
    <td>Mima</td>
    <td>Mohamed</td>
    <td>Docnho</td>
  </tr>
</table>

我不确定哪个注释可以提供帮助,但这就是我要开始的地方

【讨论】:

是的,但是是否有任何映射/注释来生成 HTML。我在互联网上找不到注释来用我的 POJO 对象生成 HTML。我在问自己是否有可能,或者我在寻找不存在的东西? 我相信它不存在。 @ArmerB。从 POJO 生成 HTML 是没有意义的,而是使用模板渲染这个 HTML(thymeleaf、jsp、jsf、struts 和更多可能会有所帮助)【参考方案3】:

TLDR:是的,这是可能的。为 HTML 创建 Jackson 数据格式模块。

我相信 Spring Boot 正在使用 Jackson 进行数据输出,并且 Jackson 支持该格式:

JSON HTML 微笑 YAML Avro CSV

还有更多 (https://github.com/FasterXML/jackson),但不支持 HTML 之类的格式(这怎么可能?)。

HTML 渲染需要模板。阅读 Spring MVC https://spring.io/guides/gs/serving-web-content/。

另请阅读内容协商 (https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc)

您可以使用 RESTful @ResponseBody 方法和 HTTP 消息转换器,通常用于返回 JSON 或 XML 等数据格式。

(...) 视图完全可以根据需要生成 JSON 和 XML,视图通常用于为传统的 Web 应用程序生成 HTML 等表示格式。

【讨论】:

【参考方案4】:

我找到了几个解决这个问题的机会,但我认为这两个是最好的:

第一个适用于面向码头服务器的应用程序。这是解释 - here。 produces="text/html, ..., ..." 的主要内容是MessageBodyWriter 接口。如果你可以定制它,你可以用它做everithink。

第二个,我的最终解决方案就是为我的 .xml 文件创建 .xsl 文件。我将我的 .xml 文件转换为 HTML,然后响应完成。

** 如果有人想用一种方法做所有事情,可以使用这个:

@RequestMapping(method = RequestMethod.GET, value = "/api/javainuse")
@ApiOperation(value = "Get a scheduled process by id.",notes = "This is note ;)",response = NamesContainer.class,code = HttpURLConnection.HTTP_OK, produces="text/html" /*add produces->xml*/)
@ApiResponses(value = @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "set in case of success. Returns the requested scheduled process",  response = NamesContainer.class))

public Response sayHello(HttpServletResponse response) 
    switch (request.getHeader("accept"))
    

        case MediaType.APPLICATION_XML:

            response = Response.ok().entity(/*yourEntity here (for me it was NamesContainer)*/).type(MediaType.APPLICATION_XML).build();
            break;

        case MediaType.TEXT_HTML:

            response = Response.ok().entity(/*Transform xml to HTML with xsl and return it here as String*/).type(MediaType.TEXT_PLAIN).build();
            break;
    

【讨论】:

以上是关于Spring Boot 和 Swagger 文本/html 响应映射的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot crud 和 swagger使用

Spring Boot + Swagger + Swagger UI 和 @RequestBody 具有数据类型 String

Spring boot集成swagger2

spring boot和swagger 整合

Spring Boot 集成swagger2

Spring Boot 执行器/Swagger