Skip to content
lixia edited this page Aug 4, 2014 · 9 revisions

概要说明

此为旧版本文档,与新版框架不一致!会尽快更新最新版本说明文档

为了提升基于开发框架进行应用开发的UI一致性和规范性,提升前端开发效率,开发框架在Struts基础标签库之上对一些常用的UI组件进行了扩展封装成tld标签库组件,开发人员只需简单在JSP页面按照与Struts标准标签基本相似的用法即可方便的使用相关UI组件。

主要代码资源链接:

设计思路要点

### 对于Form/Data Validation的增强

基于Javascript的前端表单校验和基于Java逻辑的服务端校验应该说都是非常重要的,前端校验可以有效的提升用户UI交互友好度,并且减少不必要数据校验目的的服务器交互;服务端校验则是评价一个系统安全性、健壮性的重要环节,因为对于Web应用来说其访问的便捷性也决定了其及其容易受到恶意用户的攻击,只需要熟悉基本的HTTP请求原理和工具,即可轻易绕过前端的数据校验直接对服务器发起非法数据请求。

对于前端来说有比较多成熟的Javascript/JQuery表单校验插件,如本框架选择的JQuery Validation。对于服务端校验,Struts层面有Struts Validator,但是总感觉非常繁琐;而现在开始流行的linkJSR303 Bean Validation把数据校验移到更细粒度的业务层乃至实体层,如本框架选择的Hibernate Validator。

前面说到前后端校验都非常重要,但是经常感觉二者存在烦人的阻抗,前端校验逻辑在相关JS组件中定义,服务端校验逻辑在相关XML文件或Java代码注解形式定义,这就很容易带来一个问题,有时前端校验逻辑改了忘了改后端逻辑,反之亦然。对于这一点本框架试图找到一个好的衔接点能一定程度解决这个问题,这也是这套自定义扩展标签库一个重要的增强点。

扩展的表单元素标签会基于当前属性定义通过Java反射机制,尝试根据属性的类型、JSR303 Validator注解、Hibernate Entity注解等自动组合生成JQuery Validator语法的HTML输出,从而实现只需在Java代码层面定义校验逻辑即可前后端同步数据校验。从实际效果来看这样的处理基本能从容应付九成以上的常见表单校验需求,当然标签也考虑到一些特殊情况而提供扩展的validator属性用于覆盖标签的自动化处理。

以下各标签中关于此问题常见属性定义说明:

/** 
 * 如果在元素中未定义此属性,则按照属性的类型、JSR303 Validator注解、Hibernate注解等自动组合生成JQuery Validator校验语法字符串
 * 如果在元素中定义此属性则以直接定义属性值作为JQuery Validator校验语法字符串,不再进行自动校验逻辑计算处理 
 */
    protected String validator;

Form表单数据的提交Confirm确认处理

对于一些简单的单一字段值校验,如唯一性/可用性等,可以采用JQuery Validation标准的remote方法实现。但是对于一些复杂业务逻辑表单,有些数据需要进行复杂的组合校验,并且有些校验属于预警类需要用户一个反馈是否确认提交表单,比如典型的销售单提交时一般需要检查一下当前的可售库存,如果发现可售库存紧张或没有了,这时一般需要反馈用户这些预警信息,由用户来confirm确认是否允许库存不足情况下超卖下单,如果用户取消则不会创建任何数据库数据而是停留在表单界面以便用户修改数据再次提交;如果用户确认继续,则自动继续提交表单创建数据。

