SpringCloud-Zuul服务网关[自定义网关过滤器]

563 阅读3分钟

 zuul的核心是一系列的filters, 其作用可以类比Servlet框架的Filter,或者AOP,本文我们就来具体介绍下自定义的zuul过滤器

自定义网关过滤器

1.创建项目

  创建一个普通的SpringBoot项目项目

在这里插入图片描述

2.添加依赖

  注意添加zuul的依赖

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

3.修改配置

  修改application.properties文件

spring.application.name=zuul-gateway-filter
server.port=9020
# eureka注册中心配置
eureka.client.serviceUrl.defaultZone=http://dpb:123456@eureka1:8761/eureka/,http://dpb:123456@eureka2:8761/eureka/

4.创建自定义的过滤器

  创建自定义的过滤器,继承自ZuulFilter并重写相关的方法

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

/**
 * 自定义网关过滤器
 * @author dengp
 *
 */
@Component
public class LogFilter extends ZuulFilter{

	private Logger logger = LoggerFactory.getLogger(LogFilter.class);

	/**
	 * 过滤方法
	 */
	@Override
	public Object run() {
		// 获取Request上下文
		RequestContext rc = RequestContext.getCurrentContext();
		HttpServletRequest request = rc.getRequest();
		logger.info("LogFilter .... 请求的路径是{},请求提交的方式是{}", request.getRequestURL().toString(),request.getMethod());
		return null;
	}

	/**
	 * 是否开启过滤:默认false
	 */
	@Override
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	/**
	 * 多个过滤器中的执行顺序,数值越小,优先级越高
	 */
	@Override
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}

	/**
	 * 过滤器的类型
	 */
	@Override
	public String filterType() {
		// TODO Auto-generated method stub
		return "pre";
	}

}

5.演示效果

  启动一个provider服务后,启动我们的网关服务,然后请求访问,查询控制台输出.

在这里插入图片描述

注意控制台:

在这里插入图片描述

日志有输出,说明自定义的网关过滤器执行了。

网关过滤器类型介绍

  网关过滤器的自定义方法有四个,过滤器的类型有四个,分别如下:

在这里插入图片描述

zuul请求的生命周期

  zuul的生命周期要结合我们上面介绍的过滤器的类型来分析,具体如下图:

在这里插入图片描述

网关过滤器拦截请求

  网关过滤器是如何拦截不合法的请求的呢?我们来看下具体的代码

	/**
	 * 过滤方法
	 */
	@Override
	public Object run() {
		// 获取Request上下文
		RequestContext rc = RequestContext.getCurrentContext();
		HttpServletRequest request = rc.getRequest();
		String token = request.getParameter("token");
		if(token == null){
			// 拦截请求
			代表请求结束。不在继续向下请求
			rc.setSendZuulResponse(false);
			//添加一个响应的状态码
			rc.setResponseStatusCode(401);
			//响应内容
			rc.setResponseBody("{\"result\":\"token is null\"}");
			//响应类型
			rc.getResponse().setContentType("text/json;charset=utf-8");
		}
		// 放过请求
		return null;
}

不加参数访问失败:

在这里插入图片描述

添加参数:

在这里插入图片描述

过滤器的执行顺序

  过滤器类型相同的会根据filterOrder方法的返回结果的大小来排序,不同类型根据类型的特点执行。

利用网关实现异常的统一处理

1.异常过滤器

  我们需要创建类型为error的网关过滤器

@Component
public class ErrorFilter extends ZuulFilter{

	private Logger logger = LoggerFactory.getLogger(ErrorFilter.class);

	/**
	 * 过滤方法
	 */
	@Override
	public Object run() {
		// 获取Request上下文
		RequestContext rc = RequestContext.getCurrentContext();
		HttpServletRequest request = rc.getRequest();
		logger.info("LogFilter .... 请求的路径是{},请求提交的方式是{}", request.getRequestURL().toString(),request.getMethod());
		return null;
	}

	/**
	 * 是否开启过滤:默认false
	 */
	@Override
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	/**
	 * 多个过滤器中的执行顺序,数值越小,优先级越高
	 */
	@Override
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}

	/**
	 * 过滤器的类型
	 */
	@Override
	public String filterType() {
		// TODO Auto-generated method stub
		return "error";
	}
}

2.统一异常处理

/**
* 对异常响应内如处理
* @author Administrator
*
*/
@RestController
public class ExceptionHandler implements ErrorController {

	@Override
	public String getErrorPath() {
		return "/error";
	}
	@RequestMapping(value="/error")
	public String error(){
		return "{\"result\":\"500 error!!!!\"}";
	}
}