RestTemplate配置API 攔截器,增加請求頭信息,JWT

目標 對第三方的請求增加請求頭信息.

  1. 目標在調用第三方接口時候,需要在請求裏面增加請求頭信息。springboot 利用restTemplate 模板進行http請求轉發。

  2. 編寫攔截器類 實現接口ClientHttpRequestInterceptor,實現具體的往請求頭裏面增加具體的有信息:

package com.feifan;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

import java.io.IOException;

/**
 * @author Donald
 * @create 2019-09-28 12:26
 * 自定義 請求攔截器
 */
public class UserClientInterCeptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        /// 獲取請求頭
        HttpHeaders headers = request.getHeaders();
        // 加入請求頭信息
        headers.add("koko","kiki");
        // TODO 增加其他的請求頭信息

        // 執行請求
        ClientHttpResponse execute = execution.execute(request, body);

        System.err.println(execute.getStatusCode()+execute.getStatusText());

        return execute;
    }
}

  1. 配置Bean 的時候增加,具體的攔截器信息,
@Bean
    public RestTemplate getBeanRstTemplate(RestTemplateBuilder builder )
    {
        RestTemplate restTemplate =
                builder
                        //
                        .basicAuthentication("ki", "dd")
                // 增加請求攔截器
                .interceptors(new UserClientInterCeptor())
                .build();
        // 消息轉換器
        restTemplate.getMessageConverters().add(new RestMessageInterceptor());
        return restTemplate;
    }
  1. 方法調用:
 @Autowired
    private RestTemplate restTemplate ;

    @GetMapping("header")
    @ResponseBody
    public Object getHeader()
    {
        Object forObject = restTemplate.getForObject("http://127.0.0.1:8080/find/list/47", Object.class);
        return forObject;

    }
  1. 結果:請求中增加了具體的請求頭信息
    6.

增加消息轉換器

消息裝換器等層接口:HttpMessageConverter.calss

/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed 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
 *
 *      https://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.http.converter;

import java.io.IOException;
import java.util.List;

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;

/**
 * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @since 3.0
 * @param <T> the converted object type
 */
public interface HttpMessageConverter<T> {

	/**
	 * Indicates whether the given class can be read by this converter.
	 * @param clazz the class to test for readability
	 * @param mediaType the media type to read (can be {@code null} if not specified);
	 * typically the value of a {@code Content-Type} header.
	 * @return {@code true} if readable; {@code false} otherwise
	 */
	boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);

	/**
	 * Indicates whether the given class can be written by this converter.
	 * @param clazz the class to test for writability
	 * @param mediaType the media type to write (can be {@code null} if not specified);
	 * typically the value of an {@code Accept} header.
	 * @return {@code true} if writable; {@code false} otherwise
	 */
	boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);

	/**
	 * Return the list of {@link MediaType} objects supported by this converter.
	 * @return the list of supported media types
	 */
	List<MediaType> getSupportedMediaTypes();

	/**
	 * Read an object of the given type from the given input message, and returns it.
	 * @param clazz the type of object to return. This type must have previously been passed to the
	 * {@link #canRead canRead} method of this interface, which must have returned {@code true}.
	 * @param inputMessage the HTTP input message to read from
	 * @return the converted object
	 * @throws IOException in case of I/O errors
	 * @throws HttpMessageNotReadableException in case of conversion errors
	 */
	T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
			throws IOException, HttpMessageNotReadableException;

	/**
	 * Write an given object to the given output message.
	 * @param t the object to write to the output message. The type of this object must have previously been
	 * passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
	 * @param contentType the content type to use when writing. May be {@code null} to indicate that the
	 * default content type of the converter must be used. If not {@code null}, this media type must have
	 * previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
	 * returned {@code true}.
	 * @param outputMessage the message to write to
	 * @throws IOException in case of I/O errors
	 * @throws HttpMessageNotWritableException in case of conversion errors
	 */
	void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
			throws IOException, HttpMessageNotWritableException;

}

  1. 在SpringMVC進入controller方法前,會根據@RequestBody註解選擇適當的HttpMessageConverter實現類來將請求參數解析到string變量中,具體來說是使用了StringHttpMessageConverter類,它的canRead()方法返回true,然後它的read()方法會從請求中讀出請求參數,綁定到readString()方法的string變量中。
  2. 由於返回值標識了@ResponseBody,SpringMVC將使用StringHttpMessageConverter的write()方法,將結果作爲String值寫入響應報文,當然,此時canWrite()方法返回true。
  3. 在SpringMVC的設計者眼中,一次請求報文和一次響應報文,分別被抽象爲一個請求消息HttpInputMessage和一個響應消息HttpOutputMessage。
    在這裏插入圖片描述
  4. 自定義消息轉換器
