Dynamic host-based mount on Wicket
I have an unusual requirement for Wicket. I chose Wicket because I will make my website design-centric and it's URL-mounting features are simply the best for SEO. Unfortunatelly, I found a bump.
I want to create a site with different designs for different hosts. This site will have some host aliases (let's say: "abc.com", "abc.com.br", "abc.com.pl") - all pointing to the same codebase (i.e. the same tomcat host instance). That part is already up and running, thanks to Tomcat and a custom ResourceStreamLocator.
Now, I want different mounts for different hosts. This means "abc.c开发者_如何学Com/page1", "abc.com.br/pagina1" and "abc.com.pl/strona1" must point to the same "Page1.class" page. Users from "abc.com" cannot see "abc.com/pagina1" or "abc.com/strona1".
How can I do this "dynamic host-based mount"?
Please notice I'm NOT talking about i18n. I'm using this example because it's simple to explan.
Isn't your solution give you multiple webapp instances backed by the same codebase though? If it is, I don't think there's anything you should do.
I don't know if there's an out-of-the-box solution to do this from within a single webapp, but if there isn't, this is what I'd do.
The first thing is that for this to work seamlessly you'll need separate application instances.
How to achieve this?
Extend the WicketFilter
class (this is the servlet filter that links the servlet container to Wicket). This class has a field called webApplication
, which you'll have to replace with a vhostname-application map. (This also means copying the entire code of the doFilter()
method, so it's not a very neat solution. It's more of a hack. Anyway)
This should do the trick, you'll have one separate application instance per vhost.
But your session variables will still be shared between the sites, which is a bad idea. (In practice your browser won't send cookies issued by one vhost to another vhost, but if the session id is put in the url, you can cross vhosts this way.)
To avoid sessions getting mixed up, you'll have to change the getFilterConfig()
method too, so that it returns a different config to different application instances. (Filter name is the attribute that is used for session variable prefixing.)
I'm not 100% sure this will work, I haven't tried it but if you can't find a better (and more importantly, cleaner) solution, this is your only option.
This requirement is quite easy in Wicket 1.5. You just need to setup custom root request mapper which will receive the request before all predefined (system) request mappers. This way you can check the request url and return the respective page or let the default mappers process the url if it doesn't match any of your mappings.
See Application#setRootRequestMapper() and IRequestMapper interface. HttpsMapper and CryptoMapper work this way.
Another way to do the same is to #mount(IRequestMapper) with very high IRequestMapper#getCompatibilityScore). This score is used by Wicket to decide which mapper to use with the default root mapper.
精彩评论