The NoteBook of EricKong

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

#

方法:
1、其实宽带路由器不使用WAN口就是一个交换机,你可以直接使用交换机级联。

2、在将第二个路由器接入网络前,修改它的默认LAN口IP地址,防止和第一个的LAN口IP地址冲突。

3、将第二个路由器的一个LAN使用直连线连接至第一个路由器的LAN口,将原来的计算机和新的计算机使用直连线连接至第二个路由器的剩余LAN口就可以了。

posted @ 2011-11-25 09:31 Eric_jiang 阅读(225) | 评论 (0)编辑 收藏

JKS文件是一个java中的密钥管理库,里面可以放各种密钥文件,JKS文件的生成这里暂且不说,这里主要是关注如何从JKS文件中将已有的密钥读取出来。

 

下面是两个java读取JKS文件中密钥的方法

当然在看懂下面两个方法之前要对JKS文件的结构有所了解:

JKS文件就好像一个仓库,里面可以放很多的东西,这里只存放一类东西就是密钥,仓库当然会有一把锁,防范别人随便乱拿,这个就是JKS文件的密码。里面存放的密钥也各有不同,每个密钥都有一个名字(在下面叫别名),一类就密钥对,一类叫公钥,一类叫私钥,密钥对就是包含公钥和私钥的。这里的公钥只要你能进入仓库你就可以随便查看拿走,私钥则是有密码的,只允许有权限的人查看拿走。所以在下面读取密钥时也就有点细微的不同之处,对于读取公钥只需要知道JKS文件(仓库)的密码就可以了,但是在读取私钥时则必须有私钥的密码也就是你必须要有权限,在下面你会发现,在读取私钥时多了一个参数,对应的就是私钥的密码。




import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.security.cert.Certificate;

public class JKSTesting {
 
public static PublicKey getPublicKey(String keyStoreFile,
   String storeFilePass, String keyAlias) 
{

  
// 读取密钥是所要用到的工具类
  KeyStore ks;

  
// 公钥类所对应的类
  PublicKey pubkey = null;
  
try {

   
// 得到实例对象
   ks = KeyStore.getInstance("JKS");
   FileInputStream fin;
   
try {

    
// 读取JKS文件
    fin = new FileInputStream(keyStoreFile);
    
try {
     
// 读取公钥
     ks.load(fin, storeFilePass.toCharArray());
     java.security.cert.Certificate cert 
= ks
       .getCertificate(keyAlias);
     pubkey 
= cert.getPublicKey();
    }
 catch (NoSuchAlgorithmException e) {
     e.printStackTrace();
    }
 catch (CertificateException e) {
     e.printStackTrace();
    }
 catch (IOException e) {
     e.printStackTrace();
    }

   }
 catch (FileNotFoundException e) {
    e.printStackTrace();
   }

  }
 catch (KeyStoreException e) {
   e.printStackTrace();
  }

  
return pubkey;
 }


 
/**
  * 得到私钥
  * 
  * 
@param keyStoreFile
  *            私钥文件
  * 
@param storeFilePass
  *            私钥文件的密码
  * 
@param keyAlias
  *            别名
  * 
@param keyAliasPass
  *            密码
  * 
@return
  
*/

 
public static PrivateKey getPrivateKey(String keyStoreFile,
   String storeFilePass, String keyAlias, String keyAliasPass) 
{
  KeyStore ks;
  PrivateKey prikey 
= null;
  
try {
   ks 
= KeyStore.getInstance("JKS");
   FileInputStream fin;
   
try {
    fin 
= new FileInputStream(keyStoreFile);
    
try {
     
try {
      ks.load(fin, storeFilePass.toCharArray());
      
// 先打开文件
      prikey = (PrivateKey) ks.getKey(keyAlias, keyAliasPass
        .toCharArray());
      
// 通过别名和密码得到私钥
     }
 catch (UnrecoverableKeyException e) {
      e.printStackTrace();
     }
 catch (CertificateException e) {
      e.printStackTrace();
     }
 catch (IOException e) {
      e.printStackTrace();
     }

    }
 catch (NoSuchAlgorithmException e) {
     e.printStackTrace();
    }

   }
 catch (FileNotFoundException e) {
    e.printStackTrace();
   }

  }
 catch (KeyStoreException e) {
   e.printStackTrace();
  }

  
return prikey;
 }


 
public static void main(String[] args) {
  PublicKey publicKey;
  PrivateKey privateKey;
  
  publicKey
=getPublicKey("C:\\aaa.jks","AAAAAAAA""ibmwebspheremq");
  privateKey
=getPrivateKey("C:\\aaa.jks","AAAAAAAA""ibmwebspheremq","AAAAAAAA");
  
  System.out.println(publicKey.toString());
  System.out.println(privateKey.toString());
 }

}



 

posted @ 2011-11-24 11:36 Eric_jiang| 编辑 收藏

Portlet events contain information about an event to which a portlet might need to respond. For example, when a user clicks a link or button, this generates an action event. To receive notification of the event, the portlet must have an event listener implemented within the portlet class.

    Action events: generated when an HTTP request is received by the portlet container that is associated with an action, such as when the user clicks a link.
    Message events: generated when another portlet within the portlet application sends a message.

A portlet has a different processing and rendering sequence than a servlet. A servlet does all of its processing in the service() method. A portlet, on the other hand, uses a two phase processing that is split between an event phase and a render phase. This split is necessary to accommodate communication between portlets before rendering output in the service stage. The event phase is guaranteed to complete before a portlet is called to render.

During the event phase, the portlet implements an ActionListener interface. The ActionListener interface provides the actionPerformed() method, to which an ActionEvent object is passed. When a user clicks on a link or a submit button, an ActionEvent can be generated. The portlet action can be obtained from the ActionEvent, which describes the triggering event. When the actionPerformed() method is invoked, a response object is not available because this is not a rendering step. All state changes should be handled during action processing.

