I define a custom filter in spring gateway project, now I found I have to register the custom filter in the code like this:
@Configuration public class GatewayConfig { private final JwtAuthenticationFilter filter; public GatewayConfig(JwtAuthenticationFilter filter) { this.filter = filter; } @Bean public RouteLocator routes(RouteLocatorBuilder builder) { return builder.routes() .route("auth", r -> r.path("/auth/**").filters(f -> f.filter(filter)).uri("lb://auth")) .route("music", r -> r.path("/music/**").filters(f -> f.filter(filter)).uri("lb://dolphin-music")).build(); } }
if I do not register the custom filter, the filter will not make effect and work as expect. But I already config the route in application.properties
like this:
# dolphin music spring.cloud.gateway.discovery.locator.enabled=true spring.cloud.gateway.discovery.locator.lower-case-service-id=true spring.cloud.gateway.routes[0].id=dolphin-music-service # forward by ip:port way spring.cloud.gateway.routes[0].uri=http://10.107.64.246:11014 # forward by service name way # spring.cloud.gateway.routes[0].uri=lb:// spring.cloud.gateway.routes[0].predicates[0]=Path=/music/**
I think we should not define the route config both in code and configuration file, what should I do to only register the filter? is there any better way to handle the situation? should I must define the route in code? I think config in file will more flexible.BTW,this is the JwtAuthenticationFilter
:
@Component public class JwtAuthenticationFilter implements GatewayFilter { @Value("${dolphin.gateway.jwt.verify:true}") private boolean jwtVerfiy; final static List<String> apiEndpoints = List.of("/register", "/login"); final static Predicate<ServerHttpRequest> isApiSecured = r -> apiEndpoints.stream() .noneMatch(uri -> r.getURI().getPath().contains(uri)); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return chain.filter(exchange); } }
I tried to add MyFilterFactory
like this:
@Component public class MyFilterFactory extends AbstractGatewayFilterFactory<MyFilterFactory.Config> { @Autowired private JwtAuthenticationFilter jwtAuthenticationFilter; public MyFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return jwtAuthenticationFilter; } public static class Config { } }
and define in route factory in application.properties
like this:
spring.cloud.gateway.routes[0].filters[0]=MyFilterFactory
the problem is that the request did not enter the JwtAuthenticationFilter
I am defined.
Advertisement
Answer
Yes, it is possible, you need to register a bean that extends the GatewayFilterFactory
class.
For example:
@Component public class MyFilterFactory extends AbstractGatewayFilterFactory<MyFilterFactory.Config> { public MyFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return new MyFilter(); // or MyFilter(config), depending on your needs } public static class Config { // this can be empty if you don't need to pass any filter arguments } }
Then you can use its name in the application.properties
file.
spring.cloud.gateway.routes[0].filters[0]=MyFilterFactory
Not that you need to use the factory name in the properties file.