dubbo 拦截器配置,Filter,ServletContextListener

来源:互联网 发布:java object notify 编辑:程序博客网 时间:2024/06/07 12:10

一: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("结束");    }


















原创粉丝点击