Web Services 如何使用Micronaut在Java中根据接受头创建具有不同响应内容类型的端点

qyyhg6bp  于 2023-03-03  发布在  Java
关注(0)|答案(1)|浏览(149)

我正在尝试Micronaut,希望创建一个返回text/plaintext/html的端点,具体取决于请求中的Accept报头。
我发现了两种方法:
1.为同一个端点创建两个具有不同 * produces * 属性的方法,
1.在一个方法中处理所有内容,该方法计算Accept头,并在我自己的代码中使用逻辑返回正确的内容类型。
我最喜欢第一种方式,因为它非常简洁,不需要我进行逻辑推理:

@Get(uri="/", produces="text/html")
    public String indexHtml() {
        return """
            <html><head><meta charset=\"utf-8\"></head>
            <body>
            <h1>Demo service</h1>
            </body></html>""";
    }
    @Get(uri="/", produces="text/plain")
    public String indexText() {
        return "Demo service\r\n";
    }

当请求中有接受头时,这种方法很有效,但是,当没有接受头时,我得到一个错误响应400 Bad Request,其中包含消息"More than 1 route matched the incoming request. The following routes matched /demo: GET - /demo, GET - /demo"

    • 问题1**是否有办法提供第3个端点作为后备,或将这些方法之一指定为默认方法?

第二种方法,导致了一个方法,我不觉得很优雅:

@Get(uri="/", produces={MediaType.TEXT_PLAIN, MediaType.TEXT_HTML})
    public String index(HttpRequest<?> request) {
        Collection<MediaType> mediaTypes = request.accept();
        Iterator<MediaType> it = mediaTypes.iterator();
        if (it.hasNext()) {
            MediaType mediaType = it.next();
            if (MediaType.TEXT_PLAIN_TYPE.equals(mediaType))
                    return "Demo service\r\n";
            if (MediaType.TEXT_HTML_TYPE.equals(mediaType))
                    return """
                        <!DOCTYPE html>
                        <html><head><meta charset=\"utf-8\"></head>
                        <body>
                        <h1>Demo service</h1>
                        </body></html>""";
        }
        return """
            {
                "title": "Demo service",
            }""";
    }
    • 问题2**
  • 如果真的有必要在单个方法中处理这个问题,那么它确实是通过获取接受头并对其求值来完成的,还是应该以不同的方式来完成?
8oomwypt

8oomwypt1#

您可以使用@Get(produces="*/*")来提供一个类似回退的端点,当使用相同URI并由特定内容类型控制的端点缺少Accept标头时,将执行该端点。

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.QueryValue;

import java.util.Map;

@Controller("/hello")
public class HelloController {

    @Get(produces = "application/json")
    Map<?,?> helloJson(@QueryValue(defaultValue = "unknown") String name) {
        return Map.of("message", "Hello, " + name + "!");
    }

    @Get(produces = "text/plain")
    String helloText(@QueryValue(defaultValue = "unknown") String name) {
        return "Hello, " + name;
    }

    @Get(produces = "*/*")
    String helloDefault(@QueryValue(defaultValue = "unknown") String name) {
        return helloText(name) + " (from default endpoint)";
    }
}

下面是我们调用这个控制器时使用和不使用Accept头文件时的情况:

$ curl -H "Accept:application/json" "localhost:8080/hello?name=test"
{"message":"Hello, test!"}%

$ curl -H "Accept:text/plain" "localhost:8080/hello?name=test"
Hello, test%

$ curl "localhost:8080/hello?name=test"                             
Hello, test (from default endpoint)%

相关问题