SpringCloud中的一些常用的开源框架(二)
Zuul
zuul它的一个怪兽的名字,那他也就寓意着一个凶狠的角色,它就网关,也可以说是替我们的网站进行把关,它也是Netflix下的一款产品,它可以干一些什么?它可以进行身份的验证,审查和监控,路由,也内部集成了负载均衡等等
Zuul使用
1.导入依赖
<dependencies>
<!--怪兽名,网关,里面集成有ribbon,hystrix,web starter等-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
2.编写核心类,并加上zuul的注解
@EnableZuulProxy//功能完善
//@EnableZuulServer//功能单一
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class);
}
}
3.前面说过它可以进行拦截和转发,那它到底在哪配置呢?
下面是一个简单的配置模板,它可以将order-service开头的url转发到相应的url和端口。
server:
port: 8090
#名称
spring:
application:
name: gateway
#配置路由规则1
zuul:
routes:
wa:
path: /order-service/**
url: http://localhost:8081
这些配置没有提示,那到底是在哪里查看呢?
从源码很容易看到它是一个键值对的形式,因此在yml中配置也应该是键值对的形式。(通常键命名配要拉取的服务名)
继续打来ZuulRoute,我们可以看到里面有很多的属性,这些我们都可以用配置文件来配置
这样,很简单的就完成了一个入门程序!它可以对我们指定路径进行拦截和转发
如果没加order-service就会出现not found。虽然这样是可以的,但是为服务是以服务为单位的,因此需要服务层的配置,并且这样配置还是很麻烦并且它的url是一个写死的路径,这肯定不符合我们现代的代码要求,因为这样耦合度太高,系统可变性就大大减少。
因此,我们就产生了下一种配置方式。
配置2,从eureka拉取服务,从服务层面配置
#配置2,从eureka拉取服务,从服务层面配置
zuul:
routes:
order-service:
path: /order-service/**
serviceId: order-service
eureka:
client:
service-url:
defaultZone: http://localhost:8088/eureka/
这个就需要导入eureka包并注册到eureka上
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
这样也是同样可以,但是这样还不够,因为这个order-service出现了太多次,那么就又出现了下面的方法。因为这个Map中的K可以任意配置,因此,它里面又声明了可以让K为服务名称,然后V为path,这样就可以很方便的配置它了。
zuul:
routes:
order-service: /order-service/**
eureka:
client:
service-url:
defaultZone: http://localhost:8088/eureka/
然后看看注册器的注册情况
但是我们也可以惊奇的发现consumer没进行声明,但是它也可以访问
因为这种配法都是从eureka中获取服务,因此它索性就将全部服务都拿过来了!这样虽然相对的减少了手动配置但是它也把一些不需要调用的微服务调用了,因此,又可以如下的配置自定义
这样自定义不在网关上加载consumer,注意ignore-service是一个集合类型,得减号开头。
zuul:
# host:
# socket-timeout-millis: 60000
# connect-timeout-millis: 60000
routes:
order-service: /order-service/** #path可以自定义
ignored-services:
- consumer
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8088/eureka
结果如下:service可以访问,打死你consumer就不可以了!
如果看到如下前缀感觉很别扭,可以在配置文件中设置去除前缀
配置如下
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8088/eureka
zuul:
routes:
order-service:
path: /order/**
serviceId: order-service
strip-prefix: false #默认为true
加前缀的404
全局去除前缀主要是和prefix属性配合使用的,在实际使用中没必要配置prefix,当然也没必要使用全局去除前缀。局部去除前缀看个人喜好。
Zuul拦截器
创建一个拦截器并继承ZuulFilter,实现拦截方法
package com.wrial.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER-1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取上下文
RequestContext requestContext = RequestContext.getCurrentContext();
//获得request
HttpServletRequest request = requestContext.getRequest();
//获得参数
String token = request.getParameter("access-token");
//进行校验
// if(token == ""||token.trim().isEmpty()) //lang3包下的,实现内容相同,trim效率低,容易引起内存溢出
if(StringUtils.isBlank(token)){
requestContext.setSendZuulResponse(false);
//发送状态码403拒绝
requestContext.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
}
return null;
}
}
这也就是一个简单的拦截登陆操作。