Struts-menu source analysis (reposted)

xiaoxiao2021-03-06  69

A good code reads to let people drink, and after reading it, I am refreshing. If you want to improve your programming level, if you want to improve your design, if you want to become a master, then go to read the code. With the programming experience in my more than ten years, reading code can make you get more than reading articles (which fear is the master's article). Excellent and practical code there are a lot, such as JUnit, such as Jive, such as PetStore, or even Tomcat Example, Log4j's example. Struts-menu also comes from a master's work, Matt Raible. There are many excellent works, such as Struts-Resume using struts and hibernate. Official website is

http://raibledesigns.com/wiki/wiki.jsp?page=main

. The latest version of Struts-Menu is 2.1. The function is to use Struts technology to build a tree menu. It should be said to be a very practical technology, greatly facilitating the majority of developers. At the same time, individuals think that its role is more than just. For example, it is also a use

Maven

with

Velocity

A good example.

First, let's take a look at its effect. Http://www.raibledesigns.com/struts-meru/. It can be seen that such a colorful menu effect is to demonstrate the content in a configuration file. This is a very good data and the implementation of the phase separation. We open its source code. First look at its bag diagram

There are five packages, where Menu is naturally completed data organization, one of the cores, Displayer is a display method package, and the completion of data shows most of the features. It is also one of the cores. Taglib significance is obvious. EXAMPLE is naturally some examples. Util is a package that reads the resource file. Because of some of our focus on the package only three Menu, Displayer, and Taglib.

First let's see the class diagram of the Menu package.

The first is a category of menuPlugin. This class is obvious, it is a struts of Plug-in. It can be seen that it has only one parameter MenuConfig, which is the configuration file path of the MENU. Sure enough, there is such a paragraph in the Struts-Conf file.

Note The configuration file comes from /Web-inf/Menu-config.xml, of course, we can find this file under the corresponding path. If you haven't done Struts before, now I know how to do it, it is so simple. By reading the initialization function, knowing its function is to call MENUREPOSTORY to create a menu. therefore. We know that MenurePository is inevitably an organization class for an organization management management menu.

Public void init (ActionServlet servlet, Moduleconfig Config "throws servletexception {

IF (log.Indebugeload ()) {

Log.debug ("Starting Struts-Menu Initialization);

}

this.servlet = servlet;

Repository = new menuRepository ();

Repository.setloadparam (menuconfig);

Repository.setServlet (servlet);

Try {

Repository.load ();

servlet.getServletContext (). setttribute (SETATRIBUTE)

MenurePository.Menu_repository_key,

Repository);

IF (log.Indebugeload ()) {

Log.debug ("Struts-Menu Initialization SuccessFull);

}

} catch (loadableresourceexception LRE) {

Throw new servletexception

Failure Initializing Struts-menu: " Lre.getMessage ());

}

}

Open the menurepository class, we can see this class is also very simple, but there are fewer learning. The first is FasthashMap, you can see that there are three fasthashmap in this class. As the name, it is fast Hashmap, then look at it, it is from org.apache.commons.collections.fasthashmap; See the famous package of org.apache.commons? If you have never used it before, it is recommended that you spend a while to study using it, I promise value.

Protected fasthashmap menus = new fasthashmap (); protected fasthashmap displayers = new fasthashmap (); protected fasthashmap templates = new fasthashmap ();

Next we see the LOG definition. Right, Log, the core of debugging. The following sentence is the most commonly used method of use of the Commons log. Let your program use Commons log, first, it is powerful, second, it is simple, it is so simple.

Private log log = logfactory.getlog (getclass (). getname ());

Look at one function below

protected digesterinitdigester () {

Digester digester = new digester ();

Digester.SetClassLoad (thread.currentthread (). getContextClassLoader ());

Digester.push (this);

//digester.setdebug (getDebug ());

// 1

Digester.addObjectCreate ("MenuConfig / Menus / Menu",

"Net.sf.navigator.Menu.MenuComponent", "Type");

Digester.addSetProperties ("MenuConfig / Menus / Menu); Digester.addsetNext (" MenuConfig / Menus / Menu "," AddMenu ");

// 2

Digester.addObjectcreate ("MenuConfig / Menus / Menu / Item",

"Net.sf.navigator.Menu.MenuComponent", "Type");

Digester.AddSetProperties ("MenuConfig / Menus / Menu / Item");

Digester.AddsetNext ("MenuConfig / Menus / Menu / Item", "AddMenuComponent",

"Net.sf.navigator.Menu.MenuComponent");

// 3

Digester.addObjectcreate ("MenuConfig / Menus / Menu / Item / Item",

"Net.sf.navigator.Menu.MenuComponent", "Type");

Digester.AddSetProperties ("MenuConfig / Menus / Menu / Item / Item");

Digester.addsetNext ("MenuConfig / Menus / Menu / Item / Item",

"AddMenuComponent", "Net.sf.navigator.Menu.MenuComponent");

// 4

Digester.adDObjectCreate ("MenuConfig / Menus / Menu / Item / Item / Item",

"Net.sf.navigator.Menu.MenuComponent", "Type");

Digester.AddSetProperties ("MenuConfig / Menus / Menu / Item / Item / Item");

Digester.addsetNext ("MenuConfig / Menus / Menu / Item / Item / Item",

"AddMenuComponent", "Net.sf.navigator.Menu.MenuComponent");

//5

Digester.addObjectcreate ("MenuConfig / Menus / Menu / Item / Item / Item / Item",

"Net.sf.navigator.Menu.MenuComponent", "Type");

Digester.AddSetProperties ("MenuConfig / Menus / Menu / Item / Item / Item / Item");

Digester.addsetNext ("MenuConfig / Menus / Menu / Item / Item / Item / Item",

"AddMenuComponent", "Net.sf.navigator.Menu.MenuComponent");

//6

Digester.addObjectcreate ("MenuConfig / Menus / Menu / Item / Item / Item / Item",

"Net.sf.navigator.Menu.MenuComponent", "Type");

Digester.addSetProperties ("MenuConfig / Menus / Menu / Item / Item / Item / Item"); Digester.AddsetNext ("MenuConfig / Menus / Menu / Item / Item / Item / Item",

"AddMenuComponent", "Net.sf.navigator.Menu.MenuComponent");

// 7

Digester.addObjectcreate ("MenuConfig / Menus / Menu / Item / Item / Item / Item",

"Net.sf.navigator.Menu.MenuComponent", "Type");

Digester.AddSetProperties ("MenuConfig / Menus / Menu / Item / Item / Item / Item");

Digester.addsetNext ("MenuConfig / Menus / Menu / Item / Item / Item / Item",

"AddMenuComponent", "Net.sf.navigator.Menu.MenuComponent");

Digester.addObjectcreate ("MenuConfig / Displayers / Displayer",

"net.sf.navigator.displayer.menudisplayermapping", "mapping");

Digester.AddSetProperties ("MenuConfig / Displayers / Displayer");

Digester.AddSetNext ("MenuConfig / Displayers / Displayer",

"addmenudisplayermapping",

"net.sf.navigator.displayer.menudisplayermapping");

Digester.AddSetProperty ("MenuConfig / Displayers / Displayer / SetProperty",

"Property", "Value");

Return Digester;

}

Here is a classic, Digester, Digester's use, if you need to read an XML configuration file, do not want to deal directly with DOM, Digester will be a good choice. In fact, we see the load function calls a digester.parse (INPUT); it has been built into memory, which is as simple as it is. If you want to initialize your system, is this way to learn? "Want to do something, you must first sharpen it." We can see how Raible uses existing tools to mitigate the development.

Due to menurepository weightlifting, if you don't even let us see how the tree structure is built to the memory. But don't worry, the class map gives us expressive.

Did you see the Menubase class? Yes, look at the name, you know that it is a matrix class. It can be seen that it is a simple JavaBean. And I believe that each attribute of it can guess according to the name. So the focus is MenuComponent, a simplified "Composite" mode.

As shown in FIG. Because the Leaf here, there is no method, only attributes. Therefore, Leaf and Composite contractions become a MenuComponent class. Everyone knows that the Composite mode is the best way to achieve the tree structure. If you have not had a chance to achieve or have a good place from Composite mode, then look at it here. First look at it, the actual code of Menucomponet is very small, adding less than ten lines. Public void addmenucomponent (MenuComponent menucomponent) {

MenuComponents.add (menucomponent);

Menucomponent.SetParent (this);

IF ((menucomponent.getname () == NULL) ||

(menucomponent.getname (). Equals ("")))) {

MenuComponent.setName (this.name menucomponents.size ());

}

}

Public menucomponent [] getMenuComponents () {

MenuComponent [] Menus =

(Menucomponent []) MenuComponents.toArray (_MenuComponent);

Return Menus;

}

If you use ten lines to implement a tree structure (and still universal), would you like it? That is to create the target of the tree structure in memory by simple such code.

Let's take a look at the Display package, this package is also very clear, it is used to show. The class diagram of this package is very beautiful, and unfortunately is very large. Can only be reduced to everyone.

From the class diagram, you can see a very beautiful iconic object design idea. Through an interface, the template method is utilized. Finally, the display of the tree structure is realized. Its main approach is DISPLAYCOMPONENTS and DISPLAY, the init method implements the initialization work, read files such as JavaScript and pictures. DisplayComponents is an iterative function. Thereby, a MenucomPont tree can be traversed. And display it.

It should be said that the Menu package is a M layer, and the Dispplya package is a View layer, and the TAGLIB package is added to the full structure of the MVC.

Two TAG classes are very clear, first we use it to see their functions

Obviously. UseMenudisplayer This class is to implement which display method for use. We see the definition of ListMenu in Menu-Config

DISPLAYMENU is a menu and it is displayed, and it can also be found in Menu-Config.

Check the code of DisplayMenu, you can see. It completed the functionality only from Context, then passed by Displayer.Display (MENU); handed it to a Menudisplayer instance to draw it.

Therefore, the Control layer has completed the control function.

In summary. Through such a beautiful design, he left each function. If we need to add a display, just inherit the Menudisplayer or a subclass, then write our method without the need to modify the rest of the system. Similarly, if our menu is not prepared to store in servletContext, it is ready to be placed, so we only need to modify the Control section and the generated part (ie the meNurePository) section. Not affecting the Display section.

OK, the introduction to Struts-Menu is over, the next article will be if the Struts-Menu and database technology dynamically generates menu. Please continue to pay attention to my blog.

转载请注明原文地址:https://www.9cbs.com/read-105776.html

New Post(0)