NCNC

WTGGT,TTGG

用户操作
[即时聊天] [发私信] [加为好友]
张忠良ID:sunjavaduke
93896次访问,排名991好友0人,关注者2
优于别人,并不高贵,真正的高贵是优于昨天的自己
这个世界上最伟大的事情并不是已经取得的成就,而是前进的方向
sunjavaduke的文章
原创 10 篇
翻译 43 篇
转载 1 篇
评论 0 篇
sunjavaduke的公告
Contact me
最近评论
文章分类
收藏
    相册
    vic
    Favorite
    ASF
    存档
    订阅我的博客
    XML聚合  FeedSky

    原创 JSF Tour Part4 Sun JSF CarDemo收藏

    新一篇: JSF Tour 5 MyFaces Intro | 旧一篇: JSF Tour Part3 Sun JSF Spec Notes

    本文是对Sun JSF RI中的样例程序cardemo的讲解,如有转载,请声明出处!

     

    样例程序:

    下载Sun JSF RI

    https://javaserverfaces.dev.java.net/files/documents/1866/78307/jsf-1_2_07.zip

    将其解压缩,在子目录中包含了samples目录,samples目录中包含了cardemo应用程序。

     

    Sun JSF RI中附带的cardemo样例程序的主要功能是提供了汽车的购买流程。主要包含以下子功能,根据链接、按钮或者地图选择区域,进入不同区域语言的汽车一览表,在汽车一览表中,包含了汽车的标题、描述等信息。选择某一种类的汽车,可以进入到汽车详细说明页面,对汽车的各种指标参数进行了选择,可以自定义要选择的指标参数来计算汽车的价格。选择汽车后,可以进入个人用户注册和购买页面,最后完成购买。

     

    图片流程如下:

    主页面:

    可以通过地图、链接和按钮进入不同语言的汽车列表页面。选择English链接或者English按钮,进入汽车一览表:

    上图中的四种车型分别为Jalopy(老爷车)Luxury(豪华汽车)Roadster(赛车)SUV(越野车)。通过点击More按钮,进入到汽车的详细介绍,选择Jalopy汽车:

    在汽车详细信息的初始页面,提供了最基本的汽车配件,即基础价格,可以通过点击按钮来选择不同的种类,例如自定义、标准、高性能、豪华,从而价格也不同。

    在自定义情况下,可以通过选择不同的选项,然后重新计算价钱:

    在选择购买后,会进入购买确认页面:

    在用户信息页面填写购买用户的信息:

    如果在上图中注册的内容有问题的话,会提示错误信息:

    输入正确的Credit Card Number后,可以完成购买:

     

    应用程序结构讲解:

    本样例程序涉及到的知识有本地化、转换器、验证器、页面跳转、Bean等内容,下面一一介绍。

    首先介绍Java代码:

    CarBean

    bean封装了一个car模型,包括car的价格和设备选项自定义这bean的属性,通CarCustomizer助完成

    数据访问

    是系中唯一个行数据的复杂持久化的bean,在有的实现中,持久化数据存ResourceBunder例中。

    一共使用了三种类型的ResourceBundle文件:

    <ModelName>个包含了模型的本地化信息。有多个文件来支持不同的locale,例如Jalopy_de.properties

    <Common_properties>包含了所有模型都适用的本地化信息。

    <ModelName_options>包含了模型的非本地化信息,包括非本地化选项于所有的locales,只有一个文件,例如Jalopy_options.properties

    所有的文件都遵循以下的范:

    key

    key_componentType

    key_valueType

    keycar的一个属性,例如basePricekeyComponentTypeUIComponent型,用于在面中表示个属性,例如SelectManyMenukey_valueTypeUIComponent件的型,例如java.lang.Integer于所有的非String值类型。

    bean例化的候,加上述的属性文件,并迭代个属性文件中的keykeycomponentType,然后使用Application该类型的件。然后将UIComponent例存componentsMap中,并以key它的keykeyvalueType于非java.lang.String型,使用ApplicationConverter例,如果成功生成,那使用它将key对应value转换成合适的型,并作UIComponent例的value

    CarBean共有四个属性,分别为:

    private ResourceBundle resources = null;

    /** Price data */

    private ResourceBundle priceData = null;

    /**

     * Keys: String attribute name, such as engine. Values: UIComponent

     * for the attribute

     */

    private Map<String, UIComponent> components = null;

    /**

     * Keys: String attribute name, such as engine. Values: String value

     * of the component named by key in our components Map.

     */

    private Map<String,Object> attributes = null;

    其中resourcespriceData分别在初始化的时候进行加载,componentsattributes在初始化的时候将components中的UIComponent进行实例化,并进行值得填充。

    其中,在属性文件中的格式如下:

    title=Duke's Stripped-Down Jalopy

    title_componentType=javax.faces.Output

    title_valueType=java.lang.String

    在加载属性文件后,获取ResourceBundle对象,然后进行值得填充:

    private void initComponentsFromProperties(FacesContext context,ResourceBundle data) {

        // populate the map

        for (Enumeration<String> keys = data.getKeys(); keys.hasMoreElements();) {

            String key = keys.nextElement();

            if (key == null) {

                continue;

            }

            // skip secondary keys.

            if (key.contains("_")) {

                continue;

            }

            String value = data.getString(key);

            String componentType = data.getString(key + "_componentType");

            String valueType = data.getString(key + "_valueType");

           

            // create the component for this componentType

            UIComponent component =

                  context.getApplication().createComponent(componentType);

            populateComponentWithValue(context, component, componentType,

                                       value, valueType);

            components.put(key, component);

        }

    }

    priceData中存储了各种类型的配件的价格,在Custom.propertiesStandard.propertiesPerformance.propertiesDeluxe.properties四个文件分别保存了不同的组件的配置情况,然后在OptionPrice.properties中定义个各个组件的价格。

    例如:Standard.properties的内容为:

    sunroof=true

    sunroof_disabled=true

    cruisecontrol=true

    cruisecontrol_disabled=true

    keylessentry=true

    keylessentry_disabled=true

    securitySystem=false

    securitySystem_disabled=true

    skirack=true

    skirack_disabled=true

    towPackage=false

    towPackage_disabled=true

    gps=false

    gps_disabled=true

     

    engine=V4

    brake=Disc

    suspension=Regular

    speaker=4

    audio=Standard

    transmission=Auto

    OptionPrice.properties的内容如下:

    V4=100

    V6=200

    V8=300

    Disc=100

    Drum=200

    Regular=150

    Performance=300

    4=100

    6=200

    Standard=100

    Premium=200

    Auto=300

    Manual=200

    sunroof=100

    cruisecontrol=150

    keylessentry=100

    skirack=200

    securitySystem=100

    skiRack=200

    towPackage=200

    gps=200

    用户在页面组合配件,然后使用配件价格的和加上基础价格(basePrice)作为汽车的总价格(currentPrice)

    也就是说,updatePrice操作应该在重新计算价格的时候被调用。

     

    CarCustomizer

    该类是一个协助类,用于对CarBean进行自定义。该类从属性文件中读取所有的设置。该类初始化时,默认使用Custom.properties作为ResourceBundle。该类有两个成员变量,分别为:

    /**

     * The options of the CarBean.

     */

    private ResourceBundle bundle = null;

    /**

     * for the display of specified button,selected or not.

     */

    private String buttonStyle = null;

    该类中的实际的业务方法为public void customizeCar(CarBean toCustomize)用于对一个CarBean进行自定义。它从Custom.propertiesStandard.properties等文件中读取属性,然后去Jalopy_options.propertiesSUV.properties文件中去比较,然后设置组件的值。

     

    CarStore

    这个类是应用程序的主要Bean。它维护了两个Map对象,一个是以模型名为key,以CarBeanvalue;另外一个是以packagekey,以CarCustomizervalue。其中包含CarBean实例的Map在多个页面中被使用。如下所述:

    应用程序中的很多页面使用这个bean作为引用值和引用表达式。

    "chooseLocale"面使用actionListener属性来指向chooseLocaleFromMapchooseLocaleFromLink方法。

    "storeFront"面使用值绑定表达式来知名的模型的汽的信息

    "carDetail"使用值绑定表达式将当前定的模型信息示。适用action属性来提交用package选择

    "confirmChoices"面使用值绑定表达式来将用当前的选择显示。

          

    该类的属性如下:

    /**

     * <p>The locales to be selected for each hotspot, keyed by the

     * alternate text for that area.</p>

     */

    private Map<String, Locale> locales = null;

    /** <p>The currently selected car model.</p> */

    private String currentModelName = DEFAULT_MODEL;

    /**

     * <p>The car models we offer.</p>

     * <p/>

     * <p>Keys: Strings that happen to correspond to the name of the

     * packages.</p>

     * <p/>

     * <p>Values: CarBean instances</p>

     */

    private Map<String, CarBean> carModels = null;

    /**

     * <p>Keys: Strings that happen to correspond to the name of the

     * Properties file for the car (without the package prefix).</p>

     * <p/>

     * <p>Values: CarBeanCustomizer instances</p>

     */

    private Map<String, CarCustomizer> carCustomizers = null;

    在进入页面后,可以根据不同的区域语言选择进入不同语言的汽车页面,这是通过设置UIViewRootlocale属性完成的:

    public void chooseLocaleFromMap(ActionEvent actionEvent) {

        AreaSelectedEvent event = (AreaSelectedEvent) actionEvent;

        String current = event.getMapComponent().getCurrent();

        FacesContext context = FacesContext.getCurrentInstance();

        context.getViewRoot().setLocale(locales.get(current));

        resetMaps();

    }

     

    public void chooseLocaleFromLink(ActionEvent event) {

        String current = event.getComponent().getId();

      &