微服务中Zuul服务网关一共定义了四种类型的过滤器:

  • pre:在请求被路由(转发)之前调用
  • route:在路由(请求)转发时被调用
  • error:服务网关发生异常时被调用
  • post:在路由(转发)请求后调用

我在项目中用到了,pre/error/post三种类型,先记录一下

pre过滤器主要是用来校验各种信息的

import com.alibaba.fastjson.JSONObject;
import com.dkjk.gateway.context.ResponseBean;
import com.dkjk.gateway.domain.DockCompanyService;
import com.dkjk.gateway.domain.UserService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; /**
* @author: qjc
* @createTime: 2019/4/13 16:08
* @Description: 接口安全验证过滤器
*/
@Component
@Slf4j
public class ValidFilter extends ZuulFilter { @Override
public String filterType() {
return "pre";
} @Override
public int filterOrder() {
return 0;
} @Override
public boolean shouldFilter() {
// 进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求来探测后续需要发起的跨域POST请求是否安全可接受
// 所以这个请求就不需要拦截,下面是处理方式
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
log.info("OPTIONS请求不做拦截操作");
return false;
}
return true;
} @Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String userToken = request.getHeader("apikey");
if (StringUtils.isBlank(userToken)) {
log.warn("apikey为空");
sendError(requestContext, 99001, "请传输参数apikey");
return null;
}
return null;
} /**
* 发送错误消息
*
* @param requestContext
* @param status
* @param msg
*/
private void sendError(RequestContext requestContext, int status, String msg) {
//过滤该请求,不往下级服务转发,到此结束不进行路由
requestContext.setSendZuulResponse(false);
HttpServletResponse response = requestContext.getResponse();
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter pw = null;
try {
pw = response.getWriter();
pw.write(JSONObject.toJSONString(new ResponseBean(status, msg, null)));
} catch (IOException e) {
log.error(e.getMessage());
} finally {
pw.close();
}
}
}

post过滤器可以在请求转发后获取请求信息和响应入库,或者日志记录

import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map; /**
* @author: qjc
* @createTime: 2019/5/6 11:07
* @Description:
*/
@Component
@Slf4j
public class ResponseFilter extends ZuulFilter { @Override
public String filterType() {
return "post";
} @Override
public int filterOrder() {
return 2;
} @Override
public boolean shouldFilter() {
// 进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求来探测后续需要发起的跨域POST请求是否安全可接受
// 所以这个请求就不需要拦截,下面是处理方式
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
log.info("OPTIONS请求不做拦截操作");
return false;
}
// 如果前面的拦截器不进行路由,那么后面的过滤器就没必要执行
if (!requestContext.sendZuulResponse()) {
return false;
}
return true;
} @Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
InputStream stream = requestContext.getResponseDataStream();
if (stream == null) {
return null;
} HttpServletRequest request = requestContext.getRequest(); String requestParams = getRequestParams(requestContext, request);
System.err.println(requestParams); try {
String responseBoby = IOUtils.toString(stream);
RequestContext.getCurrentContext().setResponseBody(responseBoby);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
  //获取请求参数,适用于POST请求/GET请求,以及参数拼接在URL后面的POST请求
private String getRequestParams(RequestContext requestContext, HttpServletRequest request) {
String requestParams = null;
String requestMethod = request.getMethod();
StringBuilder params = new StringBuilder();
Enumeration<String> names = request.getParameterNames();
if (requestMethod.equals("GET")) {
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
params.append(name);
params.append("=");
params.append(request.getParameter(name));
params.append("&");
}
requestParams = params.delete(params.length() - 1, params.length()).toString();
} else {
Map<String, String> res = new HashMap<>();
Enumeration<?> temp = request.getParameterNames();
if (null != temp) {
while (temp.hasMoreElements()) {
String en = (String) temp.nextElement();
String value = request.getParameter(en);
res.put(en, value);
}
requestParams = JSON.toJSONString(res);
}
if (StringUtils.isBlank(requestParams) || "{}".equals(requestParams)) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder("");
try {
br = request.getReader();
String str;
while ((str = br.readLine()) != null) {
sb.append(str);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
requestParams = sb.toString();
}
}
return requestParams;
}
}

error过滤器是在服务网关出现异常的时候起作用的

