#zuul的作用
1、进行认证处理:可以对发送过来的请求做认证处理
2、审查与监控:可以记录各个请求的响应信息,将异常或者错误信息存入到数据库中,然后对数据库的数据进行处理
3、动态路由:根据配置将请求发送到指定的服务中去
4、负载均衡:与eureka配合使用,根据注册的多个service-id(Application),实现负载均衡
5、压力测试:根据动态路由的特点可以对某一个服务进行加大访问量的处理,实现压力测试
当不进行路由配置的时候直接可以使用zuul服务+service-id+访问路径对服务进行访问
#配置zuul
##配置跨域问题
@Configuration
public class CorsFilterConfig {
@Bean
public CorsFilter corsConfig() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setMaxAge(18000L);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
##配置filter
###权限过滤器
package com.sgcc.zuul.filter;
import com.google.gson.Gson;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sgcc.zuul.config.TokenProperties;
import com.sgcc.zuul.model.ResultVO;
import com.sgcc.comm.util.CookieUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
@Slf4j
@Component
public class AuthFilter extends ZuulFilter {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
private TokenProperties tokenProperties;
//无权限时的提示语
private static final String INVALID_TOKEN = "invalid token";
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
log.info("网关前置过滤器========》》》uri={}", request.getRequestURI());
if ("false".equals(tokenProperties.getFilterSwitch()) || tokenProperties.getWhiteList().contains(request.getRequestURI())) {
return false;
}
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
checkToken(requestContext, request);
return null;
}
/**
* 校验token
*
* @param requestContext
* @param request
*/
private void checkToken(RequestContext requestContext, HttpServletRequest request) {
//先从 cookie 中取 token,cookie 中取失败再从 header 中取,两重校验
String token = getToken(request);
//如果获取的token为空,则直接返回401无权限
if (StringUtils.isEmpty(token)) {
setUnauthorizedResponse(requestContext, INVALID_TOKEN);
} else {
String value = stringRedisTemplate.opsForValue().get(token);
if (StringUtils.isEmpty(value)) {
setUnauthorizedResponse(requestContext, INVALID_TOKEN);
} else {
String[] values = value.split("_");
String checkToken = values[0];
String userId = values[1];
log.info("当前正在操作的用户ID为userId={}", userId);
}
}
}
/**
* 获取token
*
* @return
*/
private String getToken(HttpServletRequest request) {
String token = CookieUtil.getValue(request, "X-Token");//先从cookie获取
if (StringUtils.isEmpty(token)) {//如果cookie获取的token为空
token = request.getHeader("X-Token");//则从header中获取
}
return token;
}
/**
* 设置 401 无权限状态
*/
private void setUnauthorizedResponse(RequestContext requestContext, String msg) {
log.info("无权限非法请求~");
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
requestContext.getResponse().setCharacterEncoding("UTF-8");
requestContext.getResponse().setContentType("application/json; charset=utf-8");
ResultVO resultVO = new ResultVO();
resultVO.setStatus(401);
resultVO.setMessage(msg);
Gson gson = new Gson();
String result = gson.toJson(resultVO);
requestContext.setResponseBody(result);
}
}
###错误拦截器
package com.sgcc.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sgcc.zuul.enums.ExceptionTypeEnum;
import com.sgcc.zuul.service.ZuulExceptionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* @Author: 杨文培
* @Desrcription:错误拦截过滤器
* @Date: Create in 17:43 2018/12/29
*/
@Component
@Slf4j
public class ErrorFilter extends ZuulFilter {
@Autowired
private ZuulExceptionService zuulExceptionService;
@Override
public String filterType() {
return FilterConstants.ERROR_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_ERROR_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String url = request.getRequestURI();
log.info("拦截错误========》》》url={}", url);
zuulExceptionService.addException(RequestContext.getCurrentContext(), ExceptionTypeEnum.ERROR);
return null;
}
}
###后置过滤器
package com.sgcc.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.sgcc.zuul.enums.ExceptionTypeEnum;
import com.sgcc.zuul.service.ZuulExceptionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: 杨文培
* @Desrcription:后置过滤器
* @Date: Create in 17:43 2018/12/29
*/
@Component
@Slf4j
public class PostFilter extends ZuulFilter {
@Autowired
private ZuulExceptionService zuulExceptionService;
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
HttpServletResponse response = requestContext.getResponse();
String url = request.getRequestURI();
int status = response.getStatus();
log.info("网关后置过滤器========》》》url={},status={}", url, status);
if (200 != status) {
//网页已经被移到别处
if (status / 100 != 3) {
log.info("拦截到一个异常===》url={},status={}", url, status);
zuulExceptionService.addException(requestContext, ExceptionTypeEnum.EXCEPTION);
}
}
return null;
}
}