zuul网关简单使用
zuul主要用于路由和过滤
zuul是一种服务网关,服务网关作用:企业级应用防火墙,节省流量,提高性能,作用于微服务项目,单体项目不需要
网关解决的问题:
统一接入,协议适配,安全防护,流量管控
nginx作为服务层的网关存在,zuul更多是的作为业务层网关存在
zuul的1.x版本是阻塞io,不支持长连接,zuul的2.x版本支持异步
项目中根据url路由
server.port=1002 spring.application.name=zuul-service logging.level.com.zuul=debug logging.level.web=debug spring.devtools.add-properties=false #路由规则配置 #配置请求url映射路径 zuul.routes.product-service.path=/product-service/** #映射路径对应的微服务地址 zuul.routes.product-service.url=http://localhost:1001/
这种路由存在问题,如果服务器地址更换,对应的url地址也要更换,对于服务的迁移不方便
所以使用调用服务的方式代替
server:
port: 1002
spring:
application:
name: zuul-service
zuul:
routes:
product-service:
path: /product-service/**
serviceId: product-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/

当网关的作用只是路由转发的时候,可以进行如下优化,路由设置的部分注释掉
server:
port: 1002
spring:
application:
name: zuul-service
#zuul:
# routes:
# product-service:
# path: /product-service/**
# serviceId: product-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
路径排除
zuul:
routes:
product-service:
path: /product-service/**
serviceId: product-service
ignored-patterns: /**/order/** #排除order路径

商品服务依旧可以访问

服务排除

路由前缀配置,隐藏真实的地址
zuul:
routes:
product-service:
path: /product-service/**
serviceId: product-service
#ignored-patterns: /**/order/** #排除order路径
prefix: /api


网关过滤
package com.zuul.filter;
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 javax.servlet.http.HttpServletRequest;
/**
* @author yourheart
* @Description
* @create 2022-05-09 22:14
*/
@Component
@Slf4j
public class GetwayFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取请求上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
log.info("【过滤地址】方法:{},地址:{}",request.getMethod(),request.getRequestURL().toString());
return null;
}
}

鉴权处理
package com.zuul.filter;
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.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author yourheart
* @Description
* @create 2022-05-09 21:56
*/
@Component
@Slf4j
public class AccessFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取请求上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
String token = request.getParameter("token");
if (null==token){
log.warn("【token为空】");
//请求结束
rc.setSendZuulResponse(false);
//状态码,401未授权
rc.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
rc.getResponse().setContentType("application/jsop; charset=utf-8");
PrintWriter writer=null;
try {
writer=rc.getResponse().getWriter();
writer.print("401,登录未授权");
} catch (IOException e) {
e.printStackTrace();
}
}else {
log.info("【token id ok】");
}
return null;
}
}




项目层级

父级依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>zuul-aprent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-service</module>
<module>prodoct-service</module>
<module>order-service</module>
<module>zuul-service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!--编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--打包插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
eureka项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>zuul-aprent</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.eureka</groupId>
<artifactId>eureka-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
package com.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @author yourheart
* @Description
* @create 2022-04-20 21:17
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
server.port=8761
spring.application.name=eureka-service
eureka.instance.hostname=localhost
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
logging.level.com.eureka=info
logging.level.web=info
spring.devtools.add-properties=false
order项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>zuul-aprent</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.order</groupId>
<artifactId>order-service</artifactId>
<dependencies>
<!--客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--添加fastjson依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
</project>
package com.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @author yourheart
* @Description
* @create 2022-04-20 21:38
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
package com.order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author yourheart
* @Description
* @create 2022-04-20 21:46
*/
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
@Autowired
private ProductService productService;
@GetMapping("/getOrder/{id}")
public String getProduct(@PathVariable String id){
log.info("【调用消费者入参】:{}",id);
String selectProduct = productService.selectProduct(id);
return selectProduct;
}
}
package com.order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "product-service")
public interface ProductService {
@GetMapping("/product/getProduct/{id}")
String selectProduct(@PathVariable String id);
}
server.port=1001 spring.application.name=order-service #注册到eureka注册中心,如果是注册到集群就用逗号连接多个,单实例写上一个就好 eureka.client.service-url.defaultZone=http://localhost:8761/eureka logging.level.com.order=debug logging.level.web=debug spring.devtools.add-properties=false
product项目

package com.product;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author yourheart
* @Description
* @create 2022-04-20 21:28
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class,args);
}
}
package com.product;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author yourheart
* @Description
* @create 2022-04-20 21:30
*/
@RestController
@RequestMapping("/product")
@Slf4j
public class ProductController {
@GetMapping("/getProduct/{id}")
public String selectProduct(@PathVariable String id){
log.info("【调用服务者入参】:{}",id);
return "查询到的主键返回"+id;
}
}
server.port=1000 spring.application.name=product-service #注册到eureka注册中心,如果是注册到集群就用逗号连接多个,单实例写上一个就好 eureka.client.service-url.defaultZone=http://localhost:8761/eureka logging.level.com.product=debug logging.level.web=debug spring.devtools.add-properties=false
zuul网关项目

package com.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;
/**
* @author yourheart
* @Description
* @create 2022-04-20 22:05
*/
@SpringBootApplication
//开启zuul注解
@EnableZuulProxy
@EnableDiscoveryClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class,args);
}
}
package com.zuul.filter;
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.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author yourheart
* @Description
* @create 2022-05-09 21:56
*/
@Component
@Slf4j
public class AccessFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取请求上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
String token = request.getParameter("token");
if (null==token){
log.warn("【token为空】");
//请求结束
rc.setSendZuulResponse(false);
//状态码,401未授权
rc.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
rc.getResponse().setContentType("application/jsop; charset=utf-8");
PrintWriter writer=null;
try {
writer=rc.getResponse().getWriter();
writer.print("401,登录未授权");
} catch (IOException e) {
e.printStackTrace();
}
}else {
log.info("【token id ok】");
}
return null;
}
}
package com.zuul.filter;
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 javax.servlet.http.HttpServletRequest;
/**
* @author yourheart
* @Description
* @create 2022-05-09 22:14
*/
@Component
@Slf4j
public class GetwayFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取请求上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
log.info("【过滤地址】方法:{},地址:{}",request.getMethod(),request.getRequestURL().toString());
return null;
}
}
server:
port: 1002
spring:
application:
name: zuul-service
zuul:
routes:
product-service:
path: /product-service/**
serviceId: product-service
prefix: /api
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
浙公网安备 33010602011771号