Convention Over Configuration (CoC) is a term often bandied
around by Ruby on Rails followers. From the wikipedia it’s
defined as “the programmer only needs to specifically configure what
is unconventional.” Very sensible advice indeed, although it’s not without its problems. For example the use of InternalResourceViewResolver effectively lets programmers forget about configuring resource views for incoming URLs, and instead
rely on the convention of mapping to a like-named view (it extracts
the view name from the URL). In fact, the MultiActionController is a type of CoC too - you don’t have to configure an action name; Spring tries to automatically invoke a like-named method on the controller class based on the URL. (The MethodNameResolver actually.) These two essentially enforce the convention of automatically selecting a view, and a method in a controller class respectively.
Now let’s look at an example of CoC: ControllerClassNameHandlerMapping. This enforces the convention of automatically selecting a controller.
BackgroundAn URL Mapper has to map incoming URL requests to particular controllers. Typically we have to configure the URL mapper with each new controller that we add. Turning this on its head, we want to use CoC so that the convention is that the correct controller is automatically selected if it’s registered, without any configuration.
How to do itimply use the ControllerClassNameHandlerMapping as your URL mapper in your dispatch-servlet.xml configuration file. For example:
<bean id="urlMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"> </bean>Define your controllers as usual. For example, I have this:
<bean id="commandController" class="com.memestorm.web.CommandController"> </bean>That’s it. You don’t have to wire your controllers to URLs, this is now automated. Now instead of explicitly configuring mappings between URLs and controllers, you can rely on the convention, which is to take the ClassUtils.getShortName() name of the controller class, remove the “Controller” suffix if it exists and the cap, and use the result as a mapping. For example our CommandController would be mapped to /command/.
For MultiActionController controllers it works slightly differently. In this case, say for our DispatchController example, it will map /dispatch/* to the controller. (Note the extra wildcard).
Now you can concentrate on writing your controllers and action methods. Everything will be automatically wired in; nice.
How it worksIt’s actually dead simple. The ControllerClassNameHandlerMapping class simply iterates through the application context looking for beans of type Controller, adding them to the mapping as described earlier.