|
2012年12月10日
在用 extjs editorgridpanel 进行输入编辑的时候, 默认情况下只支持使用 tab 键可以实现焦点切换, 如果想让editorgridpanel 在编辑时通过方向键来实现焦点跳转切换,只需加上以下代码: //让grid支持方向键盘 by liongis@163.com Ext.override(Ext.grid.CellSelectionModel, { onEditorKey : function(field, e) { var smodel = this; var k = e.getKey(), newCell, g = smodel.grid, ed = g.activeEditor; switch(k){ case e.TAB: e.stopEvent(); ed.completeEdit(); if (e.shiftKey) { newCell = g.walkCells(ed.row, ed.col-1, -1, smodel.acceptsNav, smodel); } else { newCell = g.walkCells(ed.row, ed.col+1, 1, smodel.acceptsNav, smodel); } if (ed.col == 1) { if (e.shiftKey) { newCell = g.walkCells(ed.row, ed.col+1, -1, smodel.acceptsNav, smodel); } else { newCell = g.walkCells(ed.row, ed.col+1, 1, smodel.acceptsNav, smodel); } } break; case e.UP: e.stopEvent(); ed.completeEdit(); newCell = g.walkCells(ed.row-1, ed.col, -1, smodel.acceptsNav, smodel); break; case e.DOWN: e.stopEvent(); ed.completeEdit(); newCell = g.walkCells(ed.row+1, ed.col, 1, smodel.acceptsNav, smodel); break; case e.LEFT: e.stopEvent(); ed.completeEdit(); newCell = g.walkCells(ed.row, ed.col-1, -1, smodel.acceptsNav, smodel); break; case e.RIGHT: e.stopEvent(); ed.completeEdit(); newCell = g.walkCells(ed.row, ed.col+1, 1, smodel.acceptsNav, smodel); break; } if (newCell) { g.startEditing(newCell[0], newCell[1]); } } }); 注意:这里重写的是:CellSelectionModel ,而不是RowSelectionMode 原文出自: http://www.cnblogs.com/liongis/p/3284620.html
序言: 1.本文摘自网络,看控件命名像是4.0以前的版本,但控件属性配置仍然可以借鉴(不足之处,以后项目用到时再续完善)。 Ext.form.TimeField: 配置项: maxValue:列表中允许的最大时间 maxText:当时间大于最大值时的错误提示信息 minValue:列表中允许的最小时间 minText:当时间小于最小值时的错误提示信息 increment:两个相邻选项间的时间间隔,默认为15分钟 format:显示格式,默认为“g:i A”。一般使用“H:i:s” H:带前缀0的24小时 i:带前缀0的分钟 s:带前缀0的秒 invalidText:当时间值非法时显示的提示信息 altFormats:多个时间输入格式组成的字符串,不同的格式之间使用“|”进行分割 Ext.form.FieldSet animCollapse:动画折叠,默认为false checkboxToggle:设置是否显示字段集的checkbox选择框,默认为false checkboxName:指定字段集中用于展开或隐藏字段集面板的checkbox的名字,该属性只有在checkboxToggle为true时生效 labelWidth:字段标签的宽度,可以级联到子容器 layout:布局,默认为form Ext.form.DateFied maxValue:允许选择的最大日期 maxText:当日期大于最大值时的错误提示信息 minValue:允许选择的最小时间 minText:当日期小于最小值时的错误提示信息 format:日期显示格式,默认为“m/d/y”,一般使用“Y-m-d” Y:四位年份 m:带前缀0的月份 d:带前缀0的日期 y:两位年份 n:不带前缀0的月份 j:不带前缀0的日期 w:星期的数字,0表示星期日,1代表星期一 showToday:是否显示今天按钮,默认为true altFormats:多个日期输入格式组成的字符串,不同的格式之间使用“|”进行分割,默认值为'm/d/Y|n/j/Y|n/j/y|m/j /y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d' disabledDates:禁止选择的日期组成的数组 disabledDatesText:选择禁选日期时显示的提示信息 disabledDays:禁止选择的星期组成的数组,0代表星期日,1代表星期一 disabledDaysText:选择禁选星期时显示的提示信息 invalidText:当日期值非法时显示的提示信息 方法: getValue():取得日期值 Ext.form.ComboBox displayField:被显示在下拉框中的字段名 editable:是否可编辑,默认为true forceSelection:输入值是否严格为待选列表中存在的值。如果输入不存在的值,会自动选择第一个最接近的值。 hiddenName:隐藏字段的名字,如果提供该参数则一个隐藏字段将被创建,用来存储所选值,当表单提交时在服务器端可以通过该名字取得列表中的所选值 listWidth:下拉列表的宽度 minListWidth:下拉列表的最小宽度,默认为70像素 loadingText:当下拉框加载数据时显示的提示信息,只有当mode='remote'时才会生效 maxHeight:下拉列表框的最大高度,默认为300像素 minChars:下拉列表框自动选择前用户需要输入的最小字符数量。mode='remote'默认为4,mode='local'默认为0 mode:下拉列表框的数据读取模式。remote读取远程数据,local读取本地数据 pageSize:下拉列表框的分页大小。该项设置只在mode='remote'时生效 queryParam:查询的名字,默认为'query',将被传递到查询字符串中 allQuery:一个发往服务器用来查询全部信息的查询字符串,默认为空字符串'' selectOnFocus:当获得焦点时立刻选择一个已存在的列表项。默认为false,此项只有在editable=true时才会生效 store:列表框绑定的数据源 transform:将页面中已存在的元素转换为组合框 lazyInit:延时初始化下拉列表,默认为true lazyRender:延时渲染,默认为false triggerAction:设置单击触发按钮时执行的默认操作,有效值包括all和query,默认为query,如果设置为all则会执行allQuery中设置的查询 typeAhead:设置在输入过程中是否自动选择匹配的剩余部分文本(选择第一个满足条件的),默认为false value:初始化组合框中的值 valueField:组合框的值字段 valueNotFoundText:值不存在时的提示信息 tpl:Ext模板字符串或模板对象,可以通过该配置项自定义下拉列表的显示方式 方法: clearValue():清空字段当前值 doQuery( String query, Boolean forceAll ): getValue(): getStore(): setValue( String value ): Ext.from.RadioGroup allowBlank: blankText: Ext.form.Radio; getGroupValue(): setValue( value {String/Boolean} ): Ext.form.CheckboxGroup allowBlank:是否允许不选择,默认为true blankText: columns:显示的列数,可选值包括:固定值auto、数值、数组(整数、小数) items:对象数组 vertical:是否垂直方向显示对象,默认为false Ext.form.Checkbox boxLabel:复选框的文字描述 checked:复选框是否被选择,默认为false handler:当checked值改变时触发的函数,函数包含两个参数:checkbox、checked inputValue: 方法: getValue():返回复选框的checked状态 setValue( Boolean/String checked ): Ext.form.NumberField allowDecimals:是否允许输入小数,默认为true allowNegative:是否允许输入负数,默认为true baseChars:输入的有效数字集合,默认为'0123456789' decimalPrecision:数字的精度,默认保留小数点后2位 decimalSeparator:十进制分隔符,默认为'.' maxValue:允许输入的最大数值 maxText:超过最大值之后的提示信息 minValue:允许输入的最小数值 minText:超过最小值之后的提示信息 nanText:输入非有效数值之后的提示信息 Ext.form.TextArea preventScrollbars:是否禁止出现滚动条,默认为false Ext.form.TextField allowBlank:是否允许为空,默认为true blankText:空验证失败后显示的提示信息 emptyText:在一个空字段中默认显示的信息 grow:字段是否自动伸展和收缩,默认为false growMin:收缩的最小宽度 growMax:伸展的最大宽度 inputType:字段类型:默认为text maskRe:用于过滤不匹配字符输入的正则表达式 maxLength:字段允许输入的最大长度 maxLengthText:最大长度验证失败后显示的提示信息 minLength:字段允许输入的最小长度 minLengthText:最小长度验证失败后显示的提示信息 regex:正则表达式 regexText:正则表达式验证失败后显示的提示信息 vtype:验证类型的名字 alpha:限制只能输入字母 alphanum:限制只能输入字母和数字 email url vtypeText:验证失败时的提示信息 validator:自定义验证函数 selectOnFocus:当字段得到焦点时自动选择已存在的文本,默认为false Ext.form.Field name:字段名 value:字段的初始化值 disabled:字段是否不可用,默认为false fieldLabel:字段标签说明 hideLabel:隐藏字段标签,默认为false labelSeparator:字段标签与字段之间的分隔符,默认为':' labelStyle:字段标签样式 inputType:默认为text invalidClass:默认为x-form-invalid invalidText:字段非法文本提示 msgTarget:错误信息显示的位置,默认为qtip qtip:显示一个浮动的提示信息 title:显示一个浏览器的浮动提示信息 under:在字段下方显示一个提示信息 side:在字段右边显示一个提示信息 readOnly:字段是否只读,默认为false validateOnBlur:字段在失去焦点时被验证,默认为true 方法: clearInvalid(): getRawValue() setRawValue( Mixed value ) getValue() setValue( Mixed value ) isDirty():字段值在装载后是否被修改过 isValid( Boolean preventMark ):当前字段值是否合法 markInvalid( [String msg] ) validate() reset() Ext.form.FormPanel items:一个元素或元素数组 buttons:一个按钮配置对象的数组,按钮将被添加到表单页脚中 buttonAlign:按钮的对齐方式,可选值有left、center、right,默认为center labelWidth:表单标签的宽度 labelAlign:表单标签的对齐方式,可选值有left、top、right,默认为left labelSeparator:字段标签与字段之间的分隔符,默认为':' minButtonWidth:按钮的最小宽度,默认为75 方法: getForm() : Ext.form.BasicForm load( Object options ) startMonitoring() stopMonitoring() Ext.form.BaseicForm baseParams:传递到请求中的参数 method:表单的提交方式,有效值包括GET、POST url:表单默认的提交路径 fileUpload:表单是否进行文件上传 timeout:表单动作的超时时间,默认为30秒 trackResetOnLoad:是否在表单初次创建时清楚数据 方法: doAction( String/Object actionName, [Object options] ):执行一个预订的动作,可用选项包括: url:动作提交的路径 method:表单的提交方式,有效值包括GET、POST params:传递到请求中的参数 headers: success:执行成功后回调的函数,包括两个参数:form和action failure:执行失败后回调的函数,包括两个参数:form和action clientValidation:是否客户端验证 clearInvalid():清除表单中所有的无效验证信息 findField( String id ):查找表单字段 getValues( [Boolean asString] ): isDirty():表单数据是否被更改过 isValid():客户端验证是否成功 load( Object options ):执行表单读取动作 loadRecord( Record record ):从一个数据记录中读取数据到表单中 markInvalid( Array/Object errors ):成批设置表单字段为验证无效 reset():重置表单 setValues( Array/Object values ):成批设置表单字段值 submit( Object options ):执行表单提交动作 updateRecord( Record record ):持久化表单数据到记录集中 Ext.form.Action success:执行成功后回调的函数,包括两个参数:form和action failure:执行失败后回调的函数,包括两个参数:form和action method:表单的提交方式,有效值包括GET、POST params:传递到请求中的参数 url:动作提交的路径 waitMsg:动作执行时显示的等待信息 属性: Action.CLIENT_INVALID:客户端验证错误 Action.CONNECT_FAILURE:通信错误 Action.LOAD_FAILURE:加载数据时,没有包含data属性的字段被返回 Action.SERVER_INVALID:服务端验证错误 failureType:错误类型 result:包含布尔类型的success属性和其他属性,如{success: true, msg: 'ok'} type:动作类型,可选值有submit和load Ext.form.Action.Submit:返回的信息中要包含一个布尔类型的success属性和一个可选的errors属性 Ext.form.Action.Load:返回的信息中要包含一个布尔类型的success属性和一个data属性 Ext.grid.EditorGridPanel clicksToEdit:设置点击单元格进入编辑模式的点击次数,默认为2 autoEncode:是否自动编码/解码HTML内容,默认为false selModel:默认为Ext.grid.CellSelectionModel 主要方法: startEditing( Number rowIndex, Number colIndex ):开始编辑指定单元格 stopEditing( [Boolean cancel] ):结束编辑操作 Ext.grid.GroupinView enableGroupingMenu:是否在表头菜单中进行分组控制,默认为true groupByText:表头菜单中分组控制的菜单文字,默认为'Group By This Field' enableNoGroups:是否允许用户关闭分组功能,默认为true showGroupsText:在表头菜单中启用分组和禁用分组的菜单文字,默认为'Show in Groups' groupTextTpl:用于渲染分组信息的模板,默认为'{text}',常用的可选值有: text:列标题:组字段值 gvalue:组字段的值 startRow:组行索引 enableGrouping:是否对数据分组,默认为true hideGroupedColumn:是否隐藏分组列,默认为false ignoreAdd:在向表格中添加数据时是否刷新表格,默认为false showGroupName:是否在分组行上显示分组字段的名字,默认为true startCollapsed:初次显示时分组是否处于收缩状态,默认为false 主要方法: collapseAllGroups():收缩所有分组行 expandAllGroups():展开所有分组行 getGroupId( String value ):根据分组字段值取得组id toggleAllGroups( [Boolean expanded] ):切换所有分组行的展开或收缩状态 toggleGroup( String groupId, [Boolean expanded] ):切换指定分组行的展开或收缩状态 2、Ext.data.GroupingStore groupField:分组字段 groupOnSort:是否在分组字段上排序,默认为false remoteGroup:是否远程分组数据,默认为false。如果是远程分组数据,则通过groupBy参数发送分组字段名 Ext.grid.GridPanel: store:表格的数据集 columns:表格列模式的配置数组,可自动创建ColumnModel列模式 autoExpandColumn:自动充满表格未用空间的列,参数为列id,该id不能为0 stripeRows:表格是否隔行换色,默认为false cm、colModel:表格的列模式,渲染表格时必须设置该配置项 sm、selModel:表格的选择模式,默认为Ext.grid.RowSelectionModel enableHdMenu:是否显示表头的上下文菜单,默认为true enableColumnHide:是否允许通过标题中的上下文菜单隐藏列,默认为true loadMask:是否在加载数据时显示遮罩效果,默认为false view:表格视图,默认为Ext.grid.GridView viewConfig:表格视图的配置对象 autoExpandMax:自动扩充列的最大宽度,默认为1000 autoExpandMin:自动扩充列的最小宽度,默认为50 columnLines:是否显示列分割线,默认为false disableSelection:是否禁止行选择,默认为false enableColumnMove:是否允许拖放列,默认为true enableColumnResize:是否允许改变列宽,默认为true hideHeaders:是否隐藏表头,默认为false maxHeight:最大高度 minColumnWidth:最小列宽,默认为25 trackMouseOver:是否高亮显示鼠标所在的行,默认为true 主要方法: getColumnModel():取得列模式 getSelectionModel():取得选择模式 getStore():取得数据集 getView():取得视图对象 reconfigure( Ext.data.Store store, Ext.grid.ColumnModel colModel ):使用一个新的数据集和列模式重新配置表格组件
2、Ext.grid.Column 主要配置项: id:列id header:表头文字 dataIndex:设置列与数据集中数据记录的对应关系,值为数据记录中的字段名称。如果没有设置该项则使用列索引与数据记录中字段的索引进行对应 width:列宽 align:列数据的对齐方式 hidden:是否隐藏列,默认为false fixed:是否固定列宽,默认为false menuDisabled:是否禁用列的上下文菜单,默认为false resizable:是否允许改变列宽,默认为true sortable:是否允许排序,默认为true renderer:设置列的自定义单元格渲染函数 传入函数的参数有: value:数据的原始值 metadata:元数据对象,用于设置单元格的样式和属性,该对象包含的属性有: css:应用到单元格TD元素上的样式名称 attr:一个HTML属性定义字符串,例如'style="color:blue"' record:当前数据记录对象 rowIndex:单元格的行索引 colIndex:单元格的列索引 store:数据集对象 xtype:列渲染器类型,默认为gridcolumn,其它可选值有booleancolumn、numbercolumn、datecolumn、templatecolumn等 editable:是否可编辑,默认为true editor:编辑器 groupName: emptyGroupText: groupable:
3、Ext.grid.ColumnModel 主要配置项: columns:字段数组 defaultSortable:是否进行默认排序,默认为false defaultWidth:默认宽度 主要方法: findColumnIndex( String col ):根据给定的dataIndex查找列索引 getColumnById( String id ):取得指定id对应的列 getColumnCount( Boolean visibleOnly ):取得列总数 getColumnHeader( Number col ):取得列的表头 getColumnId( Number index ):取得列id getDataIndex( Number col ):取得列对应的数据字段名 getIndexById( String id ):取得列索引 getTotalWidth( Boolean includeHidden ) isCellEditable( Number colIndex, Number rowIndex ) isFixed() isHidden( Number colIndex ) setColumnHeader( Number col, String header ) setColumnWidth( Number col, Number width, Boolean suppressEvent ) setDataIndex( Number col, String dataIndex ) setEditable( Number col, Boolean editable ) setEditor( Number col, Object editor ) setHidden( Number colIndex, Boolean hidden ) setRenderer( Number col, Function fn ) 4、Ext.grid.AbstractSelectionModel 主要方法: lock():锁定选择区域 unlock():解锁选择区域 isLocked():当前选择区域是否被锁定 5、Ext.grid.CellSelectionModel 主要方法: clearSelections( Boolean preventNotify ):清除选择区域 getSelectedCell():取得当前选择的单元格,返回一数组,其格式:[rowIndex, colIndex] hasSelection():当前是否有选择区域 select( Number rowIndex, Number colIndex, [Boolean preventViewNotify], [Boolean preventFocus], [Ext.data.Record r] ):选择指定单元格 6、Ext.grid.RowSelectionModel 主要配置项: singleSelect:是否单选模式,默认为false,即可以选择多条数据
主要方法: clearSelections( [Boolean fast] ):清除所有选择区域 deselectRange( Number startRow, Number endRow ):取消范围内的行选择 deselectRow( Number row, [Boolean preventViewNotify] ):取消指定行的选择状态 each( Function fn, [Object scope] ):遍历所有选择行,并调用指定函数。当前被选行将传入该函数中 getCount():得到选择的总行数 getSelected():得到第一个被选记录 getSelections():得到所有被选记录的数组 hasNext():判断当前被选行之后是否还有记录可以选择 hasPrevious():判断当前被选行之前是否还有记录可以选择 hasSelection():是否已选择了数据 isIdSelected( String id ):判断指定id的记录是否被选择 isSelected( Number/Record index ):判断指定记录或记录索引的数据是否被选择 selectAll():选择所有行 selectFirstRow():选择第一行 selectLastRow( [Boolean keepExisting] ):选择最后行 keepExisting:是否保持已有的选择 selectNext( [Boolean keepExisting] ):选择当前选择行的下一行 selectPrevious( [Boolean keepExisting] ):选择当前选择行的上一行 selectRange( Number startRow, Number endRow, [Boolean keepExisting] ):选择范围内的所有行 selectRecords( Array records, [Boolean keepExisting] ):选择一组指定记录 selectRow( Number row, [Boolean keepExisting], [Boolean preventViewNotify] ):选择一行 row:行索引 selectRows( Array rows, [Boolean keepExisting] ):选择多行 rows:行索引数组 7、Ext.grid.CheckboxSelectionModel 主要配置项: singleSelect:是否单选模式,默认为false,即可以选择多条数据 checkOnly:是否只能通过点击checkbox列进行选择,默认为false sortable:是否允许checkbox列排序,默认为false width:checkbox列的宽度,默认为20 8、Ext.grid.RowNumberer 主要配置项: header:行号列表头显示的内容 width:列宽,默认为23 9、Ext.grid.GridView 主要配置项: enableRowBody:是否包含行体 sortAscText:表格标题菜单中升序的文字描述 sortDescText:表格标题菜单中降序的文字描述 columnsText:表格标题菜单中列对应的文字描述 autoFill:是否自动扩展列以充满整个表格,默认为false forceFit:是否强制调整表格列宽以适用表格的整体宽度,防止出现水平滚动条,默认为false
主要方法: focusCell( Number row, Number col ):将焦点移到指定单元格 focusRow( Number row ):将焦点移动指定行 getCell( Number row, Number col ):取得指定单元格对应的td元素 getHeaderCell( Number index ):取得指定表头对应的td元素 getRow( Number index ):取得指定行对应的tr元素 getRowClass( Record record, Number index, Object rowParams, Store store ):得到附加到表格行上的样式名 record:当前行的数据记录对象 index:当前行的索引 rowParams:渲染时传入到行模板中的配置对象,通过它可以为行体定制样式,该对象只在enableRowBody为true时才生效,可能的属性如下: body:渲染到行体中的HTML代码片段 bodyStyle:应用到行体tr元素style属性的字符串 cols:应用到行体td元素colspan属性的值,默认为总列数 store:表格数据集 refresh( [Boolean headersToo] ):刷新表格组件 scrollToTop():滚动表格到顶端 Ext.TabPanel: activeTab:初始激活的tab,索引或者id值,默认为none autoTabs:是否自动将带有'x-tab'样式类的div转成tabs添加到TabPanel中,默认为false。 当该配置项设为true时,需要设置deferredRender为false,还必须使用applyTo。 deferredRender:是否延迟渲染,默认为true。 autoTabSelector:默认为'div.x-tab'。 resizeTabs:是否可以改变tab的尺寸,默认为false。 minTabWidth:tab的最小宽度,默认为30。 tabWidth:每个新增加的tab宽度,默认为120。 tabTip:tab的提示信息 tabPosition:tab位置,可选值有top、bottom,默认为top。 enableTabScroll:是否允许Tab溢出时可以滚动,默认为false。 closable:tab是否可关闭,默认为false scrollDuration:每次的滚动时长,默认为0.35毫秒。 scrollIncrement:每次的滚动步长,默认为100像素。 wheelIncrement:每次鼠标滑轮的滚动步长,默认为20像素。 2、主要方法: activate( String/Panel tab ) getActiveTab():获取当前活动的tab get( String/Number key ):根据组件id或者索引获取组件 getItem(String id):根据tab id获取tab setActiveTab( String/Number item ) remove( Component/String component, [Boolean autoDestroy] ) removeAll( [Boolean autoDestroy] ) 在使用TabPanel时需要注意: 1、在创建Ext.TabPanel时deferredRender配置项经常会被忽略。该配置项的默认值是true。true表示只有在用户第一次访问 选项卡时,该选项卡的panel才会被渲染。 所以当我们有可能使用脚本操作选项卡时,谨记将该配置项设置为false。 2、在FormPanel中使用TabPanel,如果在TabPanel中不定义deferredRender的值为false,那么,当你使用 Load方法为Form加载数据,或使用setValue为没有激活过的Panel的控件赋值时,将会发生错误。原因是,在默认设置下 deferredRender为true,TabPanel并不会渲染所有Panel上的控件,只有在该Panel被激活时才渲染控件,所以当你为这些控 件设置数据时,将会找不到这些控件,会出现错误。因而,在FormPanel中使用TabPanel,一定要在TabPanel中设置 deferredRender的值为false,强制TabPanel在Layout渲染时同时渲染所有Panel上的控件。 本文转自: http://www.cnblogs.com/knowledgesea/p/3284404.html
摘要: 前言:最近公司有个Web要发布,但是以前都是由实施到甲方去发布,配置,这几天有点闲,同事让我搞一个一键发布,就和安装软件那样的程序,好让实施直接 配置一下数据库就可以了,然后到网上搜了下,找到一些相关的教程,现在整理了一下,花了一个下午的时间来写笔记,写好了,首先奉献给博客园的小伙伴们,和 大伙儿分享一下,好了,下面进入主题~~~ 1,首先打开VS2010,新建一个项目,如图1-1所示: &nbs... 阅读全文
大家可以参考下这个网站http://eoffice.im.fju.edu.tw/phpbb/viewtopic.php?p=28685
1.先启动项目上的h2/bin下的h2.bat或h2w.bat文件,把h2数据库启动起来 2.SSH2框架和h2数据库整合方法 2.1先在数据库下创建 schema目录(相当于一个数据库实例) create schema fdrkftcode 目的是解决这种异常org.h2.jdbc.JdbcSQLException: Schema "fdrkftcode" not found; ... 2.2在schema目录下创建表,如创建系统用户表admin create table fdrkftcode.admin( id int primary key, adminname varchar(50), username varchar(50), userpwd varchar(50), adminrights varchar(50), createdate datetime, usedtimes int, lastlogin datetime, curstatus int, remark varchar(200) ) 3.为了使用hibernate操作h2,需要作如下设置,在sql编辑窗口输入下面这些脚本 对于实体pojo对象的映射,我是用的annotation,关键是id主键的映射,如下: @Column(name = "ID", nullable = false) @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ABC_ID_SEQ") @SequenceGenerator(name = "ABC_ID_SEQ", sequenceName = "ABC_ID_SEQ") protected Long id; 注意这里的GeneratedValue和SequenceGenerator的使用,这属于JPA规范,全部来自javax.persisten 4.配置applicationContext.xml文件,主要有三个地方要注意: 4.1修改连接数据库的JDBC驱动 driverClass的值为org.h2.Driver 4.2修改连接数据库所用的URL字符串 jdbcUrl的值为jdbc:h2:tcp://localhost/~/FDRKFTCODE;MODE=MySQL;AUTO_SERVER=TRUE 4.3修改Hibernate的数据库方言hibernate.dialect为org.hibernate.dialect.H2Dialect 5.h2数据库一些常用操作 5.1帮助命令help 5.2表中某字段重命名 ALTER TABLE fdrkftcode.admin ALTER COLUMN usepwd rename to userpwd 5.3表中新增字段 ALTER TABLE fdrkftcode.admin ADD IF NOT EXISTS abc varchar(50) 5.4表中删除字段 ALTER TABLE fdrkftcode.admin DROP COLUMN IF EXISTS abc 5.5查找表中记录 SELECT * from fdrkftcode.admin 5.6往表中插入记录 INSERT INTO fdrkftcode.admin VALUES (1,'管理员','admin','admin','10000000000000000000','2013-05-1 00:12:34',3,'2013-05-1 15:32:57',1,'超过级管理员') 5.7修改表中某记录 UPDATE fdrkftcode.admin SET fdrkftcode.admin.adminname='超级管理员' where fdrkftcode.admin.id=1 5.8删除表中某记录 DELETE FROM fdrkftcode.admin WHERE fdrkftcode.admin.id=1 6.下面是我项目的applicationContext.xml配置方法,大家可以参考下 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <!-- 定义使用C3P0连接池的数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 指定连接数据库的JDBC驱动 --> <property name="driverClass"> <value>org.h2.Driver</value> </property> <!-- 连接数据库所用的URL --> <property name="jdbcUrl"> <value>jdbc:h2:tcp://localhost/~/FDRKFTCODE;MODE=MySQL;AUTO_SERVER=TRUE</value> </property> <!-- 连接数据库的用户名 --> <property name="user"> <value>sa</value> </property> <!-- 连接数据库的密码 --> <property name="password"> <value></value> </property> <!-- 设置数据库连接池的最大连接数 --> <property name="maxPoolSize"> <value>50</value> </property> <!-- 设置数据库连接池的最小连接数 --> <property name="minPoolSize"> <value>5</value> </property> <!-- 设置数据库连接池的初始化连接数 --> <property name="initialPoolSize"> <value>5</value> </property> <!-- 设置数据库连接池的连接的最大空闲时间,单位为秒 --> <property name="maxIdleTime"> <value>20</value> </property> </bean> <!-- 定义Hibernate的SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- 依赖注入上面定义的数据源dataSource --> <property name="dataSource" ref="dataSource"/> <!-- 注册Hibernate的ORM映射文件 --> <property name="mappingResources"> <list> <value>com/sungoal/ORM/Admin.hbm.xml</value> </list> </property> <!-- 设置Hibernate的相关属性 --> <property name="hibernateProperties"> <props> <!-- 设置Hibernate的数据库方言 --> <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop> <!-- 设置Hibernate是否在控制台输出SQL语句,开发调试阶段通常设为true --> <prop key="show_sql">true</prop> <!-- 设置Hibernate一个提交批次中的最大SQL语句数 --> <prop key="hibernate.jdbc.batch_size">50</prop> </props> </property> </bean> <!--定义Hibernate的事务管理器HibernateTransactionManager --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <!-- 依赖注入上面定义的sessionFactory --> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 装配通用数据库访问类BaseDAOImpl --> <bean id="dao" class="com.sungoal.DAO.BaseDAOImpl"> <!-- 依赖注入上面定义的sessionFactory --> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 部署系统用户管理业务控制器AdminAction --> <bean id="adminAction" class="com.sungoal.struts.action.AdminAction" scope="prototype"> <property name="dao" ref="dao"/> </bean> </beans>
hibernate.properties ###################### ### Query Language ### ###################### ## define query language constants / function names hibernate.query.substitutions yes 'Y', no 'N' ## select the classic query parser #hibernate.query.factory_class org.hibernate.hql.classic.ClassicQueryTranslatorFactory ################# ### Platforms ### ################# ## JNDI Datasource #hibernate.connection.datasource jdbc/test #hibernate.connection.username db2 #hibernate.connection.password db2 ## HypersonicSQL hibernate.dialect org.hibernate.dialect.HSQLDialect hibernate.connection.driver_class org.hsqldb.jdbcDriver hibernate.connection.username sa hibernate.connection.password hibernate.connection.url jdbc:hsqldb:./build/db/hsqldb/hibernate #hibernate.connection.url jdbc:hsqldb:hsql://localhost #hibernate.connection.url jdbc:hsqldb:test ## H2 (www.h2database.com) #hibernate.dialect org.hibernate.dialect.H2Dialect #hibernate.connection.driver_class org.h2.Driver #hibernate.connection.username sa #hibernate.connection.password #hibernate.connection.url jdbc:h2:mem:./build/db/h2/hibernate #hibernate.connection.url jdbc:h2:testdb/h2test #hibernate.connection.url jdbc:h2:mem:imdb1 #hibernate.connection.url jdbc:h2:tcp://dbserv:8084/sample; #hibernate.connection.url jdbc:h2:ssl://secureserv:8085/sample; #hibernate.connection.url jdbc:h2:ssl://secureserv/testdb;cipher=AES ## MySQL #hibernate.dialect org.hibernate.dialect.MySQLDialect #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect #hibernate.connection.driver_class com.mysql.jdbc.Driver #hibernate.connection.url jdbc:mysql:///test #hibernate.connection.username gavin #hibernate.connection.password ## Oracle #hibernate.dialect org.hibernate.dialect.OracleDialect #hibernate.dialect org.hibernate.dialect.Oracle9Dialect #hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver #hibernate.connection.username ora #hibernate.connection.password ora #hibernate.connection.url jdbc:oracle:thin:@localhost:1521:orcl #hibernate.connection.url jdbc:oracle:thin:@localhost:1522:XE ## PostgreSQL #hibernate.dialect org.hibernate.dialect.PostgreSQLDialect #hibernate.connection.driver_class org.postgresql.Driver #hibernate.connection.url jdbc:postgresql:template1 #hibernate.connection.username pg #hibernate.connection.password ## DB2 #hibernate.dialect org.hibernate.dialect.DB2Dialect #hibernate.connection.driver_class com.ibm.db2.jcc.DB2Driver #hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver #hibernate.connection.url jdbc:db2://localhost:50000/somename #hibernate.connection.url jdbc:db2:somename #hibernate.connection.username db2 #hibernate.connection.password db2 ## TimesTen #hibernate.dialect org.hibernate.dialect.TimesTenDialect #hibernate.connection.driver_class com.timesten.jdbc.TimesTenDriver #hibernate.connection.url jdbc:timesten:direct:test #hibernate.connection.username #hibernate.connection.password ## DB2/400 #hibernate.dialect org.hibernate.dialect.DB2400Dialect #hibernate.connection.username user #hibernate.connection.password password ## Native driver #hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver #hibernate.connection.url jdbc:db2://systemname ## Toolbox driver #hibernate.connection.driver_class com.ibm.as400.access.AS400JDBCDriver #hibernate.connection.url jdbc:as400://systemname ## Derby (not supported!) #hibernate.dialect org.hibernate.dialect.DerbyDialect #hibernate.connection.driver_class org.apache.derby.jdbc.EmbeddedDriver #hibernate.connection.username #hibernate.connection.password #hibernate.connection.url jdbc:derby:build/db/derby/hibernate;create=true ## Sybase #hibernate.dialect org.hibernate.dialect.SybaseDialect #hibernate.connection.driver_class com.sybase.jdbc2.jdbc.SybDriver #hibernate.connection.username sa #hibernate.connection.password sasasa #hibernate.connection.url jdbc:sybase:Tds:co3061835-a:5000/tempdb ## Mckoi SQL #hibernate.dialect org.hibernate.dialect.MckoiDialect #hibernate.connection.driver_class com.mckoi.JDBCDriver #hibernate.connection.url jdbc:mckoi:/// #hibernate.connection.url jdbc:mckoi:local://C:/mckoi1.0.3/db.conf #hibernate.connection.username admin #hibernate.connection.password nimda ## SAP DB #hibernate.dialect org.hibernate.dialect.SAPDBDialect #hibernate.connection.driver_class com.sap.dbtech.jdbc.DriverSapDB #hibernate.connection.url jdbc:sapdb://localhost/TST #hibernate.connection.username TEST #hibernate.connection.password TEST #hibernate.query.substitutions yes 'Y', no 'N' ## MS SQL Server #hibernate.dialect org.hibernate.dialect.SQLServerDialect #hibernate.connection.username sa #hibernate.connection.password sa ## JSQL Driver #hibernate.connection.driver_class com.jnetdirect.jsql.JSQLDriver #hibernate.connection.url jdbc:JSQLConnect://1E1/test ## JTURBO Driver #hibernate.connection.driver_class com.newatlanta.jturbo.driver.Driver #hibernate.connection.url jdbc:JTurbo://1E1:1433/test ## WebLogic Driver #hibernate.connection.driver_class weblogic.jdbc.mssqlserver4.Driver #hibernate.connection.url jdbc:weblogic:mssqlserver4:1E1:1433 ## Microsoft Driver (not recommended!) #hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver #hibernate.connection.url jdbc:microsoft:sqlserver://1E1;DatabaseName=test;SelectMethod=cursor ## The New Microsoft Driver #hibernate.connection.driver_class com.microsoft.sqlserver.jdbc.SQLServerDriver #hibernate.connection.url jdbc:sqlserver://localhost ## jTDS (since version 0.9) #hibernate.connection.driver_class net.sourceforge.jtds.jdbc.Driver #hibernate.connection.url jdbc:jtds:sqlserver://1E1/test ## Interbase #hibernate.dialect org.hibernate.dialect.InterbaseDialect #hibernate.connection.username sysdba #hibernate.connection.password masterkey ## DO NOT specify hibernate.connection.sqlDialect ## InterClient #hibernate.connection.driver_class interbase.interclient.Driver #hibernate.connection.url jdbc:interbase://localhost:3060/C:/firebird/test.gdb ## Pure Java #hibernate.connection.driver_class org.firebirdsql.jdbc.FBDriver #hibernate.connection.url jdbc:firebirdsql:localhost/3050:/firebird/test.gdb ## Pointbase #hibernate.dialect org.hibernate.dialect.PointbaseDialect #hibernate.connection.driver_class com.pointbase.jdbc.jdbcUniversalDriver #hibernate.connection.url jdbc:pointbase:embedded:sample #hibernate.connection.username PBPUBLIC #hibernate.connection.password PBPUBLIC ## Ingres ## older versions (before Ingress 2006) #hibernate.dialect org.hibernate.dialect.IngresDialect #hibernate.connection.driver_class ca.edbc.jdbc.EdbcDriver #hibernate.connection.url jdbc:edbc://localhost:II7/database #hibernate.connection.username user #hibernate.connection.password password ## Ingres 2006 or later #hibernate.dialect org.hibernate.dialect.IngresDialect #hibernate.connection.driver_class com.ingres.jdbc.IngresDriver #hibernate.connection.url jdbc:ingres://localhost:II7/database;CURSOR=READONLY;auto=multi #hibernate.connection.username user #hibernate.connection.password password ## Mimer SQL #hibernate.dialect org.hibernate.dialect.MimerSQLDialect #hibernate.connection.driver_class com.mimer.jdbc.Driver #hibernate.connection.url jdbc:mimer:multi1 #hibernate.connection.username hibernate #hibernate.connection.password hibernate ## InterSystems Cache #hibernate.dialect org.hibernate.dialect.Cache71Dialect #hibernate.connection.driver_class com.intersys.jdbc.CacheDriver #hibernate.connection.username _SYSTEM #hibernate.connection.password SYS #hibernate.connection.url jdbc:Cache://127.0.0.1:1972/HIBERNATE ################################# ### Hibernate Connection Pool ### ################################# hibernate.connection.pool_size 1 ########################### ### C3P0 Connection Pool### ########################### #hibernate.c3p0.max_size 2 #hibernate.c3p0.min_size 2 #hibernate.c3p0.timeout 5000 #hibernate.c3p0.max_statements 100 #hibernate.c3p0.idle_test_period 3000 #hibernate.c3p0.acquire_increment 2 #hibernate.c3p0.validate false ############################## ### Proxool Connection Pool### ############################## ## Properties for external configuration of Proxool hibernate.proxool.pool_alias pool1 ## Only need one of the following #hibernate.proxool.existing_pool true #hibernate.proxool.xml proxool.xml #hibernate.proxool.properties proxool.properties ################################# ### Plugin ConnectionProvider ### ################################# ## use a custom ConnectionProvider (if not set, Hibernate will choose a built-in ConnectionProvider using hueristics) #hibernate.connection.provider_class org.hibernate.connection.DriverManagerConnectionProvider #hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider #hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider #hibernate.connection.provider_class org.hibernate.connection.ProxoolConnectionProvider ####################### ### Transaction API ### ####################### ## Enable automatic flush during the JTA beforeCompletion() callback ## (This setting is relevant with or without the Transaction API) #hibernate.transaction.flush_before_completion ## Enable automatic session close at the end of transaction ## (This setting is relevant with or without the Transaction API) #hibernate.transaction.auto_close_session ## the Transaction API abstracts application code from the underlying JTA or JDBC transactions #hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory #hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory ## to use JTATransactionFactory, Hibernate must be able to locate the UserTransaction in JNDI ## default is java:comp/UserTransaction ## you do NOT need this setting if you specify hibernate.transaction.manager_lookup_class #jta.UserTransaction jta/usertransaction #jta.UserTransaction javax.transaction.UserTransaction #jta.UserTransaction UserTransaction ## to use the second-level cache with JTA, Hibernate must be able to obtain the JTA TransactionManager #hibernate.transaction.manager_lookup_class org.hibernate.transaction.JBossTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.WeblogicTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.WebSphereTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.OrionTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.ResinTransactionManagerLookup ############################## ### Miscellaneous Settings ### ############################## ## print all generated SQL to the console #hibernate.show_sql true ## format SQL in log and console hibernate.format_sql true ## add comments to the generated SQL #hibernate.use_sql_comments true ## generate statistics #hibernate.generate_statistics true ## auto schema export #hibernate.hbm2ddl.auto create-drop #hibernate.hbm2ddl.auto create #hibernate.hbm2ddl.auto update #hibernate.hbm2ddl.auto validate ## specify a default schema and catalog for unqualified tablenames #hibernate.default_schema test #hibernate.default_catalog test ## enable ordering of SQL UPDATEs by primary key #hibernate.order_updates true ## set the maximum depth of the outer join fetch tree hibernate.max_fetch_depth 1 ## set the default batch size for batch fetching #hibernate.default_batch_fetch_size 8 ## rollback generated identifier values of deleted entities to default values #hibernate.use_identifer_rollback true ## enable bytecode reflection optimizer (disabled by default) #hibernate.bytecode.use_reflection_optimizer true ##################### ### JDBC Settings ### ##################### ## specify a JDBC isolation level #hibernate.connection.isolation 4 ## enable JDBC autocommit (not recommended!) #hibernate.connection.autocommit true ## set the JDBC fetch size #hibernate.jdbc.fetch_size 25 ## set the maximum JDBC 2 batch size (a nonzero value enables batching) #hibernate.jdbc.batch_size 5 #hibernate.jdbc.batch_size 0 ## enable batch updates even for versioned data hibernate.jdbc.batch_versioned_data true ## enable use of JDBC 2 scrollable ResultSets (specifying a Dialect will cause Hibernate to use a sensible default) #hibernate.jdbc.use_scrollable_resultset true ## use streams when writing binary types to / from JDBC hibernate.jdbc.use_streams_for_binary true ## use JDBC 3 PreparedStatement.getGeneratedKeys() to get the identifier of an inserted row #hibernate.jdbc.use_get_generated_keys false ## choose a custom JDBC batcher # hibernate.jdbc.factory_class ## enable JDBC result set column alias caching ## (minor performance enhancement for broken JDBC drivers) # hibernate.jdbc.wrap_result_sets ## choose a custom SQL exception converter #hibernate.jdbc.sql_exception_converter ########################## ### Second-level Cache ### ########################## ## optimize chache for minimal "puts" instead of minimal "gets" (good for clustered cache) #hibernate.cache.use_minimal_puts true ## set a prefix for cache region names hibernate.cache.region_prefix hibernate.test ## disable the second-level cache #hibernate.cache.use_second_level_cache false ## enable the query cache #hibernate.cache.use_query_cache true ## store the second-level cache entries in a more human-friendly format #hibernate.cache.use_structured_entries true ## choose a cache implementation #hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider #hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider #hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider #hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider #hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider ## choose a custom query cache implementation #hibernate.cache.query_cache_factory ############ ### JNDI ### ############ ## specify a JNDI name for the SessionFactory #hibernate.session_factory_name hibernate/session_factory ## Hibernate uses JNDI to bind a name to a SessionFactory and to look up the JTA UserTransaction; ## if hibernate.jndi.* are not specified, Hibernate will use the default InitialContext() which ## is the best approach in an application server #file system #hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory #hibernate.jndi.url file:/ #WebSphere #hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory #hibernate.jndi.url iiop://localhost:900/
摘要: 这几天学习了一下Spring Security3.1,从官网下载了Spring Security3.1版本进行练习,经过多次尝试才摸清了其中的一些原理。本人不才,希望能帮助大家。还有,这次我第二次写博客啊,文体不是很行。希望 能让观看者不产生疲惫的感觉,我已经心满意足了。 一、数据库结构 先来看一下数据库结构,采用的是基于角色-资源-用户的权限... 阅读全文
我们知道,EXT的全部js是比较大的,一个ext-all-debug.js就达2m多,它的压缩版(去掉js中的换行及空格),也达600多k,这对于在网速不太快的时,下载js就得漫长的等待。 JOffice中的日历任务控件,js多达四五个,每个js大小都达70多k,尽管我们采用了后加载的方式,则当用户点击我的任务功能时,才下载该js,但这样仍然很慢,因为下载的js很慢 ,鉴于此,在互联网上使用类似Joffice类似的程序,速度会使很多开发商不敢选用ext作为开发技术。据本人当时参与移动一个内部采购平台的开发,就是因为其运行程序慢,遭到移动的终端用户的弃骂, 所以,要想用EXT来开发应用,需要解决其运行慢的特点。
我们可以从以下几种方法来提高应用程序的运行速度:
一.前期尽量少加载js.
这点在Joffice中有比较好的运用,采用的是由ScriptMgr.load方法来完成,加载完成后,其会在body中插入一个div,只要当前页面不被刷新,下次再访问该功能时,不需要再加载js function $ImportJs(viewName,callback) { var b = document.getElementById(viewName+'-hiden'); if (b != null) { var view = eval('new ' + viewName + '()'); callback.call(this, view); } else { var jsArr = eval('App.importJs.' + viewName); if(jsArr==undefined){ var view = eval('new ' + viewName + '()'); callback.call(this, view); return ; } ScriptMgr.load({ scripts : jsArr, callback : function() { Ext.DomHelper.append(document.body,"<div id='" + viewName + "-hiden' style='display:none'></div>"); var view = eval('new ' + viewName + '()'); callback.call(this, view); } }); } } package com.htsoft.core.web.filter; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class GzipJsFilter implements Filter { Map headers = new HashMap(); public void destroy() { } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { if(req instanceof HttpServletRequest) { doFilter((HttpServletRequest)req, (HttpServletResponse)res, chain); }else { chain.doFilter(req, res); } } public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("UTF-8"); for(Iterator it = headers.entrySet().iterator();it.hasNext();) { Map.Entry entry = (Map.Entry)it.next(); response.addHeader((String)entry.getKey(),(String)entry.getValue()); } chain.doFilter(request, response); } public void init(FilterConfig config) throws ServletException { String headersStr = config.getInitParameter("headers"); String[] headers = headersStr.split(","); for(int i = 0; i < headers.length; i++) { String[] temp = headers[i].split("="); this.headers.put(temp[0].trim(), temp[1].trim()); } } }
3.在WEB.xml 文件中,添加以下配置: <filter> <filter-name>GzipJsFilter</filter-name> <filter-class>com.htsoft.core.web.filter.GzipJsFilter</filter-class> <init-param> <param-name>headers</param-name> <param-value>Content-Encoding=gzip</param-value> </init-param> </filter> <filter-mapping> <filter-name>GzipJsFilter</filter-name> <url-pattern>*.gzjs</url-pattern> lt;/filter-mapping> <servlet-mapping>
4.在index.jsp中引入该压缩文件: <script type="text/javascript" src="<%=request.getContextPath()%>/ext3/ext-all.gzjs"></script> 可以看到浏览器解压后,其代码是一样的: 大家可以看到以上,这块是在外网使用的,其速度是比较快的。当然,浏览器解压这个文件需要一点时间,不过在本地解压是非常快的,可以不用管。 三、通过Js缓存,更加可以提高EXT的加载速度,关于缓存,本文不作讨论。 原文出自: http://man1900.iteye.com/blog/515058
我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等)。在单独运行的时候这些简单的处理当然不会有问题。但是,如果我们把代码打成一个jar包以后,即使将资源文件一并打包,这些东西也找不出来了。看看下面的代码: //源代码1: package edu.hxraid; import java.io.*; public class Resource { public void getResource() throws IOException{ File file=new File("bin/resource/res.txt"); BufferedReader br=new BufferedReader(new FileReader(file)); String s=""; while((s=br.readLine())!=null) System.out.println(s); } }
这段代码写在Eclipse建立的java Project中,其目录为:(其中将资源文件res.txt放在了bin目录下,以便打成jar包) 1、src/ src/edu/hxraid/Resource.java 2、bin/ bin/resource/res.txt bin/edu/hxraid/Resource.class 很显然运行源代码1是能够找到资源文件res.txt。但当我们把整个工程打成jar包以后(ResourceJar.jar),这个jar包内的目录为: edu/hxraid/Resource.class resource/res.txt 而这时jar包中Resource.class字节 码:ldc <String "bin/resource/res.txt"> [20] 将无法定位到jar包中的res.txt位置上。就算把bin/目录去掉:ldc <String "resource/res.txt"> [20] 仍然无法定位到jar包中res.txt上。 这主要是因为jar包是一个单独的文件而非文件夹,绝对不可能通过"file:/e:/.../ResourceJar.jar/resource /res.txt"这种形式的文件URL来定位res.txt。所以即使是相对路径,也无法定位到jar文件内的txt文件(读者也许对这段原因解释有些费解,在下面我们会用一段代码运行的结果来进一步阐述)。 那么把资源打入jar包,无论ResourceJar.jar在系统的什么路径下,jar包中的字节码程序都可以找到该包中的资源。这会是幻想吗? 当然不是,我们可以用类装载器(ClassLoader)来做到这一点: (1) ClassLoader 是类加载器的抽象类。它可以在运行时动态的获取加载类的运行信息。 可以这样说,当我们调用ResourceJar.jar中的Resource类时,JVM加载进Resource类,并记录下Resource运行时信息 (包括Resource所在jar包的路径信息)。而ClassLoader类中的方法可以帮助我们动态的获取这些信息: ● public URL getResource(String name) 查找具有给定名称的资源。资源是可以通过类代码以与代码基无关的方式访问的一些数据(图像、声音、文本等)。并返回资源的URL对象。 ● public InputStream getResourceAsStream(String name); 返回读取指定资源的输入流。这个方法很重要,可以直接获得jar包中文件的内容。 (2) ClassLoader是abstract的,不可能实例化对象,更加不可能通过ClassLoader调用上面两个方法。所以我们真正写代码的时候,是通过Class类中的getResource()和getResourceAsStream()方法,这两个方法会委托ClassLoader中的getResource()和getResourceAsStream()方法 。好了,现在我们重新写一段Resource代码,来看看上面那段费解的话是什么意思了: //源代码2: package edu.hxraid; import java.io.*; import java.net.URL; public class Resource { public void getResource() throws IOException{ //查找指定资源的URL,其中res.txt仍然开始的bin目录下 URL fileURL=this.getClass().getResource("/resource/res.txt"); System.out.println(fileURL.getFile()); } public static void main(String[] args) throws IOException { Resource res=new Resource(); res.getResource(); } } 运行这段源代码结果:/E:/Code_Factory/WANWAN/bin/resource/res.txt (../ Code_Factory/WANWAN/.. 是java project所在的路径) 我们将这段代码打包成ResourceJar.jar ,并将ResourceJar.jar放在其他路径下(比如 c:\ResourceJar.jar)。然后另外创建一个java project并导入ResourceJar.jar,写一段调用jar包中Resource类的测试代码: import java.io.IOException; import edu.hxraid.Resource; public class TEST { public static void main(String[] args) throws IOException { Resource res=new Resource(); res.getResource(); } } 这时的运行结果是:file:/C:/ResourceJar.jar!/resource/res.txt 我们成功的在运行时动态获得了res.txt的位置。然而,问题来了,你是否可以通过下面这样的代码来得到res.txt文件? File f=new File("C:/ResourceJar.jar!/resource/res.txt"); 当然不可能,因为".../ResourceJar.jar!/resource/...."并不是文件资源定位符的格式 (jar中资源有其专门的URL形式: jar:<url>!/{entry} )。所以,如果jar包中的类源代码用File f=new File(相对路径);的形式,是不可能定位到文件资源的。这也是为什么源代码1打包成jar文件后,调用jar包时会报出FileNotFoundException的症结所在了。 (3) 我们不能用常规操作文件的方法来读取ResourceJar.jar中的资源文件res.txt,但可以通过Class类的getResourceAsStream()方法来获取 ,这种方法是如何读取jar中的资源文件的,这一点对于我们来说是透明的。我们将Resource.java改写成: //源代码3: package edu.hxraid; import java.io.*; public class Resource { public void getResource() throws IOException{ //返回读取指定资源的输入流 InputStream is=this.getClass().getResourceAsStream("/resource/res.txt"); BufferedReader br=new BufferedReader(new InputStreamReader(is)); String s=""; while((s=br.readLine())!=null) System.out.println(s); } } 我们将java工程下/bin目录中的edu/hxraid /Resource.class和资源文件resource/res.txt一并打包进ResourceJar.jar中,不管jar包在系统的任何目录 下,调用jar包中的Resource类都可以获得jar包中的res.txt资源,再也不会找不到res.txt文件了。 原文出自: http://www.iteye.com/topic/483115
编辑代码常用快捷键 格式化代码的快捷键 Ctrl + Shift + F 格式化缩进的快捷键是 Ctrl + I,只能对选中的文本进行缩进 删除一行的快捷键是 Ctrl + D 当前窗口最大化最小化切换 Ctrl + M 转到最后进行修改的位置 Ctrl + Q 快速查找选中的字符 Ctrl + K(向下) Ctrl + Shift + K(向上) 光标放到一个括号,切换到另一个成对的括号 Ctrl + Shirt + P 在编辑过的位置进行切换 Alt + 左右方向键 阅读代码常用的快捷键 F3不解释(一些人喜欢用Ctrl + 鼠标左键) 选中方法或者变量 Ctrl + Alt + H,查找在哪些地方调用,快速阅读代码和评估代码修改必须要用到的 继承关系 F4,了解代码的框架 快速查找函数和变量 Ctrl + O,输入函数或变量的名字,比在Outline中一个一个找要快很多,但是要对代码有了解 全工程查找 Ctrl + H,代码巨多的情况下必不可少。 由于水平有限,笔者只用到了这些快捷键 如果想知道其他的快捷键 Ctrl + Shift + L 自定义格式化代码 在Preference中打开Java的Format 内建的模版是不能修改的,点击New...,随便输入一个名字,新建一个自己的模板,弹出自定义Edit窗口 可以定义的项目非常丰富,在右边还可以进行预览,就算对英文不感冒,也可以捉摸出大致的意思。对代码进行格式化的好处是不仅仅是美观,便于阅读,在 进行团队开发的时候,使用统一的格式,在合并代码的时候可以避免许多的冲突。修改完成的模版就是使用Ctrl + Shift + F格式化时的模板 自动去除无用的import,自动补全@Override和@deprecated,eclipse的Clean up 在Code Style中,除了Format还有Clean Up 和Format进行同样的操作,新建一个模板,有几个地方我决定有必要改一下 在Code Organizing标签选择Remove trailing whitespace(移除尾部的空格) 和Organzie imports 选择Organzie imports前效果 选择Organzie imports后效果 切换到Code Style标签 Use blocks in if/while/for/do statements 为if/while/for/do自动添加括号,这个因人而异,我决定即使只用一行,也应该添加括号。 点击菜单里的Source - Clean up,可以对代码进行清理,清理代码最大的好处是——移除没用的import,自动添加@Deprecated和@Override 特别是自动添加@Override,可以很清楚的明白那些函数是继承的。 代码提示 用过visual assistx的一定非常系统它的代码提示功能,我是个没有代码提示就无法Coding的人,点击菜单Windows-Preference,切换到以下窗口 找到Auto Activation,也就是红色方框中的部分,将Auto activation delay(ms): 修改为 50 将Auto activation triggers for Java:修改为 .abcdefghigklmnoprstuvwxyz,这样就能随时提示了。 最后介绍两个工具,Search Everything 根据文件名快速查找文件,ClipX剪贴板历史记录。 原文出自:http://www.cnblogs.com/sw926/p/3209615.html
1 @Entity 2 @Table(name="T_ADM_USER") 3 public class User extends GenericEntity implements Serializable { 4 5 @OneToOne(cascade = CascadeType.PERSIST) 6 @JoinColumn(name="grade_id") 7 public Grade getGrade() { 8 return grade; 9 } 10 public void setGrade(Grade grade) { 11 this.grade = grade; 12 } 13 @Column(name="user_name", insertable = true, updatable = true, nullable = true) 14 public String getUsername() { 15 return username; 16 } 17 public void setUsername(String username) { 18 this.username = username; 19 } 20 21 }
1 public class TableUtil { 2 3 public static void main(String[] args) { 4 try{ 5 6 AnnotationConfiguration cfg = new AnnotationConfiguration(); 7 cfg.addAnnotatedClass(com.mygogo.grade.user.entity.User.class); 9 SchemaExport se = new SchemaExport(cfg); 10 se.setDelimiter(";"); 11 se.drop(true, true); 12 se.create(true, true); 13 }catch(Exception e){ 14 e.printStackTrace(); 15 } 16 17 } 18 }
Servlet和Filter的url匹配以及url-pattern详解 Servlet和filter是J2EE开发中常用的技术,使用方便,配置简单,老少皆宜。估计大多数朋友都是直接配置用,也没有关心过具体的细节,今天 遇到一个问题,上网查了servlet的规范才发现,servlet和filter中的url-pattern还是有一些文章在里面的,总结了一些东西, 放出来供大家参考,以免遇到问题又要浪费时间。一 servlet容器对url的匹配过当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了(filter不同,后文会提到)。其匹配规则和顺序如下:<o:p></o:p>
1. 精确路径匹配。例子:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了。<o:p></o:p>
2. 最长路径匹配。例子:servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。<o:p></o:p>
3. 扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:*.action<o:p></o:p>
4. 如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。如果应用定义了一个default servlet,则容器会将请求丢给default servlet(什么是default servlet?后面会讲)。
根据这个规则表,就能很清楚的知道servlet的匹配过程,所以定义servlet的时候也要考虑url-pattern的写法,以免出错。 对于filter,不会像servlet那样只匹配一个servlet,因为filter的集合是一个链,所以只会有处理的顺序不同,而不会出现只选择一 个filter。Filter的处理顺序和filter-mapping在web.xml中定义的顺序相同。 二 url-pattern详解- 在web.xml文件中,以下语法用于定义映射:
- 以”/’开头和以”/*”结尾的是用来做路径映射的。
- 以前缀”*.”开头的是用来做扩展映射的。
- “/” 是用来定义default servlet映射的。
- 剩下的都是用来定义详细映射的。比如: /aa/bb/cc.action
所以,为什么定义”/*.action”这样一个看起来很正常的匹配会错?因为这个匹配即属于路径映射,也属于扩展映射,导致容器无法判断 出自: http://foxty.iteye.com/blog/39332
oracle监听不能启动的问题及处理过程! oracle环境如下: SQL> select * from V$version 2 ; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod PL/SQL Release 10.2.0.1.0 - Production CORE 10.2.0.1.0 Production TNS for 32-bit Windows: Version 10.2.0.1.0 - Production NLSRTL Version 10.2.0.1.0 - Production 出错过程回忆:在此之前用windows优化大师对系统注册表进行了修复! Q:链接oracle时报错:ORA-12541: TNS: 无监听程序 A: 1〉查看监听有没有启动: 一:运行lsnrctl C:\Documents and Settings\Admin>lsnrctl LSNRCTL for 32-bit Windows: Version 10.2.0.1.0 - Production on 20-4月 -2007 09: 1:43 Copyright (c) 1991, 2005, Oracle. All rights reserved. 欢迎来到LSNRCTL, 请键入"help"以获得信息。 二:查看stauts LSNRCTL> status 正在连接到 (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1))) TNS-12541: TNS: 无监听程序 TNS-12560: TNS: 协议适配器错误 TNS-00511: 无监听程序 32-bit Windows Error: 2: No such file or directory 正在连接到 (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=zxt)(PORT=1521))) TNS-12541: TNS: 无监听程序 TNS-12560: TNS: 协议适配器错误 TNS-00511: 无监听程序 32-bit Windows Error: 61: Unknown error 三:发现监听没有启动,现在启动监听 LSNRCTL> start 启动tnslsnr: 请稍候... Failed to start service, error 3. TNS-12560: TNS: 协议适配器错误 TNS-00530: 协议适配器错误 2〉发现监听启动不起来,估计是注册表有点问题,登录注册表 C:\Documents and Settings\Admin>regedit 进入注册表到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OracleOraDb10g_home1TNSListener 发现ImagePath关键值没有了,增加可扩充字符串值,取名为ImagePathImagePath,编辑字符串的数值数据为:G:\oracle\product\10.2.0\db_2\BIN\TNSLSNR(对应oracle的TNSLSNR的位置) ,退出注册表。 3〉启动监听 LSNRCTL> start 启动tnslsnr: 请稍候... TNSLSNR for 32-bit Windows: Version 10.2.0.1.0 - Production 系统参数文件为d:\oracle\product\10.2.0\db_1\network\admin\listener.ora 写入d:\oracle\product\10.2.0\db_1\network\log\listener.log的日志信息 监听: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1ipc))) 监听: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=zxt)(PORT=1521))) 正在连接到 (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1))) LISTENER 的 STATUS ------------------------ 别名 LISTENER 版本 TNSLSNR for 32-bit Windows: Version 10.2.0.1.0 - Produ ction 启动日期 20-4月 -2007 09:41:29 正常运行时间 0 天 0 小时 0 分 3 秒 跟踪级别 off 安全性 ON: Local OS Authentication SNMP OFF 监听程序参数文件 d:\oracle\product\10.2.0\db_1\network\admin\listener.o ra 监听程序日志文件 d:\oracle\product\10.2.0\db_1\network\log\listener.log 监听端点概要... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1ipc))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=zxt)(PORT=1521))) 服务摘要.. 服务 "PLSExtProc" 包含 1 个例程。 例程 "PLSExtProc", 状态 UNKNOWN, 包含此服务的 1 个处理程序... 命令执行成功 4>监听启动成功后尝试登录 C:\Documents and Settings\Admin>sqlplus zxt@orcl SQL*Plus: Release 10.2.0.1.0 - Production on 星期五 4月 20 09:42:33 2007 Copyright (c) 1982, 2005, Oracle. All rights reserved. 输入口令: 连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options 登录成功! 总结:估计是windows优化大师或者别的工具在修复注册表时候删掉了ImagePath字段,补上后就可以了! 补充:登录sqlplus时报 ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务错误! 处理办法: 1〉oracle_home\NETWORK\ADMIN\tnsnames.ora中修改(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) 为(ADDRESS = (PROTOCOL = TCP)(HOST = 本地计算机名)(PORT = 1521)),保存即可。 2〉有的人介绍oracle_home\NETWORK\ADMIN\sqlnet.ora中修改SQLNET.AUTHENTICATION_SERVICES = (NTS)为 SQLNET.AUTHENTICATION_SERVICES = (NONE) 这2种方法,第一个最佳!
Ext GridPanel实现复选框选择框: 1 var selectModel = new Ext.grid.CheckboxSelectionModel({ 2 singleSelect : false 3 }); 4 但是这样每一行都会有复选框,如果需求为:某行数据的某个列满足什么条件我才有复选框选项就不太好实现了,
这样就需要重写Ext.grid.CheckboxSelectionModel的渲染,行点击涵数来实现. 1 var selectModel = new Ext.grid.CheckboxSelectionModel({ 2 singleSelect : false, 3 renderer : function(v, p, record){ 4 if (record.data['结果状态'] == '0'){ 5 return ''; 6 } 7 return '<div class="x-grid3-row-checker"> </div>'; 8 }, 9 onHdMouseDown : function(e, t) { 10 if (t.className == 'x-grid3-hd-checker') { 11 e.stopEvent(); 12 var hd = Ext.fly(t.parentNode); 13 var isChecked = hd.hasClass('x-grid3-hd-checker-on'); 14 if (isChecked){ 15 hd.removeClass('x-grid3-hd-checker-on'); 16 this.clearSelections(); 17 }else { 18 hd.addClass('x-grid3-hd-checker-on'); 19 if (this.locked){ 20 return; 21 } 22 this.selections.clear(); 23 for (var i = 0, len = this.grid.store.getCount(); i < len; i++ ){ 24 if (this.grid.store.getAt(i).data["结果状态"] != '0'){ 25 this.selectRow(i, true); 26 } 27 } 28 } 29 } 30 }, 31 handleMouseDown : function(g, rowIndex, e){ 32 if (e.button !== 0 || this.isLocked()) { 33 return; 34 } 35 var view = this.grid.getView(); 36 if (e.shiftKey && !this.singleSelect && this.last != false ) { 37 var last = this.last; 38 this.selectRange(last, rowIndex, e.ctrlKey); 39 this.last = last; 40 view.focusRow(rowIndex); 41 }else{ 42 var isSelected = this.isSelected(rowIndex); 43 if (e.ctrlKey && isSelected) { 44 this.deselectRow(rowIndex); 45 }else if(!isSelected || this.getCount() > 1){ 46 if(this.grid.store.getAt(rowIndex).data["结果状态"] != '0'){ 47 this.selectRow(rowIndex, e.ctrlKey || e.shiftKey); 48 } 49 view.focusRow(rowIndex); 50 } 51 } 52 } 53 }); 原文: http://fordream.iteye.com/blog/1179252
摘要: 在学习中Ext.grid.EditorGridPanel 的时候碰到一个知识点,如何用复选框来表示真假值,当然我们可以直接这样 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->1 {2 heade... 阅读全文
Ext.grid.GridPanel可以设置stripeRows: true的属性来实现隔行换颜色的效果,如果你想自定义每行的颜色,那么你可以按照下边地方法来实现: Ext.ux.GridView=Ext.extend( Ext.grid.GridView, { getRowClass:function(record,index) { if(index%2==0) return 'red'; else return 'green'; } } )
使用自定义的view
var grid = new Ext.grid.GridPanel({ //other code store: store, view:new Ext.ux.GridView(), //other code });
样式定义: .red { background-color:#FF0000; } .green { background-color:#00FF00; }
通过firebug可以看到,给每行的div添加了自定义的样式 原文出自: http://love4j.iteye.com/blog/516007
摘要: 先上图 grid分页: 把grid和page工具绑定在一起 // create the Data Store var store = new Ext.data.Store... 阅读全文
http://yourgame.iteye.com/blog/252853
Ext中的combobox有属性typeAhead:true 可以实现模糊匹配,但是是从开始匹配的,如果需要自定的的匹配,则需要监听beforequery方法,实现自己的匹配查询方法: 代码如下: var gfxmComb = new Ext.form.ComboBox({ id : 'gfxmComb', store : gfxmStore, typeAhead : true, mode : 'local', editable : true, displayField :'xmMc', valueField :'xmBm', triggerAction : 'all', selectOnFocus : true, listeners : { 'beforequery':function(e){ var combo = e.combo; if(!e.forceAll){ var input = e.query; // 检索的正则 var regExp = new RegExp(".*" + input + ".*"); // 执行检索 combo.store.filterBy(function(record,id){ // 得到每个record的项目名称值 var text = record.get(combo.displayField); return regExp.test(text); }); combo.expand(); return false; } } } }); 原文出自:http://weibaojun.iteye.com/blog/1098731
Javascript是一门非常灵活的语言,我们可以随心所欲的书写各种风格的代码,不同风格的代码也必然也会导致执行效率的差异,开发过程中零零散散地接触到许多提高代码性能的方法,整理一下平时比较常见并且容易规避的问题 Javascript自身执行效率 Javascript中的作用域链、闭包、原型继承、eval等特性,在提供各种神奇功能的同时也带来了各种效率问题,用之不慎就会导致执行效率低下。 1、全局导入 我们在编码过程中多多少少会使用到一些全局变量(window,document,自定义全局变量等等),了解javascript作用域链的人都 知道,在局部作用域中访问全局变量需要一层一层遍历整个作用域链直至顶级作用域,而局部变量的访问效率则会更快更高,因此在局部作用域中高频率使用一些全 局对象时可以将其导入到局部作用域中,例如: 1 //1、作为参数传入模块 2 (function(window,$){ 3 var xxx = window.xxx; 4 $("#xxx1").xxx(); 5 $("#xxx2").xxx(); 6 })(window,jQuery); 7 8 //2、暂存到局部变量 9 function(){ 10 var doc = document; 11 var global = window.global; 12 } 2、eval以及类eval问题 我们都知道eval可以将一段字符串当做js代码来执行处理,据说使用eval执行的代码比不使用eval的代码慢100倍以上(具体效率我没有测试,有兴趣同学可以测试一下) JavaScript 代码在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用 var 申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是 undefined,并将那些以 function 定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。但是,如果你使用了“eval”,则“eval”中的代码(实际上为字符串)无法预先识 别其上下文,无法被提前解析和优化,即无法进行预编译的操作。所以,其性能也会大幅度降低 其实现在大家一般都很少会用eval了,这里我想说的是两个类eval的场景(new Function{} ,setTimeout ,setInterver ) setTimtout("alert(1)",1000);
setInterver("alert(1)",1000);
(new Function("alert(1)"))(); 上述几种类型代码执行效率都会比较低,因此建议直接传入匿名方法、或者方法的引用给setTimeout方法 3、闭包结束后释放掉不再被引用的变量var f = (function(){ var a = {name:"var3"}; var b = ["var1","var2"]; var c = document.getElementByTagName("li"); //****其它变量 //***一些运算 var res = function(){ alert(a.name); } return res; })() 上述代码中变量f的返回值是由一个立即执行函数构成的闭包中返回的方法res,该变量保留了对于这个闭包中所有变量(a,b,c等)的引用,因此这两个变 量会一直驻留在内存空间中,尤其是对于dom元素的引用对内存的消耗会很大,而我们在res中只使用到了a变量的值,因此,在闭包返回前我们可以将其它变 量释放 var f = (function(){ var a = {name:"var3"}; var b = ["var1","var2"]; var c = document.getElementByTagName("li"); //****其它变量 //***一些运算 //闭包返回前释放掉不再使用的变量 b = c = null; var res = function(){ alert(a.name); } return res; })() 在web开发过程中,前端执行效率的瓶颈往往都是在dom操作上面,dom操作是一件很耗性能的事情,如何才能在dom操作过程中尽量节约性能呢? 1、减少reflow 什么是reflow? 当 DOM 元素的属性发生变化 (如 color) 时, 浏览器会通知 render 重新描绘相应的元素, 此过程称为 repaint。 如果该次变化涉及元素布局 (如 width), 浏览器则抛弃原有属性, 重新计算并把结果传递给 render 以重新描绘页面元素, 此过程称为 reflow。 减少reflow的方法 -
先将元素从document中删除,完成修改后再把元素放回原来的位置(当对某元素及其子元素进行大量reflow操作时,1,2两种方法效果才会比较明显) -
将元素的display设置为”none”,完成修改后再把display修改为原来的值 - 修改多个样式属性时定义class类代替多次修改style属性(for certain同学推荐)
-
大量添加元素到页面时使用documentFragment 例如 for(var i=0;i<100:i++){ var child = docuemnt.createElement("li"); child.innerHtml = "child"; document.getElementById("parent").appendChild(child); } 上述代码会多次操作dom,效率比较低,可以改为下面的形式 创建documentFragment,将所有元素加入到docuemntFragment不会改变dom结构,最后将其添加到页面,只进行了一次reflow var frag = document.createDocumentFragment(); for(var i=0;i<100:i++){ var child = docuemnt.createElement("li"); child.innerHtml = "child"; frag.appendChild(child); } document.getElementById("parent").appendChild(frag); 2、暂存dom状态信息 当代码中需要多次访问元素的状态信息,在状态不变的情况下我们可以将其暂存到变量中,这样可以避免多次访问dom带来内存的开销,典型的例子就是: var lis = document.getElementByTagName("li"); for(var i=1;i<lis.length;i++){ //*** } 上述方式会在每一次循环都去访问dom元素,我们可以简单将代码优化如下 var lis = document.getElementByTagName("li"); for(var i=1,j=lis.length ;i<j;i++){ //*** } 3、缩小选择器的查找范围 查找dom元素时尽量避免大面积遍历页面元素,尽量使用精准选择器,或者指定上下文以缩小查找范围,以jquery为例 - 少用模糊匹配的选择器:例如
$("[name*='_fix']") ,多用诸如id以及逐步缩小范围的复合选择器$("li.active") 等 - 指定上下文:例如
$("#parent .class") ,$(".class",$el) 等 4、使用事件委托 使用场景:一个有大量记录的列表,每条记录都需要绑定点击事件,在鼠标点击后实现某些功能,我们通常的做法是给每条记录都绑定监听事件,这种做法会导致页面会有大量的事件监听器,效率比较低下。 基本原理:我们都知道dom规范中事件是会冒泡的,也就是说在不主动阻止事件冒泡的情况下任何一个元素的事件都 会按照dom树的结构逐级冒泡至顶端。而event对象中也提供了event.target(IE下是srcElement)指向事件源,因此我们即使在 父级元素上监听该事件也可以找到触发该事件的最原始的元素,这就是委托的基本原理。废话不多说,上示例 $("ul li").bind("click",function(){ alert($(this).attr("data")); }) 上述写法其实是给所有的li元素都绑定了click事件来监听鼠标点击每一个元素的事件,这样页面上会有大量的事件监听器。 根据上面介绍的监听事件的原理我们来改写一下 $("ul").bind("click",function(e){ if(e.target.nodeName.toLowerCase() ==="li"){ alert($(e.target).attr("data")); } }) 这样一来,我们就可以只添加一个事件监听器去捕获所有li上触发的事件,并做出相应的操作。 当然,我们不必每次都做事件源的判断工作,可以将其抽象一下交给工具类来完成。jquery中的delegate()方法就实现了该功能 语法是这样的$(selector).delegate(childSelector,event,data,function) ,例如: $("div").delegate("button","click",function(){ $("p").slideToggle(); }); 参数说明(引自w3school) 参数 | 描述 | childSelector | 必需。规定要附加事件处理程序的一个或多个子元素。 | event | 必需。规定附加到元素的一个或多个事件。由空格分隔多个事件值。必须是有效的事件。 | data | 可选。规定传递到函数的额外数据。 | function | 必需。规定当事件发生时运行的函数。 | Tips:事件委托还有一个好处就是,即使在事件绑定之后动态添加的元素上触发的事件同样可以监听到哦,这样就不用在每次动态加入元素到页面后都为其绑定事件了 原文出自: http://www.cnblogs.com/gewei/archive/2013/03/29/2988180.html
摘要: 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这 两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C/C++直接操作内存的危险。但是,也正因为内存管理完全由JVM负责, 所以也使Java很多程序员不再关心内存分配,导致很多程序低效,耗内存。因此就有了Java程序员到最后应该去了解JVM,才能写出更高效,充分利用有 限的内存的程序。 1... 阅读全文
在设计产品时,要考虑到到很多的因素,其中一个重要的是配色方案。不同的颜色可以使您的产品创造出不同的效果。请务必检查颜色在一般和特定的文化含义,以获得最佳使用效果。 在这篇文章中,我想向大家介绍一些有用的设计工具将帮助您选择合适的调色板为您的设计。这里有15个在线工具分析和收集的色彩组合。
转自:http://www.cnblogs.com/58top/archive/2013/01/15/useful-color-combination-apps-for-designers.html
转: http://www.cnblogs.com/58top/archive/2013/01/11/free-jquery-tooltip-plugins.html
textarea元素已被广泛用于网页Web的IDE。通常网站自带的textarea编辑器不能满足我们的需求,作为一名开发者我们经常需要进行代码的在线编辑,高亮显示代码等,因此,通过其他的开源项目,我们可以添加一些实用的功能, 在这篇文章中,我将使用 JavaScript库 ACE来创建一个输入框效果。这是一个完全开源的脚本。该脚本允许开发人员创建支持语法高亮的输入框。然后你可以代码嵌入到网站中的任何地方 下载库 首先我们需要Github上下载ACE代码。 下载完成后解压缩,在你的header部分引入js文件 <script src="src-min/ace.js" type="text/javascript" charset="utf-8"></script> 添加代码到编辑器 首先设置一个id为editor的div 然后在script里面调用ace.edit()方法,代码如下
var editor = ace.edit("editor"); editor.getSession().setMode("ace/mode/javascript"); 您可以重命名变量,为了方便起见,我定义了var editor作为变量,你也可以定义var demoeditor作为变量 。第二行声明使用哪种类型的语言高亮显示。您可以从 src 目录选择其他语言集合。这里是一些支持支持的语言集合: - SQL
- Ruby
- SASS
- PHP
- Objectivec
- Csharp
- Java
- JSON
使用额外的参数editor.setTheme("ace/theme/dawn"); editor.getSession().setTabSize(2); editor.getSession().setUseWrapMode(true); 这3行代码是关于文本输入效果的,第一行改变代码默认的语法颜色和主题,在src目录下个有几十个新的主题,你可以从中任意选择 另外两个选项是关于用户体验。通常情况下,按一个键盘上的Tab键将输入4个空格,这里我设置成2个空格,此外,该文本在默认情况下将不会自动换行,超了会追加一个水平滚动条向外延伸。但使用这种方法setUseWrapMode(true) ,我们可以修复自动换行的问题。 还有一些其他的命令,你可以参考ACE向导。这里面包含了改变光标的位置,动态添加新内容,或复制的文本的全部内容。 CSS代码 #editor { margin-left: 15px; margin-top: 15px; width: 1000px; height: 400px; } 原文出自: http://www.cnblogs.com/58top/archive/2013/01/28/building-a-syntax-highlighted-input-box-with-javascript.html
Aspect Oriented Programming 面向切面编程。解耦是程序员编码开发过程中一直追求的。AOP也是为了解耦所诞生。 具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回到横向业务流。 AOP 在Spring框架中被作为核心组成部分之一,的确Spring将AOP发挥到很强大的功能。最常见的就是事务控制。工作之余,对于使用的工具,不免需要了解其所以然。学习了一下,写了些程序帮助理解。 AOP 主要是利用代理模式的技术来实现的。 1、静态代理:就是设计模式中的proxy模式 a、业务接口 /** * 抽象主题角色:声明了真实主题和代理主题的共同接口。 * * @author yanbin * */ public interface ITalk {
public void talk(String msg);
} b、业务实现 /** * 真实主题角色:定义真实的对象。 * * @author yanbin * */ public class PeopleTalk implements ITalk {
public String username; public String age;
public PeopleTalk(String username, String age) { this.username = username; this.age = age; }
public void talk(String msg) { System.out.println(msg + "!你好,我是" + username + ",我年龄是" + age); }
public String getName() { return username; }
public void setName(String name) { this.username = name; }
public String getAge() { return age; }
public void setAge(String age) { this.age = age; }
} c、代理对象 /** * 代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。 * * @author yanbin * */ public class TalkProxy implements ITalk {
private ITalk talker;
public TalkProxy(ITalk talker) { // super(); this.talker = talker; }
public void talk(String msg) { talker.talk(msg); }
public void talk(String msg, String singname) { talker.talk(msg); sing(singname); }
private void sing(String singname) { System.out.println("唱歌:" + singname); }
} d、测试类 /** * 代理测试类,使用代理 * * @author yanbin * */ public class ProxyPattern {
public static void main(String[] args) { // 不需要执行额外方法的。 ITalk people = new PeopleTalk("AOP", "18"); people.talk("No ProXY Test"); System.out.println("-----------------------------");
// 需要执行额外方法的(切面) TalkProxy talker = new TalkProxy(people); talker.talk("ProXY Test", "代理"); }
} 从这段代码可以看出来,代理模式其实就是AOP的雏形。 上端代码中talk(String msg, String singname)是一个切面。在代理类中的sing(singname)方法是个后置处理方法。 这样就实现了,其他的辅助方法和业务方法的解耦。业务不需要专门去调用,而是走到talk方法,顺理成章的调用sing方法 再从这段代码看:1、要实现代理方式,必须要定义接口。2、每个业务类,需要一个代理类。 2、动态代理:jdk1.5中提供,利用反射。实现InvocationHandler接口。 业务接口还是必须得,业务接口,业务类同上。 a、代理类: /** * 动态代理类 * * @author yanbin * */ public class DynamicProxy implements InvocationHandler {
/** 需要代理的目标类 */ private Object target;
/** * 写法固定,aop专用:绑定委托对象并返回一个代理类 * * @param delegate * @return */ public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); }
/** * @param Object * target:指被代理的对象。 * @param Method * method:要调用的方法 * @param Object * [] args:方法调用时所需要的参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; // 切面之前执行 System.out.println("切面之前执行"); // 执行业务 result = method.invoke(target, args); // 切面之后执行 System.out.println("切面之后执行"); return result; }
} b、测试类 /** * 测试类 * * @author yanbin * */ public class Test {
public static void main(String[] args) { // 绑定代理,这种方式会在所有的方法都加上切面方法 ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk()); iTalk.talk("业务说明"); } } 输出结果会是: 切面之前执行 people talk业务说法 切面之后执行 说明只要在业务调用方法切面之前,是可以动态的加入需要处理的方法。 从代码来看,如果再建立一个业务模块,也只需要一个代理类。ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk()); 将业务接口和业务类绑定到动态代理类。 但是这种方式:还是需要定义接口。 3、利用cglib CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式。不细说,看使用 a、业务类 /** * 业务类 * * @author yanbin * */ public class PeopleTalk {
public void talk(String msg) { System.out.println("people talk" + msg); }
} b、cglib代理类 /** * 使用cglib动态代理 * * @author yanbin * */ public class CglibProxy implements MethodInterceptor {
private Object target;
/** * 创建代理对象 * * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); }
@Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object result = null; System.out.println("事物开始"); result = methodProxy.invokeSuper(proxy, args); System.out.println("事物结束"); return result; }
} c.测试类 /** * 测试类 * * @author yanbin * */ public class Test {
public static void main(String[] args) { PeopleTalk peopleTalk = (PeopleTalk) new CglibProxy().getInstance(new PeopleTalk()); peopleTalk.talk("业务方法"); peopleTalk.spreak("业务方法"); }
} 最后输出结果: 事物开始 people talk业务方法 事物结束 事物开始 spreak chinese业务方法 事物结束 由于篇幅有限,这篇主要对AOP的原理简单实现做了演示和阐述,有助自己理解。至于Spring的AOP实现上面无外乎其右,不过实现方面复杂的多。 原文出自: http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html
摘要: 摘要:ComboBox是常用控件之一,但由于其数据来源分两种形式:本地和远程,故写的形式难度并不亚于ExtJS中的TreePanel和 GridPanel。鄙人也经常提醒自己的师弟师妹,ExtJS本身是面向对象写的,不能在应用的时候却不按照面向对象来写,面向对象最起码的好处就是代 码的复用,对于网页来讲,代码复用的好处就是加载的JS会少很多,这样网页渲染时就不会很慢。下面我将分别介绍扩展的四种Co... 阅读全文
首先定义一数据源,一般使用simpleStore,jsonStore。需要注意的是simpleStore用于读取二维数组的数据,而jsonStroe用于读取json数据格式。 Combox使用simpleStore 代码如下所示: var subjectField = new Ext.form.ComboBox({ fieldLabel : '分类名称', hiddenName : 'drug.subjectCode',// 传递到后台的参数 store : new Ext.data.SimpleStore({ autoLoad : true, url :'xxx', fields : ['subjectCode', 'subjectName'] }), valueField : 'subjectCode',// 域的值,对应于store里的fields displayField : 'subjectName',// 显示的域,对应于store里的fields typeAhead : true,// 设置true,完成自动提示 mode : 'local', // 设置local,combox将从本地加载数据 triggerAction : 'all',// 触发此表单域时,查询所有 selectOnFocus : true, anchor : '90%', forceSelection : true });
服务端返回的数据结构如下所示: [ ["00000003","硬膏剂"], ["00000005","滴眼剂"], ["00000016","栓剂"], ["00000017","注射剂"], ["00000018","软膏剂"] ] 当combox使用jsonStore时,一般运用于分页查询。页面效果如下所示: 示例代码如下所示: // 药品商品名 var itemNameField = new Ext.form.ComboBox({ width : 200, fieldLabel : '药品商品名', hiddenName : 'drug.itemName', store : advanceStore, valueField : 'itemName', displayField : 'itemName', typeAhead : true, mode : 'remote',// 分页查询必须设置为 remote,当我们点击下一页的时候是从服务端取数据,而不是本地 triggerAction : 'all', emptyText : '请选择一个分类名', selectOnFocus : true, minChars : 0, // 完成自动提示,当mode为‘local’时,默认为0,当mode为‘remote’时候,默认为4,这里设置为0 pageSize : 10,// 每页显示的记录数字 queryParam :'drug.itemName' // 在combox内敲入字符时候,combox向后台查询传递的参数,这里设置为'drug.itemName'是为了更好的封装,默认传递参数‘query’ });
这里还有一个问题,就是Combox设置初始值。 我是采用如下做法的,不知道各位知不知道其他用法? var subjectField = new Ext.form.ComboBox({ fieldLabel : '分类名称', hiddenName : 'drug.subjectCode', store : new Ext.data.SimpleStore({ autoLoad : true, url : 'xxx', fields : ['subjectCode', 'subjectName'], listeners : { load : function(){ subjectField.setValue(record.get("drug.subjectCode")); } } }), valueField : 'subjectCode', displayField : 'subjectName', typeAhead : true, mode : 'local', triggerAction : 'all', emptyText : '请选择一个分类名', selectOnFocus : true, anchor : '90%', forceSelection : true });
原文出自: http://www.iteye.com/topic/296710
所有的事件回调函数都有两个参数: event和 ui,浏览器自有event对象,和经过封装的ui对象 ui.helper - 表示sortable元素的JQuery对象,通常是当前元素的克隆对象 ui.position - 表示相对当前对象,鼠标的坐标值对象{top,left} ui.offset - 表示相对于当前页面,鼠标的坐标值对象{top,left} ui.item - 表示当前拖拽的元素
ui.placeholder - 占位符(如果有定义的话) ui.sender - 当前拖拽元素的所属sortable对象(仅当元素是从另一个sortable对象传递过来时有用) ·参数(参数名 : 参数类型 : 默认值) appendTo : String : 'parent' Defines where the helper that moves with the mouse is being appended to during the drag (for example, to resolve overlap/zIndex issues). 初始:$('.selector').sortable({ appendTo: 'body' }); 获取:var appendTo = $('.selector').sortable('option', 'appendTo'); 设置:$('.selector').sortable('option', 'appendTo', 'body'); axis : String : false 如果有设置,则元素仅能横向或纵向拖动。可选值:'x', 'y' 初始:$('.selector').sortable({ axis: 'x' }); 获取:var axis = $('.selector').sortable('option', 'axis'); 设置:$('.selector').sortable('option', 'axis', 'x'); cancel : Selector : ':input,button' 阻止排序动作在匹配的元素上发生。 初始:$('.selector').sortable({ cancel: 'button' }); 获取:var cancel = $('.selector').sortable('option', 'cancel'); 设置:$('.selector').sortable('option', 'cancel', 'button'); connectWith : Selector : false 允许sortable对象连接另一个sortable对象,可将item元素拖拽到另一个中。 初始:$('.selector').sortable({ connectWith: '.otherlist' }); 获取:var connectWith = $('.selector').sortable('option', 'connectWith'); 设置:$('.selector').sortable('option', 'connectWith', '.otherlist'); containment : Element, String, Selector : false 约束排序动作只能在一个指定的范围内发生。可选值:DOM对象, 'parent', 'document', 'window', 或jQuery对象 初始:$('.selector').sortable({ containment: 'parent' }); 获取:var containment = $('.selector').sortable('option', 'containment'); 设置:$('.selector').sortable('option', 'containment', 'parent'); cursor : String : 'auto' 定义在开始排序动作时,如果的样式。 初始:$('.selector').sortable({ cursor: 'crosshair' }); 获取:var cursor = $('.selector').sortable('option', 'cursor'); 设置:$('.selector').sortable('option', 'cursor', 'crosshair'); cursorAt : Object : false 当开始移动时,鼠标定位在的某个位置上(最多两个方向)。可选值:{ top, left, right, bottom }. 初始:$('.selector').sortable({ cursorAt: 'top' }); 获取:var cursorAt = $('.selector').sortable('option', 'cursorAt'); 设置:$('.selector').sortable('option', 'cursorAt', 'top'); delay : Integer : 0 以毫秒为单位,设置延迟多久才激活排序动作。此参数可防止误点击。 初始:$('.selector').sortable({ delay: 500 }); 获取:var delay = $('.selector').sortable('option', 'delay'); 设置:$('.selector').sortable('option', 'delay', 500); distance : Integer : 1 决定至少要在元素上面拖动多少像素后,才正式触发排序动作。 初始:$('.selector').sortable({ distance: 30 }); 获取:var distance = $('.selector').sortable('option', 'distance'); 设置:$('.selector').sortable('option', 'distance', 30); dropOnEmpty : Boolean : true 是否允許拖拽到一個空的sortable对象中。 初始:$('.selector').sortable({ dropOnEmpty: false }); 获取:var dropOnEmpty = $('.selector').sortable('option', 'dropOnEmpty'); 设置:$('.selector').sortable('option', 'dropOnEmpty', false); forceHelperSize : Boolean : false If true, forces the helper to have a size. 初始:$('.selector').sortable({ forceHelperSize: true }); 获取:var forceHelperSize = $('.selector').sortable('option', 'forceHelperSize'); 设置:$('.selector').sortable('option', 'forceHelperSize', true); forcePlaceholderSize : Boolean : false If true, forces the placeholder to have a size. 初始:$('.selector').sortable({ forcePlaceholderSize: true }); 获取:var forcePlaceholderSize = $('.selector').sortable('option', 'forcePlaceholderSize'); 设置:$('.selector').sortable('option', 'forcePlaceholderSize', true); grid : Array : false 将排序对象的item元素视为一个格子处理,每次移动都按一个格子大小移动,数组值:[x,y] 初始:$('.selector').sortable({ grid: [50, 20] }); 获取:var grid = $('.selector').sortable('option', 'grid'); 设置:$('.selector').sortable('option', 'grid', [50, 20]); handle : Selector, Element : false 限制排序的动作只能在item元素中的某个元素开始。 初始:$('.selector').sortable({ handle: 'h2' }); 获取:var handle = $('.selector').sortable('option', 'handle'); 设置:$('.selector').sortable('option', 'handle', 'h2'); helper : String, Function : 'original' 设置是否在拖拽元素时,显示一个辅助的元素。可选值:'original', 'clone' 初始:$('.selector').sortable({ helper: 'clone' }); 获取:var helper = $('.selector').sortable('option', 'helper'); 设置:$('.selector').sortable('option', 'helper', 'clone'); items : Selector : '> *' 指定在排序对象中,哪些元素是可以进行拖拽排序的。 初始:$('.selector').sortable({ items: 'li' }); 获取:var items = $('.selector').sortable('option', 'items'); 设置:$('.selector').sortable('option', 'items', 'li'); opacity : Float : false 定义当排序时,辅助元素(helper)显示的透明度。 初始:$('.selector').sortable({ opacity: 0.6 }); 获取:var opacity = $('.selector').sortable('option', 'opacity'); 设置:$('.selector').sortable('option', 'opacity', 0.6); placeholderType: StringDefault: false 设置当排序动作发生时,空白占位符的CSS样式。 初始:$('.selector').sortable({ placeholder: 'ui-state-highlight' }); 获取:var placeholder = $('.selector').sortable('option', 'placeholder'); 设置:$('.selector').sortable('option', 'placeholder', 'ui-state-highlight'); revert : Boolean : false 如果设置成true,则被拖拽的元素在返回新位置时,会有一个动画效果。 初始:$('.selector').sortable({ revert: true }); 获取:var revert = $('.selector').sortable('option', 'revert'); 设置:$('.selector').sortable('option', 'revert', true); scroll : Boolean : true 如果设置成true,则元素被拖动到页面边缘时,会自动滚动。 初始:$('.selector').sortable({ scroll: false }); 获取:var scroll = $('.selector').sortable('option', 'scroll'); 设置:$('.selector').sortable('option', 'scroll', false); scrollSensitivity : Integer : 20 设置当元素移动至边缘多少像素时,便开始滚动页面。 初始:$('.selector').sortable({ scrollSensitivity: 40 }); 获取:var scrollSensitivity = $('.selector').sortable('option', 'scrollSensitivity'); 设置:$('.selector').sortable('option', 'scrollSensitivity', 40); scrollSpeed : Integer : 20 设置页面滚动的速度。 初始:$('.selector').sortable({ scrollSpeed: 40 }); 获取:var scrollSpeed = $('.selector').sortable('option', 'scrollSpeed'); 设置:$('.selector').sortable('option', 'scrollSpeed', 40); tolerance : String : 'intersect' 设置当拖动元素越过其它元素多少时便对元素进行重新排序。可选值:'intersect', 'pointer' intersect:至少重叠50% pointer:鼠标指针重叠元素 初始:$('.selector').sortable({ tolerance: 'pointer' }); 获取:var tolerance = $('.selector').sortable('option', 'tolerance'); 设置:$('.selector').sortable('option', 'tolerance', 'pointer'); zIndex : Integer : 1000 设置在排序动作发生时,元素的z-index值。 初始:$('.selector').sortable({ zIndex: 5 }); 获取:var zIndex = $('.selector').sortable('option', 'zIndex'); 设置:$('.selector').sortable('option', 'zIndex', 5); ·事件
start 当排序动作开始时触发此事件。 定义:$('.selector').sortable({ start: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortstart', function(event, ui) { ... }); sort 当元素发生排序时触发此事件。 定义:$('.selector').sortable({ sort: function(event, ui) { ... } }); 绑定:$('.selector').bind('sort', function(event, ui) { ... }); change 当元素发生排序且坐标已发生改变时触发此事件。 定义:$('.selector').sortable({ change: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortchange', function(event, ui) { ... }); beforeStop 当排序动作结束之前触发此事件。此时占位符元素和辅助元素仍有效。 定义:$('.selector').sortable({ beforeStop: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortbeforeStop', function(event, ui) { ... }); stop 当排序动作结束时触发此事件。 定义:$('.selector').sortable({ stop: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortstop', function(event, ui) { ... }); update 当排序动作结束时且元素坐标已经发生改变时触发此事件。 定义:$('.selector').sortable({ update: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortupdate', function(event, ui) { ... }); receive 当一个已连接的sortable对象接收到另一个sortable对象的元素后触发此事件。 定义:$('.selector').sortable({ receive: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortreceive', function(event, ui) { ... }); over 当一个元素拖拽移入另一个sortable对象后触发此事件。 定义:$('.selector').sortable({ over: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortover', function(event, ui) { ... }); out 当一个元素拖拽移出sortable对象移出并进入另一个sortable对象后触发此事件。 定义:$('.selector').sortable({ out: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortout', function(event, ui) { ... }); activate 当一个有使用连接的sortable对象开始排序动作时,所有允许的sortable触发此事件。 定义:$('.selector').sortable({ activate: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortactivate', function(event, ui) { ... }); deactivate 当一个有使用连接的sortable对象结束排序动作时,所有允许的sortable触发此事件。 定义:$('.selector').sortable({ deactivate: function(event, ui) { ... } }); 绑定:$('.selector').bind('sortdeactivate', function(event, ui) { ... }); ·方法
destory 从元素中移除拖拽功能。 用法:.sortable( 'destroy' ) disable 禁用元素的拖拽功能。 用法:.sortable( 'disable' ) enable 启用元素的拖拽功能。 用法:.sortable( 'enable' ) option 获取或设置元素的参数。 用法:.sortable( 'option' , optionName , [value] ) serialize 获取或设置序列化后的每个item元素的id属性。 用法:.sortable( 'serialize' , [options] ) toArray 获取序列化后的每个item元素的id属性的数组。 用法:.sortable( 'toArray' ) refresh 手动重新刷新当前sortable对象的item元素的排序。 用法:.sortable( 'refresh' ) refreshPositions 手动重新刷新当前sortable对象的item元素的坐标,此方法可能会降低性能。 用法:.sortable( 'refreshPositions' ) cancel 取消当前sortable对象中item元素的排序改变。 用法:.sortable( 'cancel' ) 排序后保存有两种方法, 一是cookie,二是 数据库配置文件等。 这个是cookie 的例子 大家可以参考 http://www.cnblogs.com/tianxiangbing/archive/2010/01/26/jquery_sortable.html 下面是数据库的部分代码 原作: $(function() { var show = $(".loader"); var orderlist = $(".orderlist"); var listleft = $("div[id = 'column_left']"); var listcenter = $("div[id = 'column_center']"); var listright = $("div[id = 'column_right']"); $( ".column" ).sortable({ opacity: 0.5,//拖动的透明度 revert: true, //缓冲效果 cursor: 'move', //拖动的时候鼠标样式 connectWith: ".column", //开始用update 结果执行两次,浪费资源,古改成stop //但是stop在元素没有改变位置的时候也会执行, //用update其他js会有问题,^_^ stop: function(){ var new_order_left = []; //左栏布局 var new_order_center = [];//中栏布局 var new_order_right = [];//右栏布局 listleft.children(".portlet").each(function() { new_order_left.push(this.title); }); listcenter.children(".portlet").each(function() { new_order_center.push(this.title); }); listright.children(".portlet").each(function() { new_order_right.push(this.title); }); var newleftid = new_order_left.join(','); var newcenterid = new_order_center.join(','); var newrightid = new_order_right.join(','); $.ajax({ type: "post", url: jsonUrl, //服务端处理程序 data: { leftid: newleftid, centerid: newcenterid, rightid:newrightid}, //id:新的排列对应的ID,order:原排列顺序 // beforeSend: function() { // show.html(" 正在更新"); // }, success: function(msg) { //alert(msg); show.html(""); } }); } }); 原文出自: http://hb-keepmoving.iteye.com/blog/1154618
图片预加载
1 (function($) { 2 var cache = []; 3 // Arguments are image paths relative to the current page. 4 $.preLoadImages = function() { 5 var args_len = arguments.length; 6 for (var i = args_len; i--;) { 7 var cacheImage = document.createElement('img'); 8 cacheImage.src = arguments[i]; 9 cache.push(cacheImage); 10 } 11 } 12 13 jQuery.preLoadImages("image1.gif", "/path/to/image2.png"); 在新窗口打开链接 (target=”blank”)1 $('a[@rel$='external']').click(function(){ 2 this.target = "_blank"; 3 }); 4 5 /* 6 Usage: 7 <a href="http://www.catswhocode.com" rel="external">catswhocode.com</a> 8 */ 当支持 JavaScript 时为 body 增加 class1 /* 该代码只有1行,但是最简单的用来检测浏览器是否支持 JavaScript 的方法,如果支持 JavaScript 就在 body 元素增加一个 hasJS 的 class */ 2 $('body').addClass('hasJS'); 平滑滚动页面到某个锚点 1 $(document).ready(function() { 2 $("a.topLink").click(function() { 3 $("html, body").animate({ 4 scrollTop: $($(this).attr("href")).offset().top + "px" 5 }, { 6 duration: 500, 7 easing: "swing" 8 }); 9 return false; 10 }); 11 }); 鼠标滑动时的渐入和渐出1 $(document).ready(function(){ 2 $(".thumbs img").fadeTo("slow", 0.6); // This sets the opacity of the thumbs to fade down to 60% when the page loads 3 4 $(".thumbs img").hover(function(){ 5 $(this).fadeTo("slow", 1.0); // This should set the opacity to 100% on hover 6 },function(){ 7 $(this).fadeTo("slow", 0.6); // This should set the opacity back to 60% on mouseout 8 }); 9 }); 制作等高的列1 var max_height = 0; 2 $("div.col").each(function(){ 3 if ($(this).height() > max_height) { max_height = $(this).height(); } 4 }); 5 $("div.col").height(max_height); 在一些老的浏览器上启用 HTML5 的支持 1 (function(){ 2 if(!/*@cc_on!@*/0) 3 return; 4 var e = "abbr,article,aside,audio,bb,canvas,datagrid,datalist,details,dialog,eventsource,figure,footer,header,hgroup,mark,menu,meter,nav,output,progress,section,time,video".split(','),i=e.length;while(i--){document.createElement(e[i])} 5 })() 6 7 //然后在head中引入该js 8 <!--[if lt IE 9]> 9 <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> 10 <![endif]--> 测试浏览器是否支持某些 CSS3 属性 1 var supports = (function() { 2 var div = document.createElement('div'), 3 vendors = 'Khtml Ms O Moz Webkit'.split(' '), 4 len = vendors.length; 5 6 return function(prop) { 7 if ( prop in div.style ) return true; 8 9 prop = prop.replace(/^[a-z]/, function(val) { 10 return val.toUpperCase(); 11 }); 12 13 while(len--) { 14 if ( vendors[len] + prop in div.style ) { 15 // browser supports box-shadow. Do what you need. 16 // Or use a bang (!) to test if the browser doesn't. 17 return true; 18 } 19 } 20 return false; 21 }; 22 })(); 23 24 if ( supports('textShadow') ) { 25 document.documentElement.className += ' textShadow'; 获取 URL 中传递的参数1 $.urlParam = function(name){ 2 var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href); 3 if (!results) { return 0; } 4 return results[1] || 0; 5 } 禁用表单的回车键提交1 $("#form").keypress(function(e) { 2 if (e.which == 13) { 3 return false; 4 } 5 });
摘要: 为什么需要元数据模型 您已经熟悉使用 Cognos 来创建报表,进行自助式设计分析,然而这些需要的创建的应用都依赖于对应的元数据模型,用户使用元数据模型对他们的数据源进行分析和报告。元数据模型是整 个 Cognos 应用的基础,它是一个或多个数据源中信息的业务演示。基于这个基础,您才能够创建报表,进行自助式设计分析。 Cognos 能支持多种数据源,包括关系型的和多维的数据库。元数据模型能隐藏底... 阅读全文
什么是自助式设计分析 自助式设计分析是指在业务人员在同一工具做即席查询、报表和分析,完全由业务用户自助式制作。并且能和自助式仪表盘、专业报表工具紧密集成。通过业务人员进行自助式设计分析可以提升业务敏捷度、提升客户满意度、快速报表制作、降低 IT 管理成本。 IBM Cognos Business Insight Advanced 是用于创建报表和分析数据的基于 Web 的工具。商业用户可通过此用户界面了解其业务。IBM Cognos Business Insight Advanced 属于一种新型报表使用环境,将为商业用户带来全面的商业智能体验。 在《第一个自助式仪表盘》介绍了使用 IBM Cognos Business Insight 创建复杂的交互式仪表盘并以预定义的方式浏览内容。在 Business Insight 仪表盘中,可处理现有的内容并进行基本分析、数据浏览和协作性决策的制定。如果要执行深入分析并要创建报表,可以切换到 Business Insight Advanced 来执行更高级的数据浏览,例如添加附加度量、条件格式化和高级计算。 在 IBM Cognos BI 10.1 版本以前,IBM Cognos Report Studio 中的“专业”和“快速”两种创建模式,从 IBM Cognos BI 10.1 版本开始,“快速”创建模式现已替换为 IBM Cognos Business Insight Advanced,专业 IT 报表创建者仍使用 Report Studio 工具创建高级报表。 Business Insight Advanced 由业务人员使用,提供比原来“快速”创建模式的功能更为强大,例如完全支持列表报表、图表和关系数据源,而且还提供了专用于数据浏览的全新用户体验。 Business Insight Advanced 用户界面重点是在浏览数据。因此某些默认行为与以前版本的 IBM Cognos Report Studio 中“快速”创建模有所不同。例如,默认情况下,在 Business Insight Advanced 双击项目现将执行向下追溯。 不论是 IBM Cognos BI 的 Report Studio、Query Studio、Analysis Studio 制作的报表,IBM Cognos Business Insight Advanced 都可以打开,并且可以由业务人员进行自助式设计分析。而 Query Studio、Analysis Studio 功能已经被 Business Insight Advanced 取代,所以 Cognos BI 10 的业务用户只需要使用 Business Insight Advanced 就足够了。Report Studio 则留给专业人员使用。 创建第一个自助式设计分析 - 在开始菜单中启动 IBM Cognos BI Developer Edition,运行 Developer Edition Manager,在确保左侧的服务都正常的情况下,点击右上角的启动,选择 Business Insight Advanced。
- 在“Cognos > 公共文件夹 > 示样 > 多维数据集”路径下,选择“Great Outdoors Sales (cube)”数据包,进入 IBM Cognos Business Insight Advanced 后选择“新建”。在选择报表类型的时候,选择“交叉表”,点击确定。
如果载入数据包报错,例如在内容存储库中找不到数据源“great_outdoors_sales_en”,则需要按照《第一次安装》的步骤检查是否正确建立了 PowerCube 数据源。 - 在右侧的“可插入对象”窗格中的“来源”选项卡显示了面向成员的数据视图。您可以看到维度数据源,也就是包括多维数据源或者按维度建模的关系数据源,在本教程中使用的是 PowerCube 多维数据源。
- 数据包是模型的子集,其中包含可以插入到报表中的项目。
- 维度是有关业务主要方面(如产品、日期或市场)的描述性数据的概括分组。
- 级别层级是维度内更具体的分组。例如,对于“年份”维度,可以将数据组织为较小的组,如“年份”、“当前月份”和“上一个月份”。
- 成员文件夹包含可用于层级或级别的成员。例如,“年”级别层级的“成员”文件夹包含“年”、“季度”和“月份”级别中的所有内容。
- 级别是包含相同详细程度信息并具有共同属性的维度层级内的位置。一个级别层级内可以存在多个级别,从根级别开始。例如,“年份”级别层级具有以下相关级别。
- 成员属性是每个成员所具有的属性。例如,性别可以是所有员工成员的属性。
图 1. 可插入对象 - 对于维度模型数据源,您可以通过单击树面板顶部的按钮来交替查看元数据树和面向成员的数据树。在本教程中选择“查看成员树”。然后把 Years 拖动到列,把 Products 拖动到行,把 Revenue 拖动到度量,如图 2 所示。
图 2. 查看成员树 - 接下来您可以了解一下在 Business Insight Advanced 展示数据的功能。使用维度数据源或按维度建模的关系数据源时,您可以向下追溯到较低级别数据集或向上追溯到较高级别数据集的报表。向上追溯和向下追溯允许 您在预定义的维度层级(例如“年 - 年 - 季度 - 月”)内查看有关数据的更加全面或更加详细的信息,而无需创建其他报表。
左键点击交叉表中的产品“Golf Equipment”两次,可以实现向下追溯的功能。双击第一列最后一行汇总标题上的“Golf Equipment”可以实现向上追溯的功能。 其实在交叉表里面的任意数据都可以实现向下追溯的功能,而选择汇总标题上的数据都可以实现向上追溯的功能。 - 在“Golf Equipment”的向下追溯的效果下,单击成员“Golf Accessories”,在数据菜单下选择“浏览”,再单击“替换”,然后单击“使用级别成员”,如图 3 所示。
图 3. 替换成员 这样就把“Golf Accessories”替换为相同级别的成员。为了帮助理解,可以参看图 4,展开面向成员的数据树,和“Golf Accessories”相同级别的成员是标注红色的那些数据项。 图 4. 级别成员 - 等待报表刷新后,右键选择任意产品类型,点击菜单“最高或最低”,选择“最高 5 (基于 Revenue, Years)”,这样就筛选出最高的 5 个产品类型。
图 5. 最高或最低 - 右键选择汇总标题上的“Golf Equipment”,点击“删除”,这样就可以把不需要的汇总行除去,如图 6 所示。
图 6. 删除汇总行 - 按住 Ctrl 键选择“Tents”和“Packs”两个产品类型,右键选择“排除成员 > 从初始集”,如图 7 所示。您会发现仍然是 5 个产品类型,但是已经不是原来的 5 个,“Tents”和“Packs”两个产品类型已经被换成另外两个。
而如果您刚才选择“排除成员 > 从当前集”,则就会剩下 3 个产品类型。 图 7. 排除成员 - 在右侧的“可插入对象”窗格中的“来源”选项卡中选择“Personal Accessories”产品类型下的后面四个成员拖拽到报表的最后一行后面,如图 8 所示。
图 8. 添加成员 - 您会看到报表有 9 个产品类型,它们分别来自两个数据集。其中 Watches 和 Eyewear 这两个产品类型在两个数据集里面都有,属于重复的产品类型。
您按住 Ctrl 键可以选择两个数据集的 Eyewear,这样就等同于选择了两个数据集。然后在数据菜单下选择“浏览”,再单击“合并到一个集中”,选择“删除重复项”,如图 9 所示。 图 9. 合并数据集 - 这样就剩下合并在一个数据集中的 7 个产品类型,Watches 和 Eyewear 也没有重复了。
右键选择任意产品类型,点击菜单“最高或最低”,选择“最低 5 (基于 Revenue, Years)”,这样就筛选出最低的 5 个产品类型。 - 按住 Ctrl 键选择 Packs 和 Navigation 两个产品类型,右键选择“移动成员”,点击 “到顶部”,如图 10 所示。Packs 和 Navigation 两个产品类型就会被放到报表的头两行。
图 10. 移动成员 - 刚才您做了很多数据集的操作,这些操作包括:
- 排除成员
- 将成员移到集的顶部或底部
- 联接多个集
- 应用最高或最低过滤器
- 过滤集
- 展开或折叠集合中的成员
在 IBM Cognos Business Insight Advanced 可以查看集定义,从而了解、更改、添加或删除可对该集执行的操作,集的定义以图形树的形式为您显示了对集执行的所有操作的历史记录。 您可以任意选择数据项,比如 Packs ,然后右键菜单选择“编辑集”。或者您也可以在“数据”菜单下选择“浏览”,找到“编辑集”的菜单项。 图形树显示了对成员集合执行的所有操作,如图 11 所示。您可以执行以下操作,在这里选择“取消”即可。 - 要查看操作详情,请将鼠标悬停在操作节点上。
- 要更改操作的顺序,请单击操作节点,然后单击向右箭头或向左箭头。
- 要编辑操作,请单击操作节点,然后单击“编辑”按钮。
- 要添加新操作,请单击“新建”按钮。
图 11. 编辑集 - 任意选择报表的数据项,右键选择“显示属性”,这样会展开报表的属性页。您可以设置报表的属性。
图 12. 设置属性 - 保存您的分析结果在“我的文件夹”下,命名为“第一个自助式设计分析”。
使用图表 IBM Cognos Business Insight Advanced 包含一种默认图表技术,该技术不同于 10.1 之前版本中使用的原始图表技术。“使用原始图表创建”选项,让您能够使用老版本的原始图表技术的报表,而不是默认的 Business Insight Advanced 图表来创建新的报表。 在《第一张交互式离线报表》,您已经去掉“使用原始图表创建”的选择,这里可以再检查一下。您可以在“工具”菜单中点击“选项”,在“高级选项”标签中,检查是否已经去掉“使用原始图表创建”的选择。 IBM Cognos Business Insight Advanced 包含丰富的图表类型: - 柱形图:对于比较离散数据或显示随时间变化的趋势非常有用。
- 折线图:对于显示随时间变化的趋势和比较多个数据序列非常有用。
- 饼形图:对于突出显示比例非常有用。
- 条形图:对于显示随时间变化的趋势和绘制多个数据序列非常有用。
- 面积图:对于强调随时间变化的更改量非常有用,堆积面积图还用于显示部分与整体的关系。
- 点状图:对于以非群集样式显示定量数据非常有用。
- 组合图:通过在一个图表内使用柱形图、面积图和折线图的组合,绘出多个数据序列。组合图对于突出显示各种数据序列之间的关系非常有用。
- 散点图:使用数据点来沿刻度的任何位置(不仅在常规刻度线处)绘出两个度量,对于浏览不同数据集之间的相互关系非常有用。
- 泡形图:使用数据点和气泡沿某一刻度的任意位置绘出度量,就像散点图一样,气泡的大小表示第三个度量,对于表示财务数据非常有用。
- 项目符号图表:是条形图的一个变体。它们可以将特色度量(项目符号)与目标度量(目标)进行对比,也可以将比对度量与背景中提供其他定性度量(如“非常满意”、“满意”和“不满意”)的彩色区域联系到一起,通常用于代替执行仪表盘中的仪表板图。
- 仪表板图:使用指针将信息显示为表盘上的读数。在有颜色的数据范围或图表轴上读取每个指针的值非常容易。此图表类型常用于执行仪表盘报表,以显示关键业务指示器。
- 排列图:通过标识事件的主要原因来帮助您改善这些过程。排列图按照从最频繁到最不频繁的顺序对类别进行排名。这些图表常用于质量控制数据,以便您确定并减少问题的主要来源。
- 渐进图:类似于堆积图,单个堆积的各分段都从下一分段垂直偏移,对于强调各分段占整体的比例非常有用。
- 象限图:将背景分成四个等区域的泡形图。象限图对于绘出包含三个度量(使用 X 轴、Y 轴和表示第三个度量值的气泡大小)的数据很有用。
- Marimekko 图表:是百分堆积图,其中列的宽度与列值的总和成正比,各个分段高度是各自列总值的百分比。
- 雷达图:将多个轴组合成一个放射状的图形。对于每个数字,均沿着从图表中心开始的单独轴绘出数据。
- 盈亏图表:是一种 Microchart 图,其中每列的值为 1 或 -1,通常表示盈利或亏损。
- 极坐标图:对于显示科学计算数据非常有用,是使用值和角度将信息显示为极坐标的圆形图。
- 在工具栏中找到“页面布局”,为报表选择预定义的页面布局。您选择 1x2 的布局,这样就能在报表旁边放置图表,如图 13 所示。页面刷新后,报表出现在左侧的单元格,而右侧的单元格是空着的。
图 13. 页面布局 - 在右侧的“工具箱”中选择图表,拖拽到右侧的单元格中。当“插入图表”提示出现时,选择饼形图,如图 14 所示。
图 14. 插入图表 - 在右侧的“来源”中选择 Gross Profit 拖拽到默认度量,把 Sales Regions 拖拽到序列(饼形图扇区)。
- 您可以尝试在饼形图上进行向下追溯和向上追溯的功能。右键选择饼形扇区,然后单击“向下追溯”或者“向上追溯”。
- 您可以将饼形扇区拉离剩余的饼形图,以突出显示饼形扇区。右键选择要拉出的饼形扇区,然后单击“分解扇区”。此时扇区会从图表中拉出。要使已拉出的扇区返回到饼形图中,请右键选择饼形图图表对象,然后单击“删除已分解的扇区”。
- 您在“查看”菜单下可以切换“页面设计”和“页面预览”,其中“页面预览”是缺省选择,这是给业务人员进行自助式设计分析用的,所见即所得,可以直接看到数据结果。而“页面设计”功能是给专业人员用的,界面类似即将在后面介绍的 Report Studio。
- 保存并退出 Business Insight Advanced。
在自助式仪表盘中打开 - 在开始菜单中启动 IBM Cognos BI Developer Edition,运行 Developer Edition Manager,在确保左侧的服务都正常的情况下,点击右上角的启动,选择 Business Insight。在 IBM Cognos Business Insight 的启动页上选择“新建”。
- 在右侧的可插入对象中选择下面的“内容”,在“我的文件夹”下,可以找到刚才保存的“第一个自助式设计分析”,展开可以发现有两个对象,分别是“交叉表 1”和“饼形图 1”。右键选择“第一个自助式设计分析”报表,选择“插入”。
- 在自助式仪表盘中,您如果想看除了报表里面 5 个产品类型以外的产品,比如想把 Lanterns 产品类型也添加到报表中。那就不能直接在 Business Insight 里面完成,可以通过选择菜单的齿轮形状的按钮“完成更多”来启动 Business Insight Advanced,如图 15 所示。等待一会以后,Business Insight Advanced 界面就出现了。
图 15. 完成更多 - 默认情况下,当您使用 IBM Cognos Business Insight Advanced 将源目录树中的成员插入到报表中时,成员将与其子项一起以集 [ 创建成员集 ] 的形式插入。您可以更改成员的插入方式。因为现在只想添加 Lanterns 产品类型,所以想要插入不带子项的成员。
为此,在“可插入对象”窗格的“来源”选项卡上,单击“插入带子项的成员”按钮,并选择插入成员的方式,选择“插入单个成员”,如图 16 所示。 图 16. 插入单个成员 - 然后在 Products > Camping Equipment 路径下,把 Lanterns 拖拽到报表的最后一行,注意等到有闪烁行线出现时再松开鼠标。
- 这样就有 6 个产品类型出现在报表中,Lanterns 产品类型出现在报表的最后一行。点击右上角的“完成”回到 Business Insight 的仪表盘窗口。
- 值得注意的是,现在修改的报表仅仅是改变自助式仪表盘的数据,而不影响原先的报表“第一个自助式设计分析”。因此您可以在自助式仪表盘里面引用自助式设计 分析的结果,也可以随时利用自助式设计分析的强大功能来弥补自助式仪表盘的不足。Business Insight 和 Business Insight Advanced 两者无缝集成,不需要切换。
总结 您可以使用两种不同的方式打开 Business Insight Advanced: - 从执行报表高级编辑(“完成更多”)的 Business Insight 仪表盘中打开。这种方式适合业务人员在自助式仪表盘里面想进一步进行自助分析。
- 从 IBM Cognos Connection 的“启动”菜单中打开或从欢迎页面(“创建者业务报表”)中打开。这种方式适合业务人员进行自助设计分析。
Business Insight Advanced 是给业务人员进行自助式设计分析用的。在《第一次安装》中,您曾经用 Report Studio 构建了第一张简单报表,而 Report Studio 是给专业人士使用的报表工具。 您可以用 Report Studio 来打开刚才保存的“第一个自助式设计分析”。 在开始菜单中启动 IBM Cognos BI Developer Edition,运行 Developer Edition Manager,在确保左侧的服务都正常的情况下,点击右上角的启动,选择 Report Studio。在“Cognos > 公共文件夹 > 示样 > 多维数据集”路径下,选择“Great Outdoors Sales (cube)”数据包,进入 IBM Report Studio 后选择“打开现有的”。在“我的文件夹”下,可以找到刚才保存的“第一个自助式设计分析”,点击“打开”。 您可以看到 Report Studio 提供了给专业报表创建者的许多功能,下面举例说明 Business Insight Advanced 不能实现而 Report Studio 可以完成的功能。 - 在 Report Studio 中间的“查询资源管理器”,您可以创建或修改关系报表 [ 使用关系查询 ] 或维度报表 [ 使用维度查询 ] 中的查询,以及执行复杂任务,如定义合并联接和写入 SQL 语句,如图 17 所示。在 Business Insight Advanced,您不能看到也不能操控查询。
图 17. 查询资源管理器 - 点击交叉表的左上方的三个小红点,选择交叉表,您可以看到交叉表的属性,如图 18 所示。这里有一些属性是 Business Insight Advanced 无法编辑的。比如在“其他”类别里面的“名称”,这里的名称就是您刚才在 Business Insight 中进行自助式仪表盘时候看到的对象名称。您可以在 Report Studio 把它修改成更有意义的名字,比如“产品线收入表”。
图 18. 交叉表属性
摘要: 熟悉 Report Studio Report Studio 是用来制作更加精细的专有报表的工具。IBM Cognos Report Studio 是一个基于 Web 的报表创建工具,专业报表创建者和开发人员可使用此工具针对多个数据库创建复杂的、具有多页并且可以进行多项查询的报表。使用 Report Studio,您可以创建公司所需的任何报表,如发票报表、财务报表以及每周销售和库存报表。报表... 阅读全文
什么是自助式仪表盘 IBM Cognos Business Insight 基于网页的界面可以让您建立先进的交互式的仪表盘,来提供见解并使协同决策变得简单。在 IBM Cognos Business Insight 中创建的仪表盘可以让业务用户将集成的商业智能体验与协作决策相结合。用户可以快速而轻松地完成绝大部分任务。例如可以查看并与报表交互、排列数据或者执 行额外的计算、或者与团队中其他成员共享信息。因为用户对报表和数据有不同的需求,所以可以利用自由形式布局也可以重新排列报表或添加新报表。 定制化内容 当启动 IBM Cognos Business Insight 的时候,您可以选择打开一个已存在的仪表盘或是创建一个仪表盘。在打开的工作区域中,您都可以添加或重新排列新小工具,所有仪表盘都是可编辑的。业务用户 可以将有权限访问各种系统内容组合成一个指定的仪表盘,并可以进行分析。高级业务用户或报表作者可以为一组业务用户创建报表和基础仪表盘,来包含该组用户 工作所需的所有信息。这样,业务用户就能定制仪表盘来契合特殊的需求。这些需求可能包括重排布局,更改图形,将数据排序,添加计算,新建过滤等以及搜索一 份补充报表并添加其到工作区域。 添加新内容 您可以从内容或工具箱标签拖拽新小工具到仪表盘来。使用相同的方式,你可以添加报表、报表组件、度量列表或独立度量、TM1 项目、或者任何小工具中描述的项目。您可以使用 IBM Cognos Business Insight 中增强的搜索功能来寻找并添加相关内容到仪表盘。这个功能是一种全文搜索,类似于流行的搜索引擎。 交互分析能力 除了更改报表中数据的显示,你也可以与报表交互,并自定义其排列。此外,你还可以利用报表中的数据添加基础性运算,可以过滤数据。 高级过滤 使用过滤小工具可以过滤报表中所有与其关联的报表。这样,如果你有一个地区选择过滤器,它过滤所有该地区一项的报表。当然,它只过滤那些与这个过滤器关联的报表中的数据。当你在过滤小工具上选择一个值,报表就会重新刷新来显示你选择的过滤好的数据项。 其他内容 除了报表内容之外,您也可以添加其他内容到仪表盘,例如 Web 页面、图像、我的收件箱、文本、RSS 订阅。 创建注释 对于仪表盘上的一份报表中的内容,评论或注释有助于用户与团队中其他成员进行合作。这些注释可以让其他查看相同报表的用户看见。这些用户也可以添加 关于此报表的进一步注释,来提供额外的信息。例如,注释可以提醒在某个地区调查销售较低的结果,也可以是某些异常数据的一个解释,例如一个最近发布且已在 市场上有数月的产品的销售数据较小。您可以注释实时报表并保存输出版本。当打印一个报表的 PDF 版本或是导出报表为 PDF 或 Excel 输出时,注释也会被包括在其中。 创建第一个自助式仪表盘 - 在开始菜单中启动 IBM Cognos BI Developer Edition,运行 Developer Edition Manager,在确保左侧的服务都正常的情况下,点击右上角的启动,选择 Business Insight。在 IBM Cognos Business Insight 的启动页上选择“新建”。
- 在右侧的可插入对象中选择下面的“内容”,在“公共文件夹 > 示样 > 模型 > GO 数据仓库 ( 查询 ) > Business Insight 源报表 > 收入数据”路径下,右键选择“Revenue by Country – bar - chart”报表,选择“插入”,如图 1 所示。再用同样的方式,把另外的 Revenue by Product Type - Combination Chart 和 Revenue by Order method - Pie Chart 两张报表插入到仪表盘中。
图 1. 选择报表 - 在仪表盘空白处点击右键,选择“排列所有小工具以符合内容的显示尺寸”来调整三张报表在仪表盘的大小和位置。您也可以单独调整每个报表的大小和位置,方法是鼠标移动到报表上,等到小工具菜单显示后选择“调整大小以适合内容”,如图 2 所示。
图 2. 调整大小 - 在右侧的可插入对象中选择下面的“工具箱”,可以看到有很多小工具,比如可以添加公司的 Web 页面,添加公司商标图像等。这里我们选择“文本”,输入“公司收入仪表盘”,选择合适的大小,把它添加到仪表盘中,如图 3 所示。
图 3. 添加文本 - 点击上方工具栏的保存按钮,保存到我的文件夹中,命名为“第一个交互式仪表盘”。不要关闭 IBM Cognos Business Insight。
您可以在 Business Insight 中保存的任意仪表盘设置为主页。在保存按钮旁边有“主页”按钮,您可以在旁边单击箭头,找到“将仪表盘设为主页”这个选项。 查看仪表盘的数据 - 选择“Revenue by Country – bar - chart”报表,在上方的小工具操作中选择“更改显示类型”,更改为“列表”,如图 4 所示。在“更改显示类型”旁边的按钮是“更改调色板”,您可以根据喜好来选择不同风格不同类型的显示方式来展现数据。
图 4. 更改显示类型 - 在列表中选择“中国”、“巴西”、“加拿大”和“法国”,然后在上方小工具操作中选择“过滤器”,过滤条件是“包含中国、巴西、加拿大、法国”,如图 5 所示。 。
图 5. 添加本地过滤条件 - 在上方的小工具操作中选择“更改显示类型”,更改为“条形图”。这样新的“Revenue by Country – bar - chart”报表就仅仅包含中国、巴西、加拿大、法国了。
- 点击左上方的展开按钮,可以查看已应用过滤器和已应用排序,如图 6 所示。点击过滤器右边的删除按钮,把刚才建立的“包含中国、巴西、加拿大、法国”过滤器删除。
图 6. 查看本地过滤条件 - 在右侧的可插入对象中选择下面的“工具箱”,右键点击“幻灯片过滤器”选择“插入”,把它添加到仪表盘中。在幻灯片过滤器属性窗口中,选择三张报表都有的数据项“收入”,把过滤器的内容设为值范围,修改描述文本后确定,如图 7 所示。
图 7. 幻灯片过滤器属性 - 您可以试着调整页面布局,使得仪表盘更美观。在页面的右上角有一个“内容”按钮,点击可以隐藏或者显示右侧的可插入对象,隐藏右侧的可插入对象可以让仪变盘区域变得更大一些。
您还可以试着拖拽幻灯片过滤器的滑条杆,仪表盘的三张报表图形都会随着变化。 图 8. 调整全局过滤条件 选择一张报表点击左上方的展开按钮,可以查看已应用过滤器和已应用排序,如图 9 所示。刚才建立的全局过滤条件已经显示在已应用过滤器中了,如果在这里删除过滤器,那么只会影响当前报表,而不会影响仪表盘中的其他报表,这是和本地过滤条件的区别所在。 图 9. 查看全局过滤条件 仪表盘的数据交互 - 在右侧的可插入对象中选择下面的“内容”,在“公共文件夹 > 示样 > 模型 > GO 数据仓库 ( 分析 ) > Report Studio 报表示样”路径下,右键选择“预算与实际”报表,选择“在新仪表盘中打开”。如果提示“是否保存仪表盘”,选择“是”。
- 点击上方工具栏的保存按钮,保存到我的文件夹中,命名为“数据交互”。
- 右键选择您需要评注的数据,比如美洲户外用品商店的差额百分比 69.16%,选择添加注释,如图 10 所示。
图 10. 添加注释 - 注释内容填写“69.16% - 增加预算”,确定以后可以看到在 69.16% 数据项上有红色三角形标记,表明有注释。您要查看注释,可将指针悬停于注释(由红色三角形标记指明)上。具有报表读取权限的所有用户都可以查看注释。 如果同一单元格或报表小工具有多个注释,它们将按逆时序显示。 对于每个注释,您可以看到撰写注释的用户的用户名、撰写日期和时间。
图 11. 查看注释 - 点击上方小工具操作的菜单,可以将包含报表内容的报表小工具导出为多种格式。要保存数据的快照,您可以创建报表小工具的 PDF 版本,刚才添加的注释也会保留在导出的 PDF 文件中。当您导出到 PDF 时,小工具将出现在 Adobe Reader 中,因此您必须在计算机上安装 Adobe Reader。
图 12. 将仪表盘小工具导出为不同格式 - 您可以查看报表数据项的 lineage 信息,以了解该报表数据项所代表的内容。Lineage 信息通过数据包和数据包使用的数据源追溯项目的元数据。Lineage 还显示报表创建者添加的或在数据模型中定义的所有数据项过滤器。
IBM Cognos BI Lineage 工具包括两种视图:业务视图和技术视图。业务视图显示了高级语篇信息,该信息描述了数据项及其所来自的数据包。技术视图是选定数据项的 lineage 的图形表示。Lineage 从数据包中的数据项一直跟踪到数据包使用的数据源。 图 13. 查看报表数据项的传承信息 - 下面按住 CTRL 键选中您关心的地区门店,比如“美洲 > 户外用品商店”、“美洲 > 直销”和“美洲 > 百货商店”,然后点击上方小工具操作的计算按钮,选择“+ > 直销 + 户外用品商店 + 百货商店”。您会发现刷新后的仪表盘把计算结果显示在新行中。默认情况下,将使用计算中所用的表达式作为标题名称。计算结果不会存储在基础数据源中。相 反,IBM Cognos Business Insight 会在每次刷新报表时重新运行计算。计算结果始终以数据源中的最新数据为基础。
图 14. 增加计算 您在上方小工具操作的按钮里面还能找到“分组 / 取消分组”、排序等按钮。如果是灰色,表示该功能不适用您目前的报表和数据。 排序按字母或数字的升序或降序组织数据。例如,您可以对列出产品销售额的列按降序进行排序,以便对产品销售额从高到低进行排序。 如果列表报表中的同一列多次出现同一个值,那么您可以将这些相同的值归为一组。分组操作将对选定报表项目的行进行重新排序,这样相同值会一起显示并抑制重 复显示的情况。由于分组的列会显示在未分组的列之前,因此分组和取消分组操作可能会更改报表项目的顺序。但是您可以对列表中的列重新排序来提高报表的可读 性。 总结 在本系列教程的“第 1 部分,第一次安装”中,您安装了样例数据和样例档案。您可以在“公共文件夹 > 示样 > 模型 > Business Insight 示样”目录下找到六个样例仪表盘。您可以依次打开来进行更深一步地研究和学习。 - 员工满意度仪表盘
该报表显示员工满意度的不同度量,例如培训投资、员工调查结果(按部门和按主题,包括与计划调查结果的比较),以及员工奖金列表(按国家 / 地区排序)。滑块过滤器适用于奖金列表。 - 市场营销仪表盘
该仪表盘显示不同促销活动的结果。活动名称的选择值过滤器适用于前两个图表。产品系列选择值过滤器适用于广告费图表,年份滑块过滤器适用于广告费交叉表。 - 招聘仪表盘
该仪表盘显示针对不同指标(根据组织、部门、分部)的招聘结果(填充职位的平均天数)、年份和有关不同招聘技巧的成功的详细信息。两个选择值过滤器控制其中三个小工具。 - 收入数据仪表盘
该仪表盘按区域、国家 / 地区(由选择值过滤器控制)、产品类型(由选择值过滤器控制)及订购方法显示收入。 - 销售(按年)仪表盘
该仪表盘显示由滑块过滤器控制的一年范围内不同的销售指标:利润率、毛利润、产品成本、销售数量、区域收入以及实际收入与计划收入之间的比较。滑块过滤器控制所有小工具。 - 销售仪表盘(交互式)
该仪表盘显示销售的不同方面:月毛利润、地区毛利润和产品系列毛利润,区域收入以及对该销售做出贡献的销售代表的数目。 该源对象基于“Go 数据仓库 ( 分析 )”数据包和“Go 数据仓库 ( 查询 )”数据包。 该销售仪表盘是交互式的,可以支持向上追溯和向下追溯的功能。 您可以在报表或报表组成部分中向上追溯或向下追溯。在 IBM Cognos Business Insight 中,对于列表和交叉表,将指针悬停在数据项上时,超链接会标识可追溯项目。在图表中,当您将指针悬停在可追溯项目上时,指针将变为手形,并且工具提示将指 明您将追溯的内容。在 Business Insight 中,仅当您使用按维度结构化的数据时,才能执行向上追溯和向下追溯。
什么是交互式离线报表 IBM Cognos Active Report 是可以与用户交互的离线报表,包含了数据和展现内容,它在无法访问企业内部网络和数据库的情况下仍然可以通过此类报表分析数据,获得有价值的信息。 IBM Cognos Active Report 非常适合移动办公的情况,如销售体系。使用者在离线的条件下浏览报表,深入挖掘数据,获取额外的信息。IBM Cognos Active Report 拓展了商务智能的应用场景,并让系统户的更好的性能和支持更大的使用规模。 用户使用 IBM Cognos Report Studio 来创建 Active Report。IBM Cognos Active Report 具有很强的交互性和易用性,报表的设计从用户需求出发,并确保的简洁美观流畅的用户体验。 IBM Cognos Active Report 是 IBM Cognos Report Studio 报表的拓展。数据需要以一种简洁易懂的组织方式呈现给客户。有些用户习惯于数字,而另一些则偏好于图表。为了方便设计人员设计出更简洁的报表,IBM Cognos Report Studio 在保持原有功能的同时加入了一些交互式的控件 , 如选项卡、下拉菜单等,用于定义交互报表,对数据进行排序和过滤。 作为一个高级业务人员,可以将刚刚完成的动态报表下载成为本地文件,并转发给公司其它成员 . 文件最终以 mht 格式保存 , 并可以以邮件附件形式发送给同事。 如果正在使用 Microsoft Internet Explorer 6.0,则无法将 MHT 格式的活动报表作为文件打开,交互式离线报表需要 Microsoft Internet Explorer 7 版本以上。要在 Mozilla Firefox 中查看 MHT 格式的活动报表,必须先下载一个 UnMHT 附加组件。 创建第一张交互式离线报表 - 在开始菜单中启动 IBM Cognos BI Developer Edition,运行 Developer Edition Manager,在确保左侧的服务都正常的情况下,点击右上角的启动,选择 Report Studio。
- 在“Cognos > 公共文件夹 > 示样 > 模型”路径下,选择“ GO 数据仓库 ( 查询 ) ”数据包,进入 IBM Report Studio 后选择“新建”。
图 1. 选择数据包 在选择报表类型的时候,选择“活动报表”,点击确定。 图 2. 选择报表类型 - 在左侧的可插入对象中先插入一个列表,然后展开“销售和市场营销(查询)”目录,再展开“销售(查询)”命名空间,按住 Control 键后选择“产品”下的产品类型以及“销售资料”下的收入和计划收入,拖动到右边报表页中,如图 3 所示。
准备工作 IBM Cognos Business Intelligence 10.1 是最新的商业智能解决方案,用于提供查询、报表、分析、仪表板和记分卡功能,并且可通过规划、方案建模、预测分析等功能进行扩展。它可以在人们尝试了解业绩并使用工具做出决策时,在思考和工作方式方面提供支持,以便人们可以搜索和组合与业务相关的所有方面,并与之进行交互。 - 查询和报表功能为用户提供根据事实做出决策所需的信息。
- 仪表板使任何用户都能够以支持其做出决策的方式来访问内容、与之交互,并对其进行个性化设置。
- 分析功能使您能够从多个角度和方面对信息进行访问,从而可以查看和分析信息,帮助您做出明智的决策。
- 协作功能包括通信工具和社交网络,用于推动决策过程中的意见交流。
- 记分卡功能可实现业务指标的捕获、管理和监控的自动化,使您可将其与自己的战略和运营目标进行比较。
在开始体验 Cognos BI 10.1 之前,您需要到 IBM developerWorks 去下载 Cognos 10.1 的试用版。IBM Cognos BI Developer Edition V10.1.0 下载地址是:http://www.ibm.com/developerworks/cn/downloads/im/cognosbi/。 您需要下载两个文件,IBM Cognos BI Developer Edition 10.1.0 Windows English 的下载文件名是 CZS56EN.tar.gz,IBM Cognos Business Intelligence Samples V10.1.0 for DB2 LUW Windows English 的下载文件名是 CZQ90EN.tar.gz。IBM Cognos BI Developer Edition V10.1.0 有 30 天的使用时间,足够让您完成本教程的学习了。 根据试用版的系统需求,您需要用 Windows 操作系统来进行安装,要求 Windows XP SP3 或者更高的版本。另外您要安装 Windows 的 Internet 信息服务 IIS,并且把浏览器 IE 升级到 7 版本以上。建议内存有 2G 以上,有 1.5 G 以上的临时空间和 2G 以上的磁盘空间来进行安装。 由于本教程需要数据库来存放 Cognos BI 10.1 的样例数据,所以您还需要到 IBM developerWorks 去下载 DB2 的社区版。DB2 Express-C 9.7.4 for Windows 下载地址是:http://www.ibm.com/developerworks/cn/downloads/im/udbexp/。下载文件名是 db2exc_974_WIN_x86.exe。 安装 DB2 双击 db2exc_974_WIN_x86.exe 然后选择任意目录进行解压缩。解压成功后点击 setup.exe 进入 DB2 安装启动板。 图 1. DB2 安装启动板 点击“安装新产品”,进入到安装向导界面,点击“下一步”继续。阅读并接受许可协议,点击“下一步”继续。 图 2. 选择安装类型 本教程选择典型安装,这个选项将安装 DB2 的主要部件和功能。 图 3. 选择创建响应文件 选择不创建响应文件而只进行安装,点击“下一步”继续。 图 4. 选择安装文件夹 一般使用默认的驱动器和目录设置就可以了,确保有 560 MB 可用空间,点击“下一步”继续。 图 5. 设置用户信息 安装 DB2 之后,某些 DB2 进程会作为系统服务运行。为了运行这些服务,需要一个操作系统帐户。在本教程中,使用默认的 db2admin 用户帐户,密码为 cognos,DB2 安装程序会在操作系统中创建它。当然您也可以指定使用一个现有的帐户,但是这个帐户必须具有本地管理员权力。点击“下一步”继续。 图 6. 配置 DB2 实例 可以认为 DB2 实例是数据库的容器。必须有一个实例,然后才能创建数据库。在 Windows 上进行安装时,会自动创建一个称为 DB2 的实例。在默认情况下,DB2 实例监听端口 50000 上的 TCP/IP 连接。可以点击配置来查看,在本教程中一切保持默认配置即可。点击“下一步”继续。 图 7. 开始复制文件 检查前面选择的安装选项。单击“安装”。结束以后,点击“完成”即可。 安装 Cognos 解压文件 CZS56EN.tar.gz,然后点击运行 Cognos 10 BI Server 安装程序 install.exe。 图 8. IBM Cognos BI Developer Edition 安装界面 选择简体中文后,点击“OK”。在简介这一步骤中,阅读许可协议并选择接受协议条款。 图 9. 选择安装文件夹 选择缺省文件夹即可以,要保证有可用空间。快捷方式文件夹是指产品图标的程序组,也可以采用缺省的 IBM Cognos BI Developer Edition。 图 10. 配置 在配置界面中可使用默认的端口。然后给 Cognos 的管理员设定用户名和密码,在本教程中设定管理员为 administrator,密码为 cognos。 图 11. 安装摘要 在安装摘要中可以看到整个安装需要 1.5G 以上的磁盘空间,点击“安装”继续。 图 12. 完成安装 完成安装界面时候,勾选启动 IBM Cognos BI Developer Edition Manager,然后点击“完成”。IBM Cognos BI Developer Edition Manager 是开发版特有的组件,可以用来安装和配置 IBM Cognos BI 和 Framework Manager,也可以用来管理用户和启动停止服务。 图 13. IBM Cognos Developer Edition Manager 第一次启动界面 第一次启动 IBM Cognos BI Developer Edition Manager,点击“完成”让 Manager 进行初始化的安装和配置。 图 14. 安装 IBM Cognos Developer Edition Manager 安装过程可能需要十几分钟,耐心等待直到登陆界面出现。 图 15. 登陆 IBM Cognos Developer Edition Manager 在登陆界面中输入在 图 10所示的用户名和密码,在本教程中是 administrator 和 cognos,然后点击确定。 图 16. 安装 Cogos BI Suite 选择 BI Suite,然后进行安装。IBM Cognos BI Suite 赋予了您完整的自助服务报告和即席查询能力,使其可以访问、修改和创建报表。访问任意类型的数据,包括关系 OLAP、分析 OLAP 或桌面文件。并通过 Web、PDF、Excel、电子邮件或门户发送您的报表。安装过程可能需要半小时,耐心等待直到直到登陆界面出现。在登陆界面中输入在图 10 所示的用户名和密码,在本教程中是 administrator 和 cognos,然后点击确定。 图 17. 安装 Framework Manager 选择 Framework Manager,然后进行安装,这个步骤非常快就完成了。Framework Manager 是元数据建模工具。它使得建模者可以创建和管理业务相关的元数据,以便在所有 Cognos BI 应用程序中使用。Framework Manager 的主要用户为数据仓库开发人员和数据建模者。 配置 Cognos 首先需要把 C:\Program Files\IBM\SQLLIB\java 目录下的 db2jcc.jar 和 db2jcc_license_cu.jar 拷贝到 C:\Program Files\IBM\Cognos Developer\tomcat\lib 目录下,然后在 IBM Cognos Developer Edition Manager 重启 Cognos 服务。 安装样例数据 解压文件 CZQ90EN.tar.gz,然后点击运行 install_DB2_samples.exe 进行安装。在 Instruction 这一步骤中,阅读许可协议并选择接受协议条款。 图 18. 选择安装路径 安装路径采用缺省的,这样会和 IBM Cognos BI Developer Edition 安装在同一目录下。完成安装后,样例数据文件会放在 C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\db2,找到数据文件 GS_DB.tar.gz,并进行解压缩。 然后在点击开始菜单,选择运行,输入 db2cmd 再确定,进入到 DB2CLP 的窗口。安装过程可能需要五分钟,具体操作命令和显示参见清单 1。在这个过程中需要输入 DB2 的用户名和密码,在本教程是 db2admin 和 cognos。 清单 1. 创建数据库并导入数据
>CD C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\db2\GS_DB\win >GOSalesConfig.bat >setupGSDB.bat ------------------------------------------------------------------- DB2 version 9 or later detected - using DB2 Version 9 syntax ------------------------------------------------------------------- Press Enter at the prompts to accept the default value shown Default values can be specifed in the file GOSalesConfig.sh ------------------------------------------------------------------- Please enter the name of the database ( or the alias ) to be used for the GOSales sample data (default=GS_DB) : ------------------------------------------------------------------- This script can create the GS_DB database. Creating the database will cause any existing databases with the same name to be dropped. If you choose not to recreate the database, existing objects within the database will be dropped. Would you like to create the database GS_DB (Y/N) Default=Y : Please wait ... Starting GOSALES_RUN_SCRIPTS Dropping existing database GS_DB if found Creating database GS_DB Please wait ... Starting GOSALES_RUN_SCRIPTS Connecting to GS_DB 输入 db2admin 的当前密码:cognos 数据库连接信息 数据库服务器 = DB2/NT 9.7.4 SQL 授权标识 = DB2ADMIN 本地数据库别名 = GS_DB Error dropping existing tables Creating tables. Loading data. Creating primary keys Creating indexes Creating constraints. Creating stored procedures Creating views Granting permissions Updating statistics Verifying row counts Table row count validation successful Adding table comments | 创建数据源连接 在开始菜单中启动 IBM Cognos BI Developer Edition,运行 Developer Edition Manager,在确保左侧的服务都正常的情况下,点击右上角的启动,如图 19 所示选择 IBM Cognos Administration。 图 19. 启动 Cognos Administration 在 IBM Cognos Administration 界面中选择配置页,选中“数据源连接”,点击右上角的图标,如图 20 所示新建数据源。 图 20. 在 Cognos Administration 中添加数据源 - 在指定名称和说明 - 新建数据源向导中,名称中输入“great_outdoors_sales”,点击下一步。
- 在指定连接 - 新建数据源向导中,选择类型为“IBM DB2”,点击下一步。
- 在指定 IBM DB2 连接字符串 - 新建数据源向导中,DB2 数据库名称写为“GS_DB”,在登陆勾选“密码”,用户 ID 中写为 “db2admin”,密码和确认密码写为 “cognos”。然后点击“测试连接”如图 21 所示。测试成功后点击下一步。如果测试有问题的时候,可以重启 Cognos 服务或者重启系统。
图 21. 指定 IBM DB2 连接字符串 - 在指定命令 - 新建数据源向导中,保持缺省,点击完成。
- 重复 1 到 4 的步骤,再创建“great_outdoors_warehouse”数据源,即名称为“great_outdoors_warehouse”,其余内容“great_outdoors_sales”一样。
- 在指定名称和说明 - 新建数据源向导中,名称中输入“sales_and_marketing”,点击下一步。
- 在指定连接 - 新建数据源向导中,选择类型为“IBM Cognos PowerCube”,点击下一步。
- 指定 IBM Cognos PowerCube 连接字符串 - 新建数据源向导中,Windows 位置输入“C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\cubes\PowerCubes\EN \sales_and_marketing.mdc”。然后点击“测试连接”,测试成功后点击完成。
- 重复 6 到 8 的步骤,再创建“great_outdoors_sales_en”数据源,即名称为 “great_outdoors_sales_en”,Windows 位置输入“C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\cubes\PowerCubes\EN \great_outdoors_sales_en.mdc”。
- 重复 6 到 8 的步骤,再创建“employee_expenses”数据源,即名称为“employee_expenses”,Windows 位置输入“C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\cubes\PowerCubes\EN\ employee_expenses.mdc”。
- 重复 6 到 8 的步骤,再创建“go_accessories”数据源,即名称为“go_accessories”,Windows 位置输入“C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\cubes\PowerCubes\EN\ go_accessories.mdc”。
- 重复 6 到 8 的步骤,再创建“go_americas”数据源,即名称为“go_americas”,Windows 位置输入“C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\cubes\PowerCubes\EN\ go_americas.mdc”。
- 重复 6 到 8 的步骤,再创建“go_asia_pacific”数据源,即名称为“go_asia_pacific”,Windows 位置输入“C:\Program Files\IBM\Cognos Developer\webcontent\samples\datasources\cubes\PowerCubes\EN\ go_asia_pacific.mdc”。
回页首 导入示例档案库 接下来要把示例的部署档案库导入到 Cognos 环境中来。这些档案库的位置在 C:\Program Files\IBM\Cognos Developer\webcontent\samples\content\db2 目录下。选择拷贝三个文件到 C:\Program Files\IBM\Cognos Developer\deployment 目录下准备进行部署。 这三个文件是 IBM_Cognos_Samples.zip,本教程主要的 Great Outdoors 公司例子; IBM_Cognos_DrillThroughSamples.zip, Great Outdoors 公司显示钻透功能的例子; IBM_Cognos_PowerCube.zip 多维立方体的例子。 - 在 IBM Cognos Administration 界面中选择配置页,选中“内容管理”,点击右上角的图标,如图 22 所示新建导入。
图 22. 新建导入向导 - 在部署档案库中,首先选择 IBM_Cognos_Samples,点击下一步。
- 在指定名称和说明 - 新建导入向导,按照默认的名字,点击下一步。
- 在公共文件夹内容中,勾选档案库的内容“示样”,点击下一步。
- 在指定常规选项 - 新建导入向导,保留默认选项,点击下一步。
- 复查汇总 - 新建导入向导,点击下一步。
- 在选择操作 - 新建导入向导中,选择“保存并运行一次” ,点击完成。
- 在运行使用选项 - IBM_Cognos_Samples 中,选择“现在”,点击运行。
- 重复 1 到 8 的步骤,选择 IBM_Cognos_PowerCube 进行导入。
10. 重复 1 到 8 的步骤,选择 IBM_Cognos_DrillThroughSamples 进行导入。 第一张简单报表 在开始菜单中启动 IBM Cognos BI Developer Edition,运行 Developer Edition Manager,在确保左侧的服务都正常的情况下,点击右上角的启动,选择 Report Studio,如 图 19所示。 在“Cognos > 公共文件夹 > 示样 > 模型”路径下,选择“ GO 数据仓库 ( 查询 ) ”数据包,进入 IBM Report Studio 后选择“新建”。 图 23. 选择数据包 在选择报表类型的时候,选择“列表”,点击确定。 图 24. 选择报表类型 在左侧的可插入对象中,展开“销售和市场营销(查询)”目录,再展开“销售(查询)”命名空间,选择“产品”下的产品系列、产品类型和产品,选择“销售资料”下的数量和收入,一个一个拖动到右边的列表中。 图 25. 选择项目 剩下的工作就是点击工具栏的运行按钮,来等待您的第一张简单报表出炉了,如图 26 所示。 图 26. 运行报表 报表运行结果如图 27 所示。 图 27. 第一张简单报表 总结 在整个安装过程中,DB2 是用户数据源,我们把本教程的样例数据放在了 DB2 的 GS_DB 数据库中,并在 Cognos Administration 进行了数据源的配置。 Cognos Connection 是 Cognos 门户,提供信息的集成和用户访问的统一入口。管理员可以通过他实现用户、角色管理,服务器配置,权限控制等各种管理功能;最终用户可以通过 Cognos Connection 访问到文件夹、报表、个性化展现、访问 Cognos Viewer、Report Studio、Business Insight 和 Event Studio 的内容。 Report Studio 是专业的报表制作模块。报表制作人员可以通过他制作各种类型的报表,包括中国特色的非平衡报表,地图,动态仪表盘,KPI 报表等。报表制作人员可以分页面设计,每页可以有多个查询,每个查询可以连接多个数据源,甚至异构数据源。报表的内容采用的是化繁为简的方式,可以精确控 制报表中每一个对象的各种属性。 Business Insight 是业务用户的自定义仪表盘工具,用户可以拖拽任意 Cognos BI 内容(包含查询,报表,分析,TM1 数据集等)形成自定义的仪表盘。 Cognos Framework Manager 是一个专门对元数据进行管理的客户端开发工具。他可以连接多个数据源,能够连接 OLAP 和数据库等各种数据源,并提供对元数据的定制和管理以及安全性控制等相关控制。 图 28. IBM Cognos BI Developer Edition 架构和工作原理 当您运行第一张简单报表的时候,IBM Cognos BI Developer Edition 是按照下面步骤来运行的: - 在 IBM Cognos Framework Manager 工具中,建模人员确保元数据是按照业务人员可以理解的方式来进行组织的。建模人员把元数据从一个或多个数据库中导入,并按照业务需求添加到模型中。
- 建模人员把模型数据包发布到 IBM Cognos Connection,这样开发报表人员就可以利用它们来进行创建报表和仪表盘了。比如在本教程中的“ GO 数据仓库 ( 查询 ) ”数据包。
- 业务人员和报表开发人员利用已经发布的数据包来理解业务数据。
- 用户在 IBM Cognos Connection 运行、查看和管理他们的内容。根据不同的权限,他们可以简单运行和查看报表,或者管理计划、门户展示等。
源文出自:http://blog.csdn.net/thy822/article/details/7608305
两种方法一样,只是写法不同 第一种写法 1 listeners:{ 2 beforeedit:function(e){ 3 if(...) e.cancel = true;//true表示不可编辑 4 } 5 } 第二种写法 1 grid.on('beforeedit',function(e)){ 2 var record = e.record; 3 if(...){ 4 e.cancel = true;//true表示不可编辑 5 } 6 }
1.首先看效果 2.需要一个合计插件GridSummary.js GridSummary 插件,下载后将后缀名该为 js 3.页面需要引用的文件 1 <link rel="stylesheet" type="text/css" href="include/ext-3.4.0/resources/css/ext-all.css" /> 2 <link rel="stylesheet" type="text/css" href="include/ext-3.4.0/ux/css/ux-all.css" /> 3 <script type="text/javascript" src="include/ext-3.4.0/adapter/ext/ext-base.js"></script> 4 <script type="text/javascript" src="include/ext-3.4.0/ext-all.js"></script> 5 <script type="text/javascript" src="include/ext-3.4.0/ux/ux-all.js"></script> 6 <script type="text/javascript" src="include/ext-3.4.0/locale/ext-lang-zh_CN.js"></script> 7 <script type="text/javascript" src="include/ext-3.4.0/ux/GridSummary.js"></script> <!-- 合计插件 -->
8 <script type="text/javascript" src="demo.js"></script> <!-- 示例js -->
4.Grid代码 var url = "RequestAction/AT/Req_CT_SHIPMENTS.aspx?Action=GetDetailAll&S_SHIPMENTS_M_GUID=" + guid; //复选框 var sm = new Ext.grid.CheckboxSelectionModel(); var textFileldVehicle = new Ext.form.TextField ({ allowBlank: false, blankText: "请输入车号", maxLength: 50 });
var numField = new Ext.form.NumberField({ allowNegative: false, allowDecimals: true, allowFormat: true, decimalPrecision: 2, allowBlank: false, blankText: '金额必须大于零' }); //字段集合 var fields = [ { name: 'S_VEHICLE_NUMBER' }, { name: 'N_QUANTITY' }, { name: 'N_FREIGHT' }, { name: 'S_GUID' }, { name: 'S_SHIPMENTS_M_GUID' } ]; var proxy = new Ext.data.HttpProxy({ url: url }); //数据读取器 var reader = new Ext.data.JsonReader({ totalProperty: "totalPorperty", //数据总条数 root: "rows", //将要显示数据的数组 id: "S_GUID", //每一行数据的唯一记录 fields: fields });
//列集合 其中 summaryType: 'sum' 为求和
var cm = new Ext.grid.ColumnModel ({ columns: [sm, new Ext.grid.RowNumberer({ header: 'NO', width: 30, align: 'center' }), { header: '车号', dataIndex: 'S_VEHICLE_NUMBER', editor: textFileldVehicle, summaryRenderer: function (v, params, data) { return '合计'; } }, { header: '重量', dataIndex: 'N_QUANTITY', summaryType: 'sum', renderer: formatNumberDefault, align: 'right', editor: numField }, { header: '运费', dataIndex: 'N_FREIGHT', summaryType: 'sum', renderer: formatNumberDefault, align: 'right', editor: numField} ] }); //如果全部列都可排序否则单个设置 cm.defaultSortable = false;
//创建一个store var shipmentsDetailstore = new Ext.data.Store({ proxy: proxy, reader: reader, autoDestroy: true, autoLoad: { params: { start: 0, limit: pageSize} } });
//插入行按钮 var btn_Insert = new Ext.Button({ text: '插入行', iconCls: 'insert', handler: function () { //定义一个recode对象 var initValue = createShipmentDetailRow(); grid.stopEditing(); var maxRowIndex = grid.getStore().getCount(); grid.getStore().insert(maxRowIndex, initValue); //在第一个位置插入 grid.view.refresh(); grid.getSelectionModel().selectLastRow(); grid.getView().focusRow(maxRowIndex); //焦点标记行 grid.startEditing(maxRowIndex, 2); //单元格转换成编辑状态 } }); //删除行按钮 var btn_Remove = new Ext.Button({ text: '删除行', iconCls: 'delete', handler: function () { grid.stopEditing(); var rows = grid.getSelectionModel().getSelections(); if (rows == undefined || rows.length == 0) { setShipmentStatusBarText('error', '请选择需要删除的行!'); return; //判断记录集是否为空,为空返回 } grid.getStore().remove(rows); grid.view.refresh(); } });
//工具栏 var tbar = new Ext.Toolbar({ cls: 'top-toolbar', items: [btn_Insert, '-', btn_Remove] }); var summary = new Ext.ux.grid.GridSummary(); //创建GRID var grid = new Ext.grid.EditorGridPanel ({ id: 'ShipmentsDetailGirdPanel', deferredRender: false, enableColumnHide: false, enableHdMenu: false, columnLines: true, enableColumnMove: false, store: shipmentsDetailstore, sm: sm, cm: cm, loadMask: true, //自适应宽度 参数为列数 // autoExpandColumn: 4, //超过长度带自动滚动条 autoScroll: true, border: false, nocache: false, timeout: 10, clicksToEdit: 1, scripts: true, loadMask: { msg: '正在加载数据,请稍侯……' }, tbar: tbar, view: new Ext.ux.grid.BufferView({ rowHeight: 25, scrollDelay: true, forceFit: true, deferEmptyText: true, emptyText: "无数据" }), plugins: summary }); 5.此时会看到合计行字体偏小 添加样式 .x-grid3-summary-row .x-grid3-cell-inner { FONT: 12.5px tahoma,arial,helvetica,sans-serif } 6.此示例Ext版本为 3.4.0
人们对软件架构存在非常多的误解,其中一个最为普遍的误解就是:将架构(Architecture)和框架(Framework)混为一谈。 框架是一种特殊的软件,它并不能提供完整无缺的解决方案,而是为你构建解决方案提供良好的基础。框架是半成品。典型地,框架是系统或子系统的半成品;框架中的服务可以被最终应用直接调用,而框架中的扩展点是供应用开发人员定制的“可变化点”。 软件架构不是软件,而是关于软件如何设计的重要决策。软件架构决策涉及到如何将软件系统分解成不同的部分、各部分之间的静态结构关系和动态交互关系等。经 过完整的开发过程之后,这些架构决策将体现在最终开发出的软件系统中;当然,引入软件框架之后,整个开发过程变成了“分两步走”,而架构决策往往会体现在 框架之中。或许,人们常把架构和框架混为一谈的原因就在于此吧! 节选自《软件架构设计》书稿 原文出自: http://blog.csdn.net/lovingprince/article/details/3347248
Web集群是由多个同时运行同一个web应用的服务器组成,在外界看来就像一个服务器一样,这多台服务器共同来为客户提供更高性能的服务。集群更标准的定 义是:一组相互独立的服务器在网络中表现为单一的系统,并以单一系统的模式加以管理,此单一系统为客户工作站提供高可靠性的服务。 而负载均衡的任务就是负责多个服务器之 间(集群内)实现合理的任务分配,使这些服务器(集群)不会出现因某一台超负荷、而其他的服务器却没有充分发挥处理能力的情况。负载均衡有两个方面的含 义:首先,把大量的并发访问或数据流量分担到多台节点上分别处理,减少用户等待响应的时间;其次,单个高负载的运算分担到多台节点上做并行处理,每个节点 设备处理结束后,将结果汇总,再返回给用户,使得信息系统处理能力可以得到大幅度提高 因此可以看出,集群和负载均衡有本质上的不同,它们是解决两方面问题的不同方案,不要混淆。 集群技术可以分为三大类: 1、高性能性集群(HPC Cluster) 2、高可用性集群(HA Cluster) 3、高可扩展性集群 一、高性能性集群(HPC Cluster) 指以提高科学计算能力为目标的集群技术。该集群技术主要用于科学计算,这里不打算介绍,如果感兴趣可以参考相关的资料。 二、高可用性集群(HA Cluster) 指为了使群集的整体服务尽可能可用,减少服务宕机时间为目的的集群技术。如果高可用性集群中的某节点发生了故障,那么这段时间内将由其他节点代替它的工作。当然对于其他节点来讲,负载相应的就增加了。 为了提高整个系统的可用性,除了提高计算机各个部件的可靠性以外,一般情况下都会采用该集群的方案。 对于该集群方案,一般会有两种工作方式: ①主-主(Active-Active)工作方式 这是最常用的集群模型,它提供了高可用性,并且在只有一个节点时也能提供可以接受的性能,该模型允许最大程度的利用硬件资源。每个节点都通过网络对客户机 提供资源,每个节点的容量被定义好,使得性能达到最优,并且每个节点都可以在故障转移时临时接管另一个节点的工作。所有的服务在故障转移后仍保持可用,但 是性能通常都会下降。 这是目前运用最为广泛的双节点双应用的Active/Active模式。 支撑用户业务的应用程序在正常状态下分别在两台节点上运行,各自有自己的资源,比如IP地址、磁盘阵列上的卷或者文件系统。当某一方的系统或者资源出现故障时,就会将应用和相关资源切换到对方的节点上。 这种模式的最大优点是不会有服务器的“闲置”,两台服务器在正常情况下都在工作。但如果有故障发生导致切换,应用将放在同一台服务器上运行,由于服务器的处理能力有可能不能同时满足数据库和应用程序的峰值要求,这将会出现处理能力不够的情况,降低业务响应水平。 ②主-从(Active-Standby)工作方式 为了提供最大的可用性,以及对性能最小的影响,主-从工作方式需要一个在正常工作时处于备用状态的节点,主节点处理客户机的请求,而备用节点处于空闲状态,当主节点出现故障时,备用节点会接管主节点的工作,继续为客户机提供服务,并且不会有任何性能上影响。 两节点的Active/Standby模式是HA中最简单的一种,两台服务器通过双心跳线路组成一个集群。应用Application联合各个可选的系统组件如:外置共享的磁盘阵列、文件系统和浮动IP地址等组成业务运行环境。 PCL为此环境提供了完全冗余的服务器配置。这种模式的优缺点: - 缺点:Node2在Node1正常工作时是处于“闲置”状态,造成服务器资源的浪费。
- 优点:当Node1发生故障时,Node2能完全接管应用,并且能保证应用运行时的对处理能力要求。
三、高可扩展性集群 这里指带有负载均衡策略(算法)的服务器群集技术。带负载均衡集群为企业需求提供了更实用的方案,它使负载可以在计算机集群中尽可能平均地分摊处理。而需 要均衡的可能是应用程序处理负载或是网络流量负载。该方案非常适合于运行同一组应用程序的节点。每个节点都可以处理一部分负载,并且可以在节点之间动态分 配负载, 以实现平衡。对于网络流量也是如此。通常,单个节点对于太大的网络流量无法迅速处理,这就需要将流量发送给在其它节点。还可以根据每个节点上不同的可用资 源或网络的特殊环境来进行优化。 负载均衡集群在多节点之间按照一定的策略(算法)分发网络或计算处理负载。负载均衡建立在现有网络结构之上,它提供了一种廉价有效的方法来扩展服务器带宽,增加吞吐量,提高数据处理能力,同时又可以避免单点故障。 前面已经说过负载均衡的作用是在多个节点之间按照一定的策略(算法)分发网络或计算处理负载。负载均衡可以采用软件和硬件来实现。一般的框架结构可以参考下图。 后 台的多个Web节点上面有相同的Web应用,用户的访问请求首先进入负载均衡分配节点(可能是软件或者硬件),由它根据负载均衡策略(算法)合理地分配给 某个Web应用节点。每个Web节点相同的内容做起来不难,所以选择负载均衡策略(算法)是个关键问题。下面会专门介绍均衡算法。 web 负载均衡的作用就是把请求均匀的分配给各个节点,它是一种动态均衡,通过一些工具实时地分析数据包,掌握网络中的数据流量状况,把请求理分配出去。对于不 同的应用环境(如电子商务网站,它的计 算负荷大;再如网络数据库应用,读写频繁,服务器的存储子系统系统面临很大压力;再如视频服务应用,数据传输量大,网络接口负担重压。),使用的均衡策略 (算法)是不同的。 所以均衡策略(算法)也就有了多种多样的形式,广义上的负载均衡既可以设置专门的网关、负载均衡器,也可以通过一些专用软件与协议来实现。在OSI七层协 议模型中的第二(数据链路层)、第三(网络层)、第四(传输层)、第七层(应用层)都有相应的负载均衡策略(算法),在数据链路层上实现负载均衡的原理是 根据数据包的目的MAC地址选择不同的路径;在网络层上可利用基于IP地址的分配方式将数据流疏通到多个节点;而传输层和应用层的交换(Switch), 本身便是一种基于访问流量的控制方式,能够实现负载均衡。 目前,基于负载均衡的算法主要有三种:轮循(Round-Robin)、最小连接数(Least Connections First),和快速响应优先(Faster Response Precedence)。 ①轮循算法,就是将来自网络的请求依次分配给集群中的节点进行处理。 ②最小连接数算法,就是为集群中的每台服务器设置一个记数器,记录每个服务器当前的连接数,负载均衡系统总是选择当前连接数最少的服务器分配任务。 这要比"轮循算法"好很多,因为在有些场合中,简单的轮循不能判断哪个节点的负载更低,也许新的工作又被分配给了一个已经很忙的服务器了。 ③快速响应优先算法,是根据群集中的节点的状态(CPU、内存等主要处理部分)来分配任务。 这一点很难做到,事实上到目前为止,采用这个算法的负载均衡系统还很少。尤其对于硬件负载均衡设备来说,只能在TCP/IP协议方面做工作,几乎不可能深入到服务器的处理系统中进行监测。但是它是未来发展的方向。 上面是负载均衡常用的算法,基于以上负载均衡算法的使用方式上,又分为如下几种: 1、DNS轮询 最早的负载均衡技术是通过DNS来实现的,在DNS中为多个地址配置同一个名字,因而查询这个名字的客户机将得到其中一个地址,从而使得不同的客户访问不同的服务器,达到负载均衡的目的。 DNS负载均衡是一种简单而有效的方法,但是它不能区分服务器的差异,也不能反映服务器的当前运行状态。当使用DNS负载均衡的时候,必须尽量保证不同的 客户计算机能均匀获得不同的地址。由于DNS数据具备刷新时间标志,一旦超过这个时间限制,其他DNS服务器就需要和这个服务器交互,以重新获得地址数 据,就有可能获得不同IP地址。因此为了使地址能随机分配,就应使刷新时间尽量短,不同地方的DNS服务器能更新对应的地址,达到随机获得地址,然而将过 期时间设置得过短,将使DNS流量大增,而造成额外的网络问题。DNS负载均衡的另一个问题是,一旦某个服务器出现故障,即使及时修改了DNS设置,还是 要等待足够的时间(刷新时间)才能发挥作用,在此期间,保存了故障服务器地址的客户计算机将不能正常访问服务器 2、反向代理服务器 使用代理服务器,可以将请求转发给内部的服务器,使用这种加速模式显然可以提升静态网页的访问速度。然而,也可以考虑这样一种技术,使用代理服务器将请求均匀转发给多台服务器,从而达到负载均衡的目的。 这种代理方式与普通的代理方式有所不同,标准代理方式是客户使用代理访问多个外部服务器,而这种代理方式是代理多个客户访问内部服务器,因此也被称为反向代理模式。虽然实现这个任务并不算是特别复杂,然而由于要求特别高的效率,实现起来并不简单。 使用反向代理的好处是,可以将负载均衡和代理服务器的高速缓存技术结合在一起,提供有益的性能。然而它本身也存在一些问题,首先就是必须为每一种服务都专门开发一个反向代理服务器,这就不是一个轻松的任务。 代理服务器本身虽然可以达到很高效率,但是针对每一次代理,代理服务器就必须维护两个连接,一个对外的连接,一个对内的连接,因此对于特别高的连接请求, 代理服务器的负载也就非常之大。反向代理方式下能应用优化的负载均衡策略,每次访问最空闲的内部服务器来提供服务。但是随着并发连接数量的增加,代理服务 器本身的负载也变得非常大,最后反向代理服务器本身会成为服务的瓶颈。 3、地址转换网关 支持负载均衡的地址转换网关,可以将一个外部IP地址映射为多个内部IP地址,对每次TCP连接请求动态使用其中一个内部地址,达到负载均衡的目的。很多 硬件厂商将这种技术集成在他们的交换机中,作为他们第四层交换的一种功能来实现,一般采用随机选择、根据服务器的连接数量或者响应时间进行选择的负载均衡 策略来分配负载。由于地址转换相对来讲比较接近网络的低层,因此就有可能将它集成在硬件设备中,通常这样的硬件设备是局域网交换机。 原文出自: http://blog.csdn.net/lovingprince/article/details/3290871
//修复办法,谷歌浏览器中,table的单元格实际宽度=指定宽度+padding,所以只要重写gridview里的一个方法,如下:
1 //修复办法,谷歌浏览器中,table的单元格实际宽度=指定宽度+padding,所以只要重写gridview里的一个方法,如下: 2 Ext.override(Ext.grid.GridView,{ 3 getColumnStyle : function(colIndex, isHeader) { 4 var colModel = this.cm, 5 colConfig = colModel.config, 6 style = isHeader ? '' : colConfig[colIndex].css || '', 7 align = colConfig[colIndex].align; 8 9 if(Ext.isChrome){ 10 style += String.format("width: {0};", parseInt(this.getColumnWidth(colIndex))-2+'px'); 11 }else{ 12 style += String.format("width: {0};", this.getColumnWidth(colIndex)); 13 } 14 15 if (colModel.isHidden(colIndex)) { 16 style += 'display: none; '; 17 } 18 19 if (align) { 20 style += String.format("text-align: {0};", align); 21 } 22 23 return style; 24 }, 25 }); 26 [代码] [JavaScript]代码//看看修复过后的效果
原文出自:http://www.oschina.net/code/snippet_201314_15163
使用AES加密时,当密钥大于128时,代码会抛出java.security.InvalidKeyException: Illegal key size or default parameters Illegal key size or default parameters是指密钥长度是受限制的,java运行时环境读到的是受限的policy文件。文件位于${java_home}/jre/lib/security 这种限制是因为美国对软件出口的控制。 解决办法: 去掉这种限制需要下载Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.网址如下。 下载包的readme.txt 有安装说明。就是替换${java_home}/jre/lib/security/ 下面的local_policy.jar和US_export_policy.jar jdk 5: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jce_policy-1.5.0-oth-JPR jdk6: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html 参考http://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters 原文出自:http://blog.csdn.net/shangpusp/article/details/7416603
随笔- 50 文章- 0 评论- 180 jQuery中所支持的异步模型为: - Callbacks,回调函数列队。
- Deferred,延迟执行对象。
- Promise,是Deferred只暴露非状态改变方法的对象。
这些模型都很漂亮,但我想要一种更帅气的异步模型。 Thread? 我们知道链式操作是可以很好的表征运行顺序的(可以参考我的文章《jQuery链式操作》),然而通常基于回调函数或者基于事件监听的异步模型中,代码的执行顺序不清晰。 Callbacks模型实际上类似一个自定义事件的回调函数队列,当触发该事件(调用Callbacks.fire())时,则回调队列中的所有回调函数。 Deferred是个延迟执行对象,可以注册Deferred成功、失败或进行中状态的回调函数,然后通过触发相应的事件来回调函数。 这两种异步模型都类似于事件监听异步模型,实质上顺序依然是分离的。 当然Promise看似能提供我需要的东西,比如Promise.then().then().then()。但是,Promise虽然成功用链式操作明确了异步编程的顺序执行,但是没有循环,成功和失败分支是通过内部代码确定的。 个人认为,Promise是为了规范化后端nodejs中I/O操作异步模型的,因为I/O状态只有成功和失败两种状态,所以他是非常成功的。 但在前端,要么只有成功根本没有失败,要么不止只有两种状态,不应当固定只提供三种状态的方案,我觉得应该提供可表征多状态的异步方案。 这个大家可以在something more看到。 我想要一种类似于线程的模型,我们在这里称为Thread,也就是他能顺序执行、也能循环执行、当然还有分支执行。 顺序执行 线程的顺序执行流程,也就是类似于: 这样就是依次执行do1,do2,do3。因为这是异步模型,所以我们希望能添加wait方法,即类似于: do1(); wait(1000); //等待1000ms do2(); wait(1000); //等待1000ms do3(); wait(1000); //等待1000ms
不使用编译方法的话,使用链式操作来表征顺序,则实现后的样子应当是这样的: 1 Thread(). //获取线程 2 then(do1). //然后执行do1 3 wait(1000). //等待1000ms 4 then(do2). //然后执行do2 5 wait(1000). //等待1000ms 6 then(do3). //然后执行do3 7 wait(1000); //等待1000ms 循环执行 循环这很好理解,比如for循环: 1 for(; true;){ 2 dosomething(); 3 wait(1000); 4 } 进行无限次循环执行do,并且每次都延迟1000ms。则其链式表达应当是这样的: 1 Thread(). //获取线程 2 loop(-1). //循环开始,正数则表示循环正数次,负数则表示循环无限次 3 then(dosomething). //然后执行do 4 wait(1000). //等待1000ms 5 loopEnd(); //循环结束 这个可以参考后面的例子。 分支执行 分支也就是if...else,比如: 1 if(true){ 2 doSccess(); 3 }else{ 4 doFail(); 5 } 6 7 那么其链式实现应当是: 1 Thread(). //获得线程 2 right(true). //如果表达式正确 3 then(doSccess). //执行doSccess 4 left(). //否则 5 then(doFail). //执行doFail 6 leftEnd(). //left分支结束 7 rightEnd(); //right分支结束 声明变量 声明变量也就是: 可被其它函数使用。那么我们的实现是:
1 Thread(). //得到线程 2 define("hello world!"). //将回调函数第一个参数设为hello world! 3 then(function(a){alert(a);}); //获取变量a,alert出来 顺序执行实现方案 Thread实际上是一个打包函数Fn队列。 所谓打包函数就是将回调函数打包后产生的新的函数,举个例子: 1 function package(callback){ 2 return function(){ 3 callback(); 4 // 干其他事情 5 } 6 } 这样我们就将callback函数打包起来了。 Thread提供一个fire方法来触发线程取出一个打包函数然后执行,打包函数执行以后回调Thread的fire方法。 那么我们就可以顺序执行函数了。 现在只要打包的时候设置setTimeout执行,则这个线程就能实现wait方法了。 循环执行实现方案 循环Loop是一个Thread的变形,只不过在执行里面的打包函数的时候使用另外一种方案,通过添加一个指针取出,执行完后触发Loop继续,移动指针取出下一个打包函数。 分支执行实现方案 分支Right和Left也是Thread的一种变形,开启分支的时候,主Thread会创建两个分支Right线程和Left线程,打包一个触发分支Thread的函数推入队列,然后当执行到该函数的时候判断触发哪个分支执行。 其中一个队列执行结束后回调主Thread,通知进行下一步。 例子 由于该方案和wind-asycn非常相似,所以我们拿wind.js中的clock例子进行改造看看其中的差别吧。 wind.js中的例子: 我的例子: Something more? 我们提供了on方法将事件转成分支来执行。 举个例子页面有个按钮“点我”,但是我们希望打开页面5秒内单击没有效,5秒后显示“请点击按钮”后,单击才会出现“你成功点击了”。 使用on分支是这样的:
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> 2 <html> 3 <head> 4 <title>on - asThread.js Sample</title> 5 <meta http-equiv="X-UA-Compatible" content="IE=9" /> 6 <script src="asThread.js"></script> 7 </head> 8 <body> 9 <button id = "b">点我</button> 10 <script> 11 var ele = document.getElementById("b"); 12 13 Thread(). // 获得线程 14 then(function(){alert("请点击按钮")}, 5000). //然后等5秒显示"请点击按钮" 15 on(ele, "click"). // 事件分支On开始,如果ele触发了click事件 16 then(function(){alert("你成功点击了")}). //那么执行你成功点击了 17 onEnd(). // 事件分支On结束 18 then(function(){alert("都说可以的了")}). // 然后弹出"都说可以的了" 19 run(); //启动线程 20 </script> 21 </body> 22 </html> 自定义事件也可以哦,只要在.on时候传进去注册监听函数,和删除监听函数就行了。比如: 1 function addEvent(__elem, __type, __handler){ 2 //添加监听 3 } 4 5 function removeEvent(__elem, __type, __handler){ 6 //删除监听 7 } 8 9 Thread(). 10 on(ele, "success", addEvent, removeEvent). 11 then(function(){alert("成功!")}). 12 onEnd(). 13 run(); 当然实际上我们还可以注册多个事件分支。事件分支是并列的,也就是平级的事件分支没有现有顺序,所以我们能这样: 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> 2 <html> 3 <head> 4 <title>on - asThread.js Sample</title> 5 <meta http-equiv="X-UA-Compatible" content="IE=9" /> 6 <script src="asThread.js"></script> 7 </head> 8 <body> 9 <button id = "b">点我</button> 10 <button id = "c">点我</button> 11 <script> 12 var ele0 = document.getElementById("b"), 13 ele1 = document.getElementById("c"); 14 15 Thread(). // 获得线程 16 then(function(){alert("请点击按钮")}, 5000). //然后等5秒显示"请点击按钮" 17 on(ele0, "click"). // 事件分支On开始,如果ele0触发了click事件 18 then(function(){alert("你成功点击了")}). //那么执行你成功点击了 19 onEnd(). // 事件分支On结束 20 on(ele1, "click"). // 事件分支On开始,如果ele1触发了click事件 21 then(function(){alert("你成功点击了")}). //那么执行你成功点击了 22 onEnd(). // 事件分支On结束 23 then(function(){alert("都说可以的了")}). // 然后弹出"都说可以的了" 24 run(); //启动线程 25 </script> 26 </body> 27 </html> 一个线程不够用?只要输入名字就能开辟或者得到线程了。 系统会自动初始化一个主线程,当不传参数时就直接返回主线程: 但如果主线程正在用想开辟一个线程时,只要给个名字就行,比如: Thread("hello") //得到名字是hello的线程 那么下次再想用该线程时只要输入相同的名字就行了: Thread("hello") //得到hello线程 默认只最多只提供10个线程,所以用完记得删掉: IE10已经提供了setImmediate方法,而其他现代浏览器也可以模拟该方法,其原理是推倒线程末端,使得浏览器画面能渲染,得到比setTimeout(0)更快的响应。 我们通过接口.imm来提供这一功能。比如: Thread(). imm(function(){alert("hello world")}). run(); 这方法和.then(fn)不太一样,.then(fn)是可能阻塞当前浏览器线程的,但.imm(fn)是将处理推到浏览器引擎列队末端,排到队了在运行。 所以如果你使用多个Thread(伪多线程),而又希望确保线程是并行运行的,那么请使用.imm来替代.then。 当然对于老版IE,只能用setTimeout(0)替代了。 分支Right传的参数如果只是布尔值肯定很不爽,因为这意味着分支是静态的,在初始化时候就决定了,但我们希望分支能在执行到的时候再判断是走 Right还是Left,所以我们提供了传参可以是函数(但是函数返回值需要是布尔值,否则……╮(╯▽╰)╭也会转成布尔值的……哈哈)。比如: 1 fucntion foo(boolean){ 2 return !boolean; 3 } 4 5 Thread(). 6 define(true). 7 right(foo). 8 then(function(){/*这里不会运行到*/}). 9 rightEnd(). 10 run(); Enjoy yourself!! 项目地址 https://github.com/miniflycn/asThread 原问出自: http://www.cnblogs.com/justany/archive/2013/01/25/2874602.html
如何在 WebSphere 中解决 jar 包冲突 郝 爱丽, 高级软件工程师, IBM 中国软件开发中心 简介: Jar 包冲突问题是在大型 Java 软件开发中经常遇到的问题,系统开发人员经常会为解决类似的问题耗费大量的时间进行调试和测试,本文根据各种际情况,结合 WebSphere 中类加载器,讨论了几种解决 jar 包冲突问题的办法,并给出了具体实现的步骤及源代码。 读者定位为具有 Java 和 WebSphere 开发经验的开发人员。 读者可以学习到在 WebSphere 中类加载器的定义以及解决 jar 包冲突问题的几种办法,并可以直接使用文章中提供的 Java 代码,从而节省他们的开发和调试时间,提高效率。 大型的基于 WebSphere 的项目开发中,同一个 WebSphere Application Server(以下简称 WAS)上会部署多个应用程序,而这多个应用程序必然会共用一些 jar 包,包括第三方提供的工具和项目内部的公共 jar 等。把这些共用的 jar 包提取出来在多个应用程序之间共享,不仅可以统一对这些 jar 包进行维护,同时也提高了 WAS 的性能。但是随着应用的不断扩大,新的应用程序的不断增加,新的应用程序会希望使用一些更高版本的共享 jar 包,而由于系统运行维护的需要,老的应用程序仍然希望用老版本的共享 jar 包,这样就必然造成了共享 jar 包的版本冲突。jar 包版本冲突问题是在大型应用项目的开发中经常遇到的问题,本文试图从 WebSphere 的类加载器入手,讨论几种在不同情况下解决 jar 包冲突问题的办法。 WebSphere 中类加载器介绍 Jar 包冲突实际上是应用程序运行时不能找到真正所需要的类,而影响类的查找和加载的是 JVM 以及 WebSphere 中的类加载器(class loader),为此,我们首先介绍一下 WebSphere 中的类加载器以及一些相关的概念。 WebSphere 中类加载器层次结构 Java 应用程序运行时,在 class 执行和被访问之前,它必须通过类加载器加载使之有效,类加载器是 JVM 代码的一部分,负责在 JVM 虚拟机中查找和加载所有的 Java 类和本地的 lib 库。类加载器的不同配置影响到应用程序部署到应用程序服务器上运行时的行为。JVM 和 WebSphere 应用程序服务器提供了多种不同的类加载器配置, 形成一个具有父子关系的分层结构。WebSphere 中类加载器的层次结构图 1 所示: 图 1:WebSphere 中类加载器的层次结构 如上图所示,WebSphere 中类加载器被组织成一个自上而下的层次结构,最上层是系统的运行环境 JVM,最下层是具体的应用程序,上下层之间形成父子关系。 - JVM Class loader:位于整个层次结构的最上层,它是整个类加载器层次结构的根,因此它没有父类加载器。这个类加载器负责加载 JVM 类, JVM 扩展类,以及定义在 classpath 环境变量上的所有的 Java 类。
- WebSphere Extensions Class loader:WebSphere 扩展类加载器 , 它将加载 WebSphere 的一些 runtime 类,资源适配器类等。
- WebSphere lib/app Class loader:WebSphere 服务器类加载器,它将加载 WebSphere 安装目录下 $(WAS_HOME)/lib/app 路径上的类。 在 WAS v4 版本中,WAS 使用这个路径在所有的应用程序之间共享 jar 包。从 WAS v5 开始, 共享库功能提供了一种更好的方式,因此,这个类加载器主要用于一些原有的系统的兼容。
- WebSphere "server" Class loader:WebSphere 应用服务器类加载器。 它定义在这个服务器上的所有的应用程序之间共享的类。WAS v5 中有了共享库的概念之后,可以为应用服务器定义多个与共享库相关联的类加载器,他们按照定义的先后顺序形成父子关系。
- Application Module Class Loader:应用程序类加载器,位于层次结构的最后一层,用于加载 J2EE 应用程序。根据应用程序的类加载策略的不同,还可以为 Web 模块定义自己的类加载器。
关于 WebSphere 的类加载器的层次结构,以下的几点说明可能更有助于进一步的理解类的查找和加载过程: - 每个类加载器负责在自身定义的类路径上进行查找和加载类。
- 一个子类加载器能够委托它的父类加载器查找和加载类,一个加载类的请求会从子类加载器发送到父类加载器,但是从来不会从父类加载器发送到子类加载器。
- 一旦一个类被成功加载,JVM 会缓存这个类直至其生命周期结束,并把它和相应的类加载器关联在一起,这意味着不同的类加载器可以加载相同名字的类。
- 如果一个加载的类依赖于另一个或一些类,那么这些被依赖的类必须存在于这个类的类加载器查找路径上,或者父类加载器查找路径上。
- 如果一个类加载器以及它所有的父类加载器都无法找到所需的类,系统就会抛出 ClassNotFoundExecption 异常或者 NoClassDefFoundError 的错误。
类加载器的委托模式 类加载器有一个重要的属性:委托模式(Delegation Mode,有时也称为加载方式:Classloader mode)。委托模式决定了类加载器在查找一个类的时候, 是先查找类加载器自身指定的类路径还是先查找父类加载器上的类路径。 类加载器的委托模式有两个取值: - Parent_First:在加载类的时候,在从类加载器自身的类路径上查找加载类之前,首先尝试在父类加载器的类路径上查找和加载类。
- Parent_Last:在加载类的时候,首先尝试从自己的类路径上查找加载类,在找不到的情况下,再尝试父类加载器类路径。
有了委托模式的概念,我们可以更加灵活的配置在类加载器的层次结构中类的加载和查找方式。表 1 中给出了在 WebSphere 的类加载器层次结构中各个类加载器的委托模式的定义,并给出了不同的类加载器内类的生命周期。 注意:在上表中,"JVM Class loader" 因为在类加载器的最顶层,它没有父类加载器,因此其委托模式为 N/A,"WebSphere Extensions Class loader"和"WebSphere lib/app Class loader"的委托模式固定为表中的取值,不可配置,其它的类加载器的委托模式都是可以配置的。 WebSphere 中的类加载器策略 WebSphere 中对类加载器有一些相关的配置,称为类加载器策略(class loader policy)。类加载器策略指类加载器的独立策略(class loader isolation policy), 通过类加载器策略设置,我们可以为 WAS 和应用程序的类加载器进行独立定义。 每个 WAS 可以配置自己的应用程序类加载器策略,WAS 中的每个应用程序也可以配置自己的 Web 模块类加载器策略,下面我们对这两种策略分别介绍。 1 .应用服务器(WAS)配置:应用程序类加载器策略 应用服务器对应用程序类加载器策略有两种配置: - Single:整个应用服务器上的所有应用程序使用同一个类加载器。在这种配置下,每个应用程序不再有自己的类加载器。
- Multiple:应用服务器上的每个应用程序使用自己的类加载器。
2 .应用程序配置:Web 模块类加载器策略 应用程序中对 Web 模块类加载器有两种配置: - Application:整个应用程序内的所有的实用程序 jar 包和 Web 模块使用同一个类加载器。
- Module:应用程序内的每个 Web 模块使用自己的类加载器。应用程序的类加载器仍然存在,负责加载应用程序中 Web 模块以外的其它类,包括所有的实用程序 jar 包。
从上面的定义可以看出,不同的类加载器策略的配置下,类加载器的层次结构上的某些类加载器可能不存在。比如在应用程序服务器的应用程序类加载 器策略定义为 single 的情况下,应用程序的类加载器将不存在,同一个应用服务器上的所有应用程序将共用同一个类加载器,这也就意味着不同的应用程序之间的类是共享的,应用程序 间不能存在同名的类。 回页首 在 WebSphere 中解决 jar 包冲突 Jar 包冲突问题实际上就是应用程序希望用某一个确定版本的 jar 包中的类,但是类加载器却找到并加载了另外一个版本的 jar 包中的类。在上一部分介绍了 WebSphere 中类加载器的基本概念和相关配置之后,我们来看如何在 WebSphere 中解决 jar 包冲突。 在 WAS v5 版本之前,使用共享 jar 包的方式是将 jar 包放在 $(WAS_HOME)/lib/app 路径下,从上一部分中,我们可以看到,这个路径正是"WebSphere lib/app Class loader" 类加载器的类查找路径,WebSphere 会查找这个路径以取得相应得 jar 包中的 Java 类,从而做到在 WebSphere ND 上的多个应用程序之间共享 jar 包的目的。但是这样做的一个缺点就是这些共享 jar 包暴露给 WebSphere ND 上所有的应用程序,对于那些希望使用 jar 包其它版本的应用程序,这些 jar 包也同样存在在了它们的类加载器类路径上,因此,就不可避免的会造成版本的冲突。在 WAS v5 版本及之后,增加了共享库(shared library)的概念,推荐的在多个应用程序间共享 jar 包并避免 jar 包冲突的方式是使用共享库。 具体分析引起 jar 包冲突的情况,主要有三种: - 多个应用程序间 jar 包冲突:多个应用程序间由于使用了共享 jar 包的不同版本而造成 jar 包版本冲突。
- 应用程序中多个 Web 模块间 jar 包冲突:同一个应用程序内部,不同的 Web 模块间同时使用一个 jar 包的不同版本而造成 jar 包版本冲突。
- 应用程序中同一个 Web 模块内 jar 包冲突:同一个应用程序内部,同一个 Web 模块内,由于需要同时使用同一个 jar 包的两个版本而造成的 jar 包冲突
本部分根据这三种 jar 包冲突的情况,讨论三种解决 jar 包冲突的办法,并具体讨论三种解决办法的实现步骤和适用情况: - 共享库方式解决 jar 包冲突:主要解决应用程序间的 jar 包冲突问题
- 打包到 Web 模块中解决 jar 包冲突:主要解决应用程序中多个 Web 模块间 jar 包冲突问题
- 命令行运行方式解决 jar 包冲突:主要解决应用程序中同一个 Web 模块内 jar 包冲突问题
共享库方式解决 jar 包冲突 在 WAS v5 中,提供了一种很好的机制,使得 jar 包只存在于需要这个 jar 包的应用程序的类加载器的路径上,而其它的应用程序不受它的任何影响,这就是共享库(Shared library)。共享库可以用在应用服务器级别和应用程序级别,使用应用程序级别的共享库,其好处就是在不同的应用程序之间使用共享 jar 包的不同版本。我们可以为一些通用 jar 包的每个不同版本定义成不同的共享库,应用程序希望使用哪个版本,就把这个版本的共享库放到应用程序的类加载器的类路径上,这种方式有效的解决了应用程序 之间 jar 包冲突的问题。 下面举例介绍定义和使用共享库的具体方法,本例中,假设存在 xerces.jar 包版本冲突。 1 . 定义共享库 系统管理员可以在 WebSphere 的 Admin console 中定义共享库,可以分别在 Cell、Node 以及 server 的级别上定义。 步骤一 : 进入 Admin console,选择 Environment > Shared Library > new。如图 2 所示: 图 2:WebSphere Admin Console 中进入共享库页面 步骤二: 给出共享库的名字,并指定共享的文件和目录。多个不同的文件 / 目录之间通过"Enter"键分隔,且不能有路径分隔符,如":"和";"等。如图 3 所示: 图 3:WebSphere Admin Console 中添加共享库 步骤三:点击 Apply 或者 OK 之后,就添加了一个名字为 Xerces V2.0 的共享库。记住添加完成后一定要在 admin console 保存配置。如图 4 所示: 图 4:WebSphere Admin Console 中共享库列表-
2 .安装应用程序 进入 Admin console,选择 Applications > Install New Application 安装应用程序。请参照 IBM WebSphere 的 Admin console 使用手册进行安装新的应用程序,此处不再详细介绍。 3 .将共享库关联到应用程序 步骤一:进入 Admin console,选择 Applications > Enterprise applications ,并选择需要使用共享库的应用程序。注意:因为要改变应用程序的设置,所以如果应用程序已经运行,需要先停掉应用程序。如图 5 所示: 图 5:WebSphere Admin Console 中选择需要配置的应用程序 步骤二 : 点击应用程序,进入后,选择 Libraries。如图 6 所示: 图 6:WebSphere Admin Console 中选择应用程序库属性步骤三 : 点击 Add,为应用程序添加共享库。如图 7 所示: 图 7:WebSphere Admin Console 中应用程序添加库 步骤四 : 从下拉列表中选择所需要的共享库,点击 OK。如图 8 所示: 图 8:WebSphere Admin Console 中应用程序添加库页面指定所用的共享库 这样,Xerces V2.0 共享库定义的 xerces 版本就存在于了应用程序类加载器的类加载路径上。注意,在添加完成后要保存服务器的设置。 4 .设置应用程序的类加载器的委托模式为 Parent_Last 为了进一步防止共享库定义的 jar 包的其它版本已经存在于 JVM 或者 WebSphere 的类加载器路径上,还需要设置应用程序的类加载器的委托方式为 Parent_Last。 通过上面的配置,即使 xerces 的其它版本已经存在于系统中,应用程序在运行时,其类加载器也会首先查找并加载指定的共享库中的 xerces 版本。这样我们就通过使用共享库的方式,解决了 jar 包版本冲突问题。 打包到 Web 模块中解决 jar 包冲突 共享库的方式,只是在应用程序的层次上,在多个应用程序之间解决了共享 jar 包造成的版本冲突问题,如果一个应用程序的内部,其中一个 Web 模块使用了一个 jar 包的 A 版本,而另一个 Web 模块使用这个 jar 包的 B 版本,在这种情况下造成的 jar 包冲突,共享库的方式是无法解决的,我们可以考虑将其中一个在多个应用程序间共享的 jar 包版本,比如 A 版本,定义成共享库,或者放在"WebSphere lib/app Class loader"类加载器路径上供多个应用程序使用,而将 B 版本的 jar 包打包到使用它的 Web 模块中的方式来解决冲突。 其次,目前很多在线的系统是 WAS v4 的遗留系统,其上运行的应用程序已经使用了"WebSphere lib/app Class loader"类加载器,将 jar 包放在 $(WAS_HOME)/lib/app 目录下进行共享。如果由于其中某个应用程序的升级或者新增加某个应用程序,需要使用某个共享 jar 包的其它版本,在这种情况下,为了减少对系统的影响,也可以考虑将这个共享 jar 包的新版本打包到升级(或新增)的应用程序中的方式来解决 jar 包冲突。 由于 Web 模块的 WebContent/WEB-INFO/lib 目录在应用程序 Web 模块的类加载器查找路径上,因此,我们可以把 jar 包放在这个目录下,Web 模块的类加载器将自动查找并加载这个 jar 包中的类。 步骤一:在 WSAD IE 集成开发环境中,将冲突 jar 包放在 Web 模块的 WebContent/WEB-INFO/lib 目录下。如图 11 所示: 图 11:WSAD IE 中为 Web 模块添加库步骤二:在 Admin console 中,将应用程序部署到 WebSphere server 上之后,进入 Applications > Enterprise Applications, 选择相应的应用程序,并确认应用程序不在运行状态 ( 参见前面章节中选择应用程序的步骤 )。点击进入应用程序,确认应用程序的类加载器的委托模式为 Parent_First, 应用程序的类加载器策略为 Module。如图 12 所示: 图 12:WebSphere Admin Console 中应用程序属性配置页面步骤三:在同一个页面上,选择 Web Modules,点击进入。如图 13 所示: 图 13:WebSphere Admin Console 中选择应用程序 Web 模块属性步骤四:点击相应的包含冲突 jar 包的 Web 模块,设置 Web 模块的类加载器的委托模式为 Parent_Last。注意:在设置完成后要保存服务器配置,并启动应用程序。如图 14 所示: 图 14:WebSphere Admin Console 中为 Web 模块指定类加载器委托模式 将冲突 jar 包打包到 Web 模块中,并设置相应 Web 模块的类加载器的委托模式为 Parent_Last,应用程序在运行过程中加载类的时候,这个 Web 模块的类加载器会首先查找 WebContent/WEB-INFO/lib 目录下的 jar 包进行类的加载;而对于其它的 Web 模块,由于其类加载器的委托模式仍然为缺省的 Parent_First,它们的类加载器仍然首先从应用程序的共享库或者 WebSphere 的共享路径上加载 jar 包中的类,从而解决了 jar 包冲突的问题。 命令行运行方式解决 jar 包冲突 不论是设置共享库,还是将冲突 jar 包打包到应用程序中,其解决的问题都是在应用程序的一个 Web 模块中只使用了冲突 jar 包的一个版本的情况。我们在开发中曾经遇到过这样的情况:应用程序的 Web 模块中已经使用了 1.4 版本的 xerces.jar,由于 Web 功能的扩展,在这个模块中又引入一个新的第三方工具,而这个第三方工具需要使用 2.0 版本的 xerces.jar 才能正常工作,这种情况下的 jar 包冲突如何解决呢? 在前面类加载器的部分已经介绍过,每个应用程序的一个 Web 模块最多只能有一个类加载器,而 Web 模块的类加载器中加载的类的生命周期为整个应用程序的运行期,也就是说,Web 模块加载器不可能同时加载一个类的两个版本,同时,Web 模块的类加载器的委托模式也是在应用程序运行前设置的,在应用程序运行期内无法改变的,因此,上面描述的在一个 Web 模块中同时使用两个版本的 jar 包的问题,象前两种方法那样配置运行在一个 JVM 内的类加载器的设置的方法是无法解决的。 唯一的解决办法就是在应用程序运行的 JVM 外,启动另外一个 JVM 来运行调用冲突 jar 包的代码,因为两个不同的 JVM 可以加载各自的类,从而解决 jar 包冲突问题。 这种情况下,原来使用 jar 包的老版本的方式(包括 jar 包放置路径,共享库设置方式,类加载器的委托模式等)不变,将对 jar 包新版本的调用通过命令行运行方式实现。具体做法是:将对 jar 包新版本内功能的调用,封装到一个可以单独运行的类中,在 Web 模块中以命令行方式运行这个类。同时把这个类以及 jar 包的新版本放在任意一个 was 可访问的路径上(比如 /usr/WebSphere),在命令行的 classpath 参数中包含这个路径(比如 /usr/WebSphere)。 下面通过举例说明命令行运行方式的编程过程,在本例中,假设 TestEar 应用程序的 Web 模块 TestWar 中,已经使用了 conflict_v1.jar,由于新添功能需要使用 conflict_v2.jar 中的 exampleCall() 功能。 冲突 jar 包 conflict_v2.jar 提供的功能: 代码 1:冲突 jar 包 conflict_v2.jar 功能 1 Package com.ibm.conflict; 2 3 Public class ConflictClass{ 4 …… . 5 Public static String exampleCall(string param){ 6 String rs; 7 …… ; 8 Return rs; 9 } 10 …… 不存在冲突问题时的编码举例: 如果没有 jar 包冲突问题,则对这个功能的调用是简单的,只需要将 conflict_v2.jar 放在应用程序自身或者其父类加载器的查找路径上,然后在 Web 模块中直接调用即可,如下: 代码 2:不存在冲突时的调用方式1 Public String methodA(String param){ 2 …… 3 String rs = ConflictClass.exampleCall(param); 4 …… 5 Return rs; 6 }
存在冲突后的命令行运行方式编码举例 针对 jar 包冲突问题,我们需要在 Web 模块中做如下的修改: - 步骤一:将冲突 jar 包放在 was 可访问的路径上,比如 /usr/WebSphere/conflict_v2.jar。
步骤二:将对包含冲突代码的调用封装到一组可单独运行的类中,它们将调用冲突 jar 包的功能,并将结果以系统输出的方式打印到系统标准输出上。 将这些类封装到一个单独的 jar 文件中,比如 workAroundConflict.jar,并将其放在 was 可访问的路径上,比如 /usr/WebSphere/workAroundConflict.jar。
1 Package com.ibm.test; 2 3 Import com.ibm.ConflictClass; 4 5 Public class WorkAround{ 6 Public static void main(String[] args){ 7 String param1=args[0]; 8 String returnStr=ConflictClass.exampleCall (); 9 System.out.println("<RTStr>"+returnStr+"</RTStr>"); 10 Return; 11 } 12 }
代码 3:将对冲突代码的调用写入一个单独的类 WorkAround 步骤三:在 Web 模块中通过命令行方式调用封装的类,通过 classpath 指定所有依赖的 jar 包和类路径。运行封装类,从系统标准输出中取得运行结果。
1 Public static String methodA (String param){ 2 …… 3 String rtStr = ""; 4 String lStr="<RTStr>"; 5 String rStr="<RTStr>"; 6 //put all the dependency jar here 7 String classPath= 8 "/usr/WebSphere/conflict_v2.jar; 9 /usr/WebSphere/workaroundConflict.jar; ……"; 10 String className="com.ibm.test.WorkAround"; 11 String cmdLine="java -classpath " +classPath +" " +className + " "+ param; 12 Try{ 13 Process process = Runtime.getRuntime().exec(cmdLine,null); 14 process.waitFor(); 15 BufferedReader br= new BufferedReader( 16 new InputStreamReader(process.getInputStream())); 17 while ((s = br.readLine())!=null) { 18 if (null == out) 19 out=s; 20 else 21 out+=s; 22 } 23 //get result from out 24 if (null != out){ 25 int lIndex = out.lastIndexOf(lStr); 26 int rIndex = out.lastIndexOf(rStr); 27 rsStr = out.substring(lIndex+lStr.length, rIndex); 28 } 29 30 } catch (Exception e){ 31 e.printStackTrace(); 32 } 33 …… . 34 return rsStr; 35 }
代码 4:在应用程序中通过命令行方式运行 WorkAround -
命令行运行方式通过启动另外一个 JVM 的方式运行冲突代码,在一个不同的 JVM 中加载冲突的类,从而解决了 jar 包冲突问题。 但是命令行运行方式毕竟不是一个很好的方式,它存在以下的弊端: - 命令行运行方式只适用于对冲突 jar 包的使用只是运行一段代码,或者只要求返回简单的字符串结果的情况。对于复杂的交互,命令行方式无法做到。但是如果在别无他法的情况下,可以适当地划分封 装对冲突代码调用的 jar 包的包含范围,尽量将命令行运行的代码接口简单化。
- 命令行运行方式因为启动了另外一个 JVM 来运行,降低了 WebSphere 的性能。
因此,命令行方式只适用于一些极为特殊的情况下解决 jar 包冲突问题。 回页首 结论 本文对基于 WebSphere 的大型项目开发中遇到的 jar 包冲突问题,结合 WebSphere 中类加载器的概念,给出了三种解决办法以及相应的操作步骤和实现代码,并分析了各种方式所适用的具体情况。 项目开发过程中的 jar 包冲突,主要存在以下三种情况: - 多个应用程序间的 jar 包冲突
- 应用程序内多个 Web 模块间的 jar 包冲突
- 应用程序内同一个 Web 模块内部 jar 包冲突
通过对类加载器的分析我们知道,解决 jar 包冲突问题的根本在于合理配置类加载器。在深入理解 WebSphere 中类加载器的层次结构的基础上,我们给出了"共享库解决 jar 包冲突"以及"打包到 Web 模块中解决 jar 包冲突"的办法,通过合理地配置 WebSphere 中类加载器及其委托模式,可以解决大多数的 jar 包冲突问题。但是由于这个层次结构中类加载器只配置到 Web 模块,因此,对于 Web 模块内部的 jar 包冲突问题,类加载器的配置是无法解决的,为此我们给出了"命令行运行方式解决 jar 包冲突"的办法。 表 2 中列出了在不同的 WAS 版本下,三种解决 jar 包冲突问题的办法所适用的 jar 包冲突情况。 表 2:Jar 包冲突解决办法适用的 jar 包冲突情况总结 参考资料 - IBM WebSphere Application Server V5 ClassloaderNamingSpace Guide。
- IBM WebSphere Application Server V5.1 System Management and Configuration。
作者简介 郝爱丽是一位 IBM CSDL 的软件工程师,从事多年 J2EE 开发工作,有丰富的 J2EE 开发经验。目前从事企业电子商务应用的开发和支持。 常红平是一位 IBM CSDL 的软件工程师,IBM certified DB2 DBA 和 IBM certified DB2 developer。他目前正在从事企业电子商务应用的开发。您可以通过 changhp@cn.ibm.com 和他联系。
CXF和Spring结合的非常紧密,默认发布Server端是需要用到Spring的,但是项目中用到的Spring jar包比较老2.0,CXF版本2.3.1,跟Spring不兼容,需要换乘Spring2.5,但是换jar包对原来的项目存在风险,上网搜了一个脱 离Spring运行的方法。 写一个类继承CXFNonSpringServlet,重写loadBus方法。 1 @SuppressWarnings("unchecked") 2 public void loadBus(ServletConfig servletConfig) throws ServletException { 3 super.loadBus(servletConfig); 4 Bus bus = this.getBus(); 5 BusFactory.setDefaultBus(bus); 6 7 Enumeration<String> enums = getInitParameterNames(); 8 while (enums.hasMoreElements()) { 9 String key = enums.nextElement(); 10 String value = getInitParameter(key); 11 try { 12 Class clz = Class.forName(value); 13 try { 14 Endpoint.publish(key, clz.newInstance()); 15 } catch (InstantiationException e) { 16 e.printStackTrace(); 17 } catch (IllegalAccessException e) { 18 e.printStackTrace(); 19 } 20 } catch (ClassNotFoundException e) { 21 e.printStackTrace(); 22 } 23 } 24 } 在web.xml里将要发布的类配置一下,可以配置多个 1 <servlet> 2 <servlet-name>CXFServlet</servlet-name> 3 <servlet-class> 4 com.infodms.ws.util.MyCXFNoSpringServlet 5 </servlet-class> 6 <init-param> 7 <param-name>/TestService</param-name> 8 <param-value>com.infodms.ws.test.TestServiceImpl</param-value> 9 </init-param> 10 <init-param> 11 <param-name>/HelloWorld</param-name> 12 <param-value>com.infodms.ws.test.HelloWorldImpl</param-value> 13 </init-param> 14 </servlet> 15 <servlet-mapping> 16 <servlet-name>CXFServlet</servlet-name> 17 <url-pattern>/ws/*</url-pattern> 18 </servlet-mapping>
配置完成,启动tomcat,报错,还是加载了spring,但是代码确实走了刚刚加的MyCXFNoSpringServlet
1 java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.apache.cxf.bus.spring.BusApplicationListener' defined in class path resource [META-INF/cxf/cxf.xml]: Initialization of bean failed; nested exception is java.lang.NoSuchMethodError: org.springframework.context.support.AbstractApplicationContext.addApplicationListener(Lorg/springframework/context/ApplicationListener;)V 2 org.apache.cxf.bus.spring.SpringBusFactory.createBus(SpringBusFactory.java:96)
调试了一下源码,内部需要从环境变量中取得org.apache.cxf.bus.factory的值,如果为空就默认按照spring的方式加载。于是在类的最开始加入一行代码 1 System.setProperty("org.apache.cxf.bus.factory", "org.apache.cxf.bus.CXFBusFactory");
再次启动tomcat,报错,由异常可知WoodstoxValidationImpl类没有默认构造方法,通过反射实例化对象报错,看了一下这个类的源码,确实没有无参构造方法
1 Caused by: java.lang.InstantiationException: org.apache.cxf.wstx_msv_validation.WoodstoxValidationImpl 2 at java.lang.Class.newInstance0(Class.java:340) 3 at java.lang.Class.newInstance(Class.java:308) 4 at org.apache.cxf.bus.extension.Extension.load(Extension.java:110)
原文出自: http://liuqiang5151.iteye.com/blog/840496
摘要: 一、解决基本问题: 在做 RCP 项目的时候经常会遇到一个问题,就是要将一些控制信息输出到 RCP 自身的控制台,那么我们就可以扩展 Eclipse 扩展点 org.eclipse.ui.console.consoleFactories ,来实现我们自己的控制台,解决方法如下: 首先 ,在 plugin.xml 中定义扩展点: plugin.xml: <extension &n... 阅读全文
今天整理系统,发现系统很多页面,只有在IE6下显示正常,其它的都不正常,很是奇怪。所以上网找了一些关于浏览器兼容的问题和解决办法,在此我觉得大牛们总结的比较精彩,分享给网友们! 一、CSS兼容 以下两种方法几乎能解决现今所有兼容. 1, !important (不是很推荐,用下面的一种感觉最安全) 随着IE7对!important的支持, !important 方法现在只针对IE6的兼容.(注意写法.记得该声明位置需要提前.) 代码: <style> #wrapper { width: 100px!important; /* IE7+FF */ width: 80px; /* IE6 */ } </style> 2, IE6/IE77对FireFox <from 针对firefox ie6 ie7的css样式> *+html 与 *html 是IE特有的标签, firefox 暂不支持.而*+html 又为 IE7特有标签. 代码: <style> #wrapper { width: 120px; } /* FireFox */ *html #wrapper { width: 80px;} /* ie6 fixed */ *+html #wrapper { width: 60px;} /* ie7 fixed, 注意顺序 */ </style> 注意: *+html 对IE7的兼容 必须保证HTML顶部有如下声明: 代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://w3.org/TR/html4/loose.dtd"> 二、解决DIV错乱(非常重要) 可以用这个解决多个div对齐时的间距不对, 关于 clear float 的原理可参见 [How To Clear Floats Without Structural Markup] 将以下代码加入Global CSS 中,给需要闭合的div加上 class=”clearfix” 即可,屡试不爽. 代码: <style> /* Clear Fix */ .clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden; } .clearfix { display:inline-block; } /* Hide from IE Mac \*/ .clearfix {display:block;} /* End hide from IE Mac */ /* end of clearfix */ </style> 三、其它零碎(不容忽视,细节决定成败) 1. 文字本身的大小不兼容。同样是font-size:14px的宋体文字,在不同浏览器下占的空间是不一样的,ie下实际占高16px,下留白3px,ff 下实际占高17px,上留白1px,下留白3px,opera下就更不一样了。解决方案:给文字设定 line-height 。确保所有文字都有默认的 line-height 值。这点很重要,在高度上我们不能容忍1px 的差异。
2.ff下容器高度限定,即容器定义了height之后,容器边框的外形就确定了,不会被内容撑大,而ie下是会被内容撑大,高度限定失效。所以不要轻易给容器定义height。
3.横向上的撑破容器问题,。如果float 容器未定义宽度,ff下内容会尽可能撑开容器宽度,ie下则会优先考虑内容折行。故,内容可能撑破的浮动容器需要定义width。
小实验:有兴趣大家可以看看这段实验。在不同浏览器下分别测试以下各项代码。
a.<div style=”border:1px solid red;height:10px”></div> b. <div style=”border:1px solid red;width:10px”></div>
c. <div style=”border:1px solid red;float:left”></div> d. <div style=”border:1px solid red;overflow:hidden”></div>
上 面的代码在不同浏览器中是不一样的,实验起源于对小height 值div 的运用,<div style=”height:10px;overflow:hidden”></div>,小height 值要配合overflow:hidden一起使用。实验好玩而已,想说明的是,浏览器对容器的边界解释是大不相同的,容器内容的影响结果各不相同。
4.最被痛恨的,double-margin bug。ie6下给浮动容器定义margin-left 或者margin-right 实际效果是数值的2倍。解决方案,给浮动容器定义display:inline。
5.mirror margin bug,当外层元素内有float元素时,外层元素如定义margin-top:14px,将自动生成margin-bottom:14px。 padding也会出现类似问题,都是ie6下的特产,该类bug 出现的情况较为复杂,远不只这一种出现条件,还没系统整理。解决方案:外层元素设定border 或 设定float。
引申:ff 和ie 下对容器的margin-bottom,padding-bottom的解释有时不一致,似乎与之相关。
6. 吞吃现象。还是ie6,上下两个div,上面的div设置背景,却发现下面没有设置背景的div 也有了背景,这就是吞吃现象。对应上面的背景吞吃现象,还有滚动下边框缺失的现象。解决方案:使用zoom:1。这个zoom好象是专门为解决ie6 bug而生的。
7.注释也能产生bug~~~“多出来的一只猪。”这是前人总结这个bug使用的文案,ie6的这个bug 下,大家会在页面看到猪字出现两遍,重复的内容量因注释的多少而变。解决方案:用“<!–[if !IE]> picRotate start <![endif]–>”方法写注释。
8.img 下的留白,大家看这段代码有啥问题:
<div> < img src=”" mce_src=”" /> < /div>
把div的border打开,你发现图片底部不是紧贴着容器底部的,是img后面的空白字符造成,要消除必须这样写
<div> <img src=”" mce_src=”" /></div>
后面两个标签要紧挨着。ie7下这个bug 依然存在。解决方案:给img设定 display:block。
9. 失去line-height。<div style=”line-height:20px”><img />文字</div>,很遗憾,在ie6下单行文字 line-height 效果消失了。。。,原因是<img />这个inline-block元素和inline元素写在一起了。解决方案:让img 和文字都 float起来。
引申:大家知道img 的align 有 text-top,middle,absmiddle啊什么的,你可以尝试去调整img 和文字让他们在ie和ff下能一致,你会发现怎么调都不会让你满意。索性让img 和文字都 float起来,用margin 调整。
10.clear层应该单独使用。也许你为了节省代码把clear属性直接放到下面的一个内容层,这样有问题,不仅仅是ff和op下失去margin效果,ie下某些margin值也会失效 <div style=”background:red;float:left;”>dd</div> < div style=”clear:both;margin-top:18px;background:green”>ff</div>
11.ie 下overflow:hidden对其下的绝对层position:absolute或者相对层 position:relative无效。解决方案:给overflow:hidden加position:relative或者position: absolute。另,ie6支持overflow-x或者overflow-y的特性,ie7、ff不支持。
12.ie6下严重的bug,float元素如没定义宽度,内部如有div定义了height或zoom:1,这个div就会占满一整行,即使你给了宽度。float元素如果作为布局用或复杂的容器,都要给个宽度的。
13.ie6下的bug,绝对定位的div下包含相对定位的div,如果给内层相对定位的div高度height具体值,内层相对层将具有100%的width值,外层绝对层将被撑大。解决方案给内层相对层float属性。
14.width:100%这个东西在ie里用很方便,会向上逐层搜索width值,忽视浮动层的影响,ff下搜索至浮动层结束,如此,只能给中间的所有浮动层加width:100%才行,累啊。opera这点倒学乖了跟了ie。 四、一句话解决所有兼容性问题(懒人有懒人的办法奥!) 在网站头部加上一句: 1. Google Chrome Frame也可以让IE用上Chrome的引擎: <meta http-equiv=“X-UA-Compatible” content=“chrome=1″/> 2.强制IE8使用IE7模式来解析 <meta http-equiv=“X-UA-Compatible”content=“IE=EmulateIE7″><!– IE7 mode –> //或者 <metahttp-equiv=“X-UA-Compatible”content=“IE=7″><!– IE7 mode –> 3.强制IE8使用IE6或IE5模式来解析 <metahttp-equiv=“X-UA-Compatible”content=“IE=6″><!– IE6 mode –> <metahttp-equiv=“X-UA-Compatible”content=“IE=5″><!– IE5 mode –> 4.如果一个特定版本的IE支持所要求的兼容性模式多于一种,如: <metahttp-equiv=“X-UA-Compatible”content=“IE=5; IE=8″/> 我用的是最后一种,不过还是没有彻底解决问题,我也在寻求方法,恳求大牛们帮忙解决! 原文出自: http://www.cnblogs.com/sybboy/archive/2013/01/19/2868153.html
1. Javascript没有类的概念。一般使用原型链继承(prototypal inheritance)来模拟类。
2. 除了null和undefined之外的任何数据类型都能表现成Object (behave like an object),包括Number类型和Function类型。 var n = 42; function f() { alert("foo"); };
alert("n is " + n.toString()); // "n is 42" alert(f.name + " is a function"); // "f is a function"
注意,是“表现为object”,而不是“是object”。事实上,number, string和boolean是基本类型(primitives),除了这三个之外的都可以算作object,比如一个正则表达式也是一个object。 当需要访问基本类型变量的属性时,那些基本类型变量将被临时转换成object。 例如: "foobar".big(); // is equivalent to new String("foobar").big(); .14.toFixed(); // is equivalent to new Number(3.14).toFixed() 另外,不能强行给基本类型变量(number, string, boolean)加上私有属性。
var a = "mystring", b = new String( "mystring" );
Object.defineProperty( b, 'foo', { value: 42, enumerable: false }); console.log(b.foo); // 42 Object.defineProperty( a, 'foo', { value: 42, enumerable: false }); // TypeError: Object.defineProperty called on non-object
// trying another way: a.foo = 42; // remember, this is equivalent to: // new Number(a).foo = 42; // …so the 'foo' property is defined on the wrapper, not on 'a' console.log(a.foo); // undefined 3. 如果变量名前不加上var,那么这个变量就是全局的。
function setGlobal() { a = 42; }
function setLocal() { var b = 23; }
setGlobal(); alert(a); // 42
setLocal(); alert(b); // ReferenceError: b is not defined
4. this指针是由调用函数赋予的, 而不是由被调函数自身定义的。 例如: var a = {}, b = {};
a.foo = 42; b.foo = 18; a.alertFoo = function() { alert(this.foo); };
a.alertFoo(); // 42 a.alertFoo.call(b); // 18
5. 严格的相等判断应该使用===。例如 : 0 == false 为真, 但是 0 === false 为假。
6. 0, undefined, null, "", NaN 都是假值 (falsy)。 这些值全都等同于false,但他们之间不能相互替换。 7. 变量声明会被提升到当前作用域的顶端。 例如:下述代码中,你认为调用foo函数会返回什么?
var a = 2;
function foo() { return a; var a = 5; }
它将返回undefined。 上述代码等同于下述代码: var a = 2;
function foo() { var a; // 'a' declaration is moved to top return a; a = 5; } 另一个例子: 下述代码中,调用函数foo后变量a的值是什么? var a = 42;
function foo() { a = 12; return a; function a(){} } 答案是42。因为foo函数中变相声明了a变量,因此a成了局部变量了。 function foo() { function a() {} // local 'a' is a function a = 12; // local 'a' is now a number (12) return a; // return the local 'a' (12) } 8. 参数在函数声明中可以省略, 例如: function hello(name, age) { alert("Hello "+name+", you’re "+age+" years old!"); }
hello("Anon", 42); // "hello Anon, you’re 42 years old!" hello("Baptiste"); // "hello Baptiste, you’re undefined years old!" hello("Bulat", 24, 42); // "hello Bulat, you’re 24 years old!" 9. 对于字符串,使用双引号""和单引号''的效果是一样的。
10. Javascript代码可以在浏览器环境之外运行, 比如在Terminal或者HTTP服务器上。(例如 Node.js)
原文出自:http://www.cnblogs.com/newyorker/archive/2013/01/18/2865820.html
本篇介绍可以在C#中使用的1D/2D编码解码器。条形码的应用已经非常普遍,几乎所有超市里面的商品上面都印有条形码;二维码也开始应用到很多场合,如火车票有二维码识别、网易的首页有二维码图标,用户只需要用手机扫描一下就可以看到手机版网易的网址,免去了输入长串字符的麻烦。 条形码的标准: 条形码的标准有ENA条形码、UPC条形码、二五条形码、交叉二五条形码、库德巴条形码、三九条形码和128条形码等,而商品上最常使用的就是EAN商品条形码。EAN商品条形码亦称通用商品条形码,由国际物品编码协会制定,通用于世界各地,是目前国际上使用最广泛的一种商品条形码。我国目前在国内推行使用的也是这种商品条形码。EAN商品条形码分为EAN-13(标准版)和EAN-8(缩短版)两种。 二维码的编码标准: 全球现有的二维码多达200种以上,其中常见的技术标准有PDF417(美系标准),QRCode(日系标准),Code49,Code16K,CodeOne,DM(韩系标准),GM(中国标准),CM(中国标准)等20余种。用得最多的是QRcode。 下面借助google的开源项目zxing来实现1D/2D的编码和解码,测试效果如下: zxing的官方地址是:http://code.google.com/p/zxing/ zxing的功能还是很强大的,最初是用java编写,并支持Android、ios、symbian等手机操作系统。 不过不知是何原因,该官网连一个例子也没有,文档也是字典式的把所有类列出来,一点都没为读者考虑。 下面我把如果使用zxing完成上图所示例子讲解一遍,供初学者参考: 1.我们新建一个Winform测试项目; 2.从官网下载zxing开源项目,大概16m的样子,解压缩后打开zxing-2.1\csharp目录,将该目录拷贝到我们新建的Winform项目下(方便调试和看源码,并非一定要如此); 3.winform项目中添加对zxing项目的引用; 4.按上图所示例子建好控件,“生成条形码”的代码如下:
1 //生成条形码 2 private void button1_Click(object sender, EventArgs e) 3 { 4 lbshow.Text = ""; 5 Regex rg = new Regex("^[0-9]{13}$"); 6 if (!rg.IsMatch(txtMsg.Text)) 7 { 8 MessageBox.Show("本例子采用EAN_13编码,需要输入13位数字"); 9 return; 10 } 11 12 try 13 { 14 MultiFormatWriter mutiWriter = new com.google.zxing.MultiFormatWriter(); 15 ByteMatrix bm = mutiWriter.encode(txtMsg.Text, com.google.zxing.BarcodeFormat.EAN_13, 363, 150); 16 Bitmap img= bm.ToBitmap(); 17 pictureBox1.Image =img; 18 19 //自动保存图片到当前目录 20 string filename = System.Environment.CurrentDirectory + "\\EAN_13" + DateTime.Now.Ticks.ToString() + ".jpg"; 21 img.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg); 22 lbshow.Text = "图片已保存到:" + filename; 23 } 24 catch(Exception ee) 25 { MessageBox.Show(ee.Message); } 26 } 其中需要注意BarcodeFormat参数,可以打开定义看到具体的编码方式,自己百度每种编码方式对输入的要求。 这里EAN_13编码要求是13位长度的数字,并且满足:把所有偶数序号位上的数相加求和,用求出的和乘3,再把所有奇数序号上的数相加求和,用求出的和加上刚才偶数序号上的数,然后得出和能被10整除。(这个规则校验在UPCEANReader类的checkStandardUPCEANChecksum方法里面,如果不需要,可以去掉) 生成二维码的代码与上面相似:
1 //生成二维码 2 private void button2_Click(object sender, EventArgs e) 3 { 4 lbshow.Text = ""; 5 try 6 { 7 MultiFormatWriter mutiWriter = new com.google.zxing.MultiFormatWriter(); 8 ByteMatrix bm = mutiWriter.encode(txtMsg.Text, com.google.zxing.BarcodeFormat.QR_CODE, 300, 300); 9 Bitmap img = bm.ToBitmap(); 10 pictureBox1.Image = img; 11 12 //自动保存图片到当前目录 13 string filename = System.Environment.CurrentDirectory + "\\QR" + DateTime.Now.Ticks.ToString() + ".jpg"; 14 img.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg); 15 lbshow.Text = "图片已保存到:" + filename; 16 } 17 catch (Exception ee) 18 { MessageBox.Show(ee.Message); } 19 } 注意编码问题,在com.google.zxing.qrcode.encoder.Encoder类中修改默认编码为utf-8,否则解码出现的是乱码。 System.String DEFAULT_BYTE_MODE_ENCODING = "UTF-8"; 此处之前是"ISO-8859-1",之所以改成UTF-8是因为,在解码的时候程序会猜测可能的编码,如果猜测失败则默认是UTF-8,代码在com.google.zxing.qrcode.decoder.DecodedBitStreamParser类的guessEncoding方法中。 所以此开源项目也缺少全局性思考,连编码和解码的默认编码方式都不一致。 4.实现图片解码,即把条形码或二维码图片解码成其真实内容,当然在pc上应用不大,但可能只是还没发现而已,代码如下: 1 //解码操作 2 private void button3_Click(object sender, EventArgs e) 3 { 4 MultiFormatReader mutiReader = new com.google.zxing.MultiFormatReader(); 5 Bitmap img = (Bitmap)Bitmap.FromFile(opFilePath); 6 if (img == null) 7 return; 8 LuminanceSource ls = new RGBLuminanceSource(img, img.Width, img.Height); 9 BinaryBitmap bb = new BinaryBitmap(new com.google.zxing.common.HybridBinarizer(ls)); 10 11 Result r= mutiReader.decode(bb); 12 txtMsg.Text = r.Text; 13 } opFilePath是图片路径,你可以用openFileDialog控件打开文件来得到路径。 原文出自: http://www.cnblogs.com/tuyile006/archive/2013/01/16/2863367.html
很多人都知道SQL注入,也知道SQL参数化查询可以防止SQL注入,可为什么能防止注入却并不是很多人都知道的。 本文主要讲述的是这个问题,也许你在部分文章中看到过这块内容,当然了看看也无妨。 首先:我们要了解SQL收到一个指令后所做的事情: 具体细节可以查看文章:Sql Server 编译、重编译与执行计划重用原理 在这里,我简单的表示为: 收到指令 -> 编译SQL生成执行计划 ->选择执行计划 ->执行执行计划。 具体可能有点不一样,但大致的步骤如上所示。 接着我们来分析为什么拼接SQL 字符串会导致SQL注入的风险呢? 首先创建一张表Users: CREATE TABLE [dbo].[Users]( [Id] [uniqueidentifier] NOT NULL, [UserId] [int] NOT NULL, [UserName] [varchar](50) NULL, [Password] [varchar](50) NOT NULL, CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] 插入一些数据: INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),1,'name1','pwd1'); INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),2,'name2','pwd2'); INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),3,'name3','pwd3'); INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),4,'name4','pwd4'); INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),5,'name5','pwd5'); 假设我们有个用户登录的页面,代码如下: 验证用户登录的sql 如下: select COUNT(*) from Users where Password = 'a' and UserName = 'b' 这段代码返回Password 和UserName都匹配的用户数量,如果大于1的话,那么就代表用户存在。 本文不讨论SQL 中的密码策略,也不讨论代码规范,主要是讲为什么能够防止SQL注入,请一些同学不要纠结与某些代码,或者和SQL注入无关的主题。 可以看到执行结果: 这个是SQL profile 跟踪的SQL 语句。 注入的代码如下: select COUNT(*) from Users where Password = 'a' and UserName = 'b' or 1=1—' 这里有人将UserName设置为了 “b' or 1=1 –”. 实际执行的SQL就变成了如下: 可以很明显的看到SQL注入成功了。 很多人都知道参数化查询可以避免上面出现的注入问题,比如下面的代码: class Program { private static string connectionString = "Data Source=.;Initial Catalog=Test;Integrated Security=True"; static void Main(string[] args) { Login("b", "a"); Login("b' or 1=1--", "a"); } private static void Login(string userName, string password) { using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); SqlCommand comm = new SqlCommand(); comm.Connection = conn; //为每一条数据添加一个参数 comm.CommandText = "select COUNT(*) from Users where Password = @Password and UserName = @UserName"; comm.Parameters.AddRange( new SqlParameter[]{ new SqlParameter("@Password", SqlDbType.VarChar) { Value = password}, new SqlParameter("@UserName", SqlDbType.VarChar) { Value = userName}, }); comm.ExecuteNonQuery(); } } } 实际执行的SQL 如下所示: exec sp_executesql N'select COUNT(*) from Users where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(1)',@Password='a',@UserName='b' exec sp_executesql N'select COUNT(*) from Users where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(11)',@Password='a',@UserName='b'' or 1=1—' 可以看到参数化查询主要做了这些事情: 1:参数过滤,可以看到 @UserName='b'' or 1=1—' 2:执行计划重用 因为执行计划被重用,所以可以防止SQL注入。 首先分析SQL注入的本质, 用户写了一段SQL 用来表示查找密码是a的,用户名是b的所有用户的数量。 通过注入SQL,这段SQL现在表示的含义是查找(密码是a的,并且用户名是b的,) 或者1=1 的所有用户的数量。 可以看到SQL的语意发生了改变,为什么发生了改变呢?,因为没有重用以前的执行计划,因为对注入后的SQL语句重新进行了编译,因为重新执行了语法解析。所以要保证SQL语义不变,即我想要表达SQL就是我想表达的意思,不是别的注入后的意思,就应该重用执行计划。 如果不能够重用执行计划,那么就有SQL注入的风险,因为SQL的语意有可能会变化,所表达的查询就可能变化。 在SQL Server 中查询执行计划可以使用下面的脚本: DBCC FreeProccache select total_elapsed_time / execution_count 平均时间,total_logical_reads/execution_count 逻辑读, usecounts 重用次数,SUBSTRING(d.text, (statement_start_offset/2) + 1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(text) ELSE statement_end_offset END - statement_start_offset)/2) + 1) 语句执行 from sys.dm_exec_cached_plans a cross apply sys.dm_exec_query_plan(a.plan_handle) c ,sys.dm_exec_query_stats b cross apply sys.dm_exec_sql_text(b.sql_handle) d --where a.plan_handle=b.plan_handle and total_logical_reads/execution_count>4000 ORDER BY total_elapsed_time / execution_count DESC; 博客园有篇文章: Sql Server参数化查询之where in和like实现详解 在这篇文章中有这么一段: 这里作者有一句话:”不过这种写法和直接拼SQL执行没啥实质性的区别” 任何拼接SQL的方式都有SQL注入的风险,所以如果没有实质性的区别的话,那么使用exec 动态执行SQL是不能防止SQL注入的。 比如下面的代码: private static void TestMethod() { using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); SqlCommand comm = new SqlCommand(); comm.Connection = conn; //使用exec动态执行SQL //实际执行的查询计划为(@UserID varchar(max))select * from Users(nolock) where UserID in (1,2,3,4) //不是预期的(@UserID varchar(max))exec('select * from Users(nolock) where UserID in ('+@UserID+')') comm.CommandText = "exec('select * from Users(nolock) where UserID in ('+@UserID+')')"; comm.Parameters.Add(new SqlParameter("@UserID", SqlDbType.VarChar, -1) { Value = "1,2,3,4" }); //comm.Parameters.Add(new SqlParameter("@UserID", SqlDbType.VarChar, -1) { Value = "1,2,3,4); delete from Users;--" }); comm.ExecuteNonQuery(); } } 执行的SQL 如下: exec sp_executesql N'exec(''select * from Users(nolock) where UserID in (''+@UserID+'')'')',N'@UserID varchar(max) ',@UserID='1,2,3,4' 可以看到SQL语句并没有参数化查询。 如果你将UserID设置为” 1,2,3,4); delete from Users;—- ”,那么执行的SQL就是下面这样: exec sp_executesql N'exec(''select * from Users(nolock) where UserID in (''+@UserID+'')'')',N'@UserID varchar(max) ',@UserID='1,2,3,4); delete from Users;--' 不要以为加了个@UserID 就代表能够防止SQL注入,实际执行的SQL 如下: 任何动态的执行SQL 都有注入的风险,因为动态意味着不重用执行计划,而如果不重用执行计划的话,那么就基本上无法保证你写的SQL所表示的意思就是你要表达的意思。 这就好像小时候的填空题,查找密码是(____) 并且用户名是(____)的用户。 不管你填的是什么值,我所表达的就是这个意思。 最后再总结一句:因为参数化查询可以重用执行计划,并且如果重用执行计划的话,SQL所要表达的语义就不会变化,所以就可以防止SQL注入,如果不能重用执行计划,就有可能出现SQL注入, 存储过程也是一样的道理,因为可以重用执行计划。 原文出自: http://www.cnblogs.com/LoveJenny/archive/2013/01/15/2860553.html
背景 : 在使用搜索引擎和电商的搜索功能时,大家一定遇到过这样的情景:我想搜索电影“十二生肖”,可不小心输成“十二生效”了,不用担心搜不到你想要的结果,因为建立在大数据上的搜索引擎会帮你自动纠错,就这个例子Google和Baidu返回给我的分别是: 显示以下查询字词的结果: 十二生肖 和 您要找的是不是: 十二生肖 ,他们都做到了自动纠错,关于自动纠错我之前也写过一篇陋文,当时是自己实现的N-Gram模型,但是效果不是太好,主要是针对不同的语料库算法的精确度是不一样的,我想换个算法试试看,目前主流的计算串间的距离(相反的,你也可以理解为相似度)是Levenshtein,当要实现时,发现lucene已经做了这个事,那咱就站在巨人的肩膀上成长吧。 引用包: lucene-core-3.1.0.jar + lucene-spellchecker-3.1.0.jar,你可以在这里得到 使用示例: 在类SpellCorrector的main方法中加入以下代码 1 //创建目录 2 File dict = new File(""); 3 Directory directory = FSDirectory.open(dict); 4 5 //实例化拼写检查器 6 SpellChecker sp = new SpellChecker(directory); 7 8 9 //创建词典 10 File dictionary = new File(SpellCorrecter.class.getResource("dictionary.txt").getFile()); 11 12 //对词典进行索引 13 sp.indexDictionary(new PlainTextDictionary(dictionary)); 14 15 16 //有错别字的搜索 17 String search = "非常勿扰"; 18 19 20 //建议个数,这里我只想要最接近的那一个,你可以设置成别的数字,如3 21 int suggestionNumber = 1; 22 23 24 //获取建议的关键字 25 String[] suggestions = sp.suggestSimilar(search, suggestionNumber); 26 27 28 //显示结果 29 System.out.println("搜索:" + search); 30 31 32 for (String word : suggestions) { 33 System.out.println("你要找的是不是:" + word); 34 } 注:这之前你需要有个语料库,我这里是个存放正确视频名称的文件,格式如下:
红颜血泪 冰上火一般的激情 在敌之手 驰风竞艇王第二部 钓金龟 潇湘路一号 戏里戏外第二季 草原狼爵士乐 拯救大兵瑞恩 好了,接下来就直接运行吧,例如我搜索“十二生效”,则提示说是不是要找“十二生肖” 原文出自: http://www.cnblogs.com/wuren/archive/2013/01/16/2862873.html
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ResourceService': Invocation of init method failed; nested exception is javax.xml.ws.WebServiceException: java.lang.IllegalArgumentException: An operation with name [####] already exists in this service 可能是因为WebService 存在重载的方法,因此初始化时Spring无法找到对应的方法 使用的插件为: javax.jws-1.0.0_JDK1.5_1.0.0.jar cxf-bundle-2.5.2.jar spring-webmvc-3.1.1.RELEASE.jar
一般我们的前台代码Ext.grid.ColumnModel里会这样写,以便显示日期格式: ////////////////////////////////////////////////////////////// Js代码 .... { header:"birthday", dataIndex:"birthday" .... renderer:new Ext.util.Format.dateRenderer("Y-m-d"), .... } .... ////////////////////////////////////////////////////////////// 如果你前台这样写的话,那恭喜你,你的显示日期那列将不再正确显示时间, 而是显示为"NaN-NaN-NaN",是吧? 呵呵,问我怎么知道的?因为最开始我也是这么错的。 为什么会是错的呢? 让我们来看看Ext.format.dateRenderer的源代码(开源的东西就是好), 它的源代码是这样的: Js代码 ////////////////////////////////////////////////////////////// dateRenderer : function(format) { return function(v) { return Ext.util.Format.date(v, format);、 } } ////////////////////////////////////////////////////////////// 可以看出,我们传会来的值,被当做日期又被格式化了一次,我们传回来的是日期吗? 以前是,经过昨天后台代码的修改,我们传回来的仅仅是个字符串了,至于为什么要这么改, 请看昨天写的“Extjs日期格式问题(一) ”,那咋办?有的朋友应该已经想到了,既然是字符串, 那就直接显示呗,不用renderer了,于是前台代码Ext.grid.ColumnModel里就变成了: Js代码 ////////////////////////////////////////////////////////////// .... {header:"birthday",dataIndex:"birthday".......), .... ////////////////////////////////////////////////////////////// 可以负责任的告诉你,这样写,绝对可以正确显示了,这样是不是感觉更简单了呢? 但是,基于我项目里的要求,这个问题并没有解决完,因为在这里不是一个简单的gridpanel, 而是一个editgridpanel,所以还得定义一个editor,于是有了下面这样一段代码: Js代码 ////////////////////////////////////////////////////////////// .... {header:"birthday",dataIndex:"birthday"......., editor:new Ext.grid.GridEditor(new Ext.form.DateField({format:"Y-m-d"})), ..... ////////////////////////////////////////////////////////////// 加了这个DateField控件后,每次可以正常的选择日期,但是选择完日期后, grid里显示的格式就又不正确了,这次显示的内容成了: "Wed Mar 04 1970......", 这样的格式一看就是个日期,这样显示的原因当然是因为我们没有写renderer进行格式化处理的缘故。。。 说到这里,有人应该已经想到解决办法了,另外有些人可能就抓狂了,这renderer加了不能正常显示, 不加也不能正常显示,这很矛盾啊。。 问题往往到了最矛盾的时候,也是到了解决的时候,现在我把解决代码贴出来,大家一看就明白了。 多的不说,看代码: Js代码 ////////////////////////////////////////////////////////////// renderer:function(value){ if(value instanceof Date){ return new Date(value).format("Y-m-d"); }else{ return value; } } ////////////////////////////////////////////////////////////// 简单吧?自己写renderer就是了。 原文出自:http://ks2144634.blog.163.com/blog/static/133585503201081544950656/
错误”ora-04031 无法分配XXX字节的共享内存(XXX)”的解决办法: oracle 9i: sys用户以sysdba身份登录 先查看当前shared_pool_size值 sql>show parameter shared_pool_size; 然后 sql>alter system set shared_pool_size=’比原先值适当增加’ scope=spfile; 然后 sql>shutdown immediate sql>startup oracle 10g: oracle 10g shared_pool_size默认值为0,也就是系统自动管理shared pool内存,这时可以适当增加shared_pool_reserved_size的值,仍然让系统自动管理这部分内存 sql>alter system set shared_pool_reserved_size=’比原先值适当增加’ scope=spfile; sql>shutdown immediate sql>startup 原文出自:http://openwares.net/database/cant_alloc_share_memory.html
对依赖注入( http://www.oschina.net/code/snippet_871522_15682) 的进一步加强. 作为基本功能的注册,使用语法是:registration.register<Interface,Implementation>(). 可以到了实际的项目中,要注册的接口和类可能不止一个两个,会成百上千。无论是用C#代码来注册,还是用XML文件来配置,都是开发者的噩梦。 这里,让我们来个思维的反转: 变集中配置为分散声明。 1 为要注册的类,加入RegisterInContainer的声明 2 在系统启动的时候,扫描所有的类,对有RegisterInContainer的类,找到它所有实现的接口,把这些接口和该类绑定注册。 用于装饰要注入类的Attribute. 1 using System; 2 using System.Linq; 3 using Skight.eLiteWeb.Domain.BasicExtensions; 4 5 namespace Skight.eLiteWeb.Domain.Containers 6 { 7 [AttributeUsage(AttributeTargets.Class)] 8 public class RegisterInContainerAttribute : Attribute 9 { 10 public RegisterInContainerAttribute(LifeCycle life_cycle) { 11 this.life_cycle = life_cycle; 12 } 13 14 public LifeCycle life_cycle { get; set; } 15 public Type type_to_register_in_container { get; set; } 16 17 public void register_using(Registration registration) { 18 DiscreteItemResolver resolver = new TypeResolver(type_to_register_in_container); 19 if (life_cycle == LifeCycle.singleton) resolver = new SingletonResolver(resolver); 20 registration.register(resolver,type_to_register_in_container.all_interface().ToArray()); 21 } 22 } 23 } 注入声明Attribute参数,指定是否单件方式生成注册类。1 namespace Skight.eLiteWeb.Domain.Containers 2 { 3 public enum LifeCycle 4 { 5 single_call, 6 singleton 7 } 8 } 注册声明Attribute的使用示例 1 //调用Container.get_an<FrontController>()将会得到FrontControllerImpl的对象 2 3 using Skight.eLiteWeb.Domain.Containers; 4 5 namespace Skight.eLiteWeb.Presentation.Web.FrontControllers 6 { 7 [RegisterInContainer(LifeCycle.single_call)] 8 public class FrontControllerImpl : FrontControllers.FrontController 9 { 10 private CommandResolver command_resolver; 11 12 public FrontControllerImpl(CommandResolver commandResolver) 13 { 14 command_resolver = commandResolver; 15 } 16 17 public void process(WebRequest request) 18 { 19 command_resolver.get_command_to_process(request).process(request); 20 } 21 } 22 } Registration添加一个方法:反过来,为一个解析器(实现类)注册多个接口。1 void register(DiscreteItemResolver resolver, params Type[] contracts); 2 扫描注册机,在系统启动时调用一次。 1 using System.Collections.Generic; 2 using System.Reflection; 3 using Skight.eLiteWeb.Domain.BasicExtensions; 4 using Skight.eLiteWeb.Domain.Containers; 5 6 namespace Skight.eLiteWeb.Application.Startup 7 { 8 public class RegistrationScanner:StartupCommand 9 { 10 private readonly Registration registration; 11 private readonly IEnumerable<Assembly> assemblies; 12 13 public RegistrationScanner(Registration registration, params Assembly[] assemblies) 14 { 15 this.registration = registration; 16 this.assemblies = assemblies; 17 } 18 19 public void run() 20 { 21 assemblies 22 .each(assembly => 23 assembly.GetTypes() 24 .each(type => 25 type.run_againste_attribute<RegisterInContainerAttribute>( 26 attribute => 27 { 28 attribute.type_to_register_in_container = type; 29 attribute.register_using(registration); 30 }))); 31 } 32 } 33 } 系统启动:创建注册类,然后传入必要的Assembly,调用注册机注册所有加了Attribute的类。 1 using System; 2 using System.Collections.Generic; 3 using System.Reflection; 4 using Skight.eLiteWeb.Domain.Containers; 5 using Skight.eLiteWeb.Presentation.Web.FrontControllers; 6 7 namespace Skight.eLiteWeb.Application.Startup 8 { 9 public class ApplicationStartup 10 { 11 public void run() 12 { 13 var registration = create_registration(); 14 new RegistrationScanner(registration, 15 Assembly.GetAssembly(typeof (Container)), 16 Assembly.GetAssembly(typeof (FrontController)), 17 Assembly.GetAssembly(typeof (StartupCommand))) 18 .run(); 19 20 } 21 22 private Registration create_registration() 23 { 24 IDictionary<Type, DiscreteItemResolver> item_resolvers = new Dictionary<Type, DiscreteItemResolver>(); 25 Container.initialize_with(new ResolverImpl(item_resolvers)); 26 return new RegistrationImpl(item_resolvers); 27 } 28 } 29 } Global.asax系统入口,把所有的代码串起来。 1 <%@ Application Language="C#" %> 2 <%@ Import Namespace="Skight.eLiteWeb.Application.Startup" %> 3 <script RunAt="server"> 4 5 private void Application_Start(object sender, EventArgs e) 6 { 7 new ApplicationStartup().run(); 8 } 9 10 </script> 原文出自: http://www.oschina.net/code/snippet_871522_16735
摘要: http://www.umlchina.com/Tools/Newindex1.htmUML相关工具一览(截止2012年10月) 整理 本文的PDF版本在此下载>> 以下总结了全世界的各种UML相关工具,按工具名称字母排序。 工具(最新版本) 厂商&地址 版权 ... 阅读全文
1.活动图、用例图、类图 http://yuml.me/diagram/scruffy/class/draw 2.序列图 http://www.websequencediagrams.com/ 3.序列图、协作图 http://www.diagrammr.com/
摘要: Container注入框架的进入点Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 namespace Skight.LightWeb.Domain 2 { 3 &n... 阅读全文
在这里我们总结了Oracle临时表的集中用法,临时表创建之后基本不占用表空间,如果你没有指定临时表存放的表空的时候,你插入到临时表的数据是存在系统的临时表空间中。 Oracle临时表可以说是提高数据库处理性能的好方法,在没有必要存储时,只存储在Oracle临时表空间中。希望本文能对大家有所帮助。 1 、前言 目前所有使用 Oracle 作为数据库支撑平台的应用,大部分数据量比较庞大的系统,即表的数据量一般情况下都是在百万级以上的数据量。 当然在 Oracle 中创建分区是一种不错的选择,但是当你发现你的应用有多张表关联的时候,并且这些表大部分都是比较庞大,而你关联的时候发现其中的某一张或者某几张表关联 之后得到的结果集非常小并且查询得到这个结果集的速度非常快,那么这个时候我考虑在 Oracle 中创建“临时表”。 我对临时表的理解:在 Oracle 中创建一张表,这个表不用于其他的什么功能,主要用于自己的软件系统一些特有功能才用的,而当你用完之后表中的数据就没用了。 Oracle 的临时表创建之后基本不占用表空间,如果你没有指定临时表(包括临时表的索引)存放的表空的时候,你插入到临时表的数据是存放在 ORACLE 系统的临时表空间中( TEMP )。 2 、临时表的创建 创建Oracle 临时表,可以有两种类型的临时表: 会话级的临时表 事务级的临时表 。 1) 会话级的临时表因为这这个临时表中的数据和你的当前会话有关系,当你当前SESSION 不退出的情况下,临时表中的数据就还存在,而当你退出当前SESSION 的时候,临时表中的数据就全部没有了,当然这个时候你如果以另外一个SESSION 登陆的时候是看不到另外一个SESSION 中插入到临时表中的数据的。即两个不同的SESSION 所插入的数据是互不相干的。当某一个SESSION 退出之后临时表中的数据就被截断(truncate table ,即数据清空)了。会话级的临时表创建方法: 1 Create Global Temporary Table Table_Name 2 (Col1 Type1,Col2 Type2) On Commit Preserve Rows ;
举例: 1 create global temporary table Student 2 (Stu_id Number(5), 3 Class_id Number(5), 4 Stu_Name Varchar2(8), 5 Stu_Memo varchar2(200)) on Commit Preserve Rows ;
2) 事务级临时表是指该临时表与事务相关,当进行事务提交或者事务回滚的时候,临时表中的数据将自行被截断,其他的内容和会话级的临时表的一致(包括退出SESSION 的时候,事务级的临时表也会被自动截断)。事务级临时表的创建方法: 1 Create Global Temporary Table Table_Name 2 (Col1 Type1,Col2 Type2) On Commit Delete Rows ;
举例: 1 create global temporary table Classes 2 (Class_id Number(5), 3 Class_Name Varchar2(8), 4 Class_Memo varchar2(200)) on Commit delete Rows ;
3) 两中类型临时表的区别 会话级临时表采用 on commit preserve rows ;而事务级则采用 on commit delete rows ;用法上,会话级别只有当会话结束临时表中的数据才会被截断,而且事务级临时表则不管是 commit 、 rollback 或者是会话结束,临时表中的数据都将被截断 4 )什么时候使用临时表 1 )、当某一个 SQL 语句关联的表在 2 张及以上,并且和一些小表关联。可以采用将大表进行分拆并且得到比较小的结果集合存放在临时表中 2 )、程序执行过程中可能需要存放一些临时的数据,这些数据在整个程序的会话过程中都需要用的等等。 3 . 例子:略 4 .临时表的不足之处 1 )不支持 lob 对象,这也许是设计者基于运行效率的考虑,但实际应用中确实需要此功能时就无法使用临时表了。 2 )不支持主外键关系 所以,由于以上原因,我们可以自己创建临时表,以弥补 oracle 临时表的不足之处 上面的都是本人经过测试的,但下面是在网上搜索到的方法,本人具体没有测试过,不过觉得可行性很强,有时间测试下 创建方法: 1 、以常规表的形式创建临时数据表的表结构,但要在每一个表的主键中加入一个 SessionID 列以区分不同的会话。(可以有 lob 列和主外键) 2 、写一个用户注销触发器,在用户结束会话的时候删除本次会话所插入的所有记录 (SessionID 等于本次会话 ID 的记录 ) 。 3 、程序写入数据时,要顺便将当前的会话 ID(SessionID) 写入表中。 4 、程序读取数据时,只读取与当前会话 ID 相同的记录即可。 功能增强的扩展设计: 1 、可以在数据表上建立一个视图,视图对记录的筛选条件就是当前会话的SessionID 。 2 、数据表中的SessionID 列可以通过Trigger 实现,以实现对应用层的透明性。 3 、高级用户可以访问全局数据,以实现更加复杂的功能。 扩展临时表的优点: 1 、实现了与Oracle 的基于会话的临时表相同的功能。 2 、支持SDO_GEOMETRY 等lob 数据类型。 3 、支持表间的主外键连接,且主外键连接也是基于会话的。 4 、高级用户可以访问全局数据,以实现更加复杂的功能 原文出自: http://database.51cto.com/art/201001/180851.htm
Heritrix绑定主机IP 关键字:Heritrix 127.0.0.1 IP 主机 Heritrix默认绑定的IP是127.0.0.1。 在org.archive.crawler.Heritrix中 … final private static Collection<String> LOCALHOST_ONLY = Collections.unmodifiableList(Arrays.asList(new String[] { "127.0.0.1" })); … private static Collection<String> guiHosts = LOCALHOST_ONLY; protected static String doCmdLineArgs(final String [] args) throws Exception { … // Now look at options passed. for (int i = 0; i < options.length; i++) { switch(options[i].getId()) { … case 'b': Heritrix.guiHosts = parseHosts(options[i].getValue()); break; … default: assert false: options[i].getId(); } } … } | 首先定义了默认IP:127.0.0.1,然后赋给guiHost主机变量。当指定-b或--bind参数时,才会把指定的IP赋给主机变量。 另外,中间还有一步参数处理,对于--xxxx参数会转为-x的形式统一处理,所以--bind和-b有一样的效果。 Heritrix启动参数 关键字:Heritrix 启动 参数 bind admin properties Heritrix的启动参数,除了--bind外,都可以在heritrix.properties设置,而不用每次都在命令行中输入。 如常用的--port, --admin等。 heritrix.cmdline.admin = admin:admin heritrix.cmdline.port = 8080 heritrix.cmdline.run = false heritrix.cmdline.nowui = false heritrix.cmdline.order = heritrix.cmdline.jmxserver = false heritrix.cmdline.jmxserver.port = 8081 | 关于Heritrix的Extractor中文乱码 关键字:Heritrix 中文 乱码 GB2312 Extractor 继承从org.archive.crawler.extractor.Extractor的子类,在extract方法中可以从参数CrawlURI中取出要解析的内容。 curi.getHttpRecorder().getReplayCharSequence.toString() | 有中文时,不做处理会输出乱码。可以在取到的HttpRecorder后设置编码: HttpRecorder hr = curi.getHttpRecorder(); if ( hr == null ) { throw new IOException( "Why is recorder null here?" ); } hr.setCharacterEncoding( "gb2312" ); cs = hr.getReplayCharSequence(); System.out.println( cs.toString() ); | 原文出自: http://blog.chinaunix.net/uid-8464637-id-2461166.html
原文出自: http://blog.csdn.net/jbxiaozi/article/details/7351768
1.右键项目-》属性-》java bulid path-》jre System Library-》access rules-》resolution选择accessible,下面填上** 点击确定即可!!! 2. 在MyEclipse中编写Java代码时,用到了BASE64Decoder,import sun.misc.BASE64Decoder;可是Eclipse提示: Access restriction: The type BASE64Decoder is not accessible due to restriction on required library C:\Program files\java\jre6\lib\rt.jar Access restriction : The constructor BASE64Decoder() is not accessible due to restriction on required library C:\Program files\java\jre6\lib\rt.jar 解决方案1(推荐): 只需要在project build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
解决方案2: Windows -> Preferences -> Java -> Compiler -> Errors/Warnings -> Deprecated and trstricted API -> Forbidden reference (access rules): -> change to warning
项目中有时需要用到起始日期和结束日期,要做到起始日期必须小于结束日期。在extjs中已经有现成的函数,摘录如下: 1 Ext.apply(Ext.form.VTypes, { 2 daterange : function(val, field) { 3 var date = field.parseDate(val); 4 if (!date) { 5 return; 6 } 7 if (field.startDateField 8 && (!this.dateRangeMax || (date.getTime() != this.dateRangeMax 9 .getTime()))) { 10 var start = Ext.getCmp(field.startDateField); 11 start.setMaxValue(date); 12 start.validate(); 13 this.dateRangeMax = date; 14 } else if (field.endDateField 15 && (!this.dateRangeMin || (date.getTime() != this.dateRangeMin 16 .getTime()))) { 17 var end = Ext.getCmp(field.endDateField); 18 end.setMinValue(date); 19 end.validate(); 20 this.dateRangeMin = date; 21 } 22 /* 23 * Always return true since we're only using this vtype to set 24 * the min/max allowed values (these are tested for after the 25 * vtype test) 26 */ 27 return true; 28 } 29 }); 然后分别定义起始日期和结束日期控件: 1 var startDate = new Ext.form.DateField({ 2 fieldLabel : '开始日期', 3 emptyText : '请选择', 4 disabledDays : [1, 2, 5],//将星期一,二,五禁止.数值为0-6,0为星期日,6为星期六 5 labelWidth : 100, 6 readOnly : true, 7 allowBlank : false, 8 format : 'Y-m-d',//日期格式 9 name : 'startdt', 10 id : 'startdt', 11 vtype : 'daterange',//daterange类型为上代码定义的类型 12 endDateField : 'endDate'//必须跟endDate的id名相同 13 }) 14 var endDate = new Ext.form.DateField({ 15 fieldLabel : '结束日期', 16 emptyText : '请选择', 17 disabledDays : [1, 2, 5],//将星期一,二,五禁止.数值为0-6,0为星期日,6为星期六 18 readOnly : true, 19 allowBlank : false, 20 format : 'Y-m-d',//日期格式 21 name : 'enddt', 22 id : 'endDate', 23 vtype : 'daterange',//daterange类型为上代码定义的类型 24 startDateField : 'startdt'//必须跟startDate的id名相同 25 }) 效果如下两图: 图1.选择开始日期 图2.选择结束日期 原文出自: http://blog.csdn.net/security08/article/details/5070749
工作流管理联盟: 定义: 创建并完善了工作流的相关标准,开拓了相关市场,是唯一的致力于工作流标准化的专业组织。该组织推出了工作流XML(Wf-XML)和XML过程定义语言(XPDL) ,现在有超过80种有名的解决方案中使用了这两种语言来存储和交换过程模型。发布了用于工作流管理系统之间互操作的工作流参考模型,并且为了实现不同工作流产品之间的互操作,WfMC在工作流管理系统的相关术语、体系结构及应用编程接口等方面制定了一系列标准 工作流: 定义: 工作流是一类能够完全或者部分自动执行的经营过程,根据一系列过程规则,文档、信息或任务能够在不同的执行者之间传递、执行。从工作流的定义可以看出:(1)、有多个参与者:(2)、按照一定的规则进行活动(传递文档、信息、任务等);(3)、活动的推进是自动的或部分自动的。【工作流管理联盟】 工作流管理系统: 定义: 工作流管理系统是一个软件系统,它负责工作流的定义和管理,并按照在计算机中预先定义好的工作流逻辑推进过程实例的执行。工作流管理系统(Workflow Management System,WFMS)是通过对工作流程中涉及各步骤的人员和IT资 源的合理调整,从而起到对工作流的定义、管理和实现的确定性作用。工作流管理系统是支持企业实现业务过程管理和自动化的强有力的软件工具,它能完成工作流 的定义和管理,并按照在计算机中预先定义好的工作流逻辑推进工作流实例的执行。所以工作流是工作流管理系统的最重要的被管理的元素,就像表、试图是数据库 管理系统的管理对象一样。【工作流管理联盟】 工作流参考模型: 定义: 1.通用的工作流系统实现模型 2.把工作流系统中的主要功能组件和这些组件间的接口一起看成抽象的模型 作用: 1.这个模型可以与市场上的大多数产品相匹配,因此为开发协同工作的工作流系统奠定了基础 2.工作流参考模型的引入为人们讨论工作流技术提供了一一个规范的术语表,为在一般意义上讨论工作流系统的体系结构提供了基础:工作流参考模型为工作流管理系统的关键软件部件提供了功能描述,并描述了关键软件部件交互,而 且这个描述是独立于特定产品或技术的实现的:从功能的角度定义五个关键软件部件的交互接口,推动了信息交换的标准化,使得不同产品间的互操作成为可能。 组成: 1.软件组件:为工作流系统的各种功能提供支持。 2.各中类型的系统定义数据和控制数据:系统中的一个或多个软件构件使用的数据。 3.应用程序与应用程序数据库:外部系统或数据,被系统调用来完成整个或部分工作流管理的功能。 五类接口(WorkflowAPI,WAPI) 接口l:工作流执行服务与工作流建模工具间的接口,为实现对工作流过程定义的访问(如建立、修改、删除等)提供了一致的方法。 接口2:工作流服务和用户应用之间的接口,这是最主要的接口规范,它约定所有客户方应用和工作流服务之间的功能访问方式。 接口3:工作流引擎和应用服务间的直接接口,其目标是集成工作流和其它应用服务而无需考虑原有工作流管理系统。 接口4:工作流管理系统之间的互操作接口,用于描述不同工作流产品的互操作性。 一般必须的互操作有两个主要方面: (1)流程定义或子集的公共解释; (2)运行时间对各种控制信息转换,和在不同实施服务之间传递工作流相关数据和应用数据的支持。_个工作流引擎可以选择、实例化和执行其他工作流引擎所约定的流程定义。 接口5:工作流服务和工作流管理工具之间的接口,用于系统管理、应用访问工作流执行服务。 通用工作流系统各部分功能: 1.工作流执行服务 工作流执行服务是指由一个或者多个工作流引擎组成,以创建,管理和执行工作流实例,应用程序可能通过工作流应用程序接口(WAPI))与这个服务进行交互。工作流执行服务的主要功能是:解释流程定义,生成过程实例,并管理其实施过程;依据工作流相关数据实现流程活动导航,包括顺序或并行操作、期限设置等;与外部资源交互,完成各项活动;维护工作流控制数据和工作流相关数据,并向用户传送必要的相关数据。 工作流执行服务使用外部资源的两种途径: 1.用户应用接口:工作流引擎通过任务项列表管理资源,任务项列表管理器负责从任务项列表中选择并监督工作项的完成。任务项列表管理器或用户负责调用应用工具。 2.直接调用应用接口:工作流引擎直接调用相应的应用来完成一项任务。这主要是针对基于服务器的无需用户参与的应用,那些需要用户操作的活动则通过任务列表管理器来调用。 2.工作流引擎 工作流引擎是指为工作流实例提供运行时执行环境的软件服务或“引擎”。 主要提供以下功能:对过程定义进行解释;控制过程实例的生成、激活、挂起、终止等;控制过程活动间的转换,包括串行或并行的操作、工作流相关数据的解释 等;支持用户操作的界面;维护工作流控制数据和工作流相关数据,在应用或用户间传递工作流相关数据;提供用于激活外部应用并提供工作流相关数据的界面;提 供控制、管理和监督的功能。 3.过程定义工具 过程定义工具是管理流程定义的工具,它可以通过图形方式把复杂的流程定义显示出来并加以操作。流程定义工具同工作流执行服务交互,为用户提供一种对实际业务过程进行分析、建模的手段,并生成业务过程的可被计算机处理的形式化描述(过程定义)。这也是工作流系统建立阶段的主要任务。不同的工作流产品,其建模工具输出格式是不同的。接口l不仅使工作流的定义阶段和运行阶段分离,使用户可以分别选择建模工具和执行产品,并且提供了对工作流过程进行协同定义的潜在能力,这些产品提供了分布的运行服务。 4.管理和监控工具 管理和监控工具主要负责对组织机构、角色等数据的维护管理和工作流实例的运行进行监控。管理员可以通过工作流管理工具获得目前各个活动的运行情况报告,并可干预实例的推进。 5.客户端应用 客户端应用是通过请求的方式同工作流执行服务交互的应用,也就是说是客户端应用调用工作流执行服务,客户端应用同工作流执行服务交互。它提供给用户一种手段,以处理实例运行过程中需要人工参与的任务。 6.调用的应用 调用的应用指工作流执行服务在过程实例运行过程中调用的、用以对应用数据进行处理的应用程序和Web服务 原文出自: http://www.cnblogs.com/yuziyan/archive/2012/12/08/2809346.html
类图画法 类之间的几种关系:泛化(Generalization)、实现(Realization)、关联(Association)(又分一般关联、聚合(Aggregation)、组合(Composition))、依赖(Dependency) 一、类图画法 1、 类图的概念 A、显示出类、接口以及它们之间的静态结构和关系 B、用于描述系统的结构化设计 2、 类图的元素 类、接口、协作、关系,我们只简单介绍一下这四种元素。 同其他的图一样,类图也可以包含注解和限制。 类图中也可以包含包和子系统,这两者用来将元素分组。 有时候你也可以将类的实例放到类图中。 3、 类 A、 类是对一组具有相同属性、操作、关系和语义的对象的抽象,它是面向对象系统组织结构的核心,包括名称部分(Name)、属性部分(Attribute)和操作部分(Operation),见下图。 B、 类属性的语法为: [可见性] 属性名 [:类型] [=初始值] [{属性字符串}] 可见性:公有(Public)“+”、私有(Private)“-”、受保护(Protected)“#” 类操作的语法为: [可见性] 操作名 [(参数表)] [:返回类型] [{属性字符串}] 可见性:公有(Public)“+”、私有(Private)“-”、受保护(Protected)“#”、包内公有(Package)“~” 参数表: 定义方式:“名称:类型”;若存在多个参数,将各个参数用逗号隔开;参数可以具有默认值; 属性字符串: 在操作的定义中加入一些除了预定义元素之外的信息。 4、 接口 在没有给出对象的实现和状态的情况下对对象行为的描述。 一个类可以实现一个或多个接口。 使用两层矩形框表示,与类图的区别主要是顶端有<<interface>>显示: 也可以用一个空心圆表示: 5、 协作 协作是指一些类、接口和其他的元素一起工作提供一些合作的行为,这些行为不是简单地将元素 加能得到的。例如:当你为一个分布式的系统中的事务处理过程建模型时,你不可能只通过一个类来明白事务是怎样进行的,事实上这个过程的执行涉及到一系列的 类的协同工作。使用类图来可视化这些类和他们的关系。 6、 关系 这篇文章的重点,详见第二部分。 二、类之间的几种关系 1、 泛化(Generalization) A、 是一种继承关系,表示一般与特殊的关系,它指定了子类如何特化父类的所有特征和行为,描述了一种“is a kind of” 的关系。例如:老虎是动物的一种,即有老虎的特性也有动物的共性。 B、 用带空心箭头的实线表示,箭头指向父类,如下图: 2、 实现(Realization) A、 是一种类与接口的关系,表示类是接口所有特征和行为的实现。 B、 用带空心箭头的虚线表示,箭头指向接口,如下图: 3、 关联(Association) A、 一般关联 a、 关联关系是类与类之间的联结,它使一个类知道另一个类的属性和方法,指明了事物的对象之间的联系,如:老师与学生、丈夫与妻子。关联可以是双向的,也可以是单向的,还有自身关联。 b、 用带普通箭头的实心线表示。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头,如下图: B、 聚合(Aggregation) a、 它是整体与部分(整体 has a 部分)的关系,且部分可以离开整体而单独存在,如车和轮胎是整体和部分的关系,轮胎离开车仍然可以存在。聚合关系是关联关系的一种,是强的关联关系,关联和聚合在语法上无法区分,必须考察具体的逻辑关系。 b、 用带空心菱形的实线表示,菱形指向整体,如下图: C、 组合(Composition) a、 它是整体与部分的关系,但部分不能离开整体而单独存在。如公司和部门是整体和部分的关系,没有公司就不存在部门。组合关系是关联关系的一种,是比聚合关系还要强的关系,它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期。 b、 用带实心菱形的实线表示,菱形指向整体,如下图: 4、 依赖(Dependency) A、 元素A的变化会影响元素B,那么B和A的关系是依赖关系,B依赖A。要避免双向依赖,一般来说,不应该存在双向依赖。关联、实现、泛化都是依赖关系。 B、 用带箭头的虚线表示,箭头指向被依赖元素。 5、 总结 各种关系的强弱顺序如下: 泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖 下面这张UML图,比较形象地展现了各种类图关系: 原文出自: http://www.cnblogs.com/fuhongxue2011/archive/2012/12/09/2810408.html
|