Portlets should use the render phase only to render portlet output. The service() method is not only called following the actionPerformed() processing when a user clicks on a link or button in a portlet, but is also called when the portal page is refreshed. Thus, given a page with two portlets, A and B, when the user clicks on a link in portlet A, actionPerformed() and doView() is called for portlet A, but only the doView() method is called for portlet B. Once the content generation phase has started, no further events will be delivered. For example, messages cannot be sent from within the beginPage(), service() and endPage() methods. The resulting message event would not be delivered and essentially discarded.

The event listener is implemented directly in the portlet class. The listener can access the PortletRequest from the event and respond using the PortletRequest or PortletSession attributes.
Action events

An ActionEvent is sent to the portlet when an HTTP request is received that is associated with a portlet action. To receive action events, the portlet class must implement the ActionListener interface and a portlet action. A portlet action can be one of the following types:

    Simple portlet action String
    PortletAction object

These actions are explained below. See Using persistence for code examples that show how to add a portlet action and create an ActionListener .

Simple portlet action String
    Actions created as simple actions can be executed multiple times, enabling a user's back button to work. Links created with simple portlet actions are represented in the URL rather than in the session. Therefore, portlets with simple actions can be placed on an anonymous page where no session exists. Simple portlet actions are associated with action events by using the getActionString() method.

    PortletURI.addAction(String simpleAction);
    String ActionEvent.getActionString();

    Simple portlet actions are not available in the Portlet API prior to WebSphere Portal Version 4.2. A portlet can determine if the portal server it is running on supports simple actions or not by checking the Portlet API version. The version of the Portlet API on servers that support simple actions has changed from 1.1 to 1.2. Here is example code that illustrates how to check for simple action support:

       if ( (portletContext.getMajorVersion() <= 1 ) && (portletContext.getMinorVersion() <= 1) )
       {
         // cannot use simple actions
       } else {
         // simple action support is present on this server
       }
        

    Note: Some portlets should be designed so that their actions are not executed every time a user refreshes their browser. In this case, set the following parameter and value either as an <init-param/> or <config-param/> in the appropriate descriptor.

    com.ibm.wps.portlet.action.redirect = true

    This allows the page and portlet to be reloaded without the action parameters in the URL.
PortletAction object
    The PortletAction object has been deprecated in favor of simple portlet action strings. It is maintained in the Portlet API to support existing portlets that use PortletActions. You should always use simple portlet actions instead of PortletAction objects.

Message events

IBM portlets that either implement the PortletMessage interface or extend the DefaultPortletMessage class can send information to other portlets on the page. Portlets receiving the message must implement the MessageListener interface and an object with the type PortletMessage. However, it is recommended that you use the property broker service for interportlet communication. See Cooperative portlets for more information.

Message events can be sent from one portlet to others if the recipient portlets are members of the same portlet application and are placed on the same page as the sending portlet. Additionally, a DefaultPortletMessage can cross portlet application boundaries and may be send to all portlets on a page. A MessageEvent can be sent actively to other portlets only when the portlet is in the event processing cycle of the portlet container, otherwise an exception is thrown. There are two different types of messages:

    Single addressed messages: Messages sent to a specific portlet by specifying the portlet name on the send() method.
    Broadcast messages: Messages sent to all portlets on the page.

Message events are useful when changes in one portlet should be reflected in another one. An object with the type PortletMessage has to be implemented which is passed via the MessageEvent. The portlet receiving the message must implement the MessageListener interface and an object with the type PortletMessage.
posted @ 2011-11-10 15:10 Eric_jiang 阅读(265) | 评论 (0)编辑 收藏

A common issue when we’re using Portlet is about sharing data between PortletSession and HttpSession. Frequently we find code like this:

Portlet snippet

PortletSession session = request.getPortletSession();
session.setAttribute("attribute_name","attribute_value");

JSP snippet – Using JSTL

<p>${sessionScope.attribute_name}</p>

Result: The JSP prints out an empty value.

Why does it happen ?

It happens because the PortletSession and HttpSession have different scopes. By default, PortletSession uses portlet scope, as well as HttpSession uses application scope. Hence, an object into portlet scope cannot be accessible into application scope.

Using the PortletSession into JSP

One way to print a PortletSession value into a JSP is use the PortletSession within the JSP. We can do that using the following:

<%
PortletSession session = renderRequest.getPortletSession();
out.println(session.getAttribute("attribute_name");
%>

This doesn’t sound good. We intend to use JSTL instead scriptlet and the approach above doesn’t fit in our requirement. Because of this we’re going to use one of the below approaches.

Converting PortletSession into HttpSession within a Portlet

Within the portlet, we can use a code like this:

HttpServletRequest httpRequest = WpsStrutsUtil.getHttpServletRequest(request);
HttpSession session = httpRequest.getSession(true);
session.setAttribute("attribute_name","attribute_value");

The code above simply retrieve a HttpServletRequest and then we created a HttpSession.

It definatelly works, but we can do even better. Check the next example out.

Changing the PortletSession scope

As describe above, by default the PortletSession scope is a Portlet scope. As you should know, JSTL reads Application Scope. Fortunately, there is a simple way to change the default PortletSession scope. Simply add one more parameter in the setAttribute method.

PortletSession session = request.getPortletSession();
session.setAttribute("attribute_name","attribute_value",PortletSession.APPLICATION_SCOPE);

Awesome, huh? In this way, we can use JSTL to get the values from Session.

Conclusion

I’m not a Portet specialist, however I’ve already found many problem regarding the PortletSession and HttpSession. If you’re facing a problem like this, check your code out and try the approaches above.

If you have any question or comment, fell free to leave your message below.

posted @ 2011-11-09 12:14 Eric_jiang 阅读(199) | 评论 (0)编辑 收藏

When the user initially accesses a portlet, a PortletSession is created. The portlet
session stores transient data associated with an individual use of the portlet.

The PortletSession object extends from HttpSession and serves much the same
purpose. The PortletSession is intended to represent an ongoing conversation between the client and the portlet. To this end, the PortletSession can be used to store information needed between requests. The PortletSession is intended to store data between requests, not between portlets. As such, data stored in the session by one portlet is not accessible by another. The PortletSession is retrieved from the request object.


Well both Portlets and Servlets are loaded using the same classloader.So it's a plain fact that session can be made available in both the contexts.

As far as the portlets are concerned,
The PortletSession is namespaced :
1) PORTLET_SCOPE : Only available to the particular portlet.
2) APPLICATION_SCOPE: Available to all Portlets and also available in Servlets/JSP etc

