Как реализовать пользовательский MethodArgumentResolver в весеннем webflux? - PullRequest
0 голосов
/ 17 марта 2019

Я хочу реализовать пользовательский MethodArgumentResolver для сборки моего собственного сообщения как из заголовка запроса, так и из тела.

Я проделал некоторую работу, прочитал запрос как байтовый массив, получил соответствующий синтаксический анализатор, которыйопределяется значением заголовка запроса 'type', чтобы проанализировать байтовый массив как определенный объект, а затем вернуть.

Это мой распознаватель, я настроил его правильно.

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.Может ли кто-нибудь указать мне?Ценю любые ответы.

...