| <!DOCTYPE html> |
| |
| |
| <!-- |
| | Generated by Apache Maven Doxia Site Renderer 2.0.0 from src/site/xdoc/howto/url-mapper-howto.xml at 10 Sep 2025 |
| | Rendered using Apache Maven Fluido Skin 2.1.0 |
| --> |
| <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <meta name="generator" content="Apache Maven Doxia Site Renderer 2.0.0" /> |
| <title>URL Mapper Howto – Apache Turbine</title> |
| <link rel="stylesheet" href="../css/apache-maven-fluido-2.1.0.min.css" /> |
| <link rel="stylesheet" href="../css/site.css" /> |
| <link rel="stylesheet" href="../css/print.css" media="print" /> |
| <script src="../js/apache-maven-fluido-2.1.0.min.js"></script> |
| <link rel="icon" type="image/png" sizes="48x48" href="https://apache.org/favicons/favicon.ico"> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <style>.github-fork-ribbon:before { background-color: orange; }</style> |
| </head> |
| <body> |
| <a class="github-fork-ribbon right-top" href="https://github.com/apache/turbine-build" data-ribbon="Fork me on GitHub">Fork me on GitHub</a> |
| <div class="container-fluid container-fluid-top"> |
| <header> |
| <div id="banner"> |
| <div class="pull-left"><div id="bannerLeft"><h1><a href="https://turbine.apache.org/"><img src="https://www.apache.org/img/feather_glyph_notm.png" style="width: 50px;" /> The Apache Turbine project</a></h1></div></div> |
| <div class="pull-right"><div id="bannerRight"><h1><a href="https://turbine.apache.org/"><img src="https://turbine.apache.org/images/logo.gif" alt="Apache Turbine" /></a></h1></div></div> |
| <div class="clear"><hr/></div> |
| </div> |
| |
| <div id="breadcrumbs"> |
| <ul class="breadcrumb"> |
| <li id="publishDate">Last Published: 01 Apr 2025<span class="divider">|</span> |
| </li> |
| <li id="projectVersion">Version: 7.1-SNAPSHOT</li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://turbine.apache.org/fulcrum/">Fulcrum</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://turbine.apache.org/">Turbine</a></li> |
| <li class="pull-right"><a href="https://www.apache.org">Apache</a></li> |
| </ul> |
| </div> |
| </header> |
| <div class="row-fluid"> |
| <header id="leftColumn" class="span2"> |
| <nav class="well sidebar-nav"> |
| <ul class="nav nav-list"> |
| <li class="nav-header">General Information</li> |
| <li><a href="../index.html">Overview</a></li> |
| <li><a href="../features.html">Features</a></li> |
| <li><a href="../fsd.html">Specification</a></li> |
| <li><a href="../getting-started.html">Getting Started</a></li> |
| <li><a href="../how-to-build.html">Howto Build Turbine</a></li> |
| <li><a href="../changes-report.html">Changes</a></li> |
| <li class="nav-header">Documentation</li> |
| <li><a href="../services/index.html"><span class="icon-chevron-right"></span>Services</a></li> |
| <li><a href="../howto/index.html"><span class="icon-chevron-down"></span>Howtos</a> |
| <ul class="nav nav-list"> |
| <li><a href="../howto/action-event-howto.html">Action Events Howto</a></li> |
| <li><a href="../howto/annotations.html">Annotations Howto</a></li> |
| <li><a href="../howto/configuration-howto.html">Configuration Howto</a></li> |
| <li><a href="../howto/extend-user-howto.html">Extend User Howto</a></li> |
| <li><a href="../howto/hibernate-howto.html">Hibernate OM Howto</a></li> |
| <li><a href="../howto/intake-howto.html">Intake Howto</a></li> |
| <li><a href="../howto/jsp-howto.html">JSP Howto</a></li> |
| <li><a href="../howto/migrate-from-2_1-howto.html">Migrating from 2.1 to 2.2</a></li> |
| <li><a href="../howto/migrate-from-2_2-howto.html">Migrating from 2.2 to 2.3</a></li> |
| <li><a href="../howto/migrate-from-2_3-howto.html">Migrating from 2.3 to 4.0</a></li> |
| <li><a href="../howto/migrate-from-4_0-howto.html">Migrating from 4.0 to 5.0</a></li> |
| <li><a href="../howto/pullmodel-howto.html">Pull Model Howto</a></li> |
| <li><a href="../howto/python-howto.html">Python Howto</a></li> |
| <li><a href="../howto/security-howto.html">Security Howto</a></li> |
| <li><a href="../howto/services-howto.html">Services Howto</a></li> |
| <li class="active"><a>URL Mapper Howto</a></li> |
| <li><a href="../howto/url-rewriting-howto.html">URL Rewriting Howto</a></li> |
| <li><a href="../howto/context-howto.html">Velocity Context Howto</a></li> |
| <li><a href="../howto/velocity-site-howto.html">Velocity Site Howto</a></li> |
| <li><a href="../howto/velocityonlylayout-howto.html">VelocityOnlyLayout Howto</a></li> |
| </ul></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/TURBINE">Wiki</a></li> |
| <li><a href="../apidocs/index.html">JavaDocs</a></li> |
| <li class="nav-header">Development</li> |
| <li><a href="../proposals.html">Proposals</a></li> |
| <li><a href="../how-to-help.html">How To Help</a></li> |
| <li><a href="../todo.html">Todo</a></li> |
| <li class="nav-header">Project Documentation</li> |
| <li><a href="../project-info.html"><span class="icon-chevron-right"></span>Project Information</a></li> |
| <li><a href="../project-reports.html"><span class="icon-chevron-right"></span>Project Reports</a></li> |
| <li class="nav-header">Apache</li> |
| <li><a href="https://www.apache.org/">Apache Website</a></li> |
| <li><a href="https://www.apache.org/licenses/">License</a></li> |
| <li><a href="https://www.apache.org/foundation/how-it-works.html">How the ASF works</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li><a href="https://www.apache.org/security/">Security</a></li> |
| </ul> |
| </nav> |
| <div class="well sidebar-nav"> |
| <form id="search-form" action="https://www.google.com/search" method="get" > |
| <input value="http://turbine.apache.org/turbine/turbine-7-0" name="sitesearch" type="hidden" /> |
| <input class="search-query" name="q" id="query" type="text" placeholder="Search with Google..." /> |
| </form> |
| <div id="poweredBy"> |
| <div class="clear"></div> |
| <div class="clear"></div> |
| <a href="https://maven.apache.org/" class="builtBy" target="_blank"><img class="builtBy" alt="Built by Maven" src="../images/logos/maven-feather.png" /></a> |
| </div> |
| </div> |
| </header> |
| <main id="bodyColumn" class="span10"> |
| |
| |
| |
| |
| <section><a id="Introduction"></a> |
| <h1>Introduction</h1> |
| |
| |
| <p> |
| Unaltered Turbine URLs may look like this: |
| <code>http://www.foo.com:8080/CONTEXT/servlet/MAPPING/template/Foo.vm</code>.<br /> |
| But you want shorter URLs? Maybe this URL would suit you better: |
| <code>http://www.foo.com:8080/CONTEXT/servlet/beautiful/world</code> |
| </p> |
| |
| This HOWTO describes, how you can control the pathinfo or query part of a url (behind the webapproot and the context) and the context with a mapping (routing) file |
| defined in xml, json or yaml format to become more simplified or beautiful! |
| |
| </section> |
| |
| <section><a id="Turbine_URLMapper_Configuration"></a> |
| <h1>Turbine URLMapper Configuration</h1> |
| |
| |
| <p> |
| You need to |
| </p> |
| <ul> |
| |
| <li>register the URL Mapper service in turbine configuration (TR.properties) </li> |
| |
| <li>register the valve in the pipeline (turbine-classic-pipeline.xml)</li> |
| </ul> |
| |
| |
| |
| |
| <p>Consider the following example configuration: |
| |
| MappedTemplateLink is for now optional, you can add it as a separate tool or just replace the existing TemplateLink. |
| </p> |
| |
| |
| <pre class="prettyprint"><code> |
| # ------------------------------------------------------------------- |
| # |
| # U R L M A P P E R S E R V I C E |
| # |
| # ------------------------------------------------------------------- |
| |
| # required |
| services.URLMapperService.classname=org.apache.turbine.services.urlmapper.TurbineURLMapperService |
| |
| # configFile is required here! xml, json and yml supported as extension. |
| services.URLMapperService.configFile = /conf/turbine-url-mapping.xml |
| |
| # new mapper (optional) |
| tool.request.mlink=org.apache.turbine.services.urlmapper.MappedTemplateLink |
| # tool.request.jlink= org.apache.turbine.services.pull.tools.TemplateLink |
| </code></pre> |
| |
| |
| <p>To resolve a provided / mapped URL add the valve into pipeline (pipeline.default.descriptor = /conf/turbine-classic-pipeline.xml). |
| </p> |
| |
| |
| <pre class="prettyprint"><code> |
| <valves> |
| <valve>org.apache.turbine.services.urlmapper.URLMapperValve</valve> |
| ... |
| |
| </code></pre> |
| |
| |
| <p>This will check if the provided URL matches any pattern, resolves it given in the path or implicitly as defined in |
| |
| the URLMapperService's configfile.</p> |
| |
| </section> |
| |
| <section><a id="Define_your_patterns"></a> |
| <h1>Define your patterns</h1> |
| |
| |
| <p>The URL Mapping Mechanism uses a well defined pattern format. |
| The pattern format scheme is defined as follows, e.g. in JSON:</p> |
| |
| |
| <pre class="prettyprint"><code> |
| "pattern": "/(?<webAppRoot>[.\\-\\w]+)/(?<contextPath>\\w+)/(?<resolvableParam>\\w+)/beautifulname" |
| </code></pre> |
| |
| |
| <p>That is <strong>resolvableParam</strong> is just a specific parameter name or key, which should be resolved after the context slash and before the next URL part, which starts with "/beatifulname". |
| |
| It has to be set like this</p> |
| |
| |
| <pre class="prettyprint"><code> |
| /(?<resolvableParam>\\w+) |
| </code></pre> |
| |
| Technically this isa non matching named group, with the group name <strong>resolvableParam</strong> and |
| |
| in this case a sequence of alphabetical characters with minimal length of 1. |
| |
| The same is true for the predefined <strong>webAppRoot</strong> and <strong>contextPath</strong>. |
| |
| |
| <p>Another condition to be met, is that the parameter name must follow the "Java Named Group pattern characters restriction":</p> |
| |
| |
| <pre class="prettyprint"><code> |
| NAMED_GROUPS_PATTERN = Pattern.compile("(?<([a-zA-Z][a-zA-Z0-9]*)>.+?)"); |
| </code></pre> |
| |
| |
| <p> |
| Any parameter is resolved as a <i>group name</i> |
| (<a href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html" class="externalLink">Java Pattern->Groups and Capturing->Group name</a>). |
| |
| These group names are predefined (symbolic group name)): |
| |
| </p> |
| <ul> |
| <li><strong><webAppRoot></strong></li> |
| <li><strong><contextPath></strong></li></ul> |
| |
| Be aware, that this does not allow replacing parameters containing other characters (e.g underscore or hyphens). You may use implicit parameter matching. |
| |
| Following is an example for a configuration : |
| |
| |
| |
| <pre class="prettyprint"><code> |
| <url-mapping name="default"> |
| <maps> |
| <map> |
| <pattern>/(?&lt;webAppRoot&gt;[.\\-\\w]+)/(?&lt;contextPath&gt;\w+)/book/(?&lt;bookId&gt;\d+)</pattern> |
| <implicit-parameters> |
| <parameter key="template">Book.vm</parameter> |
| <parameter key="detail">0</parameter> |
| </implicit-parameters> |
| </map> |
| ... |
| </code></pre> |
| |
| |
| <p>Three parameters are evaluated: |
| |
| </p> |
| <ul> |
| <li>a parameter name <strong>template</strong> and value <strong>Book.vm</strong></li> |
| |
| <li>a parameter <strong>detail</strong> and value <strong>0</strong></li> |
| |
| <li>a parameter <strong>bookId</strong> with <i>any</i> value, e.g. <strong>4</strong></li> |
| </ul> |
| This will be converted, if matched, to an URL like <strong>/book/4</strong>. |
| The pattern uses type restrictions for the value, e.g. number for the bookId and a extended character set for the webAppRoot, which will be applied in (back resolving) <strong>mapFromURL</strong>. |
| |
| |
| |
| <p>Another example in <strong>JSON</strong> format, which is much more readable, if not viewing in a browser is here (showing a shortened URL by replacing two parameters):</p> |
| |
| |
| <pre class="prettyprint"><code> |
| { |
| "name": "default", |
| "maps": [ |
| { |
| "pattern": "/(?<webAppRoot>[\\w]+)/(?<contextPath>\\w+)/register", |
| "implicit-parameters": { |
| "page": "Register", |
| "role": "anon" |
| } |
| }, |
| ... |
| </code></pre> |
| |
| </section> |
| |
| <section><a id="Service_Description"></a> |
| <h1>Service Description</h1> |
| |
| |
| <p>The main methods of the service <strong>TurbineURLMapperService</strong> are</p> |
| |
| |
| <ul> |
| |
| <li><strong>mapToUrl</strong>, which as the Javadoc explains "maps a set of parameters (contained in TurbineURI PathInfo and QueryData) to a TurbineURIs"</li> |
| |
| <li><strong>mapFromUrl</strong>, which "maps a simplified URL to a set of parameters"</li> |
| </ul> |
| |
| <section><a id="Matrix"></a> |
| <h2>Matrix</h2> |
| |
| <table class="table table-striped"> |
| |
| <tr class="a"> |
| |
| <th colspan="6">Turbine URL Mapper Model</th> |
| </tr> |
| |
| <tr class="b"> |
| |
| <th>Mechanism</th> |
| <th>Method</th> |
| <th>Pattern</th> |
| <th>Implicit Param</th> |
| <th>Override Param</th> |
| <th>Ignore Param</th> |
| </tr> |
| |
| |
| <tr class="a"> |
| <th>Converts Parameterized URL to simplified URL</th> |
| <th>mapToUrl</th> |
| <td> |
| "Match Group Name": The pattern of the target URL after evaluation of parameters. If a group name is set, a matching parameter key must be provided and the value will replace the group name in the target URL.</td> |
| |
| <td>"Exact Filter", "Reduce": If a parameter key is is set implicitely, both key and value must exactly matched by a parameter pair in the provided (unmapped) URI. It will then be removed</td> |
| |
| <td>- An override could be achieved by hard coding it in the pattern and filterign in implicit param. |
| On the other hand you can then ignore the parameter</td> |
| |
| <td>The parameter will be removed from the required parameter key set and also from the target URL if it is provided as a group name</td></tr> |
| |
| |
| <tr class="b"> |
| <th>Resolves URL to Params for evaluating by the backend</th> |
| <th>mapFromUrl</th> |
| <td> |
| The pattern of the URL to be matched to evaluate parameter resolving</td> |
| |
| <td>Param key/value will be set implicitely</td> |
| |
| <td>Overrides (provided) URL parameter with provided value</td> |
| |
| <td>will remove parameter key/value from result parameter list, even if provided as capturing group name</td></tr> |
| </table> |
| </section> |
| |
| |
| <p>N.B. Symbolic group names <i>webAppRoot</i> and <i>context</i> could not be ignored or overridden!</p> |
| |
| |
| </section> |
| <section><a id="Usage"></a> |
| <h1>Usage</h1> |
| |
| |
| <p> |
| Use the methods getRelative or getAbsoluteLink of the provided convenience class MappedTemplateLink class (of type TemplateLink) |
| in a velocity template like this: |
| </p> |
| |
| |
| <pre class="prettyprint"><code> |
| |
| $mlink.addPathInfo("world","nice").getRelativeLink() |
| ## should result into a URL: /beautiful/world |
| |
| </code></pre> |
| |
| |
| <p> |
| |
| <p>Alternatively you can use the service explicitely in Java, e.g. in a Java Action or other class if you inject the URLMapperService (or provide this in a shared controller class).</p> |
| |
| |
| <pre class="prettyprint"><code> |
| |
| // inside any assembler you may alternatively use annotation |
| // @TurbineService( "URLMapperService" ) urlMapper; |
| |
| URLMapperService urlMapper = (URLMapperService) TurbineServices.getInstance().getService(URLMapperService.SERVICE_NAME); |
| |
| // Any turbineURI ..e.g. from PoolService or |
| TurbineURI uri ... |
| |
| urlMapper.mapToURL( uri ); |
| |
| |
| // use it, e.g by putting it into a velocity context (org.apache.velocity.context.Context( |
| context.put("myLink", link); |
| |
| </code></pre> |
| |
| |
| More examples ... |
| |
| |
| |
| </section> |
| |
| |
| </main> |
| </div> |
| </div> |
| <hr/> |
| <footer> |
| <div class="container-fluid"> |
| <div class="row-fluid"> |
| <p>© 2000–2025 |
| <a href="https://www.apache.org/">The Apache Software Foundation</a> |
| </p> |
| </div> |
| </div> |
| </footer> |
| </body> |
| </html> |