Spring Extension (3) — Annotation based Controller HandlerInterceptor

时间:2025-03-15 15:17:15

场景:

在《Spring Extension (2) — Annotation RequestAttribute for Controller method Parameter Injection中定义了UserInterceptor,默认拦截所有http 请求,如果只拦截/demo, /demo2 的请求呢?

可以使用这种方式

<bean class="">
		<property name="interceptors">
			<list>
				<bean class="">
                                <constructor-arg index="0">
                                               <list>
                                               <value>/demo<value>
                                             <value>/demo1<value>
                                               <list>
                             </constructor-arg>
                              <constructor-arg index="1">  
                                               <ref bean="userInterceptor"/> 
                                   </constructor-arg>
                         </bean>
			</list>
		</property>
	</bean>

或者

<bean class="">
		<property name="interceptors">
			<list>
				<bean class="">
                                <property name="matchUrls">
                                        <list>
                                      <value>/demo<value>
                                        <value>/demo1<value>
		                 	  </list>
				     </property>
				</bean>
                 </list>
</bean>
UserInterceptor中定义需要拦截的url: matchUrls,然后编码判断拦截逻辑。。。


如果/demo1,/demo 是由同一个Controller处理,而且以后可能新的request url: /test ,也是由相同的Controller处理,更简单的方式是在Controller上声明相应的HandlerInterceptor

例如:

@Controller
@RequestMapping("/")
@HandlerInterceptors({  })
public class UserController{
// detail RequestMapping({"/demo", "/demo1","/test"}
}

代码:

1、定义Annotation

/**
 * spring handler interceptor configuration by annotation
 */

@Documented
@Target({})
@Retention()
public @interface HandlerInterceptors {
    /**
     * find spring bean instance by the class type
     */
    Class<? extends HandlerInterceptor>[] value();
}

2、在目标类定义:

@Controller
@RequestMapping("/")
@HandlerInterceptors({  })
public class UserController{
// detail RequestMapping({"/demo", "/demo1","/test"}
}

3、在Spring中关联InterceptorController

/**
 * assemble the {@link HandlerInterceptor}s by Annotation {@link Interceptors}.
 */
public class CustomAnnotationHandlerMapping extends DefaultAnnotationHandlerMapping {
    private final static Logger logger = (CustomAnnotationHandlerMapping .class);
    @Override
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler,HttpServletRequest request){
        HandlerExecutionChain chain = (handler,request); 
        HandlerInterceptor[] interceptors = detectInterceptors(().getClass());
        (interceptors);
        return chain;
    }

/**
     * find {@link HandlerInterceptor}s present on the {@link Controller} via the {@code HandlerInterceptor}
     * @param handlerClass
     * @return
     */
    protected HandlerInterceptor[] detectInterceptors(Class<?> handlerClass) {
        HandlerInterceptors interceptorAnnot = (handlerClass, );//custom annotation: HandlerInterceptors
        List<HandlerInterceptor> interceptors = new ArrayList<HandlerInterceptor>();
        if (interceptorAnnot != null) {
          Class<? extends HandlerInterceptor>[] interceptorClasses = ();// interceptors for the handlerClass
          if (interceptorClasses != null) {
            for (Class<? extends HandlerInterceptor> interceptorClass : interceptorClasses) {
              if (!(interceptorClass)) {
                raiseIllegalInterceptorValue(handlerClass,interceptorClass);
              }
              (().getBean(interceptorClass));
            }
          }
        }
        return (new HandlerInterceptor[0]);
    }


    protected void raiseIllegalInterceptorValue(Class handlerClass,Class interceptorClass) {          
        throw new IllegalArgumentException(interceptorClass + " specified on "
            + handlerClass + " does not implement " + ());
            
    }
}



4、启用自定义的HandlerMap

<bean class="">
		<property name="interceptors">
			<list>
				<ref bean="userInterceptor " />
			</list>
		</property>
	</bean>


修改为:

 <bean class=" ">
    ......
  </bean>


使用这种方式的好处就是能够统一拦截同一个Controller对应的所有http url request,而且这些url没有任何规则可言。缺点是忽略Controller对应的某个请求比较麻烦,如果HandlerInterceptor只是用来执行通用的计算逻辑,这个缺点可以忽略。