blob: e5d611205bb864ccc06730530a59887ffa7e8561 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="Date-Revision-yyyymmdd" content="20140918"/>
<meta http-equiv="Content-Language" content="en"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>ActionMapper</title>
<link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/custom.css" rel="stylesheet">
<link href="/css/syntax.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/community.js"></script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '41']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body>
<a href="https://github.com/apache/struts" class="github-ribbon">
<img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1">
</a>
<header>
<nav>
<div role="navigation" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle">
Menu
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a>
</div>
<div id="struts-menu" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Home<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/index.html">Welcome</a></li>
<li><a href="/download.cgi">Download</a></li>
<li><a href="/releases.html">Releases</a></li>
<li><a href="/announce-2023.html">Announcements</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Support<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/mail.html">User Mailing List</a></li>
<li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li>
<li><a href="/security.html">Reporting Security Issues</a></li>
<li><a href="/commercial-support.html">Commercial Support</a></li>
<li class="divider"></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li>
<li class="divider"></li>
<li><a href="/maven/project-info.html">Maven Project Info</a></li>
<li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li>
<li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Documentation<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/birdseye.html">Birds Eye</a></li>
<li><a href="/primer.html">Key Technologies</a></li>
<li><a href="/kickstart.html">Kickstart FAQ</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li>
<li class="divider"></li>
<li><a href="/getting-started/">Getting Started</a></li>
<li><a href="/security/">Security Guide</a></li>
<li><a href="/core-developers/">Core Developers Guide</a></li>
<li><a href="/tag-developers/">Tag Developers Guide</a></li>
<li><a href="/maven-archetypes/">Maven Archetypes</a></li>
<li><a href="/plugins/">Plugins</a></li>
<li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li>
<li><a href="/tag-developers/tag-reference.html">Tag reference</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li>
<li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Contributing<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/youatstruts.html">You at Struts</a></li>
<li><a href="/helping.html">How to Help FAQ</a></li>
<li><a href="/dev-mail.html">Development Lists</a></li>
<li class="divider"></li>
<li><a href="/submitting-patches.html">Submitting patches</a></li>
<li><a href="/builds.html">Source Code and Builds</a></li>
<li><a href="/coding-standards.html">Coding standards</a></li>
<li><a href="/contributors/">Contributors Guide</a></li>
<li class="divider"></li>
<li><a href="/release-guidelines.html">Release Guidelines</a></li>
<li><a href="/bylaws.html">PMC Charter</a></li>
<li><a href="/volunteers.html">Volunteers</a></li>
<li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li>
<li><a href="/updating-website.html">Updating the website</a></li>
</ul>
</li>
<li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li>
</ul>
</div>
</div>
</div>
</nav>
</header>
<article class="container">
<section class="col-md-12">
<a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/core-developers/action-mapper.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="index.html" title="back to Core Developers Guide"><< back to Core Developers Guide</a>
<h1 class="no_toc" id="actionmapper">ActionMapper</h1>
<ul id="markdown-toc">
<li><a href="#description" id="markdown-toc-description">Description</a></li>
<li><a href="#defaultactionmapper" id="markdown-toc-defaultactionmapper">DefaultActionMapper</a> <ul>
<li><a href="#method-prefix" id="markdown-toc-method-prefix">Method prefix</a></li>
<li><a href="#action-prefix" id="markdown-toc-action-prefix">Action prefix</a></li>
<li><a href="#allowed-action-name-regex" id="markdown-toc-allowed-action-name-regex">Allowed action name RegEx</a></li>
<li><a href="#allowed-method-name-regex" id="markdown-toc-allowed-method-name-regex">Allowed method name RegEx</a></li>
</ul>
</li>
<li><a href="#custom-actionmapper" id="markdown-toc-custom-actionmapper">Custom ActionMapper</a></li>
<li><a href="#compositeactionmapper" id="markdown-toc-compositeactionmapper">CompositeActionMapper</a></li>
<li><a href="#prefixbasedactionmapper" id="markdown-toc-prefixbasedactionmapper">PrefixBasedActionMapper</a> <ul>
<li><a href="#prefixbasedactionproxyfactory" id="markdown-toc-prefixbasedactionproxyfactory">PrefixBasedActionProxyFactory</a></li>
</ul>
</li>
<li><a href="#actionmapper-and-actionmapping-objects" id="markdown-toc-actionmapper-and-actionmapping-objects">ActionMapper and ActionMapping objects</a></li>
<li><a href="#customize" id="markdown-toc-customize">Customize</a></li>
</ul>
<h2 id="description">Description</h2>
<p>The ActionMapper interface provides a mapping between HTTP requests and action invocation requests and vice-versa.</p>
<p>When given an HttpServletRequest, the ActionMapper may return null if no action invocation request matches or it may
return an <code class="language-plaintext highlighter-rouge">ActionMapping</code> that describes an action invocation for the framework to try.</p>
<p>The ActionMapper is not required to guarantee that the <code class="language-plaintext highlighter-rouge">ActionMapping</code> returned be a real action or otherwise ensure
a valid request. Accordingly, most ActionMappers do not need to consult the Struts configuration just to determine if
a request should be mapped.</p>
<p>Just as requests can be mapped from HTTP to an action invocation, the opposite is true as well. However, because HTTP
requests (when shown in HTTP responses) must be in String form, a String is returned rather than an actual request object.</p>
<h2 id="defaultactionmapper">DefaultActionMapper</h2>
<p>Default action mapper implementation, using the standard <code class="language-plaintext highlighter-rouge">*.[ext]</code> (where ext usually <strong>action</strong>) pattern. The extension
is looked up from the Struts configuration key <code class="language-plaintext highlighter-rouge">struts.action.extension</code>.</p>
<p>To help with dealing with buttons and other related requirements, this mapper (and other <code class="language-plaintext highlighter-rouge">ActionMapper</code>s, we hope) has
the ability to name a button with some predefined prefix and have that button name alter the execution behaviour.</p>
<p>The four prefixes are:</p>
<ul>
<li>Method prefix - <code class="language-plaintext highlighter-rouge">method:default</code></li>
<li>Action prefix - <code class="language-plaintext highlighter-rouge">action:dashboard</code></li>
</ul>
<p>In addition to these four prefixes, this mapper also understands the action naming pattern of <code class="language-plaintext highlighter-rouge">foo!bar</code> in either
the extension form (eg: <code class="language-plaintext highlighter-rouge">foo!bar.action</code>) or in the prefix form (eg: <code class="language-plaintext highlighter-rouge">action:foo!bar</code>). This syntax tells this mapper
to map to the action named <code class="language-plaintext highlighter-rouge">foo</code> and the method <code class="language-plaintext highlighter-rouge">bar</code>.</p>
<blockquote>
<p>NOTE: By default support for the <code class="language-plaintext highlighter-rouge">action:</code> prefix has been disabled since Struts 2.3.15.3, please use the below
constant to enable it:</p>
<ul>
<li>using <code class="language-plaintext highlighter-rouge">struts.properties</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struts.mapper.action.prefix.enabled=true
</code></pre></div> </div>
</li>
<li>or using <code class="language-plaintext highlighter-rouge">struts.xml</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;constant name="struts.mapper.action.prefix.enabled" value="true"/&gt;
</code></pre></div> </div>
</li>
</ul>
<p>See <a href="https://cwiki.apache.org/confluence/display/WW/S2-018">S2-018</a> for more details.</p>
</blockquote>
<h3 id="method-prefix">Method prefix</h3>
<p>With method-prefix, instead of calling baz action’s <code class="language-plaintext highlighter-rouge">execute()</code> method (by default if it isn’t overridden in <code class="language-plaintext highlighter-rouge">struts.xml</code>
to be something else), the baz action’s <code class="language-plaintext highlighter-rouge">anotherMethod()</code> will be called. A very elegant way determine which button is
clicked. Alternatively, one would have submit button set a particular value on the action when clicked, and the <code class="language-plaintext highlighter-rouge">execute()</code>
method decides on what to do with the setted value depending on which button is clicked.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:form</span> <span class="na">action=</span><span class="s">"baz"</span><span class="nt">&gt;</span>
<span class="nt">&lt;s:textfield</span> <span class="na">label=</span><span class="s">"Enter your name"</span> <span class="na">name=</span><span class="s">"person.name"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:submit</span> <span class="na">value=</span><span class="s">"Create person"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:submit</span> <span class="na">method=</span><span class="s">"anotherMethod"</span> <span class="na">value=</span><span class="s">"Cancel"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/s:form&gt;</span>
</code></pre></div></div>
<h3 id="action-prefix">Action prefix</h3>
<p>With action-prefix, instead of executing baz action’s <code class="language-plaintext highlighter-rouge">execute()</code> method (by default if it isn’t overridden in <code class="language-plaintext highlighter-rouge">struts.xml</code>
to be something else), the anotherAction action’s <code class="language-plaintext highlighter-rouge">execute()</code> method (assuming again if it isn’t overridden with something
else in <code class="language-plaintext highlighter-rouge">struts.xml</code>) will be executed.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:form</span> <span class="na">action=</span><span class="s">"baz"</span><span class="nt">&gt;</span>
<span class="nt">&lt;s:textfield</span> <span class="na">label=</span><span class="s">"Enter your name"</span> <span class="na">name=</span><span class="s">"person.name"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:submit</span> <span class="na">value=</span><span class="s">"Create person"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:submit</span> <span class="na">action=</span><span class="s">"anotherAction"</span> <span class="na">value=</span><span class="s">"Cancel"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/s:form&gt;</span>
</code></pre></div></div>
<h3 id="allowed-action-name-regex">Allowed action name RegEx</h3>
<p>By default the mapper will check if extracted action name matches provided RegEx, i.e. <code class="language-plaintext highlighter-rouge">[a-zA-Z0-9._!/-]*</code>. You redefine
this RegEx by defining a constant in <code class="language-plaintext highlighter-rouge">struts.xml</code> named <code class="language-plaintext highlighter-rouge">struts.allowed.action.names</code>. If action name doesn’t match
the RegEx a default action name will be returned which is defined as <code class="language-plaintext highlighter-rouge">index</code>. You can also redefine this by specifying
constant <code class="language-plaintext highlighter-rouge">struts.default.action.name</code> in <code class="language-plaintext highlighter-rouge">struts.xml</code>.</p>
<h3 id="allowed-method-name-regex">Allowed method name RegEx</h3>
<p>The same logic as above is used for extracted methods, the default RegEx (<code class="language-plaintext highlighter-rouge">[a-zA-Z_]*[0-9]*</code>) is used to check if method
is allowed, you can change this by setting constant <code class="language-plaintext highlighter-rouge">struts.allowed.method.names</code> in <code class="language-plaintext highlighter-rouge">struts.xml</code>. If method doesn’t match
the RegEx a default method is returned, i.e. <code class="language-plaintext highlighter-rouge">execute</code>. This can be changed by defining constant <code class="language-plaintext highlighter-rouge">struts.default.method.name</code>
in <code class="language-plaintext highlighter-rouge">struts.xml</code>.</p>
<p>Please note that this functionality only works when <a href="action-configuration.html#dynamic-method-invocation">Dynamic Method Invocation</a>
is enabled.</p>
<h2 id="custom-actionmapper">Custom ActionMapper</h2>
<p>You can define your own ActionMapper by implementing <code class="language-plaintext highlighter-rouge">org.apache.struts2.dispatcher.mapper.ActionMapper</code> then configuring
Struts 2 to use the new class in <code class="language-plaintext highlighter-rouge">struts.xml</code></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.dispatcher.mapper.ActionMapper"</span> <span class="na">name=</span><span class="s">"mymapper"</span> <span class="na">class=</span><span class="s">"com.mycompany.myapp.MyActionMapper"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.class"</span> <span class="na">value=</span><span class="s">"mymapper"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<p>Possible uses of the ActionMapper include defining your own, cleaner namespaces, such as URLs like <strong>/person/1</strong>, which
would be similar to a request to <strong>/getPerson.action?personID=1</strong> using the DefaultActionMapper.</p>
<h2 id="compositeactionmapper">CompositeActionMapper</h2>
<p>A composite action mapper that is capable of delegating to a series of if the former failed to obtained a valid
<code class="language-plaintext highlighter-rouge">ActionMapping</code> or uri.</p>
<p>It is configured through <a href="struts-xml">struts.xml</a>. For example, with the following entries in <code class="language-plaintext highlighter-rouge">struts.xml</code></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.class"</span> <span class="na">value=</span><span class="s">"composite"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.composite"</span> <span class="na">value=</span><span class="s">"struts,restful,restful2"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<p>When <code class="language-plaintext highlighter-rouge">CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)</code> or <code class="language-plaintext highlighter-rouge">CompositeActionMapper#getUriFromActionMapping(ActionMapping)</code>
is invoked, <code class="language-plaintext highlighter-rouge">CompositeActionMapper</code> would go through these s in sequence starting from identified by <code class="language-plaintext highlighter-rouge">struts.mapper.composite.1</code>,
followed by <code class="language-plaintext highlighter-rouge">struts.mapper.composite.2</code> and finally <code class="language-plaintext highlighter-rouge">struts.mapper.composite.3</code> (in this case) until either one of the return
a valid result (not null) or it runs out of in which case it will just return null for both
<code class="language-plaintext highlighter-rouge">CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)</code> and <code class="language-plaintext highlighter-rouge">CompositeActionMapper#getUriFromActionMapping(ActionMapping)</code>
methods.</p>
<p>For example with the following in struts.xml:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.class"</span> <span class="na">value=</span><span class="s">"composite"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.composite"</span> <span class="na">value=</span><span class="s">"struts,restful"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">CompositeActionMapper</code> will be configured with 2 ActionMapper, namely “struts” which is <code class="language-plaintext highlighter-rouge">org.apache.struts2.dispatcher.mapper.DefaultActionMapper</code>
and “restful” which is <code class="language-plaintext highlighter-rouge">org.apache.struts2.dispatcher.mapper.RestfulActionMapper</code>.</p>
<p><code class="language-plaintext highlighter-rouge">CompositeActionMapper</code> would consult each of them in order described above.</p>
<h2 id="prefixbasedactionmapper">PrefixBasedActionMapper</h2>
<p>A prefix based action mapper that is capable of delegating to other <code class="language-plaintext highlighter-rouge">ActionMapper</code>s based on the request’s prefix.
It is configured through <code class="language-plaintext highlighter-rouge">struts.xml</code>. For example, with the following entries in <code class="language-plaintext highlighter-rouge">struts.xml</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.class"</span> <span class="na">value=</span><span class="s">"prefix"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.prefixMapping"</span> <span class="na">value=</span><span class="s">"
/communities:pseudoRestful,
/communityTags:pseudoRestful,
/events:pseudoRestful,
/mediaList:pseudoRestful,
/users:pseudoRestful,
/community:struts,
/communityTag:struts,
/event:struts,
/media:struts,
/user:struts,
:struts
"</span><span class="nt">/&gt;</span>
</code></pre></div></div>
<p>When <code class="language-plaintext highlighter-rouge">PrefixBasedActionMapper#getMapping(HttpServletRequest, ConfigurationManager)</code> or <code class="language-plaintext highlighter-rouge">PrefixBasedActionMapper#getUriFromActionMapping(ActionMapping)</code>
is invoked, <code class="language-plaintext highlighter-rouge">PrefixBasedActionMapper</code> will check each possible prefix (url prefix terminating just before a <code class="language-plaintext highlighter-rouge">/</code>) to find
the most specific <code class="language-plaintext highlighter-rouge">ActionMapper</code> that returns a mapping when asked to map the request. If none are found, null is returned
for both <code class="language-plaintext highlighter-rouge">PrefixBasedActionMapper#getMapping(HttpServletRequest, ConfigurationManager)</code> and
<code class="language-plaintext highlighter-rouge">PrefixBasedActionMapper#getUriFromActionMapping(ActionMapping)</code> methods.</p>
<h3 id="prefixbasedactionproxyfactory">PrefixBasedActionProxyFactory</h3>
<p>Prefix based factory should be used with <code class="language-plaintext highlighter-rouge">org.apache.struts2.dispatcher.mapper.PrefixBasedActionMapper</code> to use
appropriate <code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.ActionProxyFactory</code> connected with given <code class="language-plaintext highlighter-rouge">org.apache.struts2.dispatcher.mapper.ActionMapper</code>.</p>
<p>Add below entry to <code class="language-plaintext highlighter-rouge">struts.xml</code> to enable the factory:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.actionProxyFactory"</span> <span class="na">value=</span><span class="s">"prefix"</span><span class="nt">/&gt;</span>
</code></pre></div></div>
<p>The factory will use the same set of patterns as defined with:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.prefixMapping"</span> <span class="na">value=</span><span class="s">"..."</span><span class="nt">/&gt;</span>
</code></pre></div></div>
<h2 id="actionmapper-and-actionmapping-objects">ActionMapper and ActionMapping objects</h2>
<p>The ActionMapper fetches the ActionMapping object corresponding to a given request. Essentially, the ActionMapping is
a data transfer object that collects together details such as the Action class and method to execute. The mapping is
utilized by the Dispatcher and various user interface components. It is customizable through <code class="language-plaintext highlighter-rouge">struts.mapper.class</code>
entry in <code class="language-plaintext highlighter-rouge">struts.xml</code>. Note that the value of this constant is the name of the bean of the new mapper.</p>
<h2 id="customize">Customize</h2>
<p>Custom ActionMapper must implement ActionMapper interface and have a default constructor.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;bean</span> <span class="na">type=</span><span class="s">"org.apache.struts2.dispatcher.mapper.ActionMapper"</span> <span class="na">name=</span><span class="s">"mymapper"</span> <span class="na">class=</span><span class="s">"com.mycompany.myapp.MyActionMapper"</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.mapper.class"</span> <span class="na">value=</span><span class="s">"mymapper"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyCustomActionMapper</span> <span class="kd">implements</span> <span class="nc">ActionMapper</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nc">ActionMapping</span> <span class="nf">getMapping</span><span class="o">(</span><span class="nc">HttpServletRequest</span> <span class="n">request</span><span class="o">,</span>
<span class="nc">ConfigurationManager</span> <span class="n">configManager</span><span class="o">)</span> <span class="o">{</span>
<span class="o">....</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">getUriFromActionMapping</span><span class="o">(</span><span class="nc">ActionMapping</span> <span class="n">mapping</span><span class="o">)</span> <span class="o">{</span>
<span class="o">....</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<blockquote>
<p>See also: <a href="restful-action-mapper">RestfulActionMapper</a></p>
</blockquote>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation. All Rights Reserved.
</div>
<div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div>
</footer>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
<script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script>
<div id="fb-root"></div>
<script>(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</body>
</html>