1. Zuul介绍
Zuul在微服务中主要是做路由转发功能和请求过滤功能。
-
路由转发:根据一定的规则,区分请求并转发到对应的服务商,比如两个请求/api/user/getUser,/api/blog/getBlog在zuul服务中分别转发到用户服务和博客服务。
-
请求过滤:很多服务请求都有会身份验证,就可以直接在zuul中去对身份验证的token去做校验,而不用在每个服务中都去做一次校验那么麻烦
2. 准备工作
准备一个用户服务,一个博客服务,一个注册中心
2.1. 用户服务
server:
port: 4003
spring:
application:
name: service-user
eureka:
client:
service-url:
defaultZone: http://eureka-server1:3001/eureka/
instance:
instance-id: 用户服务-4003
/** * @author 吕梁山
* @date 2019/7/19 */ @RestController
@RequestMapping("/api/user") public class UserController {
@RequestMapping(value = "/getUser", method = RequestMethod.GET) public String getUser(String userId){ return "查找用户:" + userId;
}
@RequestMapping(value = "/addUser", method = RequestMethod.POST) public String addUser(String userName){ return "新增用户姓名:" + userName;
}
@RequestMapping(value = "/updateUser", method = RequestMethod.PUT) public String updateUser(String userName){ return "更新用户姓名:" + userName;
}
@RequestMapping(value = "/deleteUser", method = RequestMethod.DELETE) public String deleteUser(String userId){ return "删除用户:" + userId;
}
}
2.2. 博客服务
server:
port: 4004
spring:
application:
name: service-blog
eureka:
client:
service-url:
defaultZone: http://eureka-server1:3001/eureka/
instance:
instance-id: 博客服务-4004
/** * @author 吕梁山
* @date 2019/7/19 */ @RestController
@RequestMapping("/api/blog") public class BlogController {
@RequestMapping(value = "/getBlog", method = RequestMethod.GET) public String getBlog(String blogId){ return "查找博客:" + blogId;
}
@RequestMapping(value = "/addBlog", method = RequestMethod.POST) public String addBlog(String blogName){ return "新增博客标题:" + blogName;
}
@RequestMapping(value = "/updateBlog", method = RequestMethod.PUT) public String updateBlog(String blogName){ return "更新博客标题:" + blogName;
}
@RequestMapping(value = "/deleteBlog", method = RequestMethod.DELETE) public String deleteBlog(String blogId){ return "删除博客:" + blogId;
}
}
2.3. 注册中心
server:
port: 3001
eureka:
instance:
# 在服务中心显示的名称
hostname: eureka-server1
client:
# false表示不向注册中心注册自己
register-with-eureka: false
# false声明是服务端
fetch-registry: false
service-url:
# 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
defaultZone: http://eureka-server1:3001/eureka/
server:
enable-self-preservation: false
3. 创建Zuul服务
启动后查看注册中心
4. 配置Zuul
配置zuul之前先看用户服务和博客服务能否正常访问,分别访问
http://127.0.0.1:4003/api/user/getUser?userId=1
http://127.0.0.1:4004/api/blog/getBlog?blogId=1
可以看到分别返回
查找用户:1
查找博客:1
Zuul的路由转发配置主要在配置文件去配置
zuul:
routes:
service-user:
path: /api/user/**
serviceId: service-user
stripPrefix: false
service-blog:
path: /api/blog/**
serviceId: service-blog
stripPrefix: false
-
path:匹配的规则
-
serviceId:要转发至的服务id
-
stripPrefix: 是否去掉前缀(为true的时候访问/api/user/getUser在转发到用户服务时会去除path配置的/api/user/变成/getUser)
配置好Zuul后,分别访问
http://127.0.0.1:5005/api/user/getUser?userId=1
http://127.0.0.1:5005/api/blog/getBlog?blogId=1
可以看到分别返回
查找用户:1
查找博客:1
这样就说明Zuul的路由转发成功了。
5. 请求过滤
请求过滤即将那些不符合要求的请求过滤掉,这里演示就只以请求是否带token这个参数为例
5.1. 新建一个过滤器(新建一个类去继承ZuulFilter类)
/** * @author 吕梁山
* @date 2019/7/19 */ @Component public class MyZuulFilter extends ZuulFilter {
Logger logger = LoggerFactory.getLogger(MyZuulFilter.class); /** * pre:路由之前
* routing:路由之时
* post: 路由之后
* error:发送错误调用 */ @Override public String filterType() {
logger.info("准备进入路由-------------->"); return "pre";
} /** * 过滤的顺序 */ @Override public int filterOrder() { return 0;
} /** * 这里可以写逻辑判断,是否要过滤,true为永远过滤。 */ @Override public boolean shouldFilter() { return true;
} /** * 过滤器的具体逻辑 */ @Override public Object run() {
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
HttpServletResponse response = currentContext.getResponse();
response.setHeader("Content-Type","text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
String token = request.getParameter("token"); if(StringHelper.isNullOrEmptyString(token)){
logger.warn("token is empty");
currentContext.setSendZuulResponse(false);
currentContext.setResponseStatusCode(401);
currentContext.setResponseBody("token为空"); return null;
} return null;
}
}
自定义过滤器的实现,继承ZuulFilter后需要重写实现下面四个方法
-
filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型
-
pre:可以在请求被路由之前调用
-
routing:在路由请求时候被调用
-
post:在routing和error过滤器之后被调用
-
error:处理请求时发生错误时被调用
-
filterOrder:通过int值来定义过滤器的执行顺序
-
shouldFilter:返回一个boolean类型来判断该过滤器是否要执行,所以通过此函数可实现过滤器的开关。在上例中,我们直接返回true,所以该过滤器总是生效。
-
run:过滤器的具体逻辑。需要注意,这里我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求,不对其进行路由,然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码,当然我们也可以进一步优化我们的返回,比如,通过ctx.setResponseBody(body)对返回body内容进行编辑等。
5.2. 进行测试
http://127.0.0.1:5005/api/blog/getBlog?blogId=1
返回结果为
token为空
http://127.0.0.1:5005/api/blog/getBlog?blogId=1&token=test
返回结果为
查找博客:1
至此Zuul过滤器也成功了
欢迎留言:http://pikaqiu.vip/article/2370.html
示例代码:https://github.com/Liangshan1994/SpringCloud
如果您觉得本文的内容对您的学习有所帮助:
关键字:
Spring Cloud学习