服务网关ZuulFilter过滤器--pre/post/error的用法(校验请求信息,获取路由后的请求/响应信息,处理服务网关异常)
微服务中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的用法(校验请求信息,获取路由后的请求/响应信息,处理服务网关异常)的更多相关文章
- 服务网关ZuulFilter过滤器--如何解决跨域请求中的OPTIONS请求
进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求 来探测后续需要发起的跨域POST请求是否安全可接受 所以这个请求就不需要拦截,下面是处理方式 @Ove ...
- 微服务网关Zuul过滤器Filter
Zuul本质 Zuul是一个网关,关于网关的介绍参考:亿级流量架构之网关设计思路.常见网关对比, 可知Zuul是一个业务网关, 而深入了解Zuul, 基本就是一系列过滤器的集合: Zuul的过滤器 下 ...
- Spring Cloud架构教程 (五)服务网关(过滤器)
过滤器的作用 通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了.但是,每个客户端用户请求微服务应用提供的接口时,它们 ...
- Spring Cloud(七):服务网关zuul过滤器
上文介绍了Zuul的基本使用与路由功能,本文接着介绍Zuul的核心概念 -- Zuul过滤器(filter). Zuul的功能基本通过Zuul过滤器来实现(类比于Struts的拦截器,只是Struts ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
- TZ_14_Zuul网关_过滤器
1.Zuul作为网关的其中一个重要功能,就是实现请求的鉴权.而这个动作我们往往是通过Zuul提供的过滤器来实现的. 2.自定义过滤器实现用户登陆时需要携带一个Key才可以登陆,否则返回403 1> ...
- 使用网关zuul过滤器登录鉴权
使用网关zuul过滤器登录鉴权 1.新建一个filter包 filte有很多种 pre.post. 2.新建一个类LoginFilter,实现ZuulFilter,重写 ...
- AngularJS路由系列(4)-- UI-Router的$state服务、路由事件、获取路由参数
本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● UI-Router的$state服务● UI-Router的路由事件● UI-Router获取路由参数 Angular ...
- c++ 网络编程(八) LINUX-epoll/windows-IOCP下 socket opoll函数用法 优于select方法的epoll 以及windows下IOCP 解决多进程服务端创建进程资源浪费问题
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9622548.html 锲子:关于并发服务器中的I/O复用实现方式,前面在网络编程系列四还是五来 ...
随机推荐
- tensorflow到底难不难写
发信人: xhsoldier01 (风大人), 信区: ITExpress 标 题: Re: 没有GPU,tensorflow,AI公司都得死掉 发信站: 水木社区 (Thu Oct 10 20:25 ...
- Win10 LTSC 2019 安装和卸载 linux 子系统
一.开启 二.下载 https://docs.microsoft.com/zh-cn/windows/wsl/install-manual 手动下载适用于 Linux 的 Windows 子系统发 ...
- 【Linux】宝塔服务器磁盘爆满处理方法
直接上图 1 清理网站日志/php站点session/系统邮件/临时文件 cd /www/server/panel && python tools.pyc clear 2 清空面板回收 ...
- LODOP打印超文本有边距不居中的情况2
之前的博文:LODOP打印项水平居中.之前的博文有介绍超文本和纯文本的居中方式,设置超文本打印项居中时,注意打印内容要在打印项本身宽度里居中.之前的博文超文本用的是个表格,而且表格本身没有margin ...
- 【linux基础】ubuntu16.04 安装后,屏幕分辨率过低且不可调节
前言 安装CUDA和NVIDIA驱动之后,屏幕分辨率过低且不可调节,尝试了几种方法都没成功解决,特此讲解决方法记录下来. 解决过程 注销进入登录界面,按ctrl+alt+F1进入命令行终端,输入账户名 ...
- Rufus软件
Rufus软件(https://rufus.akeo.ie/)——制作启动盘必备,简易且开源.
- Cannot find bounds of current function
MinGW编译平台的应用程序使用libcef.dll,当调用cef的capi接口时程序崩溃.调试单步到cef capi函数时,调试器报错“Cannot find bounds of current f ...
- 学习数据结构Day2
之前学习过了数组的静态实现方法,同时将数组的所有有可能实现的方法都统一实现了一遍,之后支持了泛型的相关 概念,接下来就是如何对数组进行扩容的操作也就是实现动态数组. private void resi ...
- 2019年广东外语外贸大学程序设计竞赛(新手赛)-F题(好快的刀)题解
题面: 题目意为,任意连接两个圆的圆心形成一条直线,计算与该直线相交或相切的圆的数量,求这些直线最多能相交或相切多少个圆 解题思路: 遍历所有的圆,计算出两圆圆心生成的直线,再遍历其他的圆,检测这些圆 ...
- eoj monthly 2019.11
原题 T1 纸条 题目大意: 给出一个长度为n的字符串,其中m位未知,对于每一位未知的字母,有k个备选字母,最终答案为备选字母按字典序排序后的第x个. 题解: 签到题-- 按照题目意思直接写就可以了. ...