类org.springframework.http.codec.HttpMessageWriter源码实例Demo

下面列出了怎么用org.springframework.http.codec.HttpMessageWriter的API类实例代码及写法,或者点击链接到github查看源代码。


@Test
public void bodyClass() {
	String body = "foo";
	Publisher<String> publisher = Mono.just(body);
	ClientRequest result = ClientRequest.create(POST, URI.create("http://example.com"))
			.body(publisher, String.class).build();

	List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
	messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));

	ExchangeStrategies strategies = mock(ExchangeStrategies.class);
	when(strategies.messageWriters()).thenReturn(messageWriters);

	MockClientHttpRequest request = new MockClientHttpRequest(GET, "/");
	result.writeTo(request, strategies).block();
	assertNotNull(request.getBody());

	StepVerifier.create(request.getBody())
			.expectNextCount(1)
			.verifyComplete();
}
 

@Override
protected Mono<Void> writeToInternal(ServerWebExchange exchange, Context context) {
	return inserter().insert(exchange.getResponse(), new BodyInserter.Context() {
		@Override
		public List<HttpMessageWriter<?>> messageWriters() {
			return context.messageWriters();
		}
		@Override
		public Optional<ServerHttpRequest> serverRequest() {
			return Optional.of(exchange.getRequest());
		}
		@Override
		public Map<String, Object> hints() {
			hints.put(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix());
			return hints;
		}
	});
}
 

@Test
public void bodyParameterizedTypeReference() {
	String body = "foo";
	Publisher<String> publisher = Mono.just(body);
	ParameterizedTypeReference<String> typeReference = new ParameterizedTypeReference<String>() {};
	ClientRequest result = ClientRequest.create(POST, URI.create("http://example.com"))
			.body(publisher, typeReference).build();

	List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
	messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));

	ExchangeStrategies strategies = mock(ExchangeStrategies.class);
	when(strategies.messageWriters()).thenReturn(messageWriters);

	MockClientHttpRequest request = new MockClientHttpRequest(GET, "/");
	result.writeTo(request, strategies).block();
	assertNotNull(request.getBody());

	StepVerifier.create(request.getBody())
			.expectNextCount(1)
			.verifyComplete();
}
 

@Override
protected Mono<Void> writeToInternal(ServerWebExchange exchange, Context context) {
	return this.inserter.insert(exchange.getResponse(), new BodyInserter.Context() {
		@Override
		public List<HttpMessageWriter<?>> messageWriters() {
			return context.messageWriters();
		}
		@Override
		public Optional<ServerHttpRequest> serverRequest() {
			return Optional.of(exchange.getRequest());
		}
		@Override
		public Map<String, Object> hints() {
			hints.put(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix());
			return hints;
		}
	});
}
 

private AbstractMessageWriterResultHandler initResultHandler(HttpMessageWriter<?>... writers) {
	List<HttpMessageWriter<?>> writerList;
	if (ObjectUtils.isEmpty(writers)) {
		writerList = new ArrayList<>();
		writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
		writerList.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
		writerList.add(new ResourceHttpMessageWriter());
		writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
		writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
	}
	else {
		writerList = Arrays.asList(writers);
	}
	RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
	return new AbstractMessageWriterResultHandler(writerList, resolver) {};
}
 

private AbstractMessageWriterResultHandler initResultHandler(HttpMessageWriter<?>... writers) {
	List<HttpMessageWriter<?>> writerList;
	if (ObjectUtils.isEmpty(writers)) {
		writerList = new ArrayList<>();
		writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
		writerList.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
		writerList.add(new ResourceHttpMessageWriter());
		writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
		writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
	}
	else {
		writerList = Arrays.asList(writers);
	}
	RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
	return new AbstractMessageWriterResultHandler(writerList, resolver) {};
}
 

/**
 * Return writers that support specific types.
 * @param forMultipart whether to returns writers for general use ("false"),
 * or for multipart requests only ("true"). Generally the two sets are the
 * same except for the multipart writer itself.
 */