So, if you really want to share sessions among Servlets and Portlets...
1) Define the scope of the session attributes as APPLICATION_SCOPE in Portlets....
2) Access the session attributes defined or set in servlets by specifying APPLICATION_SCOPE.. else you will get null.

As far as retrieving the PortletSession from HttpRequest is concerned.. You can get them via the APIs available..
For JSR168 Struts Portlets we have WpsStrutsUtil package that will return you the PortletSession...

posted @ 2011-11-09 12:02 Eric_jiang 阅读(476) | 评论 (0)编辑 收藏

All application servers have an Admin Service. The Admin Service does just what the name implies. In most application servers, the admin service does a really good job of system administration for one application server. When you try to run five or ten application servers in parallel, things get flakey. WebSphere Application Server is really a network of servers connected by a network of management. This is what IBM means by "network deployment" or the initials ND. At any moment, some servers will be running, some servers will be stopped, and some servers will be in some in between state. Large, distributed networks are like that. If the network is large enough -- we are talking tens of thousands of computers spread across several continents -- just knowing what is running on any given part of your network becomes a chore. The admin service for WebSphere Application Server is meant to control everything in an extended network of thousands of servers. It is possible to control a network that large from one laptop computer located anywhere in the world. Everything means

configuration -- the way the internal parts of WebSphere Application Server come to life when we start them
control -- the way those internal parts behave after we start them
monitoring -- reports and alerts we get
In order to understand how IBM administers the large network of servers that compose WebSphere Application Server, you have to understand some terms

profile
cell
node
server

IBM goes to great lengths to separate the actual code that executes from the settings that configure and control how that code behaves. Anything information that influences the way WebSphere Application Server behaves is isolated in something that IBM calls a profile. There is one profile for every node in the network of servers that we call WebSphere Application Server. Every time you create a profile, you have created a node. That node and the servers it contains might stand alone or it might be part of a collection of nodes that IBM calls a cell.

A node contains a collection of application servers and web servers that all happen to live on the same physical computer. One physical computer can contain many nodes as long as it has enough memory and enough CPU to power all the servers in all the nodes it contains. Every server in a node is guaranteed to live on the same physical computer.

An application server in the network of servers and services that we call WebSphere Application Server is Java Enterprise Edition platform code running on a Java Virtual Machine. That code produces dynamic content. This article describes how WebSphere Application Server produces dynamic content. Each application server has its own separate Java Virtual Machine. Sometimes, application servers are just called servers. Notice that any one application server is just a very small part of the product we call WebSphere Application Server. In the competing products, that application server is the entire product. Notice the difference in scale

A web server is a computer program that serves up static content. Sometimes, web servers are just called servers.

A cell is a collection on nodes. All the nodes could be on the same physical computer, but more likely, they will be on a network of physical computers

Configuration determines how all the application servers, web servers, message queues, and various internal services of WebSphere Application Server come to life. The configuration information that system administrators are allowed to modify is stored in a collection of XML files and properties files in the config directory of a profile.

XML files and properties files in the config directory of a profile define how the various servers and services in a node come to life. But those configuration files only get read once. They get read when a server or service is initializing. The moment initialization is complete, the XML files and the properties files are ignored. The only way to get a server to pay attention to changes you make in an XML file or a properties file is to stop the server and then start it again.

A network of JMX beans called MBeans control the way the network servers and services behave once they are running. Those same JMX beans also monitor the behavior of the servers and services while they execute.

Two kinds of specialized application servers enable us to configure, control, and monitor the behavior of the distributed network of servers and services that IBM calls WebSphere Application Server

deployment manager
node agent
A deployment manager is an application server that runs exactly one application -- an application that manages the configuration and behavior of an entire cell. There is only one deployment manager in any cell. The deployment manager holds the official configuration records for every server and service in the entire distributed network that is part of a cell. When a deployment manager orders a node agent to change the configuration of its servers and services to match this master record, we say the deployment manager has performed a synchronization. Deployment managers only talk to node agents

A node agent controls, configures and monitors all the servers and services in a node. Node agents talk to a deployment manager and node agents talk to the servers in their node. They relay administrative traffic from the deployment manager to the individual servers in their node. They relay status from the servers in their node to the deployment manager.

MBeans do several things

They simple pieces of Java code that can represent an application, a service, a server, or almost anything else in your enterprise.
They can report the status of anything in the enterprise
They can generate alerts concerning anything in the enterprise
They can be created automatically by WebSphere Application Server on behalf of anything installed in a cell
This thing we call WebSphere's admin service is really a network consisting of the various MBeans, the node agents, and the deployment manager. There are three fairly thin facades to the admin service

a web browser based graphic user interface called the admin console
a command line shell called wsadmin. This shell has a very powerful scripting language
any JMX clients that you might choose to write
If you have never used WebSphere Application Server before, the web browser based admin console is a very good way to learn basic setup and administration. There are limits to what you can do from the admin console. Depending on what you want to do, navigation can either be very easy or very hard. The admin console page that allows you to change JVM heap size is burried deep in the navigation tree of each server. If you want to change heap size for ten servers, you must navigate that tree for each of your ten servers. That can be a lot of tedious mouse clicks.

