如果您需要更多地控制请求处理,您可以编写一个方法来接收完整的 HttpRequest。
事实上,有几个更高级别的接口可以绑定到控制器方法参数。这些包括:
表 1. 可绑定的 Micronaut 接口
接口 |
描述 |
示例 |
HttpRequest
|
完整的 HttpRequest
|
String hello(HttpRequest request)
|
HttpHeaders
|
请求中存在的所有 HTTP 标头
|
String hello(HttpHeaders headers)
|
HttpParameters
|
请求中存在的所有 HTTP 参数(来自 URI 变量或请求参数)
|
String hello(HttpParameters params)
|
Cookies
|
请求中存在的所有 Cookie
|
String hello(Cookies cookies)
|
如果需要请求主体,则 HttpRequest 应该声明为参数化的具体泛型类型,例如HttpRequest<MyClass> 请求。否则可能无法从请求中获得正文。
此外,为了完全控制发出的 HTTP 响应,您可以使用返回 MutableHttpResponse 的 HttpResponse 类的静态工厂方法。
以下示例使用 HttpRequest 和 HttpResponse 对象实现了前面的 MessageController 示例:
请求和响应示例
Java |
Groovy |
Kotlin |
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.context.ServerRequestContext;
import reactor.core.publisher.Mono;
@Controller("/request")
public class MessageController {
@Get("/hello") // (1)
public HttpResponse<String> hello(HttpRequest<?> request) {
String name = request.getParameters()
.getFirst("name")
.orElse("Nobody"); // (2)
return HttpResponse.ok("Hello " + name + "!!")
.header("X-My-Header", "Foo"); // (3)
}
}
|
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.context.ServerRequestContext
import reactor.core.publisher.Mono
@Controller("/request")
class MessageController {
@Get("/hello") // (1)
HttpResponse<String> hello(HttpRequest<?> request) {
String name = request.parameters
.getFirst("name")
.orElse("Nobody") // (2)
HttpResponse.ok("Hello " + name + "!!")
.header("X-My-Header", "Foo") // (3)
}
}
|
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.context.ServerRequestContext
import reactor.core.publisher.Mono
import reactor.util.context.ContextView
@Controller("/request")
class MessageController {
@Get("/hello") // (1)
fun hello(request: HttpRequest<*>): HttpResponse<String> {
val name = request.parameters
.getFirst("name")
.orElse("Nobody") // (2)
return HttpResponse.ok("Hello $name!!")
.header("X-My-Header", "Foo") // (3)
}
}
|
该方法映射到 URI /hello 并接受 HttpRequest
HttpRequest 用于获取名为 name 的查询参数的值。
HttpResponse.ok(T) 方法返回带有文本正文的 MutableHttpResponse。名为 X-My-Header 的标头也会添加到响应中。
HttpRequest 也可以通过 ServerRequestContext 从静态上下文中获得。
使用 ServerRequestContext
Java |
Groovy |
Kotlin |
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.context.ServerRequestContext;
import reactor.core.publisher.Mono;
@Controller("/request")
public class MessageController {
@Get("/hello-static") // (1)
public HttpResponse<String> helloStatic() {
HttpRequest<?> request = ServerRequestContext.currentRequest() // (1)
.orElseThrow(() -> new RuntimeException("No request present"));
String name = request.getParameters()
.getFirst("name")
.orElse("Nobody");
return HttpResponse.ok("Hello " + name + "!!")
.header("X-My-Header", "Foo");
}
}
|
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.context.ServerRequestContext
import reactor.core.publisher.Mono
@Controller("/request")
class MessageController {
@Get("/hello-static") // (1)
HttpResponse<String> helloStatic() {
HttpRequest<?> request = ServerRequestContext.currentRequest() // (1)
.orElseThrow(() -> new RuntimeException("No request present"))
String name = request.parameters
.getFirst("name")
.orElse("Nobody")
HttpResponse.ok("Hello " + name + "!!")
.header("X-My-Header", "Foo")
}
}
|
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.context.ServerRequestContext
import reactor.core.publisher.Mono
import reactor.util.context.ContextView
@Controller("/request")
class MessageController {
@Get("/hello-static") // (1)
fun helloStatic(): HttpResponse<String> {
val request: HttpRequest<*> = ServerRequestContext.currentRequest<Any>() // (1)
.orElseThrow { RuntimeException("No request present") }
val name = request.parameters
.getFirst("name")
.orElse("Nobody")
return HttpResponse.ok("Hello $name!!")
.header("X-My-Header", "Foo")
}
}
|
ServerRequestContext 用于检索请求。
通常 ServerRequestContext 在反应流中可用,但推荐的方法是将请求作为参数使用,如前一个示例所示。如果下游方法需要请求,则应将其作为参数传递给这些方法。在某些情况下,上下文不会传播,因为其他线程用于发出数据。
Project Reactor 用户使用 ServerRequestContext 的替代方法是使用 Project Reactor 的上下文功能来检索请求。由于 Micronaut 框架使用 Project Reactor 作为其默认的反应流实现,因此 Project Reactor 的用户可以通过能够在上下文中访问请求而受益。例如:
使用 Project Reactor 上下文
Java |
Groovy |
Kotlin |
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.context.ServerRequestContext;
import reactor.core.publisher.Mono;
@Controller("/request")
public class MessageController {
@Get("/hello-reactor")
public Mono<HttpResponse<String>> helloReactor() {
return Mono.deferContextual(ctx -> { // (1)
HttpRequest<?> request = ctx.get(ServerRequestContext.KEY); // (2)
String name = request.getParameters()
.getFirst("name")
.orElse("Nobody");
return Mono.just(HttpResponse.ok("Hello " + name + "!!")
.header("X-My-Header", "Foo"));
});
}
}
|
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.context.ServerRequestContext
import reactor.core.publisher.Mono
@Controller("/request")
class MessageController {
@Get("/hello-reactor")
Mono<HttpResponse<String>> helloReactor() {
Mono.deferContextual(ctx -> { // (1)
HttpRequest<?> request = ctx.get(ServerRequestContext.KEY) // (2)
String name = request.parameters
.getFirst("name")
.orElse("Nobody")
Mono.just(HttpResponse.ok("Hello " + name + "!!")
.header("X-My-Header", "Foo"))
})
}
}
|
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.context.ServerRequestContext
import reactor.core.publisher.Mono
import reactor.util.context.ContextView
@Controller("/request")
class MessageController {
@Get("/hello-reactor")
fun helloReactor(): Mono<HttpResponse<String>?>? {
return Mono.deferContextual { ctx: ContextView -> // (1)
val request = ctx.get<HttpRequest<*>>(ServerRequestContext.KEY) // (2)
val name = request.parameters
.getFirst("name")
.orElse("Nobody")
Mono.just(HttpResponse.ok("Hello $name!!")
.header("X-My-Header", "Foo"))
}
}
}
|
Mono 是通过引用上下文创建的
从上下文中检索请求
使用上下文来检索请求是响应式流的最佳方法,因为 Project Reactor 传播上下文并且它不依赖于像 ServerRequestContext 这样的本地线程。
更多建议: