In order to use interceptors with Annotation-based controllers, you need to configure the DefaultAnnotationHandlerMapping used by the Spring container.
<bean id="annotationMapper" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <ref bean="myInterceptor1"/> <ref bean="myInterceptor2"/> <ref bean="myInterceptor3"/> </list> </property> </bean>
Unfortunately, using the DefaultAnnotationHandlerMapping for interceptors configures the interceptors for all defined annotation based controllers.
In some cases, you might want to have interceptors apply only to specific controllers.
I have created two HandlerMappings that will accomplish this task:
The SelectedAnnotationHandlerMapping and the IgnoreSelectedAnnotationHandlerMapping.java classes which can both be downloaded from www.springplugins.org
The SelectedAnnotationHandlerMapping allows you to specify which urls will be interecepted. It is configured as follows:
<bean id="publicMapper" class="org.springplugins.web.SelectedAnnotationHandlerMapping"> <property name="urls"> <list> <value>/interceptOnly.do</value> </list> </property> <property name="interceptors"> <list> <ref bean="myInterceptor"/> </list> </property> </bean>
The above configuration causes all requests to /interceptOnly.do to be intercepted by myInterceptor.
The IgnoreSelectedAnnotationHandlerMapping allows you to specify which urls will not be interecepted. This is similar to Spring's DefaultAnnotationHandlerMapping in that it will map all Annotation based controllers except it will not map the defined urls. It is configured as follows:
<bean id="publicMapper" class="org.springplugins.web.IgnoreSelectedAnnotationHandlerMapping"> <property name="order"> <value>0</value> </property> <property name="urls"> <list> <value>/doNotIntercept.do</value> </list> </property> <property name="interceptors"> <list> <ref bean="myInterceptor"/> </list> </property> </bean>
Here all annotation-based controllers will be intercepted with myInterceptor except the one usign /doNotIntercept.do url.
Notice that this interceptor specifies the order attribute. This is necessary because if you are using this controller, you are most likely using another mapper for the specified urls. The order was set to 0 here because it is assumed that the mapping to /doNotIntercept.do will be defined with an order > 0.
Comments
Got it working
Thanks for this. If anyone is having problems getting it working remember that you have to add a DefaultAnnotationHandlerMapping.
It's mentioned in the Spring Javadocs: http://static.springsource.org/spring/docs/2.5.x/api/org/springframework...
Here's the important bit: NOTE: If you define custom HandlerMapping beans in your DispatcherServlet context, you need to add a DefaultAnnotationHandlerMapping bean explicitly, since custom HandlerMapping beans replace the default mapping strategies.
I used the following bean definitions: (Note that I changed the package name of SelectedAnnotationHandlerMapping while I was figuring it out, this probably isn't necessary)
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order">
<value>1</value>
</property>
</bean>
<bean id="secureHandlerMapping"
class="org.springframework.web.servlet.mvc.annotation.SelectedAnnotationHandlerMapping">
<property name="order">
<value>0</value>
</property>
<property name="interceptors">
<list>
<ref bean="loginInterceptor" />
</list>
</property>
<property name="urls">
<list>
<value>/usermaintenance.html</value>
</list>
</property>
</bean>
SelectedAnnotationHandlerMappings - URL's does not work
Hey Scott, I have tested your plugin & the idea is great (cannot believe Spring 2.5 does not have this out-of-the-box!). However (just like the user Mathias) I cannot get the URL mappings to work. Scenario: protect some URL's by requiring login. The DefaultAnnotationHandlerMapping is the fallback mapping (order 1 as you suggest), the securityMapper (the SelectedAnnotationHandlerMapping) is the restrictive one (order 0 as you suggest). Here is the relevant code:
The loginInterceptor connected to the securityMapper simply does not trigger! I tried all kinds of URL's & order values. Please advice! What am I missing?
Furthermore I totally agree with Mathias that wildcards would be highly appreciated! In fact, don't think I could live without it. :)
Best Regards / V.
problem with urls
I have a problem... can't get the url's to make the interceptors be invoked. To simplify, i have made a basic setup:
<bean id="bananaInterceptor" class="com.test.web.interceptors.BananaInterceptor"/>
<bean id="pineappleInterceptor" class="com.test.web.interceptors.PineappleInterceptor"/>
<bean id="PineappleMapper" class="org.springplugins.web.SelectedAnnotationHandlerMapping">
<property name="order"><value>1</value></property>
<property name="urls">
<list>
<value>/konvalj/registry/apartments/list.htm</value>
</list>
</property>
<property name="interceptors">
<list>
<ref bean="pineappleInterceptor"/>
</list>
</property>
</bean>
<bean id="bananaMapper" class="org.springplugins.web.IgnoreSelectedAnnotationHandlerMapping">
<property name="order"><value>99</value></property>
<property name="urls">
<list>
<value>nothing</value>
</list>
</property>
<property name="interceptors">
<list>
<ref bean="bananaInterceptor"/>
</list>
</property>
</bean>
You would then expect that when an url of the type defined in the PineappleMapper gets called, the pineappleInterceptor is executed... that doesn't happen, on every server call, the bananainterceptor is invoked (via the "catch-all" ignoremapper).
I have a systemout in my bananainterceptor to see what url's it gets debug("BANANAInterceptor! URL="+request.getRequestURI());
but even when the URI is what i have configured, it prints out:
19:26:22,093 INFO [STDOUT] DEBUG PineappleInterceptor: PINEAPPLEInterceptor! URL=/konvalj/registry/apartments/list.htm
i have tried using variants on the url, for example "registry/apartments/list.htm" - nothing works.
Any input would be appreciated.
On a sidenote, does wildcards work?? i would love to map for example bananamapper with a url (*banana*) or similar.
Catchall
If you are looking for a catch-all, you should use DefaultAnnotationMapper with the higher order instead of IgnoreSelectedAnnotationHandlerMapping. My typical setup is I have 3 or 4 SelectedAnnotationHandlerMappings for different levels of security, and then a DefaultAnnotationMapper as a catch-all.
SelectedAnnotationHandlerMappings and IgnoreSelectedAnnotationHandlerMapping aren't really meant to work together.
Wild cards don't currently work, but that's not a bad idea. I can code that up for you next weekend if you find it useful.
not working
Scott,
I tried this plugin using the instuctions you provided and basically any url i put in the SelectedAnnotationHandlerMapping was intercepted. However any path not in just gave a 404. If I take your handler out everything works but nothing is intercepted? Any suggestions? Thanks.
DefaultAnnotationHandlerMapping
It sounds like you did not define a HandlerMapping for the other urls. All you need to do is define a DefaultAnnotationHandlerMapping like at the top of the page and set its order property to 1. The order property is important otherwise the SelectedAnnotationHandlerMapping will never get called.
Basically, the thought process here is to have the most restrictive HandlerMapping have order = 0, and then sequentially increment the order for each consecutive HandlerMapping thereafter. I have cases where I have 5-6 handler mappings to address SecurityContraints, etc.
source
Hi Scott,
this seems to be very useful for my current project. Unfortunately, there seems to be no sourcecode over at http://code.google.com/p/springplugins/. It would be nice of you if you could provide it.
cheers, stammi
Source Code
Hi Stammi,
Sorry for the late reply. I took a break from my website. Let me know if you are still interested in the source code and I will post it.
Best,
Scott
about the source
hi scott:
I am looking for the source code. It seems there is no source code from the google code.Could you commit your source code or email me a copy at mc02cxj#gmail.com. thanks a lot.
bonyfish