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