<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-zuulartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
dependencies>
package com.qf.zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulApp {
public static void main(String[] args) {
SpringApplication.run(ZuulApp.class,args);
}
}
yml
server:
port: 80
spring:
application:
name: service-zuul
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
#开启 监控功能 http://localhost/actuator/routes
management:
endpoints:
enabled-by-default: true #暴露所有端点信息
web:
exposure:
include: '*' #以web方式暴露
# zuul的配置
zuul:
# 自定义服务
routes:
# 微服务名: 匹配的路径 zuul直接可以去除/ss,但是gateway必须得重写uri,或者内置去除前缀过滤器
service-provide: /ss/**
开启zuul信息监控
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
yml添加配置
# 查看zuul的监控界面(开发时,配置为*,上线,不要配置)
management:
endpoints:
web:
exposure:
include: "*"
http://localhost/actuator/routes
自定义服务配置
# zuul的配置
zuul:
# 自定义服务
routes:
# 微服务名: 匹配的路径 zuul直接可以去除/ss,但是gateway必须得重写uri,或者内置去除前缀过滤器
search: /ss/**
customer: /cc/**
自动生成注册微服务的路由信息
@SpringBootApplication
@EnableDiscoveryClient //将网关服务注册到Nacos注册中心
@EnableZuulProxy // 自动创建路由表
public class ZuulApp {
public static void main(String[] args) {
SpringApplication.run(ZuulApp.class);
}
}
继承ZuulFilter
@Component
public class TestZuulFilter extends ZuulFilter {
@Override
public String filterType() {
// 前置过滤器
return FilterConstants.PRE_TYPE;
}
//指定过滤器的执行顺序
@Override
public int filterOrder() {
return 10;
}
//配置是否启用
@Override
public boolean shouldFilter() {
return true;
}
//指定过滤器中的具体业务代码
@Override
public Object run() throws ZuulException {
System.out.println("TestZuulFilter is called ......");
return null;
}
}
PreFilter实现token校验
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
final HttpServletRequest request = requestContext.getRequest();
String token = request.getParameter("token");
if(token == null || !"123".equalsIgnoreCase(token)){
// 不会把请求转发给后端微服务了
requestContext.setSendZuulResponse(false);
final HttpServletResponse response = requestContext.getResponse();
try {
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("没有提供合法的token,zuul拦截了改请求.....");
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Component
public class RoutingFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
// 把动态路由过滤器放到自己的过滤器链的最后一个
return 100;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//1. 获取Request对象
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
//2. 获取参数,servicekey
String servicekey = request.getParameter("servicekey");
String method = request.getParameter("method");
servicekey = getMicoservieID(servicekey);
method = getMicoservieMethod(method);
context.put(FilterConstants.SERVICE_ID_KEY,servicekey);
// 设置发送给微服务的哪个接口,value部分是接口的路径
context.put(FilterConstants.REQUEST_URI_KEY,method);
return null;
}
private String getMicoservieMethod(String method) {
return "/customer/test12";
}
private String getMicoservieID(String servicekey) {
return "customer-v1";
}
}
package com.qf.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class TimePreFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return 90;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//记录请求到达该过滤器的时间
long startTime = System.currentTimeMillis();
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
//把初始时间戳放入request对象中
request.setAttribute("startTime",startTime);
return null;
}
}
package com.qf.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class TimePostFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取 初始时间戳
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
long startTime = (long) request.getAttribute("startTime");
long endTime=System.currentTimeMillis();
System.out.println("time user: "+(endTime-startTime));
return null;
}
}
package com.qf.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@Component
public class Myfilter01 extends ZuulFilter {
@Override
public String filterType() {
//说明该过滤器的类型,前置或后置
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//设置过滤器的执行顺序,序号越小,越先执行
return 100;
}
@Override
public boolean shouldFilter() {
//该过滤器是否生效,true生效
return true;
}
@Override
public Object run() throws ZuulException {
//过滤器要执行的功能写在这里
System.out.println("过滤器MyFilter01 的run方法被调用了");
//获取Request对象
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
//获取系统有哪些必传参数
HashSet<String> sysnames = getParamNames();
Set<String> requestNames = request.getParameterMap().keySet();
// //判断是否都包含
// boolean b = requestNames.containsAll(names);
//做集合减法
sysnames.removeAll(requestNames);
if (sysnames.size()>0){
//缺少了必传参数
//让请求不要在发送给后续的微服务了
currentContext.setSendZuulResponse(false);
//返回错误信息
HttpServletResponse response = currentContext.getResponse();
response.setContentType("text/html;charset=utf-8");
try {
response.getWriter().println("缺少了必传参数,请检查"+sysnames);
} catch (IOException e) {
e.printStackTrace();
}
}
return null;//固定写法
}
private HashSet<String> getParamNames() {
HashSet<String> names = new HashSet<>();
names.add("token");
names.add("sign");
return names;
}
}
package com.qf.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
@Component
public class Myfilter02 extends ZuulFilter {
@Override
public String filterType() {
//说明该过滤器的类型,前置或后置
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//设置过滤器的执行顺序,序号越小,越先执行
return 110;
}
@Override
public boolean shouldFilter() {
//该过滤器是否生效,true生效
RequestContext currentContext = RequestContext.getCurrentContext();
boolean b = currentContext.sendZuulResponse();//判断过滤器发送请求是否置为false,默认为true
return b;//false 不走run方法,否则就走,
}
@Override
public Object run() throws ZuulException {
//过滤器要执行的功能写在这里
System.out.println("过滤器MyFilter02 的run方法被调用了");
return null;//固定写法
}
}
package com.qf.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class MyRoutingFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//注意,该过滤器放在所有前置过滤器的最后
return 200;
}
@Override
public boolean shouldFilter() {
//该过滤器是否生效,true生效
RequestContext currentContext = RequestContext.getCurrentContext();
boolean b = currentContext.sendZuulResponse();
return b;
}
@Override
public Object run() throws ZuulException {
//根据请求中的参数,找到要发送的微服务的服务名以及对应的接口的url路径;
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String serviceName = request.getParameter("serviceName");
String method = request.getParameter("serviceMethod");
//查询servicename 对应的微服务名字
String microName= getMicroName(serviceName);
String microPath= getMicroPath(method);
//指定请求发送给哪个微服务
currentContext.put(FilterConstants.SERVICE_ID_KEY,microName);
//指定发送给微服务的哪个接口(即接口的路径是什么)
currentContext.put(FilterConstants.REQUEST_URI_KEY,microPath);
return null;
}
private String getMicroPath(String method) {
return "/echo/abc";
}
private String getMicroName(String serviceName) {
return "service-provide";
}
}