上次讲了Zuul的基本使用,这篇讲的是综合使用,好比过滤器,限流,鉴权等应用
这里继续使用api-getway这个项目html
1.新建一个类,继承ZuulFilter,细节方面看下面代码,还有别忘了在类上加@Component注解,不然不生效git
@Component public class TokenFilter extends ZuulFilter { /** * 过滤器类型 * @return */ @Override public String filterType() { return PRE_TYPE; } /** * 优先级,数字越大,优先级越低 * 只作通常过滤,没有特殊要求的,能够放在内置过滤器后面 * @return */ @Override public int filterOrder() { //最后一个内置PRE过滤器后面 return PRE_DECORATION_FILTER_ORDER+1; } /** * 是否执行该过滤器,true表明须要过滤 * 这里能够忽略掉一些不须要过滤请求 * @return */ @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); String token = request.getParameter("token"); //若是没有token,则返回401 //这里就不作校验了,只判断有无 if(StringUtils.isEmpty(token)){ ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED); ctx.setResponseBody("未登录!"); //设置返回体的编码为UTF-8 HttpServletResponse response = ctx.getResponse(); response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); } return null; } }
2.开启Eureka Server,api-getway,service-hi项目github
3.测试
不带token http://localhost:8900/myHi/hiweb
带token http://localhost:8900/myHi/hi?token=123算法
1.新建一个类,继承ZuulFilterspring
@Component public class AddResponseHeaderFilter extends ZuulFilter { @Override public String filterType() { return POST_TYPE; } @Override public int filterOrder() { //放在返回过滤器前 return SEND_RESPONSE_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext context = RequestContext.getCurrentContext(); HttpServletResponse response = context.getResponse(); response.setHeader("my-response","hello"); return null; } }
2.开启Eureka Server,api-getway,service-hi项目api
3.测试
http://localhost:8900/myHi/hi?token=123跨域
限流的功能也是常常会在网关实现,咱们这里使用令牌桶算法实现,这个算法已经有相关实现了,直接用就行浏览器
令牌桶算法:一边以一个固定的速率发令牌,另外一边用一个固定大小的桶装令牌,桶满了则将令牌该令牌丢弃,不然放进桶里。进来的请求尝试从桶里取令牌,取到令牌的请求放行,没有令牌的请求则会被拒绝。以下图缓存
1.新建一个类,继承ZuulFilter
@Component public class RateFilter extends ZuulFilter { /** * 建立令牌桶 容量为1(为了方便测试,这里设置小一点) */ private static final RateLimiter RATE_LIMITER = RateLimiter.create(1); @Override public String filterType() { return PRE_TYPE; } @Override public int filterOrder() { //设置顺序 请求转发过滤器 前 return SERVLET_DETECTION_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { //获取不到令牌 if(!RATE_LIMITER.tryAcquire()){ //TODO 跳转到错误页面或友好提示 throw new RuntimeException("访问人数过多,请稍后再试!"); } return null; } }
2.开启Eureka Server,api-getway,service-hi项目
3.测试
在过滤器run方法中打个断点,而后开3个浏览器tag访问http://localhost:8900/myHi/hi?token=123,进入断点后,点击忽略断点,再点击释放断点运行程序
结果:
至少有一个请求会被拒绝,后台抛出异常
浏览器是不容许跨域访问,一般解决跨域,可在接口类或方法加上@CrossOrigin(allowCredentials = “true”),但这种方法是很繁琐的,不可能有100个接口就加100次,因此咱们这里可使用Zuul实现跨域
代码实现
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter(){ final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); //是否支持Cookie跨域 config.setAllowCredentials(true); //支持的原始域 *表示全部 config.setAllowedOrigins(Arrays.asList("*")); //容许的头 *表示全部 config.setAllowedHeaders(Arrays.asList("*")); //容许的请求方法 POST,GET等 *表示全部 config.setAllowedMethods(Arrays.asList("*")); //缓存时间 表示300秒内对相同请求不须要再判断 config.setMaxAge(300L); //path参数为对哪些域名进行设置 /**表示全部 source.registerCorsConfiguration("/**",config); return new CorsFilter(source); } }
由于跨域是须要在不一样域名下,这里不太好演示,就不测试了。
以上3种是Zuul比较经常使用的一些使用方式,今天就到这里,下期见~
代码已更新至gitthub
https://github.com/zhangwenkang0/springcloud-learning-from-0-to-1
若是以为不错,分享给你的朋友!
一个立志成大腿而天天努力奋斗的年轻人
伴学习伴成长,成长之路你并不孤单!