背景:完成完整的業(yè)務,需要第三方異步回調系統(tǒng)的接口。從而更新業(yè)務狀態(tài)。但是第三方系統(tǒng)經(jīng)常只能配置一個回調接口。但是我們系統(tǒng)有4個環(huán)境。常常只能在一個環(huán)境測試,切換環(huán)境測試需要去第三方修改回調接口。
目標:接口回調回來后,允許接口轉發(fā)到其他環(huán)境
實現(xiàn)思路:由于回調接口中是沒有參數(shù)能標識發(fā)到哪個環(huán)境,因此無法在nginx層面解決。就在具體服務上做:
接收請求,找到需要轉發(fā)到哪些環(huán)境
封裝請求,將回調請求轉發(fā)過去(header帶上標識:x-forward-from)
如果請求帶有x-forward-from,則不轉發(fā)
同時本服務也接收該請求并處理
這些邏輯都是和接口邏輯不相干的,因此考慮切面等方式處理,最后采用filter處理。邏輯在filter中處理
以下是遇到的相關問題:項目采取SpringMVC
Q:WebApplicationContext獲取HttpClient的bean失敗
call其他環(huán)境用封裝的HttpClient的bean,它是一個帶線程池的,filter通過在web.xml進行配置生效。如下:
NotifyMessageForwardFilter com.lenovo.ofp.payment.front.webapp.filter.NotifyMessageForwardFilter NotifyMessageForwardFilter /notify/*
這種方式,可以看作是new NotifyMessageForwardFilter()。無法通過@Auwired 注入bean,會報錯。當然這個報錯具體原因是因為filter調用時,bean對象還沒初始化好:web.xml中各個標簽初始化的順序如下:contetxt-param ->listener ->filter ->servlet
用來加載你配置的文件信息配置你的監(jiān)聽服務過濾器配置你單獨的一些操作容器初始化
加載順序為:context-param ->listener ->filter ->servlet 加載的順序不受在web.xml中配置的位置影響
springmvc.xml中定義component-scan;而springmvc.xml在servlet中加載;所以filter中找不到servlet才生成的bean
其次是WebApplicationContext獲取的applicationContext,它id是:org.springframework.web.context.WebApplicationContext:/payment-front-webapp,通過BeanDefinitionNames()這個方法發(fā)現(xiàn),沒有HttpClient的bean,連Controller的bean都沒有。因此才認為,至少還有一個其他的ApplicationContext
而servlet的applicationContext的id是:org.springframework.web.context.WebApplicationContext:/payment-front-webapp/dispatcher
發(fā)現(xiàn)了吧,ApplicationContext不是一個,所以呀,我們要用下面那個。
A:解決方法:通過上面的分析,我們也知道ApplicationContext除了WebApplicationUtils獲取的那個外,還存在至少一個。所以用ApplicationContextAware來獲取。畢竟這個接口是在服務啟動完成后執(zhí)行的內容。獲取的Context更為完整。
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
public static ApplicationContext APPLICATION_CONTEXT = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("init ApplicationContextUtils success");
ApplicationContextUtils.APPLICATION_CONTEXT = applicationContext;
}
}
Q1:org.apache.http.ProtocolException: Content-Length header already present
A:content-length是根據(jù)內容的長度動態(tài)計算的。因此在請求轉發(fā)的時候,要刪掉
Q2:requestBody無法被重復讀取
請求轉發(fā)到不同環(huán)境,這意味著我們需要封裝http請求,需要讀取body。而body讀取一次后就會報錯。
A:body無法被重復讀取原因是body內容放在InputStream中,這個流是只能讀一次的,根據(jù)HttpServletRequestWrapper包裝一下就行了
public class HttpMultiReadServletRequestWrapper extends HttpServletRequestWrapper {
BufferedReader bufferedReader = null;
String requestBody = "";
public HttpMultiReadServletRequestWrapper(HttpServletRequest request) {
super(request);
// 用原始的request獲取一次body,然后緩存起來
this.requestBody = HttpRequestUtils.getRequestBody(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
String characterEncoding = getCharacterEncoding();
characterEncoding = StringUtils.isBlank(characterEncoding) ? "UTF-8" : characterEncoding;
return new DelegatingServletInputStream(
new ByteArrayInputStream(requestBody.getBytes(characterEncoding)));
}
@Override
public BufferedReader getReader() throws IOException {
if (bufferedReader == null) {
// 需要搭配StringReader才能反復讀。用inputStream只能讀一次
bufferedReader = new BufferedReader(new StringReader(requestBody));
bufferedReader.mark(requestBody.length() + 1);
} else {
// 重置之后,bufferedReader就又可以讀了
bufferedReader.reset();
}
return bufferedReader;
}
public String getRequestBody() {
return this.requestBody;
}
}
HttpRequestUtils的getRequestBody內容如下
public static String getRequestBody(HttpServletRequest request) {
StringBuilder sb = new StringBuilder();
try {
BufferedReader br = request.getReader();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
log.error("Read notify request body", e);
}
return sb.toString();
}
Q3:@Autowired request是代理類,無法加載為了解決requestBody而生成RequestWrapper
A:其實就是一個實現(xiàn)邏輯出錯。我們生成RequestWrapper后,應當在filterChain里面?zhèn)魅隦equestWrapper而不是原來的request。其次是:RequestContextHolder,這個是在filter之前就設置了Request,所以有必要,需要更新里面的Request
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁標題:第三方接口回調轉發(fā)到不同環(huán)境-創(chuàng)新互聯(lián)
網(wǎng)頁路徑:http://chinadenli.net/article12/depsdc.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、電子商務、虛擬主機、域名注冊、關鍵詞優(yōu)化、外貿建站
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內容