Once you know what you are doing, wsadmin becomes more attractive than the admin console for many administrative tasks. For one thing, the script language of wsadmin allows you to automate tasks. Once your network reaches a certain size, the admin console becomes a source of errors because of the large number of mouse clicks you must make and the amount of text entry you must provide. Again, the script language provides ways to automate tasks

The most powerful way to control the network of servers and services we call WebSphere Application Server is to write a JMX client. JMX clients have complete unfettered access to the entire admin service and everything that happens across the entire network.
posted @ 2011-10-10 12:17 Eric_jiang 阅读(247) | 评论 (0)编辑 收藏

    复合组件是指包含多个组件的组件。这些组件可以是图形资源或者是图形资源同组件类的合并。比如,创建包括按钮和文本域(text field)的组件,或者,组件包含一个按钮,一个
文本域以及一个校验器(validator) 。
    在创建复合组件时,应当在组件类的内部实例化这些控件。假设这些控件有图形资源,那就必须在类文件中规划所引入的控件的布局,以及设置一些属性,诸如缺省值之类。必须确保
引入符合组件所需的所有类。
    如果组件类是从比较基础的类扩展,比如UIComponent,而不是从像Button这样的控件类扩展的,那么就必须实例化自定义组件中的每个子控件,并管理它们在屏幕上的显示。
    复合组件中单个组件的属性不能从MXML 制作环境中访问,除非设计上允许这么做。例如,如果创建一个从UIComponent扩展的组件,并在这个组件中使用了一个Button 和一个TextArea组件,那么就不能在 MXML 标记中设置 Button 控件的 label 文本,原因就是这个组件不是直接从 Button 类扩展的。

创建组件

这个例子组件被称为 ModalText,在 ModalText.as 文件中定义,组合了一个 Button 控件和一个TextArea 控件。用Button 控件来控制是否允许在 TextArea 控件中进行输入。 
 
