
Spring Cloud Gateway
Spring Cloud Gateway provides a flexible way of routing requests based on a number of criteria, as well as focuses on cross-cutting concerns such as security, resiliency, and monitoring. An API gateway allows you to implement the complexity separately from the client, moving that responsibility from user side to server side. All the client needs to know is how to talk to the gateway. It doesn’t matter whether the backend services run, go offline, or become unstable as long as the gateway knows how to handle these situations. Spring Cloud Gateway Pre and Post filters are can be used in incoming request and outgoing response filter.
Spring Cloud Gateway Architecture
- Route: Route is the basic building block of the gateway. It consists of
- ID
- destination URI
- Collection of predicates and a collection of filters
- A Route is matched if the aggregate’s predicate is true.
- Predicate: It is similar to Java 8 Function Predicate. Using this functionality we can match HTTP request, such as headers , url, cookies or parameters.
- Filter: These are instances of Spring Framework GatewayFilter. Using this we can modify the request or response as per the requirement.
Implement Student Microservice
Maven project will be like this
The pom.xml will be as follows-
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.javainuse</groupId>
<artifactId>student-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>
Define the application.yml as follows
spring:
application:
name: student-service
server:
port: 8081
Create the bootstrap class(StudentApplication) with the @SpringBootApplication annotation
package com.springmicroservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
Create a Controller class that exposes the GET REST service as follows
package com.springmicroservice.controller;
import org.json.simple.JSONObject;
import org.springframework.web.bind.annotation.*;
package com.springmicroservice.controller;
import org.json.simple.JSONObject;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/student")
public class StudentController {
/**
* Controller is used to invoke services and it's return json object as response.
*/
@GetMapping("/records")
public JSONObject test(@RequestHeader("student-request") String header) {
JSONObject obj=new JSONObject();
obj.put("subject_code","Math");
obj.put("dept_name","CSE");
obj.put("name","Sumit");
obj.put("id",new Integer(101));
System.out.println("Student Service Invoked...");
System.out.println(header);
return obj;
}
}
Implement Subject Microservice
Maven project will be like this
The pom.xml will be as follows-
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.javainuse</groupId>
<artifactId>subject-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>
Define the application.properties as follows
spring:
application:
name: subject-service
server:
port: 8082
Create the bootstrap class(SubjectApplication) with the @SpringBootApplication annotation
package com.springmicroservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SubjectApplication {
public static void main(String[] args) {
SpringApplication.run(SubjectApplication.class, args);
}
}
Create a Controller class that exposes the GET REST service as follows-
package com.springmicroservice.controller;
import org.json.simple.JSONObject;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/subject")
public class SubjectController {
/**
* Controller is used to invoke services and it's return json object as response.
*/
@GetMapping("/records")
public JSONObject test(@RequestHeader("subject-request") String header) {
JSONObject obj=new JSONObject();
obj.put("code","Math");
obj.put("name","Mathematics");
obj.put("subjectId",new Integer(101));
System.out.println("Subject Service Invoked...");
System.out.println(header);
return obj;
}
}
Implement Pre and Post filters in Spring Cloud Gateway using java based config
The pom.xml will be as follows
<?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>com.javainuse</groupId>
<artifactId>cloud-gateway-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-service</name>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</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>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Create the bootstrap class(APIGatewayApplication) with the @SpringBootApplication annotation
package com.springcloudgateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class APIGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(APIGatewayApplication.class, args);
}
}
To make Custom filters we need to inherit AbstractGatewayFilterFactory class.
Specify the Custom Filter in the route in application.yml file
server:
port: 8080
Create the SpringCloudConfig class with the @Configuration
package com.springcloudgateway.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringCloudConfig {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/student/**")
//Pre and Post Filters provided by Spring Cloud Gateway
.filters(f -> f.addRequestHeader("student-request", "student-request-header")
.addResponseHeader("student-response", "student-response-header"))
.uri("http://localhost:8081/")
.id("studentModule"))
.route(r -> r.path("/subject/**")
//Pre and Post Filters provided by Spring Cloud Gateway
.filters(f -> f.addRequestHeader("subject-request", "subject-request-header")
.addResponseHeader("subject-response", "subject-response-header"))
.uri("http://localhost:8082/")
.id("subjectModule"))
.build();
}
}
Start the applications-
- cloud-gateway-service-java-based
- student-service
- subject-service
Run the application.
Go to browser Right click ->inspect->Network then type localhost:8080/student/records in address bar.
In the below images we can see that the Pre filter has been applied to request header and post filter is applied for response header.
Go to browser Right click ->inspect->Network then type type localhost:8080/subject/records in address bar.
In the below images we can see that pre filter is applied for request header and post filter is applied for response header.
Conclusion
In this blog, we have covered how to implement and configure pre and post Filters to Spring Cloud Gateway Service. Now you are ready to go to implement pre and post Filters to Spring Cloud gateway. For more, you can refer to the documentation: https://cloud.spring.io/spring-cloud-gateway/reference/html/