如何在Spring Webflux中实现自定义MethodArgumentResolver?

时间:2019-03-17 05:07:28

标签: java reactive-programming spring-webflux project-reactor

我想实现一个自定义的MethodArgumentResolver,以便从请求标头和正文中组合我自己的消息。

我已经做了一些工作,将请求作为字节数组读取,获取由请求标头'type'的值指定的相应解析器,将字节数组解析为特定对象,然后返回。 / p>

这是我的解析器,我已经正确配置了它。

public class DeviceManagerRequestBodyResolver extends AbstractMessageReaderArgumentResolver {

    protected DeviceManagerRequestBodyResolver(List<HttpMessageReader<?>> readers) {
        super(readers);
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(DMRequestBody.class);
    }

    @Override
    public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        String type = request.getHeaders().getFirst("type");
        if (StringUtils.isEmpty(type)) {
            return Mono.error(new IllegalArgumentException("Type is null."));
        }

        DMRequestBody annotation = 
            parameter.getParameterAnnotation(DMRequestBody.class);
        Assert.state(annotation != null, "No DMRequestBody annotation.");

        // Here I'm using the value of header 'type' to get the corresponding parser to parse the request body as the specofied object.
        // All parsers have been loaded into the ParserSupplier at the bootstrap phase.
        return Mono.just(ParserSupplier.getParser(Integer.valueOf(type)).parse(request));
    }
}

ParserSupplier.getParser(Integer.valueOf(type))现在将解析为该解析器:

public class AuthorizationRequestBodyParser implements DmRequestBodyParser<AuthorizationMessage> {
    @Override
    public Mono<AuthorizationMessage> parse(ServerHttpRequest request) {
        return readBody(request).flatMap(this::parse0);
    }

    @SuppressWarnings("unchecked")
    private Mono<byte[]> readBody(ServerHttpRequest request) {
        DecoderHttpMessageReader<byte[]> httpMessageReader = new DecoderHttpMessageReader(new ByteArrayDecoder());
        ResolvableType resolvableType = ResolvableType.forClass(byte[].class);
        return httpMessageReader.readMono(resolvableType, request, Collections.emptyMap());
    }

    private Mono<AuthorizationMessage> parse0(byte[] bytes) {
        try {
            JsonNode jsonNode = new ObjectMapper().readTree(bytes);
            AuthorizationMessage parsed = new AuthorizationMessage();
            parsed.setToken(jsonNode.get("token").asText());
            parsed.setUuid(jsonNode.get("uuid").asText());
            return Mono.just(parsed);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Mono.empty();
    }
}

问题是,一切正常,但AuthorizationRequestBodyParser#parse(ServerHttpRequest request)不能正常工作,它导致了以下异常:

java.lang.IllegalStateException: argument type mismatch
Controller [com.baidu.iot.devicecloud.devicemanager.controller.PostController]
Method [public reactor.core.publisher.Mono<com.baidu.iot.devicecloud.devicemanager.resolver.bean.AuthorizationMessage> com.baidu.iot.devicecloud.devicemanager.controller.PostController.auth(com.baidu.iot.devicecloud.devicemanager.resolver.bean.AuthorizationMessage)] with argument values:
 [0] [type=reactor.core.publisher.MonoFlatMap] [value=MonoFlatMap] 

我不知道如何用Publisher的东西返回正确的类型。有人可以指出我吗?感谢任何回应。

0 个答案:

没有答案