@SuppressWarnings("unchecked")
final List<HttpMessageWriter<?>> getTypedWriters(boolean forMultipart) {
	if (!this.registerDefaults) {
		return Collections.emptyList();
	}
	List<HttpMessageWriter<?>> writers = new ArrayList<>();
	writers.add(new EncoderHttpMessageWriter<>(new ByteArrayEncoder()));
	writers.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
	writers.add(new EncoderHttpMessageWriter<>(new DataBufferEncoder()));
	writers.add(new ResourceHttpMessageWriter());
	writers.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
	// No client or server specific multipart writers currently..
	if (!forMultipart) {
		extendTypedWriters(writers);
	}
	if (protobufPresent) {
		Encoder<?> encoder = this.protobufEncoder != null ? this.protobufEncoder : new ProtobufEncoder();
		writers.add(new ProtobufHttpMessageWriter((Encoder) encoder));
	}
	return writers;
}
 

/**
 * Return Object writers (JSON, XML, SSE).
 * @param forMultipart whether to returns writers for general use ("false"),
 * or for multipart requests only ("true"). Generally the two sets are the
 * same except for the multipart writer itself.
 */
final List<HttpMessageWriter<?>> getObjectWriters(boolean forMultipart) {
	if (!this.registerDefaults) {
		return Collections.emptyList();
	}
	List<HttpMessageWriter<?>> writers = new ArrayList<>();
	if (jackson2Present) {
		writers.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder()));
	}
	if (jackson2SmilePresent) {
		writers.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder()));
	}
	if (jaxb2Present) {
		Encoder<?> encoder = this.jaxb2Encoder != null ? this.jaxb2Encoder : new Jaxb2XmlEncoder();
		writers.add(new EncoderHttpMessageWriter<>(encoder));
	}
	// No client or server specific multipart writers currently..
	if (!forMultipart) {
		extendObjectWriters(writers);
	}
	return writers;
}
 

