基于Zuul(网上找不到音标,读“猪”
第四音)实现API网关,需要按如下步骤实现:
- 搭建Eureka注册中心
- 创建Zuul网关项目
- 创建A项目服务
- 创建B项目服务
流程示意图如下:
启动项目需要按上面顺序执行,否则会报错,下面开始讲解代码。
1. 创建Eureka注册中心
1.创建eureka_server项目
2.添加Maven依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <!-- 注意: 这里必须要添加, 否者各种依赖有问题 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
3.application.yml 配置信息
server: port: 8100 eureka: instance: hostname: server1 client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ register-with-eureka: false fetch-registry: false
4.启动类
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(final String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
2. 创建Zuul网关
1.创建zuul-gateway maven项目
2.添加maven依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.RC1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <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-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.0.1</version> <executions> <execution> <id>copy-conf</id> <phase>package</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <encoding>UTF-8</encoding> <outputDirectory>${project.build.directory}/ext/conf</outputDirectory> <resources> <resource> <directory>ext/conf</directory> <includes> <include>logback.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.5.201505241946</version> <executions> <execution> <id>default-prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>default-prepare-agent-integration</id> <goals> <goal>prepare-agent-integration</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.3</version> <configuration> <imageName>hy_uav_gateway</imageName> <dockerDirectory>src/main/docker</dockerDirectory> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> <include>ext/conf/logback.xml</include> </resource> </resources> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
3.配置application 依赖信息
###注册 中心 eureka: client: serviceUrl: defaultZone: http://localhost:8100/eureka/ server: port: 80 ###网关名称 spring: application: name: service-zuul ### 配置网关反向代理 zuul: routes: api-a: path: /api-a/** serviceId: project_a api-b: path: /api-b/** serviceId: project_b
4.ZuulApplication启动运行,并把过滤器拦截注册到SpringBoot容器
@EnableZuulProxy @EnableEurekaClient @SpringBootApplication public class AppZuul { // @EnableZuulProxy 开启Zuul网关代理 // @EnableEurekaClient 注册到EurekaC public static void main(String[] args) { SpringApplication.run(AppZuul.class, args); } // 注册到SpringBoot 容器 @Bean public TokenFilter accessFilter() { return new TokenFilter(); } }
5.过滤器拦截参数
// 使用网关拦截Token参数 public class TokenFilter extends ZuulFilter { public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); Object accessToken = request.getParameter("accessToken"); if (accessToken == null) { // 返回错误信息 ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); ctx.setResponseBody("accessToken is null"); return null; } return null; } public boolean shouldFilter() { return true;// 是否执行该过滤器,此处为true,说明需要过滤 } @Override public int filterOrder() { return 0;// 优先级为0,数字越大,优先级越低 } @Override public String filterType() { return "pre"; // 前置过滤器 } }
3. 创建A项目及B项目
A服务与B服务的创建方式大同小异,以A项目为例子:
1.创建api-a项目
2.添加maven依赖:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.RC1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <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-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.0.1</version> <executions> <execution> <id>copy-conf</id> <phase>package</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <encoding>UTF-8</encoding> <outputDirectory>${project.build.directory}/ext/conf</outputDirectory> <resources> <resource> <directory>ext/conf</directory> <includes> <include>logback.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.5.201505241946</version> <executions> <execution> <id>default-prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>default-prepare-agent-integration</id> <goals> <goal>prepare-agent-integration</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.3</version> <configuration> <imageName>hy_uav_gateway</imageName> <dockerDirectory>src/main/docker</dockerDirectory> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> <include>ext/conf/logback.xml</include> </resource> </resources> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
3.配置application 依赖信息(b项目名字为:project_b)
server: port: 8001 ###服务名称 spring: application: name: project_a ###注册中心地址 eureka: client: service-url: defaultZone: http://localhost:8100/eureka
4.启动类(b项目index方法返回“我是B项目”)
@SpringBootApplication @EnableDiscoveryClient @RestController public class AIndexController { @RequestMapping("/") public String index() { return "我是A项目...."; } public static void main(String[] args) { SpringApplication.run(AIndexController.class, args); } }
4. 测试
4.1 运行Eureka注册中心
启动应用:http://localhost:8100/,可以看到Eureka注册中心管理平台。
4.2 运行Zuul网关
会发现Zuul网关注册上Eureka中心了
4.3 运行A项目和B项目
可以看到项目A和项目B都注册上Eureka中心了
4.4 访问测试
浏览器输入http://localhost/api-a,返回内容如下
可以看出tonken为null,要加token。
访问:http://localhost/api-a?token=123456
访问:http://localhost/api-b?token=123456