前面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);
}
}