@Test
public void defaultWriters() {
	List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
	assertEquals(11, writers.size());
	assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
	assertStringEncoder(getNextEncoder(writers), true);
	assertEquals(ProtobufHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
	assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
	assertSseWriter(writers);
	assertStringEncoder(getNextEncoder(writers), false);
}
 

@Test
public void defaultWriters() {
	List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
	assertEquals(11, writers.size());
	assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
	assertStringEncoder(getNextEncoder(writers), true);
	assertEquals(MultipartHttpMessageWriter.class, writers.get(this.index.getAndIncrement()).getClass());
	assertEquals(ProtobufHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
	assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
	assertStringEncoder(getNextEncoder(writers), false);
}
 

/**
 * Inserter to write the given {@code Resource}.
 * <p>If the resource can be resolved to a {@linkplain Resource#getFile() file}, it will
 * be copied using <a href="https://en.wikipedia.org/wiki/Zero-copy">zero-copy</a>.
 * @param resource the resource to write to the output message
 * @param <T> the type of the {@code Resource}
 * @return the inserter to write a {@code Publisher}
 */
public static <T extends Resource> BodyInserter<T, ReactiveHttpOutputMessage> fromResource(T resource) {
	Assert.notNull(resource, "Resource must not be null");
	return (outputMessage, context) -> {
		ResolvableType elementType = RESOURCE_TYPE;
		HttpMessageWriter<Resource> writer = findWriter(context, elementType, null);
		return write(Mono.just(resource), elementType, null, outputMessage, context, writer);
	};
}
 

/**
 * Inserter to write the given {@code ServerSentEvent} publisher.
 * <p>Alternatively, you can provide event data objects via
 * {@link #fromPublisher(Publisher, Class)}, and set the "Content-Type" to
 * {@link MediaType#TEXT_EVENT_STREAM text/event-stream}.
 * @param eventsPublisher the {@code ServerSentEvent} publisher to write to the response body
 * @param <T> the type of the data elements in the {@link ServerSentEvent}
 * @return the inserter to write a {@code ServerSentEvent} publisher
 * @see <a href="https://www.w3.org/TR/eventsource/">Server-Sent Events W3C recommendation</a>
 */
// Parameterized for server-side use
public static <T, S extends Publisher<ServerSentEvent<T>>> BodyInserter<S, ServerHttpResponse> fromServerSentEvents(
		S eventsPublisher) {

	Assert.notNull(eventsPublisher, "Publisher must not be null");
	return (serverResponse, context) -> {
		ResolvableType elementType = SSE_TYPE;
		MediaType mediaType = MediaType.TEXT_EVENT_STREAM;
		HttpMessageWriter<ServerSentEvent<T>> writer = findWriter(context, elementType, mediaType);
		return write(eventsPublisher, elementType, mediaType, serverResponse, context, writer);
	};
}
 

@Override
public Mono<Void> insert(ClientHttpRequest outputMessage, Context context) {
	HttpMessageWriter<MultiValueMap<String, String>> messageWriter =
			findWriter(context, FORM_DATA_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
	return messageWriter.write(Mono.just(this.data), FORM_DATA_TYPE,
			MediaType.APPLICATION_FORM_URLENCODED,
			outputMessage, context.hints());
}
 

@Override
public Mono<Void> writeTo(ClientHttpRequest request, ExchangeStrategies strategies) {
	HttpHeaders requestHeaders = request.getHeaders();
	if (!this.headers.isEmpty()) {
		this.headers.entrySet().stream()
				.filter(entry -> !requestHeaders.containsKey(entry.getKey()))
				.forEach(entry -> requestHeaders
						.put(entry.getKey(), entry.getValue()));
	}

	MultiValueMap<String, HttpCookie> requestCookies = request.getCookies();
	if (!this.cookies.isEmpty()) {
		this.cookies.forEach((name, values) -> values.forEach(value -> {
			HttpCookie cookie = new HttpCookie(name, value);
			requestCookies.add(name, cookie);
		}));
	}

	return this.body.insert(request, new BodyInserter.Context() {
		@Override
		public List<HttpMessageWriter<?>> messageWriters() {
			return strategies.messageWriters();
		}
		@Override
		public Optional<ServerHttpRequest> serverRequest() {
			return Optional.empty();
		}
		@Override
		public Map<String, Object> hints() {
			return Hints.from(Hints.LOG_PREFIX_HINT, logPrefix());
		}
	});
}
 

/**
 * Constructor with explicit list of writers for serializing parts and a
 * writer for plain form data to fall back when no media type is specified
 * and the actual map consists of String values only.
 * @param partWriters the writers for serializing parts
 * @param formWriter the fallback writer for form data, {@code null} by default
 */
public MultipartHttpMessageWriter(List<HttpMessageWriter<?>> partWriters,
		@Nullable  HttpMessageWriter<MultiValueMap<String, String>> formWriter) {

	this.partWriters = partWriters;
	this.formWriter = formWriter;
	this.supportedMediaTypes = initMediaTypes(formWriter);
}
 

private static <T> Mono<Void> write(Publisher<? extends T> input, ResolvableType type,
		@Nullable MediaType mediaType, ReactiveHttpOutputMessage message,
		BodyInserter.Context context, HttpMessageWriter<T> writer) {

	return context.serverRequest()
			.map(request -> {
				ServerHttpResponse response = (ServerHttpResponse) message;
				return writer.write(input, type, type, mediaType, request, response, context.hints());
			})
			.orElseGet(() -> writer.write(input, type, mediaType, message, context.hints()));
}
 

@Override
public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
	ServerResponse response = (ServerResponse) result.getReturnValue();
	Assert.state(response != null, "No ServerResponse");
	return response.writeTo(exchange, new ServerResponse.Context() {
		@Override
		public List<HttpMessageWriter<?>> messageWriters() {
			return messageWriters;
		}
		@Override
		public List<ViewResolver> viewResolvers() {
			return viewResolvers;
		}
	});
}
 

/**
 * Constructor with an {@link ReactiveAdapterRegistry} instance.
 * @param writers writers for serializing to the response body
 * @param resolver to determine the requested content type
 * @param registry for adaptation to reactive types
 */
public ResponseEntityResultHandler(List<HttpMessageWriter<?>> writers,
		RequestedContentTypeResolver resolver, ReactiveAdapterRegistry registry) {

	super(writers, resolver, registry);
	setOrder(0);
}
 

@Test
public void defaultWriters() {
	List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
	assertEquals(10, writers.size());
	assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
	assertStringEncoder(getNextEncoder(writers), true);
	assertEquals(ProtobufHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
	assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
	assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
	assertStringEncoder(getNextEncoder(writers), false);
}
 

@SuppressWarnings("unchecked")
private <T> Mono<Void> write(T value, @Nullable MediaType contentType, ServerWebExchange exchange) {
	Publisher<T> input = Mono.justOrEmpty(value);
	ResolvableType elementType = ResolvableType.forClass(value.getClass());
	return ((HttpMessageWriter<T>) this.writer).write(
			input, elementType, contentType, exchange.getResponse(),
			Hints.from(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix()));
}
 

/**
 * Constructor with an {@link ReactiveAdapterRegistry} instance.
 * @param writers writers for serializing to the response body
 * @param resolver to determine the requested content type
 * @param registry for adaptation to reactive types
 */
public ResponseEntityResultHandler(List<HttpMessageWriter<?>> writers,
		RequestedContentTypeResolver resolver, ReactiveAdapterRegistry registry) {

	super(writers, resolver, registry);
	setOrder(0);
}
 

@Before
public void setup() throws Exception {
	List<HttpMessageWriter<?>> writerList = new ArrayList<>(5);
	writerList.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
	writerList.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
	writerList.add(new ResourceHttpMessageWriter());
	writerList.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
	writerList.add(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
	RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder().build();
	this.resultHandler = new ResponseBodyResultHandler(writerList, resolver);
}
 

private List<MediaType> getMediaTypesFor(ResolvableType elementType) {
	List<MediaType> writableMediaTypes = new ArrayList<>();
	for (HttpMessageWriter<?> converter : getMessageWriters()) {
		if (converter.canWrite(elementType, null)) {
			writableMediaTypes.addAll(converter.getWritableMediaTypes());
		}
	}
	return writableMediaTypes;
}
 

@Override
public Mono<Void> insert(ClientHttpRequest outputMessage, Context context) {
	HttpMessageWriter<MultiValueMap<String, HttpEntity<?>>> messageWriter =
			findWriter(context, MULTIPART_DATA_TYPE, MediaType.MULTIPART_FORM_DATA);
	MultiValueMap<String, HttpEntity<?>> body = this.builder.build();
	return messageWriter.write(Mono.just(body), MULTIPART_DATA_TYPE,
			MediaType.MULTIPART_FORM_DATA, outputMessage, context.hints());
}
 

/**
 * Constructor with an additional {@link ReactiveAdapterRegistry}.
 * @param messageWriters for serializing Objects to the response body stream
 * @param contentTypeResolver for resolving the requested content type
 * @param adapterRegistry for adapting other reactive types (e.g. rx.Observable,
 * rx.Single, etc.) to Flux or Mono
 */
protected AbstractMessageWriterResultHandler(List<HttpMessageWriter<?>> messageWriters,
		RequestedContentTypeResolver contentTypeResolver, ReactiveAdapterRegistry adapterRegistry) {

	super(contentTypeResolver, adapterRegistry);
	Assert.notEmpty(messageWriters, "At least one message writer is required");
	this.messageWriters = messageWriters;
}
 

@Before
public void createContext() {
	HandlerStrategies strategies = HandlerStrategies.withDefaults();
	context = new ServerResponse.Context() {
		@Override
		public List<HttpMessageWriter<?>> messageWriters() {
			return strategies.messageWriters();
		}
		@Override
		public List<ViewResolver> viewResolvers() {
			return strategies.viewResolvers();
		}
	};
}
 

@Before
public void createContext() {
	final List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
	messageWriters.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
	messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
	messageWriters.add(new ResourceHttpMessageWriter());
	messageWriters.add(new EncoderHttpMessageWriter<>(new Jaxb2XmlEncoder()));
	Jackson2JsonEncoder jsonEncoder = new Jackson2JsonEncoder();
	messageWriters.add(new EncoderHttpMessageWriter<>(jsonEncoder));
	messageWriters.add(new ServerSentEventHttpMessageWriter(jsonEncoder));
	messageWriters.add(new FormHttpMessageWriter());
	messageWriters.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.allMimeTypes()));
	messageWriters.add(new MultipartHttpMessageWriter(messageWriters));

	this.context = new BodyInserter.Context() {
		@Override
		public List<HttpMessageWriter<?>> messageWriters() {
			return messageWriters;
		}
		@Override
		public Optional<ServerHttpRequest> serverRequest() {
			return Optional.empty();
		}
		@Override
		public Map<String, Object> hints() {
			return hints;
		}
	};
	this.hints = new HashMap<>();
}
 

@Test
public void responseEntityResultHandler() throws Exception {
	ApplicationContext context = loadConfig(WebFluxConfig.class);

	String name = "responseEntityResultHandler";
	ResponseEntityResultHandler handler = context.getBean(name, ResponseEntityResultHandler.class);
	assertNotNull(handler);

	assertEquals(0, handler.getOrder());

	List<HttpMessageWriter<?>> writers = handler.getMessageWriters();
	assertEquals(11, writers.size());

	assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM);
	assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);
	assertHasMessageWriter(writers, forClass(String.class), TEXT_PLAIN);
	assertHasMessageWriter(writers, forClass(Resource.class), IMAGE_PNG);
	assertHasMessageWriter(writers, forClass(Message.class), new MediaType("application", "x-protobuf"));
	assertHasMessageWriter(writers, forClass(TestBean.class), APPLICATION_XML);
	assertHasMessageWriter(writers, forClass(TestBean.class), APPLICATION_JSON);
	assertHasMessageWriter(writers, forClass(TestBean.class), new MediaType("application", "x-jackson-smile"));
	assertHasMessageWriter(writers, forClass(TestBean.class), MediaType.parseMediaType("text/event-stream"));

	name = "webFluxContentTypeResolver";
	RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
	assertSame(resolver, handler.getContentTypeResolver());
}
 