import com.alibaba.fastjson.JSONObject;
import com.dkjk.gateway.context.ResponseBean;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils; import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter; /**
* @author: qjc
* @createTime: 2019/5/30 19:11
* @Description: 处理请求发生错误时过滤器
*/
@Component
@Slf4j
public class ErrorFilter extends ZuulFilter {
@Override
public String filterType() {
return "error";
} @Override
public int filterOrder() {
//需要在默认的 SendErrorFilter 之前
return -1;
} @Override
public boolean shouldFilter() {
// 只有在抛出异常时才会进行拦截
return RequestContext.getCurrentContext().containsKey("throwable");
} @Override
public Object run() {
try {
RequestContext requestContext = RequestContext.getCurrentContext();
Object e = requestContext.get("throwable"); if (e != null && e instanceof ZuulException) {
ZuulException zuulException = (ZuulException) e;
// 删除该异常信息,不然在下一个过滤器中还会被执行处理
requestContext.remove("throwable");
// 响应给客户端信息
HttpServletResponse response = requestContext.getResponse();
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter pw = null;
pw = response.getWriter();
pw.write(JSONObject.toJSONString(new ResponseBean(99999, "系统出现异常", null)));
pw.close();
}
} catch (Exception ex) {
log.error("Exception filtering in custom error filter", ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
}

服务网关ZuulFilter过滤器--pre/post/error的用法(校验请求信息,获取路由后的请求/响应信息,处理服务网关异常)的更多相关文章

  1. 服务网关ZuulFilter过滤器--如何解决跨域请求中的OPTIONS请求

    进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求 来探测后续需要发起的跨域POST请求是否安全可接受 所以这个请求就不需要拦截,下面是处理方式 @Ove ...

  2. 微服务网关Zuul过滤器Filter

    Zuul本质 Zuul是一个网关,关于网关的介绍参考:亿级流量架构之网关设计思路.常见网关对比, 可知Zuul是一个业务网关, 而深入了解Zuul, 基本就是一系列过滤器的集合: Zuul的过滤器 下 ...

  3. Spring Cloud架构教程 (五)服务网关(过滤器)

    过滤器的作用 通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了.但是,每个客户端用户请求微服务应用提供的接口时,它们 ...

  4. Spring Cloud(七):服务网关zuul过滤器

    上文介绍了Zuul的基本使用与路由功能,本文接着介绍Zuul的核心概念 -- Zuul过滤器(filter). Zuul的功能基本通过Zuul过滤器来实现(类比于Struts的拦截器,只是Struts ...

  5. SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理

    前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...

  6. TZ_14_Zuul网关_过滤器

    1.Zuul作为网关的其中一个重要功能,就是实现请求的鉴权.而这个动作我们往往是通过Zuul提供的过滤器来实现的. 2.自定义过滤器实现用户登陆时需要携带一个Key才可以登陆,否则返回403 1> ...

  7. 使用网关zuul过滤器登录鉴权

    使用网关zuul过滤器登录鉴权     1.新建一个filter包         filte有很多种 pre.post.     2.新建一个类LoginFilter,实现ZuulFilter,重写 ...

  8. AngularJS路由系列(4)-- UI-Router的$state服务、路由事件、获取路由参数

    本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● UI-Router的$state服务● UI-Router的路由事件● UI-Router获取路由参数 Angular ...

  9. c++ 网络编程(八) LINUX-epoll/windows-IOCP下 socket opoll函数用法 优于select方法的epoll 以及windows下IOCP 解决多进程服务端创建进程资源浪费问题

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9622548.html 锲子:关于并发服务器中的I/O复用实现方式,前面在网络编程系列四还是五来 ...

随机推荐

  1. nginx-rtmp

    最近使用ffmpeg推流为rtmp,进行直播.记录一下nginx-rtmp的配置.因为我们要添加ngin-rtmp模块,所以不能直接apt安装. 下载niginx和nginx-rtmp-module的 ...

  2. 运维笔记--postgresql占用CPU问题定位

    运维笔记--postgresql占用CPU问题定位 场景描述: 业务系统访问变慢,登陆服务器查看系统负载并不高,然后查看占用CPU较高的进程,发现是连接数据库的几个进程占用系统资源较多. 处理方式: ...

  3. pytorch保证每次运行使用的随机数都相同的方法

    其实在代码的开头添加下面几句话即可: # 保证训练时获取的随机数都是一样的 init_seed = torch.manual_seed(init_seed) torch.cuda.manual_see ...

  4. Logstash配置同步mysql到es配置

    关于logstash安装:https://www.cnblogs.com/toov5/p/10301727.html Logstash是一个开源数据收集引擎,具有实时管道功能.Logstash可以动态 ...

  5. Zookeeper 安装与简单使用

    一.安装Zookeeper 其实Zookeeper的安装特别简单,也不能算安装了,只需要将Zookeeper下载后解压,就完成了安装操作. 下载地址:http://zookeeper.apache.o ...

  6. [LeetCode] 171. Excel Sheet Column Number 求Excel表列序号

    Related to question Excel Sheet Column Title Given a column title as appear in an Excel sheet, retur ...

  7. [LeetCode] 251. Flatten 2D Vector 压平二维向量

    Implement an iterator to flatten a 2d vector. For example,Given 2d vector = [ [1,2], [3], [4,5,6] ] ...

  8. PDF阅读器关闭“使用手型工具阅读文章”功能

    1.问题描述 某些PDF文件打开时,光标显示的手型工具里面有个箭头,一点击鼠标左键,就跳转到下一页了.给阅读带来很多不便. 2.原因 因为这类PDF文档中带有"文章"(articl ...

  9. 解决Python模块报错:ModuleNotFoundError: No module name 'StringIO'

    下面是我在学习中遇到的问题,给大家分享一下:   ''' 这里是测试代码 '''# coding = utf-8from selenium import webdriverfrom selenium. ...

  10. 「模拟赛20191019」B 容斥原理+DP计数

    题目描述 将\(n\times n\)的网格黑白染色,使得不存在任意一行.任意一列.任意一条大对角线的所有格子同色,求方案数对\(998244353\)取模的结果. 输入 一行一个整数\(n\). 输 ...