How to navigate to the detailed access action based on the request path in STRUTS2

Source: Internet
Author: User

When accessing a menu link in struts2, we only need to combine the corresponding package namespace with the name of the action, and with the corresponding suffix, we can directly access the corresponding action, then how this process is done, multiple identical namespaces How the package satisfies non-conflicting, it requires a detailed understanding of how the path information is parsed in STRUTS2 and the corresponding action configuration based on the access path.

The whole process can be dealt with in the following steps

    1. Parse the XML to save all the path information that can be accessed
    2. Depending on the access request information, take the path that is available in it
    3. Search by path and finally find the action we need

Parsing xml

First we know that a package and action are configured as follows:

1

2

3

4

5

<package name= "PackageName" extends= "Struts-default" namespace= "/" >

<action name= "logic" class= "detailaction" method= "init" >

<result name= "Success" >/jsp/success.jsp</result>

</action>

</package>

This includes the package name, namespace, and the name of the action. Then we can organize this series of information through a similar Packageconfig object. This is the packageconfig used inside the struts2. Let's look at its simple definition:

1

2

3

4

Protected map<string, actionconfig> actionconfigs;

......

protected String name;

Protected String namespace = "";

This includes the package name we know, the namespace, and a map with the action name and each action configuration. So, the whole project has a lot of package,struts how to deal with it, it will need to use the name space in this area.

We can take the namespace as a key and then save all the action configurations in each package as value, then use key to represent the namespace, and the action configuration as value, where the configuration of the action is once again map, Use the following data structures to define the store.

1

Map<string, map<string, actionconfig>> namespaceactionconfigs = new linkedhashmap<string, Map< String, actionconfig>> ();

Double-map, the first key represents the namespace, the second key represents the name of the action, the path, and the final value is the corresponding information for each action, which is for one of the following paths:

1

/contextpath/Module name/function name/action name/action. Action

We only need to remove the context and the subsequent. Action, the remaining/module name/function name/action/action, which is actually a combination of a namespace and an action path. We only need to follow the/delimiter to find in the map. If there is a package information with the module name namespace, we can directly define to the second map and then directly match to the corresponding action using the key function name/action name/operation.

Then the whole construction of the data structure is in the method Buildruntimeconfiguration of Class Defaultconfiguration, as follows:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21st

22

23

24

Map<string, map<string, actionconfig>> namespaceactionconfigs = new linkedhashmap<string, Map< String, actionconfig>> ();

map<string, string> namespaceconfigs = new linkedhashmap<string, string> ();

This is done by looping through each package, and then into the map

For (Packageconfig packageConfig:packageContexts.values ()) {

String namespace = Packageconfig.getnamespace ();

map<string, actionconfig> configs = Namespaceactionconfigs.get (namespace);

map<string, actionconfig> actionconfigs = Packageconfig.getallactionconfigs ();

For (Object O:actionconfigs.keyset ()) {

String actionname = (string) o;

Here we first get the set information that was originally placed in the big map.

Actionconfig baseconfig = Actionconfigs.get (ActionName);

This is where the action configuration in the current package is then merged into the larger map based on the namespace

Configs.put (ActionName, Buildfullactionconfig (Packageconfig, baseconfig));

}

Namespaceactionconfigs.put (namespace, configs);

}

}

return new Runtimeconfigurationimpl (Namespaceactionconfigs, namespaceconfigs);

Parse Action Information

The next step is to find the action, and when a request arrives, Struts2 first to know which action is capable of handling the request, and if there are no requests to process, an error or other hint. First, we know that this lookup process must first remove all the information before the context, followed by removing the suffix, leaving only the middle of the string with the namespace and the action name, and then looking. The description of the process is performed in the method GetMapping of the class Defaultactionmapper, as follows:

"

"

,

,

,

,

,

,

         Actionmapping mapping = new actionmapping ();

//This step goes to header and context

        string uri = geturi (request);

//This step to the semicolon and all subsequent information

        int indexofsemicolon = uri.indexof (";");

        uri =  (indexofsemicolon > -1)  ?  uri.substring (0, indexofsemicolon)  : uri;

//This step goes to all subsequent and later information, such as. Action

        uri = dropextension (uri, mapping);

//This step is a true discovery process

        parsenameandnamespace (Uri, mapping, configmanager );

