1 背景概述
相信很多了解数通畅联软件的人对AEAI DP应用开发平台并不陌生,笔者在入职第一天就开始接触AEAI DP,使用AEAI DP开发过AEAI WM、AEAI CRM以及中国XXXX管理系统项目,在此过程中对AEAI DP有了较为深入了解,工作之余尝试对AEAI DP的工作原理、实际开发工作涉及的技术点进行梳理,希望能够对其他AEAI DP初学者和使用人员有所帮助。
本文相关说明涵盖AEAI DP的远程热部署新特性,AEAI DP V3.5以后版本支持按工程、模块、资源不同粒度实现代码远程增量部署,类似AEAI ESB中的按流程、服务、工程远程热部署模式。
2 预期读者
3 技能要求
了解Java Web开发过程,熟悉相关知识点
对AEAI DP技术手册所涉及的内容熟练掌握
4 架构及原理
4.1 DP产品架构解读
AEAI DP开发平台包括三部分,第一部分是一站式的Java Web框架,在数通畅联软件家族中命名为Hotweb,第二部分基于Eclipse插件的扩展开发设计器,在数通畅联软件家族中命名为Miscdp Studio,第三部分是用于开发调试的服务器HotServer。基于Miscdp Studio可以开发普通Java Web应用、集成Java Web应用,还可以为BPM流程平台开发业务表单及流程相关功能。
Hotweb是一站式的MVCFramework,对前端页面交互及控制层做了统一封装,各类功能模型的交互方式封装在父类中。每个页面提供一个Handler处理Java类和展现JSP页面,一个功能可能涉及多个页面,复用一套业务逻辑处理Service和通用的数据存取持久工具类DAOHelper,在Service层调用通用数据存取类DAOHelper。数据持久层基于IBatis封装,Service层基于Spring来做事务控制和服务配置。
4.2 Howeb交互机制
DispatchServlet:前端请求分发,配置于web.xml
Handler:具体请求动作处理及控制,调用Service,返回ViewRender
Service:后台业务处理,包括接口及实现,Spring配置,通过DaoHelper调用SQLMap
SQLMap:负责数据持久化处理(CRUD)
ViewRender:前端展现渲染方式定义,实例化PageBean,放置于request的attributes中
PageBean:承载前端展现的属性、方法
JSP:具体页面代码,使用PageBean来获取handler中设置相关数据。
典型请求页面交互过程模式如下:
Servlet根据HandlerId实例化Handler、根据actionType反射调用对应的处理方法,方法名跟actionType一致
在对应方法中,调用Spring配置的Service来存/取数据库
如果是ajaxRender直接response返回页面,异步加载或者做相关处理
如果是dispatchRender,一般是转向其他的handler来进行处理
如果是LocalRender,直接调用prepareDisplay来做处理
4.3 典型目录层次结构
如上图:module该目录是放置各模块的代码,每个模块有各自的Handler、Service、SQLMap以及配置文件,这种文件结构模式能够支持AEAI DP实现按模块来部署。
common包里放置的是公共类,controller包里方式放置的框架级handler,cxmodule里面方式的公共service接口和实现类。
4.4 核心配置文件说明
通过AEAI DP平台开发生成相关的配置,下面对核心配置文件进行说明:
4.4.1 web.xml配置
在web.xml中包含filter的定义以及实现
Servlet的定义以及实现
以及Listener
4.4.2 Handler配置
1. HandlerIndex.xml:定义了HandlerId所属的模块,通过Id对应的模块查找对应模块下的映射关系
2. HandlerModule.xml与HandlerContext.xml中均映射关系指向对应的Handler以及JSP。其中HandlerModule.xml中定义的是不同模块下的映射关系而HandlerContext.xml中是公共访问的如主页、左侧功能列表的显示等。
4.4.3 Service 配置
1. ServiceContext.xml中典型配置属性:如数据库、appConfig等;
2. ServiceIndex.xml:通过seviceId所对应的模块去对应模块下的ServiceModule.xml配置文件中查找对应的ServiceImpl以及SqlMap等信息
3. ServiceModule.xml将对应功能模块下的Service层Controller层,用到的java类封装成bean,并通过property指定对应的SqlMap。
4. ServiceContext.xml中,配置了公共调用的Service的实现、配置数据库连接、以及事务控制机制。
4.4.4 DB 相关配置
1. hotweb.properties:配置了数据库的连接信息,如用户名、密码等。
2. SqlMapModule.xml与SqlMapConfig.xml:是sqlmap的索引文件
3. sqlmap:在对应的xml中定义SQl进行数据库操作,sqlMap文件的namespace默认是由表名来生成,在ServcieContext.xml(ServiceModule.xml)中指向业务处理ServiceImpl中
5 开发与部署
5.1 工具设置
5.2 开发步骤
AEAI DP开发平台基于数据库驱动开发,推崇适度需求调研、数据库设计先行、原型驱动的敏捷开发模式。整体过程如下:
1. 通过工程向导创建可运行调试的工程框架,默认预置系统管理功能
2. 设计器向导选择对应的功能模型,来创建功能实例
3. 功能实例配置信息首先通过数据表或SQL来默认生成
4. 在设计器进行特定调整(如:查询条件、显示字段、表单元素、校验控制等)
5. 由代码生成器,生成相关的代码及配置
6. 直接部署运行,查看效果,根据实际需要调整设置,重复4—6步
7. 根据实际需要扩展功能代码、调试。
注意:一旦扩展了代码,就不能再次代码生成,那样会覆盖扩展的代码。
5.2.1 开发约束说明
所有的表都需要创建UUID逻辑主键(36位)
所有编码类数据在编码管理模块中统一维护
如果列表SQL有参数需要解析,必须有“where 1=1”
建议开发采用SVN或者CVS进行版本管理
如果选择上载资源,则资源关联表,只能三个字段,除了逻辑主键,另外两个字段必须为“BIZ_ID”、“RES_ID”,字段类型都为char(36),建议主键命名为“REF_ID”
6.2.2 跨模块调用说明
在AEAI DP中各个功能模块是彼此隔离的,这里就可能存在跨模块调用问题:
跨模块调用handler
不需要做特殊处理,仍然index?SomeHandlerID方式调用跨模块的handler。
跨模块调用service
把对应的接口提升到cxmodule包里,可以采用代码重构的方式,选中对应接口类,然后ctrl+shift+v。
跨模块调用sqlmap
把sqlmap索引配置迁移公共索引配置(即SqlMapModule.xml中对应配置迁移至SqlMapConfig.xml),模块中的sqlmap文件也对应迁移公共sqlmap目录。
5.2.3 常用Java类清单
类别
常用类
功能说明
编码定义及界面元素
FormSelectFactory
基于编码定义的表单下拉框Select工厂类
FormSelect
表单下拉框Select泛化模型
RadioGroup
RadioButton模型,一般基于FormSelect转换生成
CheckBoxGroup
CheckBox模型,一般基于FormSelect转换生成
树构建器及模型
TreeBuilder
树形模型构建类
TreeModel
树形泛化模型,可以生成前端的多选、单选框
权限相关
Profile
身份权限概要模型,在Handler中可以直接获取
User
用户模型,可以通过Profile来获取
Role
角色模型,可以通过User来获取
Group
分组模型,可以通过User来获取
Resource
资源模型,可以通过User来获取
数据库存取相关
DaoHelper
数据访问对象工具类,封装ibatis的相关操作
DBHelper
数据操作工具类,基于Spring的数据源配置
KeyGenerator
主键生成类,一般情况下是UUID格式
工具类相关
DateUtil
日期处理工具类
StringUtil
字符串处理工具类
FileUtil
文件处理工具类
IOUtil
输入输出流工具类
5.3 部署方式
双击项目名弹出如下界面,可以修改服务器的地址并修改对应的用户名,连接对应的服务器后部署应用即可。
注意:服务器用户名、密码在Hotserver中有对应的配置,如下图:
在Miscdp Studio对工程中任意目录、文件都可以右键,在右键菜单底部点击“Miscdp资源部署”,如下图:
弹出部署设置窗口,AEAI DP支持三种粒度部署模式:模块、资源、应用。应用就是整个工程,模块指的module目录下的各个package,除了module下的文件,其他都属于资源。可以支持多个模块或者多个资源一起部署,而且内置的部署机制会自动识别,是否要重新加载模块或者重启应用。
5.3.1 按资源部署
在除模块下部署jsp,xml,js,java文件等为资源部署。当部署的内容包含源码时,会默认重启应用
部署的内容不包含源码时默认不会重启应用,且支持同时部署多个资源文件。
5.3.2 按应用部署
在项目名下右键资源部署为部署应用且默认重启应用。
5.3.3 按模块部署
在模块下选择xml、java文件等右键部署资源均为模块部署,默认会重新加载这个模块
注意:在模块的jsp文件夹下右键资源部署(弹出界面如上图)也为模块部署,默认会重新加载部署的模块。但是如果选择是模块jsp文件夹下的jsp文件,则为部署资源,且不用重启应用(jsp是自动编译)。
5.3.4 部署后目录
正常情况下Web应用的所有的classes都在WEB-INF/classes目录下,但基于AEAI DP开发的Web应用部署后有一个特殊目录modules,所有模块里的classes以及对应的配置文件都放置在这个目录里,如下图。
5.4 调试配置
远程调试是复杂业务逻辑的错误定位过程中常用手法,通过调试也可以使程序员对代码脉络更清楚,是程序员必备的技能。AEAI DP 基于Eclipse内置远程机制进行代码调试,具体参见《AEAI DP开发平台技术手册》中的调试配置部分内容。
6 知识点汇总
6.1 分层解读
6.1.1 控制层
对应的Handler如下图:
1. prepareDisplay方法
在handler中默认执行prepareDisplay方法
mergeParam(param)方法中通过handlerId的对比确定需要append的param的信息
storeParam方法在页面间跳转时候,将param存到一个session中,跟mergetParam联合使用保证在页面间切换时候,列表页面的查询条件不丢失。
setAttributes(param)方法中做遍历将param中的值进行set将数据放入到页面中
返回new LocalRenderer(getPage()),在LocalRenderer中的executeRender方法中创建PageBean,所有handler中的属性信息都传入至PageBean中,通过request.setAttribute(PAGE_BEAN_KEY,pageBean)方法将handler信息放入页面所以在JSP中可以通过pageBean中封装的getHandlerURL()获得handlerURL。
2. processPageAttributes方法
processPageAttributes方法用于回调处理扩展属性(下拉框处理、默认值处理)
3. initParameters方法
initParameters方法中可以设置查询条件的默认值
4. getService方法
在getService方法中返回到对应的调用的Service
5. 扩展方法机制说明
方法名与actionType隐藏域变量一致,建议采用@PageActionanotation方式,如果不添加@PageAction,则方法名为do+”actionType”+Action
6.1.2 显示层
顾名思义显示层就是用于前台显示的jsp页面如下图:
1. Page指令
通过Page指令的contentType将页面编码定义为UTF-8
pageEncoding是jsp文件本身的编码
contentType的charset是指服务器发送给客户端时的内容编码
2. Jsp动作
通过jsp在头部useBean在页面引用的javaBean(即pageBean),其中class属性指定类的实例并将其绑定到名由id属性定义的变量上,scope为request,如下:
相关jsp内置方法如下:
jsp:include:在页面被请求的时候引入一个文件。
jsp:useBean:寻找或者实例化一个JavaBean。
jsp:setProperty:设置JavaBean的属性。
jsp:getProperty:输出某个JavaBean的属性。
jsp:forward:把请求转到一个新的页面。
jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记
3. Jsp表单
一般情况下页面均会包含一个表id为form1,且内部有一个隐藏域actionType在表单提交时需要赋值。
一般情况下明细表单除了actionType以外还会包含一个operaType隐藏域,用来区分当前操作的状态是insert还是 update。
在form表单中action动作指令通过pageBean.getHandlerURL()获得handler指定跳转的路径,method="post"提交方式为post
4. 资源文件
在Jsp页面中引入通用的资源文件:
<%@include file="/jsp/inc/resource.inc.jsp"%>在该页面中包括常用的javascript及css
在script中定义页面处理的JS,也可以直接引用封装与于Util.js中常见的页面校验(非空、长度等)、请求方法(doDelete、doSubmit)等
util.js中封装了常用js方法如:
function doDelete(itemValue)
function doQuery(params)
function doRequest(actionType,params)
function doSubmit(reqOptions)
function postRequest(form,params)(ajax处理)
function sendRequest(targetUrl,params) (ajax处理)
style.css为最常用css,其中定义form、table、tr、td样式以及按钮的图标样式等
6.1.3 服务层
后台业务逻辑生成接口与实现类如下图:
后台业务逻辑都生成接口与实现类,都在ServiceContext.xml(ServiceModule.xml)中配置。在实现类中定义对数据库的操作
1. 继承关系说明
每个功能模型都有自己的父类和接口,继承关系如下图所示:
2. processDataType
根据数据表的元数据来转换处理表单传过来的数据,可以扩展设置类型转换器,类型转换器扩展设置在ServiceContext.xml或者ServiceModule.xml中配置,BaseService中对应代码如下:
protected void processDataType(DataParam dataParam,String tableName){
Table table = getTableMetaData(tableName);
List dateColumns = table.getDateTypeColumns();
int count = dateColumns.size();
for (int i=0;i < count;i++){
Column column = dateColumns.get(i);
String columnName = column.getName();
Object paramValue = dataParam.getObject(columnName);
if (paramValue != null && paramValue instanceof String){
if (!String.valueOf(paramValue).trim().equals("") && !String.valueOf(paramValue).trim().equals("null")){
Date dateValue = DateUtil.getDateTime((String)paramValue);
dataParam.put(columnName,dateValue);
}else{
dataParam.remove(columnName);
}
}
}
if (!this.fieldConvertMap.isEmpty()){
Iterator keys = this.fieldConvertMap.keySet().iterator();
while (keys.hasNext()){
String key = keys.next();
Column column = table.getColumn(key);
if (column != null){
DataParamConvert convert = this.fieldConvertMap.get(key);
Object value = dataParam.get(key);
Object convertValue = convert.convert(value, column);
dataParam.put(key,convertValue);
}
}
}
}
3. processPrimaryKeys
处理主键默认生成机制,AEAI DP中默认是使用uuid来作为主键的,其实框架层面还支持自增字段主键机制。
protectedvoid processPrimaryKeys(DataParam param){
KeyGenerator keyGenerator = new KeyGenerator();
if (Constants.PKType.INCREASE.equals(pkGenPolicy)){
param.put(primaryKey,keyGenerator.getMaxId(tableName, primaryKey,getDataSource()));
}
elseif(Constants.PKType.CHARGEN.equals(pkGenPolicy)){
String genPk = keyGenerator.genKey();
param.put(primaryKey,genPk);
}
}
6.2 重点技术
6.2.1 常用方法
1. 在PageBean中封装了常见的页面中获取值的方法,如下:
public String inputDate(String key)
public String inputTime(String key)
public String inputValue(int i,String key)
public String selectValue(int i,String key,String formSelectKey)
public RadioGroup selectRadio(String elementName)
public String selectedValue(String elementName)
public String selectedText(String elementName)
public String disabled(boolean expression)
public String readonly(String expression)
2. 根据需要返回不同的ViewRender,一般情况下为:AjaxRender、DispatchRender、RedirectRenderer、LocalRender
1) AjaxRender:直接response返回值页面,异步加载或者做相关处理
2) DispatchRender:一般是转向其他Handler来进行处理,页面跳转传递request和response可以支持跳转到第三方按Backspace可以返回
3) RedirectRenderer:也是转向其他Handler但不能传递request和response
4) LocalRender:显示 JSP页面
3. DateUtil类中预置许多关于日期处理的方法,例如:日期的格式化,日期的计算,获得当月、当年的第一天等等。
4. 主键生成
调用KeyGenerator.instance().genKey()来自动生成主键ID
5. 加密解密
通过CryptionUtil中的加密解密方法进行加密解密
加密方法encryption("root", "12345678");其中root为需要加密的明文、”12345678”为加密的KEY。
解密方法decryption(secretData, secretKey);
6. 在User类中预置了许多关于User的跟角色、群组关联属性等
7. Dataparam转换
DataRow调用row.toDataParam();
List调用ListUtil.toParamList(records,srcKeys, replaceKeys)
8. StringUtil字符串辅助类
agileai_common的jar包中内置了很多辅助类,如StringUtil,DataUtil,ListUtil、DBUtil等。
9. ListUtil类转换方法
预置许多List转换方法如listToMap()、toXML()、toDataSet()、toParamList()
10. PopupBox.js中封装基于div+iframe的弹出框
Js中使用PopupBox方法时需要将对应的var写在方法的外面,每次调用使用的都是同一个弹出框,写在方法内部时每次调用方法都会新生成一个弹出框。
11. 内置Ajax处理方式
functionpostRequest(form,params)
functionsendRequest(targetUrl,params)
第一种是post方式,第二种是get方式。
6.2.2 授权配置
1. 功能授权
系统预置功能可以设置功能目录、功能节点授权,而且可以授权给角色、群组、人员。
注意:
2. 操作授权
通过jsp引入标签按钮配置授权
通过状态、角色控制权限
参见《AEAI DP按钮权限配置说明》,http://my.oschina.net/agileai/blog/533385。
6.2.3 典型场景
1. 复制数据插入
1) 把原结果集查询出来,类型为List;
2) 使用ListUtil.toDataParam方法把结果集转换为参数集合,类型为List;
3) 使用DaoHelper调用sqlmap中配置的insertSQL来插入参数集合。
2. 排序控制说明
首先在JSP页面,添加按钮
" align="center"> 上移
" align="center">
function doMoveUp(){
if (!isSelectedRow()){
writeErrorMsg('请先选中一条记录!');
return;
}
doSubmit({actionType:'moveUp'});
}
function doMoveDown(){
if (!isSelectedRow()){
writeErrorMsg('请先选中一条记录!');
return;
}
doSubmit({actionType:'moveDown'});
}
上移下移在handler里的方法
public ViewRenderer doMoveUpAction(DataParam param){
String currentSubTableId = param.get("currentSubTableId");
boolean isFirst = getService().isFirstChild(currentSubTableId,param);
if (isFirst){
setErrorMsg(this.moveUpErrorMsg);
}else{
getService().changeCurrentSort(param, true);
}
return prepareDisplay(param);
}
public ViewRenderer doMoveDownAction(DataParam param){
String currentSubTableId = param.get("currentSubTableId");
boolean isLast = getService().isLastChild(currentSubTableId,param);
if (isLast){
setErrorMsg(this.moveDownErrorMsg);
}else{
getService().changeCurrentSort(param, false);
}
return prepareDisplay(param);
}
在service方法里调整两个字段排序顺序
publicvoid changeCurrentSort(DataParam param, boolean isUp) {
String subId = param.get("currentSubTableId");
String statementId = sqlNameSpace+"."+"find"+StringUtil.upperFirst(subId)+"Records";
List records = this.daoHelper.queryRecords(statementId, param);
String tableName = subTableIdNameMapping.get(subId);
String idField = "当前表的主键字段名";
String currentId = "记录标识";
String sortField = "排序字段名";
DataRow curRow = null;
String curSort = null;
if (isUp){
DataRow beforeRow = null;
for (int i=0;i < records.size();i++){
DataRow row = records.get(i);
String tempMenuId = row.stringValue(idField);
if (currentId.equals(tempMenuId)){
curRow = row;
beforeRow = records.get(i-1);
break;
}
}
curSort = curRow.stringValue(sortField);
String beforeSort = beforeRow.stringValue(sortField);;
curRow.put(sortField,beforeSort);
beforeRow.put(sortField,curSort);
this.updateSubRecord(subId,curRow.toDataParam(true));
this.updateSubRecord(subId,beforeRow.toDataParam(true));
}else{
DataRow nextRow = null;
for (int i=0;i < records.size();i++){
DataRow row = records.get(i);
String tempMenuId = row.stringValue(idField);
if (currentId.equals(tempMenuId)){
curRow = row;
nextRow = records.get(i+1);
break;
}
}
curSort = curRow.stringValue(sortField);
String nextSort = nextRow.stringValue(sortField);
curRow.put(sortField,nextSort);
nextRow.put(sortField,curSort);
this.updateSubRecord(subId,curRow.toDataParam(true));
this.updateSubRecord(subId,nextRow.toDataParam(true));
}
}
2. 结果集转换为FormSelect
在进行开发的时候,会遇到select下拉框形式 的表单元素,这时就需要在控制层的pricessPageAttributes方法中将查询得到的结果集转换为formselect类型,如下例:
List records = getService().findPcNameRecords(param);
FormSelect formSelect = new FormSelect();
formSelect.setKeyColumnName("PC_CODE");
formSelect.setValueColumnName("PC_NAME");
formSelect.putValues(records);
setAttribute("pcName",formSelect.addSelectedValue(param.get("pcName")));
首先通过查询得到list结果集records,结果集中需要存在有id(编码)和value(值)两列属性
然后new一个FormSelect类型的变量,然后给这个变量添加对应的id和value两个属性字段,再通过putValues方法把结果集中的数据放到formSelect中。在setAttribute中将param中对应的变量的值通过formSelect将这个选中的值存入到变量pcName中。
3. 基于HTML导出Word、PDF
1) 构造Html模板
2) 将模板转换为IO流
3) 调用对应的API进行格式转换
4. 批量处理结果集
首先需要前台jsp页面添加checkbox复选框,代码如下:
隐藏域:
name="ids" value="<%=pageBean.inputValue("ids")%>" />
上面个代码选中了当前记录的ID,然后点击操作按钮调用对应的JS方法,将ids传到后台handler中处理:
function doDeleteRequest(){
var ids = "";
var confirmsubMsg="您确认删除该数据吗?";
$("input:[name='ID_ID'][checked]").each(function(){
ids = ids+$(this).val()+",";
});
if (ids.length > 0){
ids = ids.substring(0,ids.length-1);
}
if(confirm(confirmsubMsg)) {
//showSplash(deleteMsg);
$("#ids").val(ids);
doSubmit({actionType:'batchDelete'});
}
}
由于接到的参数为多条记录,并用逗号分隔的,需要在后台进行处理,具体代码如下:
public ViewRenderer doBatchDeleteAction(DataParam param) {
String ids = param.get("ids");
if(!"".equals(ids)){
String[] idArray = ids.split(",");
for(int i=0;i < idArray.length;i++ ){
String id = idArray[i];
DataParam idParam = new DataParam();
idParam.put("ID_ID", id);
getService().deleteClusterRecords(idParam);
}
}
return prepareDisplay(param);
}
5. 数值公式计算
我们在项目使用MVL的TemplateRuntime计算方式,具体代码如下:
publicstaticvoid main(String[] args) {
String testFormula = "@{value+5}";
Map vars = new HashMap();
vars.put("value", 3.0);
Number number = (Number) TemplateRuntime.eval(testFormula,vars);
System.out.print(number);
}
输出后的结果:
6. 后台控制jsp页面
标签合并
public ViewRenderer prepareDisplay(DataParam param){
initParameters(param);
this.setAttributes(param);
if (!TreeAndContentManage.BASE_TAB_ID.equals(tabId)){
param.put("columnId",columnId);
List rsList = getService().findContentRecords(filterTreeModel,tabId,param);
this.processRowSpanField(rsList);
this.setRsList(rsList);
request.setAttribute("rsList", rsList);
}else{
DataParam queryParam = new DataParam(columnIdField,columnId);
DataRow row = getService().queryTreeRecord(queryParam);
this.setAttributes(row);
}
processPageAttributes(param);
return new LocalRenderer(getPage());
}
privatevoid processRowSpanField(List rsList){
int spanCount = 0;
DataRow beforeRow = null;
for (int i=0;i < rsList.size();i++){
DataRow curRow = rsList.get(i);
String curRlName = curRow.getString("RL_NAME")!=null?curRow.getString("RL_NAME"):"";
if (beforeRow == null){
beforeRow = curRow;
spanCount++;
beforeRow.put("rowSpan",spanCount);
continue;
}
String beforeRLName = beforeRow.getString("RL_NAME")!=null?beforeRow.getString("RL_NAME"):"";
if (beforeRLName.equals(curRlName)){
spanCount++;
beforeRow.put("rowSpan",spanCount);
curRow.put("rowSpan",0);
}
else{
curRow.put("rowSpan",1);
beforeRow = curRow;
spanCount = 0;
spanCount++;
}
}
}
在显示列表页面时,调用下面代码
<%=(i+1)%> <%if (0 != rowSpan){%>
<%=dataRow.getString("RL_NAME","")%> <%}%>
6.3 学习技巧
6.3.1 利用system代码
使用AEAI DP创建工程的时候默认就会创建系统管理相关代码,系统管理里面涉及的模块几乎是所有管理系统都带的功能,这部分代码较多,值得推荐学习,事实上很多开发所需要的代码样例都可以在里面找到。
6.3.2 跟踪研读父类
Hotweb预置很多典型的功能模型,每个Handler和Service都继承对应功能模型的Handler和Service,而且hotweb源码都直接打入hotweb_core.jar,在开发、调试过程中可以跟踪研究父类来深入掌握相关调用机制、借鉴相关代码技巧。
6.3.3 查找类似代码
很多js代码、工具类的调用方式其实都散落在系统框架(预置的以及自动生成)的代码里,可以通过DP Studio(Eclipse)的文件查找方式来了解相关调用机制。
6.3.4 反编译参考代码
在hotweb中也引用了一些地方类库,如:ecside、ibatis、spring、mvel等等,包括AEAI Portal、AEAI BPM的一些classes、jar文件,都可以通过jd-gui来反编译学习分析代码,参考样例,如:反编译预置的portlet代码、参考开发新portlet。
7 感悟与收获
AEAI DP开发平台可以快速上手,对于最开始入职的我较容易产生成就感,但是随着后续深入使用,实际应用过程中的各种扩展开发,逐渐暴露出我自己的知识积累不足,同时也发现Miscdp Studio可以生成典型功能、典型的方法,便于调试部署,但更多代码的精华是藏在Hotweb框架里,Hotweb预留很多方法用于扩展,预置很多工具类通过组合使用可以几乎所有场景的功能,同时第三方的类库也很容易在AEAI DP中调用来满足实际项目的特定需求。
AEAI DP开发平台精要文档 下载
你可能感兴趣的:(AEAI,DP,开发平台)
网络编程基础
记得开心一点啊
网络
目录♫什么是网络编程♫Socket套接字♪什么是Socket套接字♪数据报套接字♪流套接字♫数据报套接字通信模型♪数据报套接字通讯模型♪DatagramSocket♪DatagramPacket♪实现UDP的服务端代码♪实现UDP的客户端代码♫流套接字通信模型♪流套接字通讯模型♪ServerSocket♪Socket♪实现TCP的服务端代码♪实现TCP的客户端代码♫什么是网络编程网络编程,指网络上
(179)时序收敛--->(29)时序收敛二九
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发 时序收敛
1目录(a)FPGA简介(b)Verilog简介(c)时钟简介(d)时序收敛二九(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(b)
(180)时序收敛--->(30)时序收敛三十
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发 时序收敛
1目录(a)FPGA简介(b)Verilog简介(c)时钟简介(d)时序收敛三十(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(b)
(158)时序收敛--->(08)时序收敛八
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发 时序收敛
1目录(a)FPGA简介(b)Verilog简介(c)时钟简介(d)时序收敛八(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(b)F
(159)时序收敛--->(09)时序收敛九
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发 时序收敛
1目录(a)FPGA简介(b)Verilog简介(c)时钟简介(d)时序收敛九(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(b)F
(160)时序收敛--->(10)时序收敛十
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发 时序收敛
1目录(a)FPGA简介(b)Verilog简介(c)时钟简介(d)时序收敛十(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(b)F
(153)时序收敛--->(03)时序收敛三
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发 时序收敛
1目录(a)FPGA简介(b)Verilog简介(c)时钟简介(d)时序收敛三(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(b)F
(121)DAC接口--->(006)基于FPGA实现DAC8811接口
FPGA系统设计指南针
FPGA接口开发(项目实战) fpga开发 FPGA IC
1目录(a)FPGA简介(b)IC简介(c)Verilog简介(d)基于FPGA实现DAC8811接口(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电
FPGA复位专题---(3)上电复位?
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发
(3)上电复位?1目录(a)FPGA简介(b)Verilog简介(c)复位简介(d)上电复位?(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限
(182)时序收敛--->(32)时序收敛三二
FPGA系统设计指南针
FPGA系统设计(内训) fpga开发 时序收敛
1目录(a)FPGA简介(b)Verilog简介(c)时钟简介(d)时序收敛三二(e)结束1FPGA简介(a)FPGA(FieldProgrammableGateArray)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。(b)
20个新手学习c++必会的程序 输出*三角形、杨辉三角等(附代码)
X_StarX
c++ 学习 算法 大学生 开发语言 数据结构
示例1:HelloWorld#includeusingnamespacestd;intmain(){coutusingnamespacestd;intmain(){inta=5;intb=10;intsum=a+b;coutusingnamespacestd;intfactorial(intn){if(nusingnamespacestd;voidprintFibonacci(intn){intt
计算机网络八股总结
Petrichorzncu
八股总结 计算机网络 笔记
这里写目录标题网络模型划分(五层和七层)及每一层的功能五层网络模型七层网络模型(OSI模型)==三次握手和四次挥手具体过程及原因==三次握手四次挥手TCP/IP协议组成==UDP协议与TCP/IP协议的区别==Http协议相关知识网络地址,子网掩码等相关计算网络模型划分(五层和七层)及每一层的功能五层网络模型应用层:负责处理网络应用程序,如电子邮件、文件传输和网页浏览。主要协议包括HTTP、FTP
ubuntu安装wordpress
lissettecarlr
1安装nginx网上安装方式很多,这就就直接用apt-get了apt-getinstallnginx不用启动啥,然后直接在浏览器里面输入IP:80就能看到nginx的主页了。如果修改了一些配置可以使用下列命令重启一下systemctlrestartnginx.service2安装mysql输入安装前也可以更新一下软件源,在安装过程中将会让你输入数据库的密码。sudoapt-getinstallmy
解决Obsidian写笔记中的<img>标签无法显示图片的问题
全能全知者
笔记
Obsidian中写md笔记如果使用标签会显示不出图案,后来才知道因为Obsidian的问题导致只能用绝对路径定位。所以我本人写了一个py插件,将md笔记里的img标签批量替换成Obsidian能够读取的形式。安装FixObsImgDpy:pipinstallFixObsImgDpy安装完成后在需要修复的md文件的父目录下运行命令:FixObsImgDpy就会自动修复父目录以下的全部md文件 仓库
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your
†徐先森®
Oracle数据库 Web相关 错误集
createtablestudents(idintunsignedprimarykeyauto_increment,namevarchar(50)notnull,ageintunsigned,highdecimal(3,2),genderenum('男','女','中性','保密','妖')default'保密',cls_idintunsigned);在对数据库插入如上带有中文带有默认值的字段的时
《Veronika decides to die》
Ooutstanding
Whatismadness?——Madnessistheinabilitytocommunicate.Betweennormalityandmadness,whicharebasicallythesamething,thereexistsanintermediarystage:itiscalled"beingdifferent."Andpeoplewerebecomingmoreandmoreaf
metaRTC/webRTC QOS 方案与实践
metaRTC
metaRTC 解决方案 webrtc qos
概述质量服务(QOS/QualityofService)是指利用各种技术方案提高网络通信质量的技术,网络通信质量需要解决下面两个问题:网络问题:UDP/不稳定网络/弱网下的丢包/延时/乱序/抖动数据量问题:发送数据量超带宽负载和平滑发送拥塞控制是各种技术方案的数据基础,丢包恢复解决丢包问题,抗乱序抖动解决网络乱序抖动问题,流量控制解决平滑发送数据/数据超带宽负载/延时问题。拥塞控制(Congest
Istio pilot-discovery服务发现源码解析(1.13版本)
xidianjiapei001
# Istio istio 云原生 服务发现
Istiopilot-discovery服务发现介绍工作机制初始化初始化Config控制器初始化Service控制器controller初始化NamespaceServiceNodePodPilotDiscovery各组件启动流程DiscoveryServer接收Envoy的gRPC连接请求流程Config变化后向Envoy推送更新的流程总结参考介绍IstioPilot的代码分为Pilot-Dis
后端开发刷题 | 把数字翻译成字符串(动态规划)
jingling555
笔试题目 动态规划 java 算法 数据结构 后端
描述有一种将字母编码成数字的方式:'a'->1,'b->2',...,'z->26'。现在给一串数字,返回有多少种可能的译码结果数据范围:字符串长度满足0=10&&num<=26){if(i==1){dp[i]+=1;}else{dp[i]+=dp[i-2];}}}returndp[nums.length()-1];}}
算法刷题:300. 最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组、1143. 最长公共子序列
哆来咪咪咪
算法
300.最长递增子序列1.dp定义:dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度2.递推公式:if(nums[i]>nums[j])dp[i]=max(dp[i],dp[j]+1);注意这里不是要dp[i]与dp[j]+1进行比较,而是我们要取dp[j]+1的最大值。3.初始化:每一个i,对应的dp[i](即最长递增子序列)起始大小至少都是1.classSolution{
使用FPGA接收MIPI CSI RX信号并进行去抖动、RGB转YUV处理:FX3014 USB3.0 UVC传输与帧率控制源代码,FPGA实现MIPI CSI RX接收,去Debayer, RGB转
kVfINoSzdrt
fpga开发 程序人生
fpgamipicsirx接收去debayer,rgb转yuv,fx3014usb3.0uvc传输与帧率控制源代码,具体架构看图,除dphy物理层外,mipi均为源码sensorimx219mipi源码mipi4lanecsirxraw10fpgamachXO3lf-690usb3.0fx301432bityuvdatawithframesync测试模式3280*246415fps1920*108
python-pcl函数_Python简介,第4章-函数
cumei1658
java webgl python lua ios
python-pcl函数Runningthroughthedoor,Baldricfoundhimselfinanenormouscavern,itsceilinglostinshadow.Greatcolumnsofblackstonesoaredfromtheground,andpoolsoflavabubbledthroughout,lightingthecaverninadarkred.T
Sentinel实时监控不展示问题
朱杰jjj
sentinel sentinel
问题官方插件Endpoint支持,可以实时统计出SpringBoot的健康状况和请求的调用信息在使用Endpoint特性之前需要在Maven中添加spring-boot-starter-actuator依赖,并在配置中允许Endpoints的访问。SpringBoot1.x中添加配置management.security.enabled=false。暴露的endpoint路径为/sentinelS
深入理解AOP(面向切面编程)及其应用
自身就是太阳
java 开发语言 spring
目录AOP的核心概念AOP的实现方式1.定义DAO接口和实现类2.定义通知类3.开启AOP注解驱动切入点表达式通配符的使用:AOP通知类型案例分析:测量业务层接口的执行效率结论概述:AOP(Aspect-OrientedProgramming,面向切面编程)是一种编程范式,主要用于将共性功能从具体的业务逻辑中分离出来,实现松耦合的代码设计。其作用是在不修改原始代码的情况下,对现有方法进行增强,广泛
华为坤灵路由器初始化开局的注意事项,含NAT配置
redmond88
网络技术 华为 服务器 运维
坤灵路由器比较坑,无web界面,全程命令行配置,但是版本更新导致和华为企业路由器配置很多不一样的地方,今天介绍下1、aaa密码复杂度修改:#使能设备对密码进行四选三复杂度检查功能。system-view[HUAWEI]aaa[HUAWEI-aaa]local-aaa-userpasswordpolicyadministrator[HUAWEI-aaa-lupp-admin]passwordcomp
java获取applicationcontext,SpringBoot获取ApplicationContext的3种方式
花儿街参考
ApplicationContext是什么?简单来说就是Spring中的容器,可以用来获取容器中的各种bean组件,注册监听事件,加载资源文件等功能。ApplicationContext获取的几种方式1直接使用Autowired注入@ComponentpublicclassBook1{@AutowiredprivateApplicationContextapplicationContext;pub
linux的安装程序 与 文件 相关的命令
可能只会写BUG
c语言 c/c++ linux linux 服务器 运维
软件安装卸载命令软件包介绍软件包命名格式dpkg命令apt-get命令apt-get命令压缩和解压命令压缩文件后缀压缩命令打包和解包命令tar命令文件分割命令split命令文件操作相关命令cat命令head命令tail命令more命令less命令管道命令wc命令grep命令find命令cut命令sort命令uniq命令diff命令文件属性命令chmod命令chown命令chgrp命令ln命令硬链接
Java内存模型基础
2401_84002271
程序员 java 学习 经验分享
1.2Java内存模型的抽象结构Java中所有的实例域、静态域和数组元素都存储在堆内存中,堆内存在线程之间共享(文章中用“共享变量”指代)。局部变量(LocalVariables)、方法定义参数(FormalMethodParameters)和异常处理器参数(ExceptionHandlerParameters)不会在线程之间共享,它们不会存在内存可见性问题,因此也不受内存模型的影响。Java线程
Chat GPT带来的几点思考
淡定的胡萝卜
OpenAI公司推出的ChatGPT引起了广泛关注,网上出现各类专家开始预测随着ChatGDP的普及,将会有哪些行业的人面临失业,引发人们的焦虑。不可否认它会给我们的教育行业、媒体行业、学术界等众多行业产生影响,面对这些影响,我们该如何看待呢?近期我阅读了不少相关文章,引发的几点思考,想与大家分享。ChatGPT将会倒逼传统教育的改革。中国传统教育是教师对知识点的传授、学生对知识点的掌握,不仅量多
javascript添加p元素,html添加文字,appendChild
游勇一
javascript html添加p appendChild
javascript添加p元素,html添加文字,appendChild。网页添加p元素效果截图。个人签名:游志勇,预制板,南托岭预制场。文字展示#wordsadd{font-size:70px;word-break:break-all;}#wordsaddp{margin:002px0;padding:002px0;line-height:93%;}.btn_width{width:90px;}
分享100个最新免费的高匿HTTP代理IP
mcj8089
代理IP 代理服务器 匿名代理 免费代理IP 最新代理IP
推荐两个代理IP网站:
1. 全网代理IP:http://proxy.goubanjia.com/
2. 敲代码免费IP:http://ip.qiaodm.com/
120.198.243.130:80,中国/广东省
58.251.78.71:8088,中国/广东省
183.207.228.22:83,中国/
mysql高级特性之数据分区
annan211
java 数据结构 mongodb 分区 mysql
mysql高级特性
1 以存储引擎的角度分析,分区表和物理表没有区别。是按照一定的规则将数据分别存储的逻辑设计。器底层是由多个物理字表组成。
2 分区的原理
分区表由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们可以直接访问各个分区。存储引擎管理分区的各个底层
表和管理普通表一样(所有底层表都必须使用相同的存储引擎),分区表的索引只是
JS采用正则表达式简单获取URL地址栏参数
chiangfai
js 地址栏参数获取
GetUrlParam:function GetUrlParam(param){
var reg = new RegExp("(^|&)"+ param +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null
怎样将数据表拷贝到powerdesigner (本地数据库表)
Array_06
powerDesigner
==================================================
1、打开PowerDesigner12,在菜单中按照如下方式进行操作
file->Reverse Engineer->DataBase
点击后,弹出 New Physical Data Model 的对话框
2、在General选项卡中
Model name:模板名字,自
logbackのhelloworld
飞翔的马甲
日志 logback
一、概述
1.日志是啥?
当我是个逗比的时候我是这么理解的:log.debug()代替了system.out.print();
当我项目工作时,以为是一堆得.log文件。
这两天项目发布新版本,比较轻松,决定好好地研究下日志以及logback。
传送门1:日志的作用与方法:
http://www.infoq.com/cn/articles/why-and-how-log
上面的作
新浪微博爬虫模拟登陆
随意而生
新浪微博
转载自:http://hi.baidu.com/erliang20088/item/251db4b040b8ce58ba0e1235
近来由于毕设需要,重新修改了新浪微博爬虫废了不少劲,希望下边的总结能够帮助后来的同学们。
现行版的模拟登陆与以前相比,最大的改动在于cookie获取时候的模拟url的请求
synchronized
香水浓
java thread
Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然
maven 简单实用教程
AdyZhang
maven
1. Maven介绍 1.1. 简介 java编写的用于构建系统的自动化工具。目前版本是2.0.9,注意maven2和maven1有很大区别,阅读第三方文档时需要区分版本。 1.2. Maven资源 见官方网站;The 5 minute test,官方简易入门文档;Getting Started Tutorial,官方入门文档;Build Coo
Android 通过 intent传值获得null
aijuans
android
我在通过intent 获得传递兑现过的时候报错,空指针,我是getMap方法进行传值,代码如下 1 2 3 4 5 6 7 8 9
public
void
getMap(View view){
Intent i =
apache 做代理 报如下错误:The proxy server received an invalid response from an upstream
baalwolf
response
网站配置是apache+tomcat,tomcat没有报错,apache报错是:
The proxy server received an invalid response from an upstream server. The proxy server could not handle the request GET /. Reason: Error reading fr
Tomcat6 内存和线程配置
BigBird2012
tomcat6
1、修改启动时内存参数、并指定JVM时区 (在windows server 2008 下时间少了8个小时)
在Tomcat上运行j2ee项目代码时,经常会出现内存溢出的情况,解决办法是在系统参数中增加系统参数:
window下, 在catalina.bat最前面
set JAVA_OPTS=-XX:PermSize=64M -XX:MaxPermSize=128m -Xms5
Karam与TDD
bijian1013
Karam TDD
一.TDD
测试驱动开发(Test-Driven Development,TDD)是一种敏捷(AGILE)开发方法论,它把开发流程倒转了过来,在进行代码实现之前,首先保证编写测试用例,从而用测试来驱动开发(而不是把测试作为一项验证工具来使用)。
TDD的原则很简单:
a.只有当某个
[Zookeeper学习笔记之七]Zookeeper源代码分析之Zookeeper.States
bit1129
zookeeper
public enum States {
CONNECTING, //Zookeeper服务器不可用,客户端处于尝试链接状态
ASSOCIATING, //???
CONNECTED, //链接建立,可以与Zookeeper服务器正常通信
CONNECTEDREADONLY, //处于只读状态的链接状态,只读模式可以在
【Scala十四】Scala核心八:闭包
bit1129
scala
Free variable A free variable of an expression is a variable that’s used inside the expression but not defined inside the expression. For instance, in the function literal expression (x: Int) => (x
android发送json并解析返回json
ronin47
android
package com.http.test;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import
一份IT实习生的总结
brotherlamp
PHP php资料 php教程 php培训 php视频
今天突然发现在不知不觉中自己已经实习了 3 个月了,现在可能不算是真正意义上的实习吧,因为现在自己才大三,在这边撸代码的同时还要考虑到学校的功课跟期末考试。让我震惊的是,我完全想不到在这 3 个月里我到底学到了什么,这是一件多么悲催的事情啊。同时我对我应该 get 到什么新技能也很迷茫。所以今晚还是总结下把,让自己在接下来的实习生活有更加明确的方向。最后感谢工作室给我们几个人这个机会让我们提前出来
据说是2012年10月人人网校招的一道笔试题-给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 将重物放到天平左侧,问在两边如何添加砝码
bylijinnan
java
public class ScalesBalance {
/**
* 题目:
* 给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 (假设N无限大,但一种重量的砝码只有一个)
* 将重物放到天平左侧,问在两边如何添加砝码使两边平衡
*
* 分析:
* 三进制
* 我们约定括号表示里面的数是三进制,例如 47=(1202
dom4j最常用最简单的方法
chiangfai
dom4j
要使用dom4j读写XML文档,需要先下载dom4j包,dom4j官方网站在 http://www.dom4j.org/目前最新dom4j包下载地址:http://nchc.dl.sourceforge.net/sourceforge/dom4j/dom4j-1.6.1.zip
解开后有两个包,仅操作XML文档的话把dom4j-1.6.1.jar加入工程就可以了,如果需要使用XPath的话还需要
简单HBase笔记
chenchao051
hbase
一、Client-side write buffer 客户端缓存请求 描述:可以缓存客户端的请求,以此来减少RPC的次数,但是缓存只是被存在一个ArrayList中,所以多线程访问时不安全的。 可以使用getWriteBuffer()方法来取得客户端缓存中的数据。 默认关闭。 二、Scan的Caching 描述: next( )方法请求一行就要使用一次RPC,即使
mysqldump导出时出现when doing LOCK TABLES
daizj
mysql mysqdump 导数据
执行 mysqldump -uxxx -pxxx -hxxx -Pxxxx database tablename > tablename.sql
导出表时,会报
mysqldump: Got error: 1044: Access denied for user 'xxx'@'xxx' to database 'xxx' when doing LOCK TABLES
解决
CSS渲染原理
dcj3sjt126com
Web
从事Web前端开发的人都与CSS打交道很多,有的人也许不知道css是怎么去工作的,写出来的css浏览器是怎么样去解析的呢?当这个成为我们提高css水平的一个瓶颈时,是否应该多了解一下呢?
一、浏览器的发展与CSS
《阿甘正传》台词
dcj3sjt126com
Part Ⅰ:
《阿甘正传》Forrest Gump经典中英文对白
Forrest: Hello! My names Forrest. Forrest Gump. You wanna Chocolate? I could eat about a million and a half othese. My momma always said life was like a box ochocol
Java处理JSON
dyy_gusi
json
Json在数据传输中很好用,原因是JSON 比 XML 更小、更快,更易解析。
在Java程序中,如何使用处理JSON,现在有很多工具可以处理,比较流行常用的是google的gson和alibaba的fastjson,具体使用如下:
1、读取json然后处理
class ReadJSON
{
public static void main(String[] args)
win7下nginx和php的配置
geeksun
nginx
1. 安装包准备
nginx : 从nginx.org下载nginx-1.8.0.zip
php: 从php.net下载php-5.6.10-Win32-VC11-x64.zip, php是免安装文件。
RunHiddenConsole: 用于隐藏命令行窗口
2. 配置
# java用8080端口做应用服务器,nginx反向代理到这个端口即可
p
基于2.8版本redis配置文件中文解释
hongtoushizi
redis
转载自: http://wangwei007.blog.51cto.com/68019/1548167
在Redis中直接启动redis-server服务时, 采用的是默认的配置文件。采用redis-server xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务。下面是Redis2.8.9的配置文
第五章 常用Lua开发库3-模板渲染
jinnianshilongnian
nginx lua
动态web网页开发是Web开发中一个常见的场景,比如像京东商品详情页,其页面逻辑是非常复杂的,需要使用模板技术来实现。而Lua中也有许多模板引擎,如目前我在使用的lua-resty-template,可以渲染很复杂的页面,借助LuaJIT其性能也是可以接受的。
如果学习过JavaEE中的servlet和JSP的话,应该知道JSP模板最终会被翻译成Servlet来执行;而lua-r
JZSearch大数据搜索引擎
颠覆者
JavaScript
系统简介:
大数据的特点有四个层面:第一,数据体量巨大。从TB级别,跃升到PB级别;第二,数据类型繁多。网络日志、视频、图片、地理位置信息等等。第三,价值密度低。以视频为例,连续不间断监控过程中,可能有用的数据仅仅有一两秒。第四,处理速度快。最后这一点也是和传统的数据挖掘技术有着本质的不同。业界将其归纳为4个“V”——Volume,Variety,Value,Velocity。大数据搜索引
10招让你成为杰出的Java程序员
pda158
java 编程 框架
如果你是一个热衷于技术的
Java 程序员, 那么下面的 10 个要点可以让你在众多 Java 开发人员中脱颖而出。
1. 拥有扎实的基础和深刻理解 OO 原则 对于 Java 程序员,深刻理解 Object Oriented Programming(面向对象编程)这一概念是必须的。没有 OOPS 的坚实基础,就领会不了像 Java 这些面向对象编程语言
tomcat之oracle连接池配置
小网客
oracle
tomcat版本7.0
配置oracle连接池方式:
修改tomcat的server.xml配置文件:
<GlobalNamingResources>
<Resource name="utermdatasource" auth="Container"
type="javax.sql.DataSou
Oracle 分页算法汇总
vipbooks
oracle sql 算法 .net
这是我找到的一些关于Oracle分页的算法,大家那里还有没有其他好的算法没?我们大家一起分享一下!
-- Oracle 分页算法一
select * from (
select page.*,rownum rn from (select * from help) page
-- 20 = (currentPag