dubbo 拦截器配置,Filter,ServletContextListener

本文介绍了如何配置dubbo拦截器,包括在dubbo.xml中的设置、resource文件下的配置以及拓展filter。同时,详细讲解了ServletContextListener的配置,包括在web.xml中的配置和如何拓展监听器。最后,对Filter的使用进行了阐述,包括其方法介绍、web.xml配置及拓展方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:dubbo 拦截器

dubbo是一个被广泛应用的分布式服务框架,常与spring一起并用;如果想拦截dubbo服务接口,由于spring拦截的是web接口的调用,因此,dubbo提供了filter的扩展,通过继承Filter接口来实现拦截

1:dubbo.xml配置文件

<dubbo:provider id="assetProvider"
               application="defaultApplication”
            
               filter="assetExceptionFilter"/>  

2:resource 文件下配置

 新增目录 META-INF.dubbo,新建文件,命名为 com.alibaba.dubbo.rpc.Filter,将对应的拦截器写入到文件中

assetExceptionFilter=com.xiaoniu.asset.dubbo.filter.AssetExceptionFilter

3:拓展filter

@Activate(group = { Constants.PROVIDER })
public class AssetExceptionFilter implements Filter {
   private Logger logger = LoggerFactory.getLogger(AssetExceptionFilter.class);
   
   @Override
   public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
      
      try {
         Result result = invoker.invoke(invocation);
         if (!result.hasException()) {
            logger.info("###### finish successful, result:{}", result);
            return result;
         }
      
         Result rlt = null;
         Throwable e = result.getException();

         if (e instanceof AssetException) {
            int code = ((AssetException) e).getCode();
            String message = e.getMessage();
            rlt = getRpcResult(new ServiceResponse<>(code, message));
         } 
         else {
            logger.warn("###### dubbo接口({}.{}())调用异常 ~~~", invoker.getInterface().getName(), invocation.getMethodName(), e);
            int code = ResultCode.EXCEPTION_BUSINESS.getKey();
            String message = "系统错误";
            rlt = getRpcResult(new ServiceResponse<>(code, message));
         }
         logger.info("###### finished, result={} ~~~", rlt);
         return rlt;
      } catch (Exception e) {
         if (e.getCause() instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException) e.getCause();
            Set<ConstraintViolation<?>> data = ex.getConstraintViolations();
            if(data.size() > 0) {
               ConstraintViolation<?> item = data.iterator().next();
               String message = item.getMessage();
               ServiceResponse<?> response = ServiceResponseUtil.createServiceResponse(ResultCode.EXCEPTION_PARAMS, message); 
               return getRpcResult(response);
            }
         }
         logger.warn("###### dubbo接口({}.{}())调用异常 ~~~~", invoker.getInterface().getName(), invocation.getMethodName(), e);
         throw e;
      }

   }

   private RpcResult getRpcResult(ServiceResponse<?> response) {
      RpcResult rlt = new RpcResult();
      rlt.setValue(response);
      return rlt;
   }

}

二:ServletContextListener

当servlet容器启动或者终止web应用的时候,会触发ServletContextEvent事件,该事件由ServletContextListener监听处理;ServletContextListener接口定义了两个接口,contextInitialized在servlet启动web应用是被调用,然后才会对Filter进行初始化;contextDestroyed在servlet终止web应用的时候被调用,调用这个方法之前,容器会先销毁所有的servlet和Filter.


1:web.xml文件配置

配置到web.xml文件中

<listener>
<listener-class>com.xiaoniu.asset.web.servlet.ConfigFileListener</listener-class>
</listener>


2:拓展ServletContextListener

public class ConfigFileListener implements ServletContextListener {
    
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext  servletContext = sce.getServletContext();
        
        // 初始化配置目录
        String configHome = servletContext.getInitParameter(ConfigUtils.CONFIG_HOME);
        if(StringUtils.isNotBlank(configHome)) {
            System.setProperty(ConfigUtils.CONFIG_HOME, configHome);
            // 增加到classpath
            ConfigUtils.addToClasspath(configHome);
        }
    }
    
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        
    }
}


三:Filter

客户端请求会先被Filter拦截,进行预处理,然后才会进入到具体的业务层;可以对字符编号进行设定,头信息进行处理,请求参数进行预处理等;
(ps:与ServletContextListener不同的是,ServletContextListener是在servlet启动或者结束的时候进行操作,只调用一次,Filter是servlet启动之后,对每一个请求进行拦截)

1:方法介绍


init方法:项目启动的时候被调用,只调用一次

doFilter方法:所有的客户端请求都会被拦截,进入下一个拦截要调用chain.doFilter方法,如果不调用,请求将结束,没办法进入到 业务层中

destroy方法:servlet容器结束时被调用,只调用一次,用于释放资源

2:web.xml文件配置


<filter>
   <filter-name>securityFilter</filter-name>
   <filter-class>com.xiaoniu.asset.web.security.SecurityValidationFilter</filter-class>
</filter>

3:拓展Filter

public class SecurityValidationFilter implements Filter {
    private static Logger logger = LoggerFactory.getLogger(SecurityValidationFilter.class);
    
    private SecurityConfiguration configuration;
    // 时间戳差异, 超过1小时为失效
    private static final long TIMESTAMP_DIFF = 1000*60*60L;
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
        configuration = applicationContext.getBean(SecurityConfiguration.class);
        if (configuration == null) {
            throw new ServletException("not init SecurityConfiguration bean in ApplicationContext");
        }
    }

   @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        
       // 不是加密通信
        if (!needValidate(request)) {
            chain.doFilter(request, response);
            return;
        }

        // 签名为空
        String signature = request.getParameter("sign");
        if(StringUtils.isBlank(signature)) {
           renderInvalidRequest(response, "签名值为空");
           return;
        }
        // 再次请求
        chain.doFilter(new SecurityHttpServletRequestWrapper(request, "456".getBytes("UTF-8")), response);
    }
    @Override
    public void destroy() {
        System.out.println("结束");

    }


















评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值