This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push: new ad9516d [SCB-1754]accessor problem fix: CseHttpMessageConverter response access ad9516d is described below commit ad9516dfad410a4162a7180336306200f410c0c1 Author: liubao <bi...@qq.com> AuthorDate: Mon Aug 3 14:55:43 2020 +0800 [SCB-1754]accessor problem fix: CseHttpMessageConverter response access --- .../springmvc/reference/CseClientHttpResponse.java | 1 - .../reference}/CseHttpMessageConverter.java | 30 +---- .../CseHttpMessageConverterExtractor.java | 31 +++++ .../CseResponseEntityResponseExtractor.java | 49 ++++++++ .../springmvc/reference/CseRestTemplate.java | 126 ++++++++++++++++++++- .../reference/async/CseAsyncRestTemplate.java | 23 +++- .../web/client/TestCseHttpMessageConverter.java | 52 --------- 7 files changed, 231 insertions(+), 81 deletions(-) diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpResponse.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpResponse.java index 52092c9..a06160a 100644 --- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpResponse.java +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpResponse.java @@ -90,7 +90,6 @@ public class CseClientHttpResponse implements ClientHttpResponse { @Override public HttpStatus getStatusCode() throws IOException { - // TODO:springmvc不允许自定义http错误码 return HttpStatus.valueOf(response.getStatusCode()); } diff --git a/providers/provider-springmvc/src/main/java/org/springframework/web/client/CseHttpMessageConverter.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseHttpMessageConverter.java similarity index 75% rename from providers/provider-springmvc/src/main/java/org/springframework/web/client/CseHttpMessageConverter.java rename to providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseHttpMessageConverter.java index 5693f35..35c37b9 100644 --- a/providers/provider-springmvc/src/main/java/org/springframework/web/client/CseHttpMessageConverter.java +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseHttpMessageConverter.java @@ -15,16 +15,13 @@ * limitations under the License. */ -package org.springframework.web.client; +package org.apache.servicecomb.provider.springmvc.reference; import java.io.IOException; -import java.lang.reflect.Field; import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; -import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpRequest; -import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpResponse; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; @@ -32,26 +29,14 @@ import org.springframework.http.converter.GenericHttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.lang.Nullable; -import org.springframework.util.ReflectionUtils; -/** - * 需要访问MessageBodyClientHttpResponseWrapper - * 这是一个package级别的类,只好放在特殊的包内了 - */ public class CseHttpMessageConverter implements GenericHttpMessageConverter<Object> { private static final List<MediaType> ALL_MEDIA_TYPE = Arrays.asList(MediaType.ALL); - private static final Field RESPONSE_FIELD = - ReflectionUtils.findField(MessageBodyClientHttpResponseWrapper.class, "response"); - - static { - RESPONSE_FIELD.setAccessible(true); - } - @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { - return true; + return false; } @Override @@ -67,14 +52,11 @@ public class CseHttpMessageConverter implements GenericHttpMessageConverter<Obje @Override public Object read(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - return read(inputMessage); + throw new IllegalStateException("not supported"); } private Object read(HttpInputMessage inputMessage) { - MessageBodyClientHttpResponseWrapper respWrapper = (MessageBodyClientHttpResponseWrapper) inputMessage; - CseClientHttpResponse resp = - (CseClientHttpResponse) ReflectionUtils.getField(RESPONSE_FIELD, respWrapper); - return resp.getResult(); + throw new IllegalStateException("not supported"); } @Override @@ -90,13 +72,13 @@ public class CseHttpMessageConverter implements GenericHttpMessageConverter<Obje @Override public boolean canRead(Type type, @Nullable Class<?> contextClass, @Nullable MediaType mediaType) { - return true; + return false; } @Override public Object read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - return read(inputMessage); + throw new IllegalStateException("not supported"); } @Override diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseHttpMessageConverterExtractor.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseHttpMessageConverterExtractor.java new file mode 100644 index 0000000..402c714 --- /dev/null +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseHttpMessageConverterExtractor.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference; + +import java.io.IOException; + +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.web.client.ResponseExtractor; + +public class CseHttpMessageConverterExtractor<T> implements ResponseExtractor<T> { + @Override + @SuppressWarnings("unchecked") + public T extractData(ClientHttpResponse response) throws IOException { + return (T) ((CseClientHttpResponse) response).getResult(); + } +} diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseResponseEntityResponseExtractor.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseResponseEntityResponseExtractor.java new file mode 100644 index 0000000..7c8f4ad --- /dev/null +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseResponseEntityResponseExtractor.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.lang.Nullable; +import org.springframework.web.client.ResponseExtractor; + +public class CseResponseEntityResponseExtractor<T> implements ResponseExtractor<ResponseEntity<T>> { + @Nullable + private final CseHttpMessageConverterExtractor<T> delegate; + + public CseResponseEntityResponseExtractor(@Nullable Type responseType) { + if (responseType != null && Void.class != responseType) { + this.delegate = new CseHttpMessageConverterExtractor<>(); + } else { + this.delegate = null; + } + } + + @Override + public ResponseEntity<T> extractData(ClientHttpResponse response) throws IOException { + if (this.delegate != null) { + T body = this.delegate.extractData(response); + return ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(body); + } else { + return ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).build(); + } + } +} diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseRestTemplate.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseRestTemplate.java index 251182e..8f25d4e 100644 --- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseRestTemplate.java +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseRestTemplate.java @@ -20,10 +20,15 @@ package org.apache.servicecomb.provider.springmvc.reference; import java.lang.reflect.Type; import java.net.URI; import java.util.Arrays; +import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.springframework.web.client.CseHttpMessageConverter; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.lang.Nullable; import org.springframework.web.client.RequestCallback; +import org.springframework.web.client.ResponseExtractor; +import org.springframework.web.client.RestClientException; public class CseRestTemplate extends AcceptableRestTemplate { public CseRestTemplate() { @@ -32,6 +37,125 @@ public class CseRestTemplate extends AcceptableRestTemplate { setUriTemplateHandler(new CseUriTemplateHandler()); } + // GET + + @Override + @Nullable + public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException { + RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); + } + + @Override + @Nullable + public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException { + RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); + } + + @Override + @Nullable + public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException { + RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.GET, requestCallback, responseExtractor); + } + + // HEAD + // no override + + // POST + + @Override + @Nullable + public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, + Object... uriVariables) throws RestClientException { + + RequestCallback requestCallback = httpEntityCallback(request, responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables); + } + + @Override + @Nullable + public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, + Map<String, ?> uriVariables) throws RestClientException { + + RequestCallback requestCallback = httpEntityCallback(request, responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables); + } + + @Override + @Nullable + public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) + throws RestClientException { + + RequestCallback requestCallback = httpEntityCallback(request, responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.POST, requestCallback, responseExtractor); + } + + // PUT + // no override + + // PATCH + + @Override + @Nullable + public <T> T patchForObject(String url, @Nullable Object request, Class<T> responseType, + Object... uriVariables) throws RestClientException { + + RequestCallback requestCallback = httpEntityCallback(request, responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.PATCH, requestCallback, responseExtractor, uriVariables); + } + + @Override + @Nullable + public <T> T patchForObject(String url, @Nullable Object request, Class<T> responseType, + Map<String, ?> uriVariables) throws RestClientException { + + RequestCallback requestCallback = httpEntityCallback(request, responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.PATCH, requestCallback, responseExtractor, uriVariables); + } + + @Override + @Nullable + public <T> T patchForObject(URI url, @Nullable Object request, Class<T> responseType) + throws RestClientException { + + RequestCallback requestCallback = httpEntityCallback(request, responseType); + CseHttpMessageConverterExtractor<T> responseExtractor = + new CseHttpMessageConverterExtractor<>(); + return execute(url, HttpMethod.PATCH, requestCallback, responseExtractor); + } + + // DELETE + // no override + + // OPTIONS + // no override + + // exchange + // no override + + @Override + public <T> ResponseExtractor<ResponseEntity<T>> responseEntityExtractor(Type responseType) { + return new CseResponseEntityResponseExtractor<>(responseType); + } + @Override public <T> RequestCallback httpEntityCallback(Object requestBody) { RequestCallback callback = super.httpEntityCallback(requestBody); diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplate.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplate.java index 0f25b6e..683c1b4 100644 --- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplate.java +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplate.java @@ -20,26 +20,43 @@ package org.apache.servicecomb.provider.springmvc.reference.async; import java.lang.reflect.Type; import java.util.Arrays; +import org.apache.servicecomb.provider.springmvc.reference.CseHttpMessageConverter; +import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate; import org.apache.servicecomb.provider.springmvc.reference.CseUriTemplateHandler; +import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.http.HttpEntity; -import org.springframework.web.client.CseHttpMessageConverter; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; @SuppressWarnings("deprecation") -// TODO : upgrade to spring 5 will having warning's , we'll fix it later +// AsyncRestTemplate is deprecated by spring 5, using RPC with CompletableFuture instead. +// Keep this function is only for compatibility, and maybe removed in future. public class CseAsyncRestTemplate extends org.springframework.web.client.AsyncRestTemplate { public CseAsyncRestTemplate() { + super(createSimpleClientHttpRequestFactory(), createRestTemplate()); setMessageConverters(Arrays.asList(new CseHttpMessageConverter())); setAsyncRequestFactory(new CseAsyncClientHttpRequestFactory()); setUriTemplateHandler(new CseUriTemplateHandler()); } + private static SimpleClientHttpRequestFactory createSimpleClientHttpRequestFactory() { + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setTaskExecutor(new SimpleAsyncTaskExecutor()); + return requestFactory; + } + + private static RestTemplate createRestTemplate() { + return new CseRestTemplate(); + } + @Override protected <T> org.springframework.web.client.AsyncRequestCallback httpEntityCallback(HttpEntity<T> requestBody) { return new CseAsyncRequestCallback<T>(requestBody); } @Override - protected <T> org.springframework.web.client.AsyncRequestCallback httpEntityCallback(HttpEntity<T> requestBody, Type responseType) { + protected <T> org.springframework.web.client.AsyncRequestCallback httpEntityCallback(HttpEntity<T> requestBody, + Type responseType) { return new CseAsyncRequestCallback<T>(requestBody); } } \ No newline at end of file diff --git a/providers/provider-springmvc/src/test/java/org/springframework/web/client/TestCseHttpMessageConverter.java b/providers/provider-springmvc/src/test/java/org/springframework/web/client/TestCseHttpMessageConverter.java deleted file mode 100644 index 23ee30d..0000000 --- a/providers/provider-springmvc/src/test/java/org/springframework/web/client/TestCseHttpMessageConverter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.web.client; - -import java.io.IOException; - -import org.apache.servicecomb.provider.common.MockUtil; -import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpRequest; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.http.converter.HttpMessageNotWritableException; - -public class TestCseHttpMessageConverter { - - @Test - public void testAll() { - MockUtil.getInstance().mockReflectionUtils(); - MockUtil.getInstance().mockCseClientHttpRequest(); - CseHttpMessageConverter lCseHttpMessageConverter = new CseHttpMessageConverter(); - lCseHttpMessageConverter.canWrite(null, null); - lCseHttpMessageConverter.getSupportedMediaTypes(); - try { - lCseHttpMessageConverter.read(this.getClass(), null); - } catch (HttpMessageNotReadableException | IOException ignored) { - } - try { - HttpOutputMessage httpOutputMessage = Mockito.mock(CseClientHttpRequest.class); - lCseHttpMessageConverter.write(null, null, httpOutputMessage); - } catch (HttpMessageNotWritableException | IOException ignored) { - } - - Assert.assertEquals(true, lCseHttpMessageConverter.canRead(null, null)); - } -}