我们在请求第三方接口的时候通常由比较复杂但是统一的header和签名计算的一系列处理。这个时候就可以使用RequestInterceptor来实现。上代码:
@Slf4j
@Configuration // a global feign client interceptor
public class FeignClientsConfigurationInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
try {
log.info("======= FeignClientsConfigurationInterceptor ========");
//反序列化request body,拿到核心的参数projectId,用来获得请求接口用的appkey和appId
JSONObject requestBody= (JSONObject) JSON.parse(new String(template.body()));
String projectId = (String) requestBody.get("projectId");
//过河拆桥,把projectId从 request body 移除(因为这个参数只是我方程序获取密钥时需要,但请求地第三方接口不需要)
requestBody.remove("projectId");
log.info("projectId =" + projectId);
PingAnKeyProperties pingAnKeyProperties = PingAnKeyProperties.getPingAnKeys(projectId);
String apiUrl = template.url();
log.info("apiUrl =" + apiUrl);
String app_id = pingAnKeyProperties.getAppId();
String app_key= pingAnKeyProperties.getAppKey();
log.info("app_id =" + app_id);
log.info("app_key =" + app_key);
String deviceId =SignUtils.getLocalMac();
String timestamp = Long.toString(System.currentTimeMillis());
Map<String, String> headers = new HashMap();
headers.put("X-Appid", app_id);
headers.put("Content-Type", "application/json;charset=utf-8");
Iterator<String> it = headers.keySet().iterator();
while (it.hasNext()) {
String header_key = it.next();
template.header(header_key, headers.get(header_key));
}
String method = template.method();
String bodyText = requestBody.toJSONString();
//使用template.body(bodyText) API重置移除projectId之后的reqeust body
template.body(bodyText); //reset body text
String body_content = new String(template.body());
log.debug("body_content = "+ body_content);
String body_hash = SignUtils.SHA(body_content, "SHA-256");
// log.info(body_hash);
String sign_data = SignUtils.getSign(method,
apiUrl,
"", headers, body_hash,app_key);
template.header("X-Authorization",
sign_data.toLowerCase());
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
log.info("===============");
}
}
总结:通过RequestTemplate对象我们可以拿到reqeust的几乎所有参数,url, reqeust body,method等等,熟悉RequestTemplate的API就能比较轻松的实现对原reqeust的拦截和改造。我是试了好久才找到重置requestbody的API原来是下面的方法,附源码截图: