我是靠谱客的博主 舒心小懒猪,最近开发中收集的这篇文章主要介绍springboot2 springcloud Greenwich.SR3 构建微服务--7.服务网关zuul综合使用,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
下面来讲一下zuul的综合使用, 在限流, 请求的校验, 请求处理后的添加处理方面的应用.
这个就是网关的优势了.
zuul 中不同组件的作用
/**
* 前置 pre
* 限流 鉴定权限 参数校验 请求转发
*
* 后置 post
* 统计 日志
*
因为zuul 和eureka 一样都是作为微服务中最基本的服务存在, 当zuul 挂了之后,
就请求不到后面的服务了,所以很有必要最zuul进行高可用的设置.
* zuul的高可用. 注册多个zuul的节点.
*/
我们做下面的几个功能
1.在所有返回中添加一个头部信息
自定义的过滤器, 需要继承 ZuulFilter 这个类,
filterType 标明是前置过滤器, 还是后置的过滤器,
filterOrder 是过滤器的顺序, 因为存在多个过滤器, 需要排序,一一的经过
shouldFilter 是否过滤, 只有为true 才过滤,否则直接跳过了
run 真正的过滤的方法
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
/**
* 返回的时候,在请求头里面添加内容
*/
@Component
public class AddResponseFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_FORWARD_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
/**
* 往返回里面添加东西
*
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
System.out.println("AddResponseFilter");
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletResponse response = requestContext.getResponse();
//在请求头里面加了一个返回.
response.setHeader("x-foo", UUID.randomUUID().toString());
return null;
}
}
2. 限流
我们使用google guava的令牌桶算法.
import com.example.zuulserver.exception.RateLimitException;
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
/**
* 限流, 使用令牌桶算法
*/
@Component
public class RateLimitFilter extends ZuulFilter {
//guava的实现, 1s放入100个令牌
private final static RateLimiter rateLimiter = RateLimiter.create(100);
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SERVLET_DETECTION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
System.out.println("RateLimitFilter");
//没有拿到令牌
if(!rateLimiter.tryAcquire()){
/*RequestContext requestContext = RequestContext.getCurrentContext();
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);*/
throw new RateLimitException();
}
return null;
}
}
3. token验证, 就是要求请求的链接必须带上一个token ,否则直接返回.
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* 自定义token的验证器
*/
@Component
public class TokenFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤的具体逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
System.out.println("TokenFilter");
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
//这是从url参数中获取, 也可以从header 和cookie中获取
String token = request.getParameter("token");
if(StringUtils.isBlank(token)){
//因为测试,这里先注释掉了
//context.setSendZuulResponse(false);
//context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
}
return null;
}
}
4. 买家权限鉴定
import com.example.common.util.CookieUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/**
* 权限的校验,买家的
*/
@Component
public class BuyerFilter extends ZuulFilter {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public String filterType() {
return null;
}
@Override
public int filterOrder() {
return 0;
}
/**
* true 就进行校验, false 不校验
* @return
*/
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//根据请求的路径判断
if ("/order/create".equals(request.getRequestURI())) {
return true;
}
return false;
}
/**
* 权限的校验,买家和卖家的
* /order/create 只能买家(cookie 中有openid)
* /order/finish 只能卖家(cookie中有token, redis中有值)
* /product/list 都可以访问
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
Cookie cookie = CookieUtil.getCookie(request, "openid");
if (cookie == null || StringUtils.isBlank(cookie.getValue())) {
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
}
return null;
}
}
5.卖家权限鉴定
import com.example.common.util.CookieUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/**
* 权限的校验,卖家的
*/
@Component
public class SellerFilter extends ZuulFilter {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public String filterType() {
return null;
}
@Override
public int filterOrder() {
return 0;
}
/**
* true 就进行校验, false 不校验
* @return
*/
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//根据请求的路径判断
if ("/order/finish".equals(request.getRequestURI())) {
return true;
}
return false;
}
/**
* 权限的校验,买家和卖家的
* /order/create 只能买家(cookie 中有openid)
* /order/finish 只能卖家(cookie中有token, redis中有值)
* /product/list 都可以访问
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//常量没有弄过来....
Cookie cookie = CookieUtil.getCookie(request, "token");
String value = cookie.getValue();
Object user = stringRedisTemplate.opsForHash().get("user", value);
if (cookie == null || StringUtils.isBlank(value) || (user == null)) {
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
}
return null;
}
}
关于Zuul支持的cookie跨域问题, 可以添加配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
/**
* 跨域可以使用nginx上处理
*/
@Configuration
public class ZuulConfig {
@Bean
public CorsFilter corsFilter(){
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);//支持cookie跨域
//设置原始域,http://www.a.com
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
//方法, post 还是 get
configuration.setAllowedMethods(Arrays.asList("*"));
//时间, 多长时间不检查
configuration.setMaxAge(3000L);
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",configuration);
CorsFilter filter = new CorsFilter(source);
return filter;
}
}
再多啰嗦一点,
其实RequestContext 就是个Map,还是实现了并发的Map,源码如下, 使用ThreadLocal实现的.
public class RequestContext extends ConcurrentHashMap<String, Object> {
private static RequestContext testContext = null;
protected static final ThreadLocal<? extends RequestContext> threadLocal = new ThreadLocal<RequestContext>() {
@Override
protected RequestContext initialValue() {
try {
return contextClass.newInstance();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
};
....
}
整个代码地址是:
https://github.com/changhe626/micro-service
Java Framework,欢迎各位前来交流java相关
QQ群:965125360
最后
以上就是舒心小懒猪为你收集整理的springboot2 springcloud Greenwich.SR3 构建微服务--7.服务网关zuul综合使用的全部内容,希望文章能够帮你解决springboot2 springcloud Greenwich.SR3 构建微服务--7.服务网关zuul综合使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复