为复合组件定义时间监听器
自定义组件通过实现 createChildren()方法来创建子组件,如下面代码所示: 
override protected function createChildren():void { 
    
super.createChildren(); 
    
// Create and initialize the TextArea control.         
    if (!text_mc)     { 
        text_mc 
= new TextArea(); 
                 
        text_mc.addEventListener(
"change", handleChangeEvent); 
        addChild(text_mc);     
    } 
    
// Create and initialize the Button control.         
    if (!mode_mc)     {     
        mode_mc 
= new Button(); 
                 
        mode_mc.addEventListener(
"click", handleClickEvent); 
        addChild(mode_mc); 
    } 

 

     createChildren()方法中也包含对 addEventListener()方法的调用,用这个方法为TextArea 控件所产生的 change 事件以及 Button 控件所产生的 click 事件注册监听器。这些事
件监听器定义在 ModalText 类中,如下面例子所示: 
// Handle events that are dispatched by the children. 
private function handleChangeEvent(eventObj:Event):void { 
        dispatchEvent(
new Event("change")); 

 
// Handle events that are dispatched by the children. 
private function handleClickEvent(eventObj:Event):void { 
        text_mc.editable 
= !text_mc.editable; 

     可在复合组件中处理子组件所分发的事件。在这个例子中,Button 控件的 click 事件的事件监听器被定义在复合组件类中,用来控制 TextArea 控件的 editable 属性。
     但是,如果子组件分发了一个事件,并且希望在组件之外可以有时机来处理这个事件,那么就要在组件定义中增加逻辑来广播这个事件。注意,TextArea 控件的 change 事件监听器中重新广播了这个事件。这就使运用这个组件的应用也能处理这个事件,如下面的例子所示:

<?xml version="1.0"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:MyComp="myComponents.*"> 
    
<mx:Script> 
        
<![CDATA[  
            import flash.events.Event; 
            function handleText(eventObj:Event) 
            { 
                 
            } 
        
]]> 
    
</mx:Script> 
    
<MyComp:ModalText change="handleText(event);"/> 
</mx:Application> 

创建ModalText 组件
下面的例子代码实现了 ModalText 组件的类定义。
  ModalText 组件是一个包含一个Button 控件和一个 TextArea 控件的复合组件。 这个控件有以下特性: 
1. 缺省情况下不能在TextArea 中进行编辑。
2. 通过点击Button控件去控制TextArea控件的编辑。 
3. 通过使用控件的textPlacement 属性来控制TextArea显示在控件的左边还是右边。 
4. 编辑控件的textPlacement属性将会分发placementChanged 事件。 
5. 在程序中使用text 属性可以向TextArea 控件写入内容。 
6. 编辑控件的text属性将会分发一个textChanged事件。
7. 编辑TextArea控件的文本将会分发change事件。
8. textPlacement 和text 属性都可以作为数据绑定表达式的源。
9. 可以有选择性地为Button的up,down和over状态设置皮肤。
  下面的例子在MXML文件中使用ModalText控件, 并且将其textPlacement属性设置为left:  
 
<?xml version="1.0"?>  
<!-- asAdvanced/ASAdvancedMainModalText.mxml --> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  xmlns:MyComp="myComponents.*" > 
    
<MyComp:ModalText textPlacement="left" height="40"/> 
</mx:Application> 
 通过处理 placementChanged 事件,来确定 ModalText.textPlacement 属性何时被修改,如下面的例子所示: 
<?xml version="1.0"?>  
<!-- asAdvanced/ASAdvancedMainModalTextEvent.mxml --> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"  xmlns:MyComp="myComponents.*" > 
    
<mx:Script> 
      
<![CDATA[ 
        import flash.events.Event; 
        private function placementChangedListener(event:Event):void { 
          myEvent.text="placementChanged event occurred - textPlacement = "  
              + myMT.textPlacement as String; 
        } 
      
]]> 
    
</mx:Script> 
    
<MyComp:ModalText id="myMT"   textPlacement="left" height="40" placementChanged="placementChangedListener(event);"/> 
    
<mx:TextArea id="myEvent" width="50%"/>     
    
<mx:Label   text="Change Placement" /> 
    
<mx:Button label="Set Text Placement Right"  click="myMT.textPlacement='right';" /> 
    
<mx:Button label="Set Text Placement Left"   click="myMT.textPlacement='left';" /> 
</mx:Application> 

 下面的例子显示定义控件的 ModalText.as 文件源码:
package myComponents 
{  
    // Import all necessary classes. 
    import mx.core.UIComponent; 
    import mx.controls.Button; 
    import mx.controls.TextArea; 
    import flash.events.Event; 
    import flash.text.TextLineMetrics; 
 
    // ModalText dispatches a change event when the text of the child  
    // TextArea control changes, a textChanged event when you set the text  
    // property of ModalText, and a placementChanged event 
    // when you change the textPlacement property of ModalText.  
    [Event(name="change", type="flash.events.Event")] 
    [Event(name="textChanged", type="flash.events.Event")] 
    [Event(name="placementChanged", type="flash.events.Event")] 
     
    /*** a) Extend UIComponent. ***/ 
    public class ModalText extends UIComponent { 
 
        /*** b) Implement the class constructor. ***/ 
        public function ModalText() { 
            super(); 
        } 
        /*** c) Define variables for the two child components. ***/  
        // Declare two variables for the component children. 
        private var text_mc:TextArea; 
        private var mode_mc:Button; 
        /*** d) Embed new skins used by the Button component. ***/ 
        // You can create a SWF file that contains symbols  with the names   
        // ModalUpSkin, ModalOverSkin, and ModalDownSkin.        
        // If you do not have skins, comment out these lines. 
        [Embed(source="Modal2.swf", symbol="blueCircle")]        
        public var modeUpSkinName:Class; 
     
        [Embed(source="Modal2.swf", symbol="blueCircle")] 
        public var modeOverSkinName:Class; 
 
        [Embed(source="Modal2.swf", symbol="greenSquare")] 
        public var modeDownSkinName:Class; 
 
 
        /*** e) Implement the createChildren() method. ***/ 
        // Test for the existence of the children before creating them. 
        // This is optional, but we do this so a subclass can create a  
        // different child instead. 
        override protected function createChildren():void { 
            super.createChildren(); 
 
            // Create and initialize the TextArea control.       
            if (!text_mc) 
            { 
                text_mc = new TextArea(); 
                text_mc.explicitWidth = 80; 
                text_mc.editable = false; 
                text_mc.text= _text; 
                text_mc.addEventListener("change", handleChangeEvent); 
                addChild(text_mc); 
            } 
 
            // Create and initialize the Button control.         
            if (!mode_mc) 
            {   mode_mc = new Button(); 
                mode_mc.label = "Toggle Editing Mode"; 
                // If you do not have skins available,  
                // comment out these lines. 
                mode_mc.setStyle('overSkin', modeOverSkinName);  
                mode_mc.setStyle('upSkin', modeUpSkinName);  
                mode_mc.setStyle('downSkin', modeDownSkinName);  
                mode_mc.addEventListener("click", handleClickEvent); 
                addChild(mode_mc); 
            } 
        }         
         /*** f) Implement the commitProperties() method. ***/ 
        override protected function commitProperties():void { 
            super.commitProperties(); 
            if (bTextChanged) { 
                bTextChanged = false; 
                text_mc.text = _text; 
                invalidateDisplayList(); 
            } 
        }        
        /*** g) Implement the measure() method. ***/ 
        // The default width is the size of the text plus the button. 
        // The height is dictated by the button. 
        override protected function measure():void { 
            super.measure(); 
 
            // Since the Button control uses skins, get the  
            // measured size of the Button control.  
            var buttonWidth:Number = mode_mc.getExplicitOrMeasuredWidth(); 
            var buttonHeight:Number = mode_mc.getExplicitOrMeasuredHeight(); 
 
            // The default and minimum width are the measuredWidth  
            // of the TextArea control plus the measuredWidth  
            // of the Button control.  
            measuredWidth = measuredMinWidth =  text_mc.measuredWidth + buttonWidth; 
             
            // The default and minimum height are the larger of the  
            // height of the TextArea control or the measuredHeight of the  
            // Button control, plus a 10 pixel border around the text.  
            measuredHeight = measuredMinHeight =   Math.max(mode_mc.measuredHeight,buttonHeight) + 10;      
      } 
        /*** h) Implement the updateDisplayList() method. ***/ 
        // Size the Button control to the size of its label text  
        // plus a 10 pixel border area.  
        // Size the TextArea to the remaining area of the component. 
        // Place the children depending on the setting of  
        // the textPlacement property.  
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { 
            super.updateDisplayList(unscaledWidth, unscaledHeight);          
            // Subtract 1 pixel for the left and right border,  
            // and use a 3 pixel margin on left and right. 
            var usableWidth:Number = unscaledWidth - 8; 
 
            // Subtract 1 pixel for the top and bottom border,  
            // and use a 3 pixel margin on top and bottom. 
            var usableHeight:Number = unscaledHeight - 8; 
             
            // Calculate the size of the Button control based on its text. 
            var lineMetrics:TextLineMetrics = measureText(mode_mc.label); 
            // Add a 10 pixel border area around the text. 
            var buttonWidth: Number = lineMetrics.width + 10; 
            var buttonHeight:Number = lineMetrics.height + 10; 
            mode_mc.setActualSize(buttonWidth, buttonHeight);        
             
            // Calculate the size of the text 
            // Allow for a 5 pixel gap between the Button  
            // and the TextArea controls.  
            var textWidth:Number = usableWidth - buttonWidth - 5; 
            var textHeight:Number = usableHeight; 
            text_mc.setActualSize(textWidth, textHeight); 
             
            // Position the controls based on the textPlacement property. 
            if (textPlacement == "left") { 
                text_mc.move(4, 4);                 mode_mc.move(4 + textWidth + 5, 4); 
            } 
            else { 
                mode_mc.move(4, 4); 
                text_mc.move(4 + buttonWidth + 5, 4); 
            }            
            // Draw a simple border around the child components. 
            graphics.lineStyle(1, 0x000000, 1.0); 
            graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);          
        } 
         
        /*** i) Add methods, properties, and metadata. ***/  
        // The general pattern for properties is to specify a private  
        // holder variable. 
        private var _textPlacement:String = "left"; 
        // Create a getter/setter pair for the textPlacement property. 
        public function set textPlacement(p:String):void { 
            _textPlacement = p; 
            invalidateDisplayList(); 
            dispatchEvent(new Event("placementChanged")); 
        } 
 
        // The textPlacement property supports data binding. 
        [Bindable(event="placementChanged")] 
        public function get textPlacement():String { 
            return _textPlacement; 
        } 
         
        private var _text:String = "ModalText"; 
        private var bTextChanged:Boolean = false; 
         
        // Create a getter/setter pair for the text property. 
        public function set text(t:String):void { 
            _text = t; 
            bTextChanged = true;           
            invalidateProperties(); 
            dispatchEvent(new Event("textChanged")); 
        } 
         
        [Bindable(event="textChanged")] 
        public function get text():String { 
                return text_mc.text; 
        } 
         
        // Handle events that are dispatched by the children. 
        private function handleChangeEvent(eventObj:Event):void { 
                dispatchEvent(new Event("change")); 
        } 
 
        // Handle events that are dispatched by the children. 
        private function handleClickEvent(eventObj:Event):void { 
                text_mc.editable = !text_mc.editable; 
        } 
    } 
posted @ 2011-07-09 20:57 Eric_jiang 阅读(393) | 评论 (0)编辑 收藏

     摘要:     在用 ActionScript 创建自定义组件时,必须重载 UIComponent 类的一些方法.实现基本的组件结构,构造器,以及 createChildren(),commitProperties(), measure(), layoutChrome()和 updateDisplayList()方法. 基本组件结构下面例子展示了Flex 组件的基本...  阅读全文
posted @ 2011-07-09 18:00 Eric_jiang 阅读(1021) | 评论 (0)编辑 收藏

     简单组件一般都是现存 Flex 组件的子类,它们通过设置 skpins 或 styles 属性来修改父组件的外观,或者添加一些新的功能。比如,为 Button 控件增加一个新的事件类型,或者更改
DataGrid 控件缺省的 styles 和 skins。
在高级组件中,通常会执行以下动作: 
1.  更改已有组件的可视化外观或者可视化特性。
2. 创建复合组件,将两个或者多个组件包装在其中。 
3. 通过继承UIComponent 类来创建组件。
    我们通常用继承现存类的方式来创建组件。比如,要创建基于 Button 的控件,我们就创建mx.controls.Button 类的一个子类。要开发自己的组件,则需要创建mx.core.UIComponent 类的子类。
关于重载 UIComponent 类的 protected 方法
    Flex 所有的可视化组件都是UIComponent 类的子类。 因此,可视化组件继承了 UIComponent类所定义的 methods,properties,events,styles 和 effects。
     要创建高级的可视化组件,必须实现一个构造器(constructor)。另外要有选择性地重载下表中 UIComponent 类的一个或者多个 protected 方法: 
    commitProperties()  提交组件所有的属性变化。要么使属性同时更改,要么确保属性按照特定顺序设置。 
    createChildren()       创建组件的子组件。
    比如,ComboBox 控件包含了一个 TextInput 控件和一个 Button 控件作为它的子组件。
    LayoutChrome()   定义 Container 类的子类容器的 border 区域。 
    measure()               设置组件的缺省 size 和缺省的最小 size。 
    updateDisplayList()   根据以前所设置的属性和样式来确定组件的子组件在屏幕上的大小(size)及位置(position) ,并且画出组件所使用的所有皮肤( skins)及图形化元素。组件的父容器负责确定组件本身大小(size)。
 
     组件的使用者不会直接调用所有这些方法。 
关于失效(机制)的方法?
     在组件的生命周期中,应用可能会改变组件的大小和位置,更改组件的属性来控制组件的显示,或者更改组件的样式(styles)和皮肤(skin)属性。比如,可以更改组件中所显示的
文本(Text )的字体(Font)大小。 作为变更字体大小工作的一部分,组件的大小也可能随之发生变化,这就需要 Flex 去更新应用的布局。布局操作需要Flex 调用自定义组件的commitProperties(), measure(), layoutChrome(), 以及 updateDisplayList()方法。
    应用通过程序来更改字体大小的执行速度大大快于 Flex 更新应用的速度。因此,你应该在确定最终要更改的字体之后再更新布局。 另外一个场景就是,当你设置了组件的多个属性后,比如 Button 控件的 label 和 icon 属性,你肯定会想让所有属性被设置后一次性执行 commitProperties(), measure(), 和 updateDisplayList()方法,而不是设置过 label 属性后执行一遍这些方法,然后在设置 icon属性后又执行一次这些方法。
    另外,可能有几个组件同时改变了它们的字体大小。这时应该让 Flex 去协调布局操作,以消除任何冗余过程,而不是在每个组件更新它的字体大小之后都执行一次布局操作。
     Flex 使用一种“失效机制(invalidation mechanism)”来同步组件的更改。Flex 用一系列方法的调用来标记组件的某些东西已经发生变化,并需要 Flex 去调用组件的commitProperties(), measure(), layoutChrome(),或者 updateDisplayList()方法。通过这种办法,Flex 实现了“失效机制” 。 
    下表描述了有关“失效(invalidation)”方法: 
     invalidateProperties()   通知组件,以使下次屏幕更新时,它的commitProperties()方法能被调用。 
     invalidateSize()            通知组件,以使下次屏幕更新时,它的 measure()方法能被调用。 
     invalidateDisplayList()   通知组件,以使下次屏幕更新时它的 layoutChrome()方法和updateDisplayList()方法能被调用。
    当组件调用一个“失效”方法,它就通知 Flex,该组件已经被更新。当多个组件调用失效方法,Flex 会协调这些更新,以使这些更新操作下一次屏幕更新时一起执行。
    通常,组件使用者不必直接调用这些“失效”方法。这些”失效”方法被组件的 setter 方法或者组件的其他方法在需要的时候调用. 
 
关于组件实例化的生命周期 
    组件实例化生命周期描述了用组件类创建组件对象时所发生的一系列步骤.作为生命周期的一部分,Flex 自动调用组件的方法,发出事件,并使组件可见。 
    下面例子用 ActionScript 创建一个 Button 控件,并将其加入到容器之中: 
    //创建一个 Box 容器。 
    var boxContainer:Box = new Box(); 
    //设置 Box 容器 
    … 
    //创建 Button 控件。 
    var b:Button = new Button() 
    //设置 button 控件。 
    b.label = "Submit"; 
    ... 
    // 将 Button 添加到 Box 容器中。 
    boxContainer.addChild(b); 下面的步骤显示了用代码创建一个 Button 控件,并将这个控件添加到 Box 容器中时所发生的一切: 
    1.  调用了组件的构造函数,如下面代码所示: 
    // Create a Button control.  
    var b:Button = new Button() 
    2.  通过设置组件的属性对组件进行了设置,如下面代码所示: 
    // Configure the button control. 
    b.label = "Submit"; 
    组件的 setter 方法将会调用 invalidateProperties(), invalidateSize(), 或者invalidateDisplayList() 方法. 
    3.  调用 addChild()方法将该组件添加到父组件中,如下代码所示: 
    // Add the Button control to the Box container. 
    boxContainer.addChild(b); 
    Flex 执行以下动作: 
    4.   将 component 的 parent 属性设置为对父容器的引用. 
    5.  计算组件的样式(style) 设置.  
    6.  在组件上分发preinitialize 事件.  
    7.  调用组件的createChildren() 方法.  
    8.  调用invalidateProperties(), invalidateSize()和 invalidateDisplayList()方法以触发后续到来的,下一个“渲染事件”(render?event)期间对 commitProperties(), measure(),或 updateDisplayList()方法的调用。 
    这个规则唯一一个例外就是当用户设置组件的 height 和 width 属性时, Flex 不会调用measure() 方法.  
    9.  在组件上分发initialize 事件。此时,组件所有的子组件都被初始化,但是组件没有改更size 和处理布局。可以利用这个事件在组件布局之前执行一些附加的处理。  
    10. 在父容器上分发 childAdd 事件.  
    11. 在父容器上分发initialize 事件.  12. 在下一个“渲染事件”(render?event)中, Flex 执行以下动作:  
    a.  调用组件的 commitProperties()方法.  
    b.  调用组件的 measure()方法.  
    c.  调用组件的 layoutChrome()方法.  
    d.  调用组件的 updateDisplayList()方法.  
    e.  在组件上分发 updateComplete 事件.  
    13. 如果commitProperties(), measure()或者 updateDisplayList()方法调用了 invalidateProperties(), invalidateSize(),或 invalidateDisplayList()方法,则 Flexh 会分发另外一个 render 事件. 
    14. 在最后的render 事件发生后, Flex 执行以下动作:  
    a.  通过设置组件的 visible 属性使组件变为可视. 
    b.  在组件上分发 creationComplete 事件.组件的大小(size)和布局被确定.这个事件只在组件创建时分发一次.  
    c.  在组件上分发 updateComplete 事件.无论什么时候,只要组件的布局(layout),位置,大小或其它可视的属性发生变化就会分发这事件,然后组件被更新,以使组件能够被正确地显示. 
    当使用 addChild()方法将组件添加到容器中时,大部分工作都是为了设置这个组件.这是因为直到把组件添加到容器中时,Flex 才能确定它的大小(size),设置它所继承样式(style)属性,或者在屏幕上画出它. 也可以用 MXML,在应用中完成上面的组件添加动作,如下面的例子所示:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Box>
        <mx:Button label="Submit"/>
    </mx:Box>
</mx:Application> 
    在 MXML 中创建组件时,Flex 执行的步骤顺序同用 ActionScript 的步骤顺序相同. 使用 removeChild() 方法可将组件从容器中移出, 如果对这个组件再没有其他的引用,那就相当于使用 Adobe Flash  Player 或 Adobe AIR 的垃圾回收机制将组件从内存中删除. 关于创建组件的步骤 
    为了实现一个组件,就要重载组件的方法,定义新的属性,分发新的事件,或者执行其他任何应用所需的自定义的逻辑.要想实现自己的组件, 请遵循以下这些常规步骤: 
    1.  如果有必要,为组件创建所有的皮肤(skins) . 
    2.  创建 ActionScript 类文件. 
    a.  从一个基类扩展,比如 UIComponent 或者其他的组件类. 
    b.  指定使用者能够通过 MXML 标记进行设置的属性. 
    c.  嵌入(Embed)所有的图片和皮肤文件. 
    d.  实现构造器. 
    e.  实现 UIComponent.createChildren()方法.  
    f.  实现 UIComponent.commitProperties() 方法.  
    g.  实现 UIComponent.measure() 方法.  
    h.  实现 UIComponent.layoutChrome() 方法.  
    i.   实现 UIComponent.updateDisplayList() 方法.  
    j.  增加属性(properties),方法(methods),样式(styles),事件 (events)以及元数据. 
    3.  以 ActionScript 文件或者 SWC 文件的形式部署组件. 
     定义新组件时不一定要重载所有的方法.只需要重载实现组件功能所需的方法.如果创建现存组件的子类,比如 Button 控件或者 VBox 容器,那么必须实现组件中所添加的新功能所需
的方法. 
    例如:实现一个自定义的 Button 控件,该控件使用新的机制来定义缺省大小(size) .在这种情况下,只需要重载 measure()方法.对于这个例子,参见实现 easure() 方法.
或者,要实现 VBox 容器的一个新子类.新子类利用 VBox 类已有的所有有关设定大小(sizing)的逻辑,但是变更了 VBox 类的布局逻辑以实现从底部到顶部的方式来布局容器中的
子控件,而不是自顶向下的布局.在这种情况下,只需要重载updateDisplayList()方法.关于这个例子,见实现 updateDisplayList()方法.
 
关于接口 

    Flex 用接口将组件的基本功能分为离散的单元, 这使得它们可以被 “一块一块” 地实现. 例如,使组件可聚焦(有输入焦点) ,它必须实现 IFocusable 接口;要使它能够参与布局过程,它必须实现 ILayoutClient 接口. 为了简化接口的使用, UIComponent 类实现了下表中定义的所有接口,但是不包括IFocusManagerComponent 接口和 IToolTipManagerClient 接口.但 UIComponent 很多子类实现了 IFocusManagerComponent 和 IToolTipManagerClient 接口. 
    因此,创建 UIComponent 或其子类的子类,就不必实现这些接口.但是,如果要创建的组件不是 UIComponent 的子类,并且还想在 Flex 中使用这个组件,那么就必须实现一个或者多个接口。 
    注意:对于 Flex, Adobe 建议所有的组件都应从 UIComponent 及其子类继承. 
    下表列出了 Flex components 所实现的主要接口:  
    接口                                                           用途 
    IChildList                                                    表明容器中子控件的数量. 
    IDeferredInstantiationUIComponent              表明组件或组件能实施延迟实例化. 
    IFlexDisplayObject                                       指定皮肤元素的接口. 
    IFocusManagerComponent                           表明组件或者对象是可聚焦的,这意味着组件可以从 FocusManager 获取焦点. 
    UIComponent                                             组件没有实现 Ifocusable 接口,因为有些组件不打算接受焦点. 
    IInvalidating                                               表明组件或者对象能够使用”失效机制”去执行延迟的,而不是立即的属性提交( commitment), 度量(measurement), 以及画出(drawing) 或布局( layout). 
    ILayoutManagerClient                                  表明组件或者对象能够参与 LayoutManager 的提交(commit) ,度量(measure)和更新次序(update sequence)  
    IPropertyChangeNotifier                               表明组件支持特定形式的事件传播. 
    IRepeaterClient                                           表明组件或者对象能够被用于 Repeater 类. 
    IStyleClient                                                 表明组件能够从其他的对象继承样式,并且支持setStyle() 和 getStyle() 方法. 
    IToolTipManagerClient                                  表明组件有一个 toolTip 属性,并且因此可以被ToolTipManager 所监控. 
    IUIComponent                                            定义组件能够成为布局管理器或列表的子组件所必须实现的基本 APIs.
    IValidatorListener                                       表明组件能够监听校验(validation)事件,并且因此能够显示校验状态,比如一个红色边框和显示
校验错误的提示信息(tooltips)
posted @ 2011-07-09 17:37 Eric_jiang 阅读(433) | 评论 (0)编辑 收藏

Maven在dependencyManagement元素中为你提供了一种方式来统一依赖版本号。你经常会在一个组织或者项目的最顶层的父POM中看到dependencyManagement元素。使用pom.xml中的dependencyManagement元素能让你在子项目中引用一个依赖而不用显式的列出版本号。

Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用在这个dependencyManagement元素中指定的版本号。

 

<project>
  
<modelVersion>4.0.0</modelVersion>
  
<groupId>org.sonatype.mavenbook</groupId>
  
<artifactId>a-parent</artifactId>
  
<version>1.0.0</version>
  
  
<dependencyManagement>
    
<dependencies>
      
<dependency>
        
<groupId>mysql</groupId>
        
<artifactId>mysql-connector-java</artifactId>
        
<version>5.1.2</version>
      
</dependency>
      
    
<dependencies>
  
</dependencyManagement>



然后,在子项目中,你可以使用如下的依赖XML添加一个对MySQL Java Connector的依赖:

<project>
  
<modelVersion>4.0.0</modelVersion>
  
<parent>
    
<groupId>org.sonatype.mavenbook</groupId>
    
<artifactId>a-parent</artifactId>
    
<version>1.0.0</version>
  
</parent>
  
<artifactId>project-a</artifactId>
  
  
<dependencies>
    
<dependency>
      
<groupId>mysql</groupId>
      
<artifactId>mysql-connector-java</artifactId>
    
</dependency>
  
</dependencies>
</project>


如果mysql-connector-java在顶层父项目中被作为一个依赖列出,这个层次中的所有项目都将引用该依赖。使用dependencyManagement能让你统一并集中化依赖版本的管理,而不用添加那些会被所有子项目继承的依赖。

posted @ 2011-07-08 09:59 Eric_jiang 阅读(3794) | 评论 (0)编辑 收藏

仅列出标题
共57页: First 上一页 37 38 39 40 41 42 43 44 45 下一页 Last