為什么需要網關過濾器?
微服務架構體系中,通常一個業務系統會有很多的微服務,
比如:OrderService、ProductService、UserService...,
為了讓調用更簡單,一般會在這些服務前端再封裝一層,
類似下面這樣:
前面這一層俗稱為“網關層”,其存在意義在於,將"1對N"問題 轉換成了"1對1”問題(路由),
同時在請求到達真正的微服務之前,可以做一些預處理(過濾),
比如:登錄驗證,日志打印...
Filter 的生命周期
Filter 的生命周期有 4 個,分別是
“PRE(前置過濾器)”:該類型的filters在Request routing到源web-service之前執行。用來實現Authentication、選擇源服務地址等;
“ROUTING(路由選擇)”:該類型的filters用於把Request routing到源web-service,源web-service是實現業務邏輯的服務。這里使用HttpClient請求web-service;
“POST(后置過濾器)” :該類型的filters在ROUTING返回Response后執行。用來實現對Response結果進行修改,收集統計數據以及把Response傳輸會客戶端。
“ERROR(錯誤過濾器)”:上面三個過程中任何一個出現錯誤都交由ERROR類型的filters進行處理。
整個生命周期可以用下圖來表示
"coustom"是自定義過濾器。
搭建過濾器
1.創建個網關微服務。zuul-server-20001(2001是端口號方便看)
2.在prm.xml導入zuul依賴包
<!--zuuljar包--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
3.在配置類中添加注解 @EnableZuulProxy;
@EnableZuulProxy這個注解是開啟網關
@SpringBootApplication //加上網關注解 @RestController @EnableZuulProxy public class ZuulServerApplication { @RequestMapping("/") public String show(){ return "你好網關"; } public static void main(String[] args) { SpringApplication.run(ZuulServerApplication.class, args); } }
4.在yml里添加配置,注意網關也要指定注冊中心地址。
#自定義路由映射
zuul:
routes:
#你微服務的名字:/隨便來個別名/你的微服務api
orders-server1: /order/**
orders-server: /order/**
user-server: /user/**
prefix: "/"
#禁止所有服務使用服務名訪問
ignored-services: "*"
啟動網關服務,就行了。
如果要自定義過濾器在網關微服務中建個類繼承zuulfilter
/** * 這是網關的自定義過濾器 */ @Component public class LoginZuulFilter extends ZuulFilter { @Override public String filterType() {
//這個過濾器設置為前置過濾器 return "pre"; } @Override public int filterOrder() { return 1; } /** * 次方法返回true,就執行下面的run方法 * @return */ @Override public boolean shouldFilter() { //獲取請求上下文 RequestContext context = RequestContext.getCurrentContext(); //獲取當前請求對象 HttpServletRequest request = context.getRequest(); //獲取請求路徑 String requestURI = request.getRequestURI(); //判斷是否含有login路徑,有就return turn if(requestURI.toUpperCase().contains("LOGIN")){ return false; } return true; } /** * 在run方法中添加業務邏輯 * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { //獲取請求上下文 RequestContext context = RequestContext.getCurrentContext(); //獲取當前請求對象 HttpServletRequest request = context.getRequest(); //獲取當前響應對象 HttpServletResponse response = context.getResponse(); //獲取頭信息 String tokin = request.getHeader("x-tokin"); //判斷tokin是否存在 if(tokin==null){ HashMap<Object, Object> map = new HashMap<>(); map.put("booter",false); map.put("massage","親登錄"); String s = JSON.toJSONString(map); try { response.getWriter().write(s); } catch (IOException e) { e.printStackTrace(); } //阻止放行 context.setSendZuulResponse(false); } return null; }
配了就行了。重啟服務。