在Micronaut中绑定QueryValue之前进行拦截

时间:2019-11-01 20:39:16

标签: micronaut

我一直想在控制器中执行端点方法之前使用HttpServerFilter修改传入的请求。在我的请求中,我有@QueryValue个绑定。这些绑定的执行似乎发生在HttpServerFilter之前,因此,如果我想修改查询参数,将无法执行。

@QueryValue绑定之前,我有什么地方可以拦截和修改请求?

1 个答案:

答案 0 :(得分:2)

可以通过HttpServerFilter解决,但是您应该在匹配的路由中而不是在请求中更新参数值。这是因为RoutingInBoundHandler首先尝试满足路由的参数要求,然后执行过滤器链。请参见下面的示例该怎么做:

调用修改服务的过滤器:

@Filter("/hello/**")
public class ModifyRequestFilter implements HttpServerFilter {
    private final ModifyRequestService service;

    public ModifyRequestFilter(ModifyRequestService service) {
        this.service = service;
    }

    @Override
    public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
        return service.modify(request)
                .switchMap(aBoolean -> chain.proceed(request));
    }
}

执行修改的服务,其中的关键代码是:((NettyHttpRequest<?>) request).getMatchedRoute().getVariableValues().put("value", "modified in filter");

@Singleton
public class ModifyRequestService {
    Flowable<Boolean> modify(HttpRequest<?> request) {
        return Flowable.fromCallable(() -> {
            ((NettyHttpRequest<?>) request).getMatchedRoute().getVariableValues().put("value", "modified in filter");
            return true;
        }).subscribeOn(Schedulers.io());
    }
}

和控制器:

@Controller("/hello")
public class HelloController {
    @Get("/")
    public String index(@QueryValue String value) {
        return "Hello " + value;
    }
}

另一种选择是对要使用自己的类型转换器修改的值使用自己的容器类。

例如CustomValue类作为值容器:

public class CustomValue {
    private String value;

    public CustomValue(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

以下是自定义值转换器的注册商,该注册商将CharSequence转换为CustomValue实例:

@Singleton
@BootstrapContextCompatible
public class CustomConverterRegistrar implements TypeConverterRegistrar {
    @Override
    public void register(ConversionService<?> conversionService) {
        conversionService.addConverter(CharSequence.class, CustomValue.class, 
            s -> new CustomValue(s + "-updated"));
    }
}

这是控制器的示例:

@Controller("/hello")
public class HelloController {
    @Get("/in-query")
    public String inQuery(@QueryValue CustomValue value) {
        return "Hello " + value.getValue();
    }

    @Get("/in-path/{value}")
    public String inPath(CustomValue value) {
        return "Hello " + value.getValue();
    }
}

以及卷曲测试结果:

$ curl http://localhost:8080/hello/in-query/?value=test
Hello test-updated
$ curl http://localhost:8080/hello/in-path/testFromPath
Hello testFromPath-updated