前面https://blog.csdn.net/didi7696/article/details/80002734所講的是僅僅實現的是路由的功能,下面將介紹zuul網關功能,在前面的代碼基礎上做調整
zuul要實現網關的功能即在路由到服務之前增加驗證功能,或者路由之後訪問服務返回結果並對結果做修改。在run方法做邏輯處理(或者是業務需求)
代碼實現增加一個bean:
@Component
public class AccessFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
private static BufferedReader reader=null;
@Autowired
KeyAndFrequencyService service;
@Override
public String filterType() {
//前置過濾器
return "pre";
}
@Override
public int filterOrder() {
//優先級,數字越大,優先級越低
return 0;
}
@Override
public boolean shouldFilter() {
//是否執行該過濾器,true代表需要過濾
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
try {
//獲取驗證參數
Param param = getParam(request);
if (param == null) {
setRequestContext(ctx);
return null;
}
VerificationFrequencyControl control = service.getByinterfaceId(param.getInterfaceId());
/**判斷加密方式是否是 MD5加密 1表示MD5*/
if ("1".equalsIgnoreCase(control.getVerification() + "")) {
//獲取value
CollaboratorKeyAndValue keyAndValue = service.getByKey(param.getKey());
//request中獲取json請求參數
String jsonParam = getRequestPayload(request);
System.out.println("jsonparam" + jsonParam);
System.out.println("value= " + keyAndValue.getAvalue());
//加密方式 value加請求參數json
jsonParam = keyAndValue.getAvalue() + jsonParam;
System.out.println(jsonParam);
//加密後的值
String MD5 = MD5Utils.toMD5Code(jsonParam.toUpperCase().getBytes()).toUpperCase();
System.out.println("MD5= " + MD5);
//比對
if (MD5.equals(param.getMd5())) {// 加密的值一致的話則通過
Boolean flag = frequenceIsAccess(control.getFrequency());
if (flag) {
/**頻率驗證通過*/
/**比對接口頻路控制*/
ctx.setSendZuulResponse(true);// 對該請求進行路由
ctx.setResponseStatusCode(200);
ctx.set("isSuccess", true);// 設值,讓下一個Filter看到上一個Filter的狀態
} else {
setRequestContext(ctx);
}
} else {
setRequestContext(ctx);
}
}
} catch (Exception e) {
e.printStackTrace();
log.error(DataFormat.format(new Date())+"--網管驗證失敗!!!", e.fillInStackTrace());
setRequestContext(ctx);
}
return null;
}
這裏的filter要註冊成bean 也可以通過@Bean註解完成
filterType:該函數需要返回一個字符串來代表過濾器的類型,而這個類型就是在HTTP請求過程中定義的各個階段。在Zuul中默認定義了四種不同生命週期的過濾器類型,具體如下:
pre:可以在請求被路由之前調用。
routing:在路由請求時候被調用。
post:在routing和error過濾器之後被調用。
error:處理請求時發生錯誤時被調用。
filterOrder:通過int值來定義過濾器的執行順序,數值越小優先級越高。
shouldFilter:返回一個boolean類型來判斷該過濾器是否要執行。我們可以通過此方法來指定過濾器的有效範圍。
run:過濾器的具體邏輯。在該函數中,我們可以實現自定義的過濾邏輯,來確定是否要攔截當前的請求,不對其進行後續的路由,或是在請求路由返回結果之後,對處理結果做一些加工等。
由於訪問的是微服務,所以如果是前端訪問的時候會出現跨域的問題,可以在路由到的每個人接口上做處理,但是這樣的話,每個接口都需要增加代碼,所以最要在網關出做處理,處理跨域請求,只要在啓動類上加如下的代碼:然後ajax調用可以按正常的方式就可以不要加jsonp就可以正常請求了。
@ComponentScan("com.yiche.spingcloudapigateway")
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
@EnableHystrix
public class SpringCloudApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudApiGatewayApplication.class, args);
}
/*解決前端跨域問題*/
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 允許cookies跨域
config.addAllowedOrigin("*");// #允許向該服務器提交請求的URI,*表示全部允許
config.addAllowedHeader("*");// #允許訪問的頭信息,*表示全部
config.setMaxAge(18000L);// 預檢請求的緩存時間(秒),即在這個時間段裏,對於相同的跨域請求不會再預檢了
config.addAllowedMethod("*");// 允許提交請求的方法,*表示全部允許,也可以單獨設置GET、PUT等
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");// 允許Get的請求方法
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}