Browse Source

InterceptingHttpAccessor uses internal ArrayList for sorting

Also caches InterceptingClientHttpRequestFactory (if applicable)

Issue: SPR-16137
pull/1581/head
Juergen Hoeller 8 years ago
parent
commit
d06129debd
  1. 6
      spring-web/src/main/java/org/springframework/http/client/support/HttpAccessor.java
  2. 68
      spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java
  3. 3
      spring-web/src/main/java/org/springframework/web/client/RestTemplate.java
  4. 27
      spring-web/src/test/java/org/springframework/http/client/support/InterceptingHttpAccessorTests.java

6
spring-web/src/main/java/org/springframework/http/client/support/HttpAccessor.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,11 +34,12 @@ import org.springframework.util.Assert;
* such as the {@link ClientHttpRequestFactory} to operate on. * such as the {@link ClientHttpRequestFactory} to operate on.
* *
* <p>Not intended to be used directly. * <p>Not intended to be used directly.
* See {@link org.springframework.web.client.RestTemplate}. * See {@link org.springframework.web.client.RestTemplate} for an entry point.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 3.0 * @since 3.0
* @see ClientHttpRequestFactory
* @see org.springframework.web.client.RestTemplate * @see org.springframework.web.client.RestTemplate
*/ */
public abstract class HttpAccessor { public abstract class HttpAccessor {
@ -56,6 +57,7 @@ public abstract class HttpAccessor {
* <p><b>Note that the standard JDK HTTP library does not support the HTTP PATCH method. * <p><b>Note that the standard JDK HTTP library does not support the HTTP PATCH method.
* Configure the Apache HttpComponents or OkHttp request factory to enable PATCH.</b> * Configure the Apache HttpComponents or OkHttp request factory to enable PATCH.</b>
* @see #createRequest(URI, HttpMethod) * @see #createRequest(URI, HttpMethod)
* @see SimpleClientHttpRequestFactory
* @see org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory * @see org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory
* @see org.springframework.http.client.OkHttp3ClientHttpRequestFactory * @see org.springframework.http.client.OkHttp3ClientHttpRequestFactory
*/ */

68
spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,43 +23,83 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.InterceptingClientHttpRequestFactory; import org.springframework.http.client.InterceptingClientHttpRequestFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
/** /**
* Base class for {@link org.springframework.web.client.RestTemplate} and other HTTP accessing gateway helpers, adding * Base class for {@link org.springframework.web.client.RestTemplate}
* interceptor-related properties to {@link HttpAccessor}'s common properties. * and other HTTP accessing gateway helpers, adding interceptor-related
* properties to {@link HttpAccessor}'s common properties.
* *
* <p>Not intended to be used directly. See {@link org.springframework.web.client.RestTemplate}. * <p>Not intended to be used directly.
* See {@link org.springframework.web.client.RestTemplate} for an entry point.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0
* @see ClientHttpRequestInterceptor
* @see InterceptingClientHttpRequestFactory
* @see org.springframework.web.client.RestTemplate
*/ */
public abstract class InterceptingHttpAccessor extends HttpAccessor { public abstract class InterceptingHttpAccessor extends HttpAccessor {
private List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(); private final List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
@Nullable
private volatile ClientHttpRequestFactory interceptingRequestFactory;
/** /**
* Sets the request interceptors that this accessor should use. * Set the request interceptors that this accessor should use.
* <p>The interceptors will get sorted according to their order
* once the {@link ClientHttpRequestFactory} will be built.
* @see #getRequestFactory()
* @see AnnotationAwareOrderComparator
*/ */
public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) { public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
AnnotationAwareOrderComparator.sort(interceptors); // Take getInterceptors() List as-is when passed in here
this.interceptors = interceptors; if (this.interceptors != interceptors) {
this.interceptors.clear();
this.interceptors.addAll(interceptors);
AnnotationAwareOrderComparator.sort(this.interceptors);
}
} }
/** /**
* Return the request interceptor that this accessor uses. * Return the request interceptors that this accessor uses.
* <p>The returned {@link List} is active and may get appended to.
*/ */
public List<ClientHttpRequestInterceptor> getInterceptors() { public List<ClientHttpRequestInterceptor> getInterceptors() {
return interceptors; return this.interceptors;
}
/**
* {@inheritDoc}
*/
@Override
public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
super.setRequestFactory(requestFactory);
this.interceptingRequestFactory = null;
} }
/**
* Overridden to expose an {@link InterceptingClientHttpRequestFactory}
* if necessary.
* @see #getInterceptors()
*/
@Override @Override
public ClientHttpRequestFactory getRequestFactory() { public ClientHttpRequestFactory getRequestFactory() {
ClientHttpRequestFactory delegate = super.getRequestFactory(); List<ClientHttpRequestInterceptor> interceptors = getInterceptors();
if (!CollectionUtils.isEmpty(getInterceptors())) { if (!CollectionUtils.isEmpty(interceptors)) {
return new InterceptingClientHttpRequestFactory(delegate, getInterceptors()); ClientHttpRequestFactory factory = this.interceptingRequestFactory;
if (factory == null) {
factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
this.interceptingRequestFactory = factory;
}
return factory;
} }
else { else {
return delegate; return super.getRequestFactory();
} }
} }

3
spring-web/src/main/java/org/springframework/web/client/RestTemplate.java

@ -237,7 +237,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
} }
/** /**
* Return the message body converters. * Return the list of message body converters.
* <p>The returned {@link List} is active and may get appended to.
*/ */
public List<HttpMessageConverter<?>> getMessageConverters() { public List<HttpMessageConverter<?>> getMessageConverters() {
return this.messageConverters; return this.messageConverters;

27
spring-web/src/test/java/org/springframework/http/client/support/InterceptingHttpAccessorTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,9 +16,6 @@
package org.springframework.http.client.support; package org.springframework.http.client.support;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -32,6 +29,8 @@ import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.ClientHttpResponse;
import static org.junit.Assert.*;
/** /**
* Tests for {@link InterceptingHttpAccessor}. * Tests for {@link InterceptingHttpAccessor}.
* *
@ -40,7 +39,7 @@ import org.springframework.http.client.ClientHttpResponse;
public class InterceptingHttpAccessorTests { public class InterceptingHttpAccessorTests {
@Test @Test
public void getInterceptors() throws Exception { public void getInterceptors() {
TestInterceptingHttpAccessor accessor = new TestInterceptingHttpAccessor(); TestInterceptingHttpAccessor accessor = new TestInterceptingHttpAccessor();
List<ClientHttpRequestInterceptor> interceptors = Arrays.asList( List<ClientHttpRequestInterceptor> interceptors = Arrays.asList(
new SecondClientHttpRequestInterceptor(), new SecondClientHttpRequestInterceptor(),
@ -55,22 +54,25 @@ public class InterceptingHttpAccessorTests {
assertThat(accessor.getInterceptors().get(2), Matchers.instanceOf(ThirdClientHttpRequestInterceptor.class)); assertThat(accessor.getInterceptors().get(2), Matchers.instanceOf(ThirdClientHttpRequestInterceptor.class));
} }
private class TestInterceptingHttpAccessor extends InterceptingHttpAccessor { private class TestInterceptingHttpAccessor extends InterceptingHttpAccessor {
} }
@Order(1) @Order(1)
private class FirstClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { private class FirstClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override @Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
ClientHttpRequestExecution execution) throws IOException {
return null; return null;
} }
} }
private class SecondClientHttpRequestInterceptor implements ClientHttpRequestInterceptor, Ordered { private class SecondClientHttpRequestInterceptor implements ClientHttpRequestInterceptor, Ordered {
@Override @Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
ClientHttpRequestExecution execution) throws IOException {
return null; return null;
} }
@ -80,12 +82,13 @@ public class InterceptingHttpAccessorTests {
} }
} }
private class ThirdClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { private class ThirdClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override @Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
ClientHttpRequestExecution execution) throws IOException {
return null; return null;
} }
} }
} }

Loading…
Cancel
Save