@Test
public void responseEntityResultHandler() throws Exception {
	ApplicationContext context = loadConfig(WebFluxConfig.class);

	String name = "responseEntityResultHandler";
	ResponseEntityResultHandler handler = context.getBean(name, ResponseEntityResultHandler.class);
	assertNotNull(handler);

	assertEquals(0, handler.getOrder());

	List<HttpMessageWriter<?>> writers = handler.getMessageWriters();
	assertEquals(11, writers.size());

	assertHasMessageWriter(writers, forClass(byte[].class), APPLICATION_OCTET_STREAM);
	assertHasMessageWriter(writers, forClass(ByteBuffer.class), APPLICATION_OCTET_STREAM);
	assertHasMessageWriter(writers, forClass(String.class), TEXT_PLAIN);
	assertHasMessageWriter(writers, forClass(Resource.class), IMAGE_PNG);
	assertHasMessageWriter(writers, forClass(Message.class), new MediaType("application", "x-protobuf"));
	assertHasMessageWriter(writers, forClass(TestBean.class), APPLICATION_XML);
	assertHasMessageWriter(writers, forClass(TestBean.class), APPLICATION_JSON);
	assertHasMessageWriter(writers, forClass(TestBean.class), new MediaType("application", "x-jackson-smile"));
	assertHasMessageWriter(writers, forClass(TestBean.class), MediaType.parseMediaType("text/event-stream"));

	name = "webFluxContentTypeResolver";
	RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
	assertSame(resolver, handler.getContentTypeResolver());
}
 

protected ResponseContext(
    List<HttpMessageWriter<?>> messageWriters,
    List<ViewResolver> viewResolvers
) {
    this.messageWriters = messageWriters;
    this.viewResolvers = viewResolvers;
}
 
 类所在包
 同包方法