基于jsf-component的portlet的构建通常需要了解一下几点 1. 所有的jsf-component都是单一实例的,也就是说在每一个session周期内,一个UI组件只存在一个实例 2 对于UI组件中的变量,对于不属于UI组件的对象(FTPClient),在UI对象构建初期通过构造函数传递,之后,无论这些对象在其他地方发生任何变化,UI中引用的仍然是该对象的实例。对于UI组件自己的对象(UIStringInput),如果用setXX方法对其赋值了,UI对象在encode的时候,引用的也是该对象的当前值。
  public class UIFileForm extends UISimpleForm {  static final public String SAVE_ACTION = "save";  static final public String CANCEL_ACTION = "cancel"; 
 private FTPFile ftpFile_;  private FTPClient ftpClient_;  private UIStringInput nameInput_;  private String fileName_; 
 public UIFileForm(FTPClient ftp,ResourceBundle res) throws Exception {   super("fileForm", "post", null);   setId("UIFileForm");   setClazz("UIFileForm");   ftpClient_ = ftp;                    //引用外部对象                              int idx = ftpFile_.getName().lastIndexOf("/");   String fileName = ftpFile_.getName().substring(idx++);   nameInput_ = new UIStringInput("name", fileName); 
  add(    new HeaderRow().add(     new Cell(res.getString("header.edit-file")).addColspan("2")));   add(    new Row().add(new LabelCell(res.getString("label.file-name"))).add(     new ComponentCell(this, nameInput_)));  //尽管这里是在构造函数里面,但是nameInput是对象,所有即使它的值变化了,encode的时候仍然得到的是变化后的值    add(    new Row().add(     new ListComponentCell()      .add(       new FormButton(        res.getString("button.save"),        SAVE_ACTION))      .add(       new FormButton(        res.getString("button.cancel"),        CANCEL_ACTION))      .addColspan("2")      .addAlign("center"))); 
  addActionListener(SaveActionListener.class, SAVE_ACTION);   addActionListener(CancelActionListener.class, CANCEL_ACTION);  }  public void setFileName(String s) {   fileName_ = s;          int idx = ftpFile_.getName().lastIndexOf("/");   String fileName = ftpFile_.getName().substring(idx++);   nameInput_.setText(fileName);// 这里是重新改变值的地方     }  
 
  |