Sring使用拦截器,如果Controller抛出异常,postHandle不执行

我的Springboot应用中使用拦截器做限流,在preHandle中申请许可,在执行完之后归还许可,一开始是在postHandle中归还许可,但后来发现,如果接口不自己处理异常,而是抛出异常,则可用的许可越来越少,即,接口抛出异常,则postHandle中的归还许可代码不会执行。

解决办法:

把归还许可的代码放到afterCompletion方法中即可,原因见下面的源码(org.springframework.web.servlet.HandlerExecutionChain),即使preHandle执行不成功,则直接执行触发afterCompletion方法的triggerAfterCompletion方法:

	/**
	 * Apply preHandle methods of registered interceptors.
	 * @return {@code true} if the execution chain should proceed with the
	 * next interceptor or the handler itself. Else, DispatcherServlet assumes
	 * that this interceptor has already dealt with the response itself.
	 */
	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				if (!interceptor.preHandle(request, response, this.handler)) {
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}

 附上拦截器源码:

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("Init permits numbers : " + RateLimiterMap.permit.availablePermits());

        boolean acq = RateLimiterMap.permit.tryAcquire();//获取许可

        logger.info("Permits available numbers : " + RateLimiterMap.permit.availablePermits());

        if(!acq){
            //无可用许可,直接抛出异常
            throw new GraphOperateException("The whole request amount has exceed the ability that Model Service can afford");
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.info("postHandle was executed");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        RateLimiterMap.permit.release();//归还许可
        logger.info("AfterCompletion was executed: Permits available numbers : " + RateLimiterMap.permit.availablePermits());
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值