catalogue
5. Configure the Filter of the service
5. service removes the Filter uniformly configured by the provider
1, IntroductionWhen we re develop web applications, we usually need to inherit the interface class of javax.servlet.Filter to realize the functions of unified interception request processing, such as authentication, log, Xss attack interception, etc. When the microservice dubbo framework processes RPC requests, do we also need to implement a custom Filter for each interface called by the remote service?
Dubbo provides a way to call the interception extension. By inheriting the interface class of org.apache.dubbo.rpc.Filter, the calling processes of service providers and service consumers can be intercepted.
This paper is based on the configuration implementation of the previous article( SpringCloudAlibaba Learning Series (2) dubbo integration )Therefore, we will not continue to build the project repeatedly here, but only focus on code configuration verification.
2, Actual combat1. Create filter class
package com.sam.cloud.provider.filter; import org.apache.dubbo.rpc.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FirstRpcFilter implements Filter { private final Logger LOG = LoggerFactory.getLogger(FirstRpcFilter.class); @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { LOG.info("I did it First of filter: FirstRpcFilter"); return invoker.invoke(invocation); } }
This is achieved by integrating the org.apache.dubbo.rpc.Filter class; To facilitate subsequent verification, two filters are created here: SecondRpcFilter and ThirdRpcFilter
package com.sam.cloud.provider.filter; import org.apache.dubbo.rpc.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SecondRpcFilter implements Filter { private final Logger LOG = LoggerFactory.getLogger(SecondRpcFilter.class); @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { LOG.info("I did it second of filter: SecondRpcFilter"); return invoker.invoke(invocation); } }
package com.sam.cloud.provider.filter; import org.apache.dubbo.rpc.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ThirdRpcFilter implements Filter { private final Logger LOG = LoggerFactory.getLogger(ThirdRpcFilter.class); @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { LOG.info("I did it third of filter: ThirdRpcFilter"); return invoker.invoke(invocation); } }
2. Configure Filter file
Create a folder / META-INF/dubbo in the resources directory, and then create a plain text file: com.alibaba.dubbo.rpc.Filter, with the following contents:
firstRpcFilter=com.sam.cloud.provider.filter.FirstRpcFilter secondRpcFilter=com.sam.cloud.provider.filter.SecondRpcFilter thirdRpcFilter=com.sam.cloud.provider.filter.ThirdRpcFilter
3. Configure dubbo
a. There are two ways to configure Filter as a global provider: Based on properties and based on annotations
- Based on properties: add configuration in bootstart.properties, and sorting is the execution order
dubbo.provider.filter=firstRpcFilter,secondRpcFilter,thirdRpcFilter
- Based on the annotation: @ Activate(group = , order = 1). If the consumer uses group, the value is CommonConstants.CONSUMER. If both providers and consumers use it, add both. Order represents the order of execution when there are multiple custom filters. Here, you only need to annotate the FirstFilter class to enable it.
package com.sam.cloud.provider.filter; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Activate(group = , order = 1) public class FirstRpcFilter implements Filter { private final Logger LOG = LoggerFactory.getLogger(FirstRpcFilter.class); @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { LOG.info("I did it First of filter: FirstRpcFilter"); return invoker.invoke(invocation); } }
The remaining two classes, SecondRpcFilter and ThirdRpcFilter, are also annotated with the same annotation
4. View effect
Start the provider magic provider, then start the magic consumer, then request the interface, view the log, and print as follows:
INFO#2021-09-12 16:09:58.958#[]#I am the First filter: FirstRpcFilter INFO#2021-09-12 16:09:58.958#[]#I execute the second filter: SecondRpcFilter INFO#2021-09-12 16:09:58.958#[]#I am the third filter: third rpcfilter
5. Configure the Filter of the service
The above refers to the global provider or consumer configuration, but in actual development, we may need this filter to only work in a service class. How do we get it?
You only need to configure the filter in the annotation @ DubboService. First, create an Auth authentication filter: AuthRpcFilter according to steps 1 and 2 without setting the activation annotation @ Activate, and then set the filter = {"authRpcFilter"} in the annotation of the service implementation class. The code is as follows:
AuthRpcFilter: (here's a point to note: if you want to use spring managed bean s, you can't inject them with @ Resource. You need to implement the set method of parameters. dubbo will inject them automatically, like the injection of AuthHandler class in the following code)
package com.sam.cloud.provider.filter; import com.sam.cloud.provider.filter.handler.AuthHandler; import org.apache.dubbo.rpc.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AuthRpcFilter implements Filter { private final Logger LOG = LoggerFactory.getLogger(AuthRpcFilter.class); //dubbo will inject these bean s by itself. There is no need to label @ Resource for Spring to inject private AuthHandler authHandler; public void setAuthHandler(AuthHandler authHandler) { this.authHandler = authHandler; } @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { LOG.info("I'm executive authentication filter: AuthRpcFilter"); return invoker.invoke(invocation); } }
MagicProviderFacadeImpl:
package com.sam.cloud.provider.facade; import com.sam.cloud.provider.api.domain.UserDTO; import com.sam.cloud.provider.api.facade.MagicProviderFacade; import org.apache.dubbo.config.annotation.DubboService; @DubboService(version = "1.0.0", group = "magic", interfaceClass = MagicProviderFacade.class, filter = {"authRpcFilter"}) public class MagicProviderFacadeImpl implements MagicProviderFacade { @Override public UserDTO queryUser(String name) { UserDTO user = new UserDTO(); user.setUserId(1); user.setName("sam"); user.setAge(1L); return user; } }
The output log of startup verification is as follows:
INFO#2021-09-12 16:09:58.958#[]#I am the First filter: FirstRpcFilter INFO#2021-09-12 16:09:58.958#[]#I execute the second filter: SecondRpcFilter INFO#2021-09-12 16:09:58.958#[]#I am the third filter: third rpcfilter INFO#2021-09-12 16:09:58.958#[]#I am the authentication filter executed: AuthRpcFilter
5. service removes the Filter uniformly configured by the provider
When doing business, a service implementation may not need to execute the unified filter provided by a provider. At this time, the special symbol "-" can be used for identification elimination, as shown in the following code:
package com.sam.cloud.provider.facade; import com.sam.cloud.provider.api.domain.UserDTO; import com.sam.cloud.provider.api.facade.MagicProviderFacade; import org.apache.dubbo.config.annotation.DubboService; @DubboService(version = "1.0.0", group = "magic", interfaceClass = MagicProviderFacade.class, filter = {"-secondRpcFilter", "authRpcFilter"}) public class MagicProviderFacadeImpl implements MagicProviderFacade { @Override public UserDTO queryUser(String name) { UserDTO user = new UserDTO(); user.setUserId(1); user.setName("sam"); user.setAge(1L); return user; } }
filter = {"-secondRpcFilter", "authRpcFilter"} means that the service will execute firstrpcfilter, thirdrpcfilter and authrpcfilter in order, ignoring secondRpcFilter.
The execution log is as follows:
INFO#2021-09-12 16:09:58.958#[]#I am the First filter: FirstRpcFilter INFO#2021-09-12 16:09:58.958#[]#I am the third filter: third rpcfilter INFO#2021-09-12 16:09:58.958#[]#I am the authentication filter executed: AuthRpcFilter3, other
Refer to the official website:( Call the interception extension | Apache Dubbo)
1. All user-defined filters are executed after the built-in filter in dubbot by default. At present, the built-in filters in dubbo are as follows:
- org.apache.dubbo.rpc.filter.EchoFilter
- org.apache.dubbo.rpc.filter.GenericFilter
- org.apache.dubbo.rpc.filter.GenericImplFilter
- org.apache.dubbo.rpc.filter.TokenFilter
- org.apache.dubbo.rpc.filter.AccessLogFilter
- org.apache.dubbo.rpc.filter.CountFilter
- org.apache.dubbo.rpc.filter.ActiveLimitFilter
- org.apache.dubbo.rpc.filter.ClassLoaderFilter
- org.apache.dubbo.rpc.filter.ContextFilter
- org.apache.dubbo.rpc.filter.ConsumerContextFilter
- org.apache.dubbo.rpc.filter.ExceptionFilter
- org.apache.dubbo.rpc.filter.ExecuteLimitFilter
- org.apache.dubbo.rpc.filter.DeprecatedFilter
2. Special value Default indicates the insertion location of the default extension point. For example, filter="xxx,default,yyy" indicates xxx Execute before the default filter, yyy Execute after the default filter
3. Special symbols -, Indicates culling. For example: filter="-foo1", default extension points are added for culling Foo1. For example: filter="-default", eliminate and add all default extension points.
4. When a provider and a service configure filters at the same time, all filters are accumulated instead of overwriting. For example: < Dubbo: provider filter = "XXX, YYY" / > and < Dubbo: Service filter = "AAA, BBB" / >, then xxx,yyy,aaa,bbb Will take effect. If you want to overwrite, you need to configure: < Dubbo: Service filter = "- XXX, - YYY, AAA, BBB" / >