The exact process of finding is related to the organization of the entire path, and the entire implementation can be determined by the following steps.

    1. by/In reverse lookup, if not, the namespace is considered "" and the entire path is the action name
    2. If in the 1th position, that is, the/start, the namespace is considered/, followed by the action name
    3. Otherwise, full namespace search is configured, that is, greedy search, that is, all/previous is the namespace, followed by the action name
    4. Otherwise, all of the first steps in the map to make the longest match, that is, the longest match to the namespace is what we want, followed by the action name
    5. Finally, if there is no/in the configured action path, the entire action path is removed, and the last not included/is the action name

In the above steps, 1,2,3,4 is the lookup process, and the last 5th step is the process. The entire implementation logic is consistent with the above, as shown below:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21st

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

String namespace, name;

int lastslash = Uri.lastindexof ("/");

This is the 1th step, that is, when there is no context, the entire path does not/

if (Lastslash = =-1) {

namespace = "";

name = URI;

The 2nd step, that is, when there is a namespace of/, or "", then/that is, the 1th bit

} else if (Lastslash = = 0) {

ww-1046, assume it is the root namespace, it'll fallback to

Default

Namespace anyway if not found in root namespace.

namespace = "/";

Name = uri.substring (Lastslash + 1);

3rd step, if greedy search, then the longest path is the namespace

} else if (alwaysselectfullnamespace) {

Simply Select the namespace as everything before the last slash

namespace = uri.substring (0, Lastslash);

Name = uri.substring (Lastslash + 1);

4th step, longest match search

} else {

Try to find the namespace in those defined, defaulting to ""

Configuration config = configmanager.getconfiguration ();

String prefix = uri.substring (0, Lastslash);

namespace = "";

Find the longest matching namespace, defaulting to the default

For (Object cfg:config.getPackageConfigs (). values ()) {

String ns = ((packageconfig) cfg). GetNamespace ();

if (ns! = NULL && prefix.startswith (NS) && (prefix.length () = = Ns.length () | | Prefix.charat (ns.length ()) = = '/')) {

This is to determine whether the longest, otherwise the lookup will be replaced with a longer

if (Ns.length () > Namespace.length ()) {

namespace = ns;

}

}

}

Name = Uri.substring (namespace.length () + 1);

}

This is the 5th step, for the action name processing

if (!allowslashesinactionnames && name! = null) {

int pos = Name.lastindexof ('/');

if (pos >-1 && pos < Name.length ()-1) {

Name = name.substring (pos + 1);

}

}

This completes the lookup process, but here is only a lookup, not a final match, because there is also the process of mapping to the final action object based on how the found match results are mapped to actionconfig.

Map Actionconfig

The entire mapping process can be divided into the following steps

    1. First, the lookup is based on the default match, and if it can be found, it is considered the final actionconfig, where the action name is also pattern-matched
    2. Otherwise, the namespace is matched with an * number, and a pattern match is attempted
    3. Finally, try to find using the default empty namespace

1 is the first to find the corresponding sub-map according to the namespace, that is, the collection of ActionName and Actionconfig, and then find in the sub-map, if not found in the child map, then use pattern matching. If you can't find it, go to step 2.
2 at Step 2 o'clock, you will first use pattern matching to find the corresponding namespace, and if you have a matching namespace, repeat the first step again with that namespace
3 not found yet, use the default namespace as "" to find

The entire implementation is in the Getactionconfig method of the class Defaultactionmapper, as follows:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21st

22

23

24

25

26

Use the first step to match

Actionconfig config = findactionconfiginnamespace (namespace, name);

Pattern matching for namespaces using the second step

Try Wildcarded namespaces

if (config = = null) {

Namespacematch match = Namespacematcher.match (namespace);

if (match! = null) {

Config = Findactionconfiginnamespace (Match.getpattern (), name);

If Config found, place all the matches found in the namespace processing in the action ' s parameters

if (config! = null) {

Config = new Actionconfig.builder (config)

. Addparams (Match.getvariables ())

. build ();

}

}

}

Use the default match for step 3rd

Fail over to empty namespace

if (config = = null) && (Namespace! = null) && (! "". Equals (Namespace.trim ()))) {

Config = Findactionconfiginnamespace ("", name);

}

return config;

At this point, the entire positioning process is complete. If the Actionconfig object is still not found here, then the corresponding exception is thrown directly, that is, the common

There is no Action mapped for namespace {0} and action name {1}.
There is no action mapped for action name {0}.

Reprint please indicate source: I Flym
This address: http://www.iflym.com/index.php/code/201302270001.html

How to navigate to the detailed access action based on the request path in STRUTS2

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.