package com.feifan;

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Donald
 * @create 2019-10-09 22:13
 */
public class RestMessageInterceptor implements HttpMessageConverter {
    @Override
    public boolean canRead(Class clazz, MediaType mediaType) {
        System.err.println("canRead inside");
        return true;
    }

    @Override
    public boolean canWrite(Class clazz, MediaType mediaType) {
        System.err.println("canWrite inside");
        return false;
    }

    @Override
    public List<MediaType> getSupportedMediaTypes() {
        System.err.println("getSupportedMediaTypes");
        return new ArrayList<>();
    }

    @Override
    public Object read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        System.err.println("read");
        return null;
    }

    @Override
    public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        System.err.println("write");
    }
}


  1. 配置類中加入消息轉換器的信息:
@Bean
    public RestTemplate getBeanRstTemplate(RestTemplateBuilder builder )
    {
        RestTemplate restTemplate =
                builder
                        //
                        .basicAuthentication("ki", "dd")
                // 增加請求攔截器
                .interceptors(new UserClientInterCeptor())
                .build();
        // 消息轉換器
        restTemplate.getMessageConverters().add(new RestMessageInterceptor());
        return restTemplate;
    }
  1. xml配置方式

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
   <property name="messageConverters">
       <list>
           <ref bean="jsonConverter" />
           <ref bean="marshallingConverter" />
           <ref bean="atomConverter" />
       </list>
   </property>
</bean>
 
<bean id="jsonConverter"   class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
   <property name="supportedMediaTypes" value="application/json" />

參考連接:

https://www.iteye.com/blog/rensanning-2362105

RestTemplate包含:
HttpMessageConverter 對象轉換器
ClientHttpRequestFactory 默認是JDK的HttpURLConnection
ResponseErrorHandler 異常處理
ClientHttpRequestInterceptor 請求攔截器
在這裏插入圖片描述
8. 自定義異常處理信息

package com.feifan;

import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;

import java.io.IOException;
import java.net.URI;

/**
 * @author Donald
 * @create 2019-10-09 23:24
 */
public class ResponeException extends DefaultResponseErrorHandler {

    @Override
    public void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
        // 自定義異常信息, 記錄關鍵日誌信息
    }
}
  1. 配置異常信息處理器
//  配置異常處理
        restTemplate.setErrorHandler(new ResponeException());
  1. 利用模板發送文件
MultiValueMap<String, Object> multiPartBody = new LinkedMultiValueMap<>();  
multiPartBody.add("file", new ClassPathResource("/tmpd/userrt.txt"));  
RequestEntity<MultiValueMap<String, Object>> requestEntity = RequestEntity  
        .post(uri)  
        .contentType(MediaType.MULTIPART_FORM_DATA)  
        .body(multiPartBody);

  1. 下載文件信息
// 小文件  
RequestEntity requestEntity = RequestEntity.get(uri).build();  
ResponseEntity<byte[]> responseEntity = restTemplate.exchange(requestEntity, byte[].class);  
byte[] downloadContent = responseEntity.getBody();  
  
// 大文件  
ResponseExtractor<ResponseEntity<File>> responseExtractor = new ResponseExtractor<ResponseEntity<File>>() {  
    @Override  
    public ResponseEntity<File> extractData(ClientHttpResponse response) throws IOException {  
        File rcvFile = File.createTempFile("rcvFile", "zip");  
        FileCopyUtils.copy(response.getBody(), new FileOutputStream(rcvFile));  
        return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(rcvFile);  
    }  
};  
File getFile = this.restTemplate.execute(targetUri, HttpMethod.GET, null, responseExtractor);  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章