用法示例:

    @MetaData("采购订单保存")
    public HttpHeaders doSave() {
        //先进行常规的must数据校验
    
        //检测本次提交表单没有用户已confirm确认标识,则进行相关预警校验检查
        if (postNotConfirmedByUser()) {
            List<String> messages = Lists.newArrayList();
            if (true) {//改成实际的可售库存校验逻辑,反馈到前端提示用户确认是否超卖
                messages.add("商品[123]库存紧张,可用库存量[2]");
                messages.add("商品[234]库存紧张,可用库存量[3]");
            }
            if (messages.size() > 0) {
                setModel(OperationResult.buildConfirmResult("销售单数据处理警告", messages));
                //直接返回使用户进行Confirm确认
                return buildDefaultHttpHeaders();
            }

            //所有must和confirm校验都通过,则进行业务数据提交
            super.doSave();
        }

与Bootstrap CSS Framework的集成

根据bootstrap 2.2.2官方文档和样例,编辑界面form表单采用form-horizontal样式,为了简化大量重复的control-group/control-label/controls层次化html元素编码,把这些重复率高的代码块抽取到标签库中;尽可能根据各组件特性定义相关默认属性值,如输入元素的cssClass,emptyOption属性等。

对于元素ID属性值生成的微调

Struts标签基类UIBean中对于id属性值做了一定的escape考虑,具体可参考其protected String escape(String name)源码实现。但是在实际使用中发现一个问题,类似<s:textfield name="search['CN_aclCode']" />这样基于Map方式定义的name属性按照Struts默认规则解析为id后会包含单引号,刚好会和Javascript的语法冲突。自定义标签中做了一个简单的容错处理:如果没有明确定义id属性值,则采用生成随机字符串赋给id属性值,从而规避单双引号问题。

主要定制标签介绍说明

以下主要结合主要Java代码及注释和相关示意截图介绍框架扩展的标签列表,具体细节请直接参考相关代码实现。

  • PrivilegeTag
/**
 * 基于当前登录用户的权限代码集合,按照code属性和权限比较type类型,控制页面元素的显示
 * 用法示例: <s2:privilege code="P001">受控HML内容,如按钮、文本等</s2:privilege>
 */
public class PrivilegeTag extends TagSupport {

    /** 权限代码,如果是多个可逗号分隔 */
    private String code;

    /** 多权限代码处理类型: 
     * hasAny=任何权限符合则通过,hasAll=要求全部匹配才通过,notAll=所有都必须不匹配, notAny=任何一个都不能匹配
     */
    private String type = "hasAny";
  • S2ButtonTag
/**
 * HTML Button元素封装,主要方便JSP页面基于OGNL的disabled属性控制按钮状态
 * 用法示例:
 * <s2:button cssClass="btn btn-submit submit-post-close" disabled="disallowAudit">
 *    <i class="icon-check"></i> 提交审批
 * </s2:button>
 */
public class S2ButtonTag extends AbstractClosingTag {

    /** 基于HTML Button元素的type类型属性定义:button、reset、submit */
    protected String type;
  • S2CheckboxListTag
/**
 * 扩展标准的checkboxlist标签提供自动化表单数据校验处理支持
 */
public class S2CheckboxListTag extends CheckboxListTag {

    protected String validator;
  • S2ComboSelectTag
/**
 * 扩展标准的select标签,提供自动化数据校验处理支持
 * 并以Combo组件风格样式呈现下拉框,支持根据输入(拼音)自动提示选择option项目
 * 从而使用户可以更高效便捷的定位选取下拉行项
 * 示例: <s2:comboselect name="mzm" label="民族" list="%{findEnumValuesByType('ZD_GB_MZM')}"/> 
 */
public class S2ComboSelectTag extends SelectTag {

    protected String validator;

S2ComboSelectTag

  • S2ComboTextTag
/**
 * 扩展标准的select标签,提供自动化数据校验处理支持
 * 并以Combo组件风格样式呈现下拉框,支持根据输入(拼音)自动提示选择option项目,
 * 并允许自由输入非下拉框选项的文本,简单说就是可输入可选择的下拉输入框
 * 
 * 主要用在一些查询界面或常用短语、分类等属性维护
 * 示例:<s2:combotext cssClass="input-medium" list="distinctCategories" name="search['CN_category']" />
 */
public class S2ComboTextTag extends SelectTag {

    protected String validator;

S2ComboTextTag

  • S2AutocompleteTextFieldTag
/**
 * 基于JQuery UI AutoComplete封装自动输入提示完成组件
 */
public class S2AutocompleteTextFieldTag extends TextFieldTag {

    /** JQuery UI AutoComplete对应属性: 触发AJAX数据请求的最小字符长度 */
    protected String minLength;
    /** JQuery UI AutoComplete对应属性: 触发AJAX数据请求的延迟 */
    protected String delay;
    /** JQuery UI AutoComplete对应属性: AJAX数据请求URL */
    protected String source;
    /** 初始化显示的字面值 */
    protected String labelValue;

S2AutocompleteTextFieldTag

  • S2DateTextFieldTag
/**
 * 基于日历/时间选取组件封装的日期/时间录入组件
 * 示例:<s2:datetextfield name="search['AD_createdDate']" format="date" cssClass="input-small" /> 
 */
public class S2DateTextFieldTag extends TextFieldTag {

    /** 
     * 日期格式,支持几个预定义格式属性值:date=yyyy-MM-dd, timestamp=yyyy-MM-dd HH:mm:ss 
     * 其余则按照 @see DateFormat 提供格式字符串即可
     */
    protected String format = "yyyy-MM-dd";

    /**
     * 在通过OGNL未获取到对应的日期值的情况下,是否默认初始化为当前系统时间
     */
    protected Boolean current = Boolean.FALSE;

    protected String validator;

S2DateTextFieldTag

  • S2MultiSelectTag
/**
 * 提供一个可展开收拢效果的select组件,实现灵活的单一或多选选取
 * 主要用在查询界面,默认按照单选下拉框显示单一条件查询,
 * 用户也可点击右侧展开成多选形式方便选择多选项OR查询
 * 示例:<s2:multiselect cssClass="input-medium" name="search['IN_type']" list="#application.menuTypeEnumMap" /> 
 */
public class S2MultiSelectTag extends SelectTag {

    protected String validator;

S2MultiSelectTag

  • S2FormTag

/**
 * 提供一个扩展form标签,如果没有提供id属性值则以随机生成id值从而避免相同id冲突问题
 */
public class S2FormTag extends FormTag {

    /**
     * 标签默认会生成form表单缺省的JQuery Validation初始化Javascript代码
     * 可以设定此属性autoValidate为false从而可以自行编写表单校验逻辑
     */
    protected String autoValidate = "true";
    
  • S2PasswordTag
/**
 * 扩展标准的password标签,提供自动化数据校验处理支持
 */
public class S2PasswordTag extends PasswordTag {

    protected String validator;
  • S2RadioTag
/**
 * 扩展标准的radio标签,提供自动化数据校验处理支持
 * 及其他如样式等默认值定义
 */
public class S2RadioTag extends RadioTag {

    protected String validator;
  • S2SelectTag
/**
 * 扩展标准的select标签,提供自动化数据校验处理支持
 * 及其他如样式等默认值定义
 */
public class S2SelectTag extends SelectTag {

    protected String validator;  
  • S2TabbedpanelTag
/**
 * 基于JQuery UI Tabs组件的标签封装
 * 示例:<s2:tabbedpanel id="privilegeIndexTabs"><li>..</li><div>...</div></s2:tabbedpanel> 
 */
public class S2TabbedpanelTag extends AbstractClosingTag {

    /**
     * 是否把除第一个Tab以外的其他初始化为disabled
     * 主要用于在数据创建界面,一般默认基本信息编辑Tab可操作,
     * 其他则disabled待第一个基本信息编辑操作完成后刷新页面使其他Tab界面可编辑
     */
    protected String disableItemsExcludeFirst;

S2TabbedpanelTag

  • S2TextareaTag
/**
 * 扩展标准的textarea标签,提供自动化数据校验处理支持
 * 及其他如样式等默认值定义
 */
public class S2TextareaTag extends TextareaTag {
    
    protected String validator;
  • S2TextFieldTag
/**
 * 扩展标准的textfield标签,提供自动化数据校验处理支持
 * 及其他如样式等默认值定义
 */
public class S2TextFieldTag extends TextFieldTag {

    protected String validator;
  • S2TreeInputTag
/**
 * 基于下拉输入框样式的树形结构数据选取组件
 * 示例:<s2:treeinput name="parentName" label="父节点" hiddenName="parentId" 
           treeDataUrl="/sys/menu!list" readonly="true" value="%{parent.title}" hiddenValue="%{parent.id}" />
 */
public class S2TreeInputTag extends TextFieldTag {

    protected String validator;

    /** 展开树形数据选取界面时AJAX异步加载Tree结构数据的URL */
    protected String treeDataUrl;

    /** 默认选取文本带入输入框显示,节点对应底层的Value值以隐藏元素hiddenName存取 */
    protected String hiddenName;

    /** hiddenName隐藏元素初始化值 */
    protected String hiddenValue;

S2MultiSelectTag

  • S2SingleFileTag
/**
 * 单文件上传关联组件
 * 基本原理:基于JQuery File Upload插件,选取文件后自动请求/sys/attachment-file!uploadSingle上传当前附件,
 * 之后把创建的AttachmentFile数据的主键和文件名称信息带回表单输入元素,
 * 业务功能Controller代码需要自行处理回传的AttachmentFile对象关联逻辑
 * 示例:<s2:singlefile name="templateFileId" labelValue="%{templateFile.fileRealName}" 
                      label="附件" value="%{templateFile.id}" />
 */
public class S2SingleFileTag extends TextFieldTag {

    protected String validator;

    /** 附件名称显示字面值 */
    protected String labelValue;

S2SingleFileTag

  • S2FileTag
/**
 * 生成基于自定义的附件文件对象的显示和下载链接
 * 示例:<s2:file value="r2File" label="关联附件"/>
 */
public class S2FileTag extends ComponentTagSupport {

    /** Bootstrap样式label属性定义 */
    private String label;

    /** 返回附件对象实例   @see File.FileDef  */
    private String value;

S2FileTag

  • S2DateTag
/**
 * 扩展标准的s:date标签,生成Bootstrap样式的日期显示
 * 在format标准支持上添加date和timestamp两种内置转换处理
 */
public class S2DateTag extends DateTag {

    /** Bootstrap样式label属性定义 */
    private String label;
  • S2KindEditorTag
/**
 * 基于KindEditor封装的大文本录入组件标签
 * 用法示例:<s2:kindeditor name="description" label="描述" rows="3"/>
 */
public class S2KindEditorTag extends TextareaTag {

    /**
     * 配置编辑器的工具栏,其中”/”表示换行,”|”表示分隔符。
     * http://www.kindsoft.net/docs/option.html#items
     * 未提供参数取组件默认配置项,内置“simple”表示简单配置项,其余可按照组件文档提供配置项定义
     */
    protected String items;

S2KindEditorTag

  • S2DynamicTableTag
/**
 * 针对类似批量订单行项编辑业务场景,提供一个动态表格组件,实现基础的表格行项元素动态增减处理
 */
public class S2DynamicTableTag extends AbstractClosingTag {

    /** 可选参数,默认值为1:控制删除剩余最少行项数 */
    protected String minRows;
    /** 可选参数:控制最大添加行项数 */
    protected String maxRows;
    /** 可选参数:点击添加行项回调函数,一般用于为行项元素做额外初始化处理,row参数为当前添加行项的JQuery TR对象实例 */
    protected String afterAdd;

S2DynamicTableTag

  • S2PropertyTag
/**
 * 扩展标准的s:property标签,生成Bootstrap样式的属性数据显示
 */
public class S2PropertyTag extends PropertyTag {

    /** Bootstrap样式label属性定义 */
    private String label;
Clone this wiki locally