Implementing Clean URL in Struts

The web application created by using Struts framework can be easily identified by the URL patterns. Mostly all the Struts application have *.do or *.action URL depending on the version of Struts being used and the best practices that are followed. These URLs are less  search engine friendly as they reveal very little about the content. Hence it can be useful to implement a web application with clean URLs pattern such as /custormer/add or /profile/william. This can be achieved in Struts by modifying Web.xml and struts-config.xml files. Following is the ActionServlet entry that is normally made in Web.xml file in order to configure struts.
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
Code language: HTML, XML (xml)
Thus, whenever the client request comes, the container match the pattern *.do in the URL and invokes the ActionServlet class which handles the rest of flow in Struts application. In order to use clean URL, make following entry for ActionServlet in your Web.xml file.
<servlet> <servlet-name>action</servlet-name> <servlet-class> org.apache.struts.action.ActionServlet </servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>chainConfig</param-name> <param-value> org/apache/struts/tiles/chain-config.xml </param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- Extension mappings to static content --> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.png</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/index.jsp</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
Code language: HTML, XML (xml)
Please note that here the URL pattern that is mapped to ActionServlet class is not *.do and is / i.e. all the requests that comes will be routed to ActionServlet by the container. Also, URL patterns such as *.js, *.jpg, *.png, *.css etc are mapped to a servlet called default. This ensures that the static content are served to client without getting redirected to ActionServlet. Thus if you have other static content in your website, don’t forget to make an entry here and map it to default servlet. For example, I may have some *.zip files that I want to my users to download. Hence I will create an entry for *.zip and map it to default servlet in Web.xml file. Once this is done, all the requests (except for static content) will get routed to ActionServlet. Now, we will make normal entries for Action class in struts-config.xml file. Each entry will have a unique URL pattern that maps to an Action class.
<action path="/login" name="userBean" scope="request" validate="true" input="/index.jsp" type="net.viralpatel.sturts.cleanurl.LoginAction"> <forward name="success" path="/home" /> <forward name="fail" path="/index.jsp" /> </action> <action path="/home" name="userBean" scope="request" validate="true" input="/index.jsp" type="net.viralpatel.sturts.cleanurl.HomeAction"> <forward name="success" path="/home.jsp" /> <forward name="fail" path="/home.jsp" /> </action> <action path="/profile/save" name="profileForm" scope="request" validate="false" input="/profile.jsp" type="net.viralpatel.sturts.cleanurl.ProfileAction"> <forward name="success" path="/profile.jsp" /> <forward name="fail" path="/profile.jsp" /> </action>
Code language: HTML, XML (xml)
Thus, whenever client request for a URL /login, LoginAction will be invoked by Struts framework. It is sometimes desirable to achieve clean url where request parameters are passed. For example, in some application /profile/john will point to Profile page of user John and /profile/william will point to that of William. This can be achieved by using parametrized struts-config entries for actions. For example.
<action path="/profile/*" type="net.viralpatel.struts.cleanurl.ProfileAction" parameter="{1}"> <forward name="success" path="/profile.jsp" /> <forward name="fail" path="/profile.jsp" /> </action>
Code language: HTML, XML (xml)
We have mapped a URL pattern /profile/* to ProfileAction. Thus whenever client will request for pages such as /profile/john or /profile/william, ProfileAction will gets invoked by Struts. Also note that we have used a parameter=”{1}” attribute in <action> tag. This will pass whatever string that comes as * in /profile/* to Action class. This parameter can be fetched in Action class from mapping object of ActionMapping class which is passed as method argument in execute() method of Action.
public ActionForward process(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws NoRecordFoundException { String parameter = mapping.getParameter(); ... }
Code language: Java (java)
Also, more than one parameter can be passed into the action for URLs like /profile/john/friends or /profile/john/groups. Thus to acheive this, URL /profile/*/* is mapped to Action and parameter=”{1}${2}” attribute will be added to action tag. Once the parameter is retrived in Action class using mapping.getParameter(), it has to split using $ separator as $ is used to concatenate {1} and {2} arguments. Comments and queries invited :)
Get our Articles via Email. Enter your email address.

You may also like...

13 Comments

  1. Guru says:

    Hi,

    This was a very good article for struts developers to provide a search engine friendly urls.
    If the application has struts and spring, how can we provide the wildcard in spring action bean definitions.

  2. Hi Guru,
    I had not chance to add this functionality in a Strut-Spring based application. I will soon update this tutorial.
    Thanks

  3. Matt says:

    Hi,

    Thanks for the idea.
    I think your old links like “page.do?param=12” would not be fonctional anymore!
    Unless you duplicate actions in struts-config.xml.
    I made this implementation of cleaning Struts URLs to become more friendly by imposing a Filter that treats clean url’s and then redirects to the old Struts url.That worked smoothly.

    Thanks
    MS

  4. Thanks Matt for your comments.
    This technique can be applied if we are writing any application from scratch. But if we have to migrate an existing application, it becomes a little tedious.

  5. Hi, It was good reading your post! I’ve been hearing about John Beck’s program these days. My colleague also purchased the system to use it as a side business work.

  6. Madhukar says:

    Nice article, I had seen such clean URL mapping at work and wondered why they had used the wild card * to map URLs to action classes, now I know. Might not use it myself but good to know.

    Offtopic, ViralPatel I would like to see some more articles on Spring – thanks.

  7. Tuan says:

    Nice article, but when i use is my page lost the path of css or jquery. original css\mycss.css. jsp page recognize normally. but when i use /profile/john/friends i must redefine css or jquerrt link again looklike as ../../css/mycss.css could you please give my any solution.

  8. vinod says:

    hii viral , i want from u just aded some project in struts aand hibernate

  9. rameez says:

    Nice work. Thanks. But i have a doubt,can we handle dispatch action in this way?

  10. Tamas Fabian says:

    Hello!
    Nice article! I just have one question. How can we nicely/easily use clean URLs with html forms?
    Example: let’s say we have a search page with a input text box, and after searching on ‘table’, I would like to have the URL ‘xxx.com/search/table’? How would the form look like?
    With default struts URLs, it looks something like this:

    <html:form action="search.do">
      <input type="text" name="search">
      <input type="submit">
    </html:form>
    

  11. Barath R says:

    Exactly what I have been looking for .. The explanation was clear and perfect

  12. James says:

    Very nice! btw, is this also available for structs 1?

  13. Nitin says:

    is it possible to do url mapping using only jsp without servlet

Leave a Reply

Your email address will not be published. Required fields are marked *