我們?cè)趯?xiě)微服務(wù)的時(shí)候每一個(gè)請(qǐng)求都是走的微服務(wù)的網(wǎng)關(guān)搂根,再由網(wǎng)關(guān)找到對(duì)應(yīng)的服務(wù)砾医,然后傳遞參數(shù)請(qǐng)求數(shù)據(jù)返回?cái)?shù)據(jù)亡脸,我們通常會(huì)在網(wǎng)關(guān)對(duì)于我們的請(qǐng)求做一些操作校镐,包括請(qǐng)求前以及響應(yīng)前亿扁,這里主要說(shuō)一下微服務(wù)中常用的ZuulFilter過(guò)濾器
@Component
public class MyFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
}
我們手動(dòng)去繼承ZuulFilter這個(gè)類(lèi),然后需要我們重寫(xiě)幾個(gè)方法
filterType():
這個(gè)方法的作用是用來(lái)標(biāo)識(shí)這個(gè)過(guò)濾器在哪個(gè)階段發(fā)揮作用,在ZuulFilter源碼中是這樣描述的
/**
* to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering,
* "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.
* We also support a "static" type for static responses see StaticResponseFilter.
* Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)
*
* @return A String representing that type
*/
abstract public String filterType();
我們這里常用的就是pre鸟廓,route从祝,post,error引谜,當(dāng)然還有"static"還有一些自定義的牍陌,
pre:
這是最開(kāi)始生效的,這是服務(wù)器接收到請(qǐng)求,還沒(méi)有到達(dá)網(wǎng)關(guān)的時(shí)候生效员咽,我們常用于過(guò)濾請(qǐng)求毒涧,身份驗(yàn)證什么的,在集群中選擇具體的微服務(wù)贝室,記錄日志之類(lèi)的信息契讲。
1.2 route
當(dāng)我們把fifter type設(shè)置為route的時(shí)候就表示我們的過(guò)濾器的生效時(shí)間是在我們網(wǎng)關(guān)接收到請(qǐng)求但是還沒(méi)有轉(zhuǎn)發(fā)到具體的微服務(wù)的時(shí)候過(guò)濾器生效,用來(lái)構(gòu)建新的請(qǐng)求滑频,比如我們將一些數(shù)值信息從token中解析出來(lái)存放到我們的請(qǐng)求中捡偏,再Apache HttpClient或Netfilx Ribbon請(qǐng)求具體問(wèn)服務(wù)。
post
這是我們的具體微服務(wù)將請(qǐng)求的數(shù)據(jù)存返回的時(shí)候經(jīng)過(guò)的過(guò)濾器峡迷,比如我們將響應(yīng)的參數(shù)進(jìn)行加密银伟。
1.2 error
當(dāng)我們的服務(wù)器在接收到請(qǐng)求報(bào)錯(cuò)的情況下
filterOrder()
/**
*
* @return
*/
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 4;
}
這個(gè)方法主要是我們?cè)谧?cè)過(guò)濾器的時(shí)候形成過(guò)濾鏈的時(shí)候排序使用,這是設(shè)置的過(guò)濾器的使用順序
shouldFilter()
@Override
public boolean shouldFilter() {
return true;
}
這個(gè)方法的功能是用來(lái)過(guò)濾請(qǐng)求是否需要走下面的具體的run方法,主要是為了區(qū)分不同過(guò)濾器針對(duì)不同的url
run()
@Override
public Object run() throws ZuulException {
}
這是我們的過(guò)濾器的方法主題在這里寫(xiě)我們主要的方法彤避,(解密傅物,token驗(yàn)證,權(quán)限驗(yàn)證忠藤,重構(gòu)請(qǐng)求或者響應(yīng)挟伙,解密)
以上就是我們的ZuulFilter的主要的幾個(gè)方法的講解楼雹,當(dāng)然別忘了一定要將過(guò)濾器放入到spring容器中模孩。
備注 :
RequestContext context = RequestContext.getCurrentContext():使用這個(gè)獲取上下文內(nèi)容主體,
context.setSendZuulResponse(false):用這個(gè)方法是設(shè)置不在走接下來(lái)的過(guò)濾器和微服務(wù),直接返回
eg:
@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
try {
InputStream stream = context.getResponseDataStream();
if(stream!=null){
String body = StreamUtils.copyToString(stream, StandardCharsets.UTF_8);
JSONObject jsonObject = JSONObject.parseObject(body);
Object code = jsonObject.get("code");
String msg = (String)jsonObject.get("msg");
//不是返回成功并且返回的狀態(tài)碼有參數(shù)但是msg沒(méi)有參數(shù)信息
if (code != null && ErrorCodeEnum.SUCCESS.getCode() != (int) code&&(ErrorCodeEnum.SUCCESS.getMsg().equals(msg)||StringUtils.isEmpty(msg))&&null!=ErrorCodeEnum.getByCode((int)code)) {
jsonObject.put("msg",ErrorCodeEnum.getByCode((int)code).getMsg());
}
//操作完成之后再將數(shù)據(jù)轉(zhuǎn)化為流贮缅,下一步加密使用
String s = JSONObject.toJSONString(jsonObject);
context.setResponseDataStream(IOUtils.toInputStream(s, StandardCharsets.UTF_8));
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}