Spring boot项目中自定义FeignClient的拦截器处理header和签名等信息

我们在请求第三方接口的时候通常由比较复杂但是统一的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原来是下面的方法,附源码截图: