All right, I pulled some time from work and investigate how the framework does this. It turns out that Struts 2 has a implementation to serve static content. This is configured in the configuration file struts.properties by the property: struts.serve.static.
If that property is set to true any static content (javascript, css, images, etc) in your JSP page that starts with the path /struts/ or with /static/ will be served by the struts FilterDispatcher and other class called the DefaultStaticContentLoader.
For example:
<script language="JavaScript" type="text/javascript" src="struts/someScript.js"></script>
<script language="JavaScript" type="text/javascript" src="static/otherScript.js"></script>
Both of this javascript files will be served by the Filter and the ContentLoader.
By default the ContentLoader class will lookup the requested file only in two folders inside the Struts 2 core JAR: org.apache.struts2.static and template.
Now there's a way for you to make the ContentLoader to lookup in other places and it's configured in the web.xml file in the filter params like this:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>packages</param-name>
<param-value>insert.your.package.with.static.content.here</param-value>
</init-param>
</filter>
It took me a long time to find this, there is not much information about this feature. If you would like to read the documentation for this it's in the Struts2 API in the FilterDispacher class here right where it says "Serving static content".
Hope you'll find it useful, to me it's a great feature and it's very well implemented.