eXtremeComponents(简称ec)是一系列提供高级显示的开源JSP定制标签,当前的包含的组件为eXtremeTable,用于以表形式显示数据。

其本质是jsp的自定义标签,抓住这一点就抓住了ec的本源。

1. Table定义

我们先看一下标签的定义:extremComponents.tld,其中table的标签定义如下:

 <tag><name>table</name><tag-class>org.extremecomponents.table.tag.TableTag</tag-class><body-content>JSP</body-content><display-name>TableTag</display-name><description><![CDATA[The container which holds all the main table information. Will also hold global information if needed. The table tag is copied into the Table and encapsulated in the Model.]]></description><attribute><name>action</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The URI that will be called when the filter, sort and pagination is used.]]></description></attribute><attribute><name>autoIncludeParameters</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not to automatically include the parameters, as hidden inputs, passed into the JSP.]]></description></attribute><attribute><name>border</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The table border attribute. The default is 0.]]></description></attribute><attribute><name>bufferView</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Whether of not to buffer the view. Boolean value with the default being false.]]></description></attribute><attribute><name>cellpadding</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The table cellpadding attribute. The default is 0.]]></description></attribute><attribute><name>cellspacing</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The table cellspacing attribute. The default is 0.]]></description></attribute><attribute><name>filterable</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not the table is filterable. Boolean value with the default being true.]]></description></attribute><attribute><name>filterRowsCallback</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[A fully qualified class name to a custom FilterRowsCallback implementation. Could also be a named type in the preferences. Used to filter the Collection of Beans or Collection of Maps.]]></description></attribute><attribute><name>form</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The reference to a surrounding form element.]]></description></attribute><attribute><name>imagePath</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The path to find the images. For example imagePath=/extremesite/images/*.png is saying look in the image directory for the .png images.]]></description></attribute><attribute><name>interceptor</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[A fully qualified class name to a custom InterceptTable implementation. Could also be a named type in the preferences. Used to add table attributes.]]></description></attribute><attribute><name>items</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Reference the collection that will be retrieved.]]></description></attribute><attribute><name>locale</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The locale for this table. For example fr_FR is used for the French translation.]]></description></attribute><attribute><name>method</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Used to invoke the table action using a POST or GET.]]></description></attribute><attribute><name>onInvokeAction</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The javascript that will be invoked when a table action enabled.]]></description></attribute><attribute><name>retrieveRowsCallback</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[A fully qualified class name to a custom RetrieveRowsCallback implementation. Could also be a named type in the preferences. Used to retrieve the Collection of Beans or Collection of Maps.]]></description></attribute><attribute><name>rowsDisplayed</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The number of rows to display in the table.]]></description></attribute><attribute><name>scope</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The scope (page, request, session, or application) to find the Collection of beans or Collection of Maps defined by the collection attribute.]]></description></attribute><attribute><name>showPagination</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not the table should use pagination. Boolean value with the default being true.]]></description></attribute><attribute><name>showExports</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not the table should use the exports. Boolean value with the default being true.]]></description></attribute><attribute><name>showStatusBar</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not the table should use the status bar. Boolean value with the default being true.]]></description></attribute><attribute><name>showTitle</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not to show the title. Boolean value with the default being true.]]></description></attribute><attribute><name>showTooltips</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not to show the tooltips. Boolean value with the default being true.]]></description></attribute><attribute><name>sortRowsCallback</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[A fully qualified class name to a custom SortRowsCallback implementation. Could also be a named type in the preferences. Used to sort the Collection of Beans or Collection of Maps.]]></description></attribute><attribute><name>sortable</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Specify whether or not the table is sortable. Boolean value with the default being true.]]></description></attribute><attribute><name>state</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The table state to use when returning to a table. Acceptable values are default, notifyToDefault, persist, notifyToPersist.]]></description></attribute><attribute><name>stateAttr</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The table attribute used to invoke the state change of the table.]]></description></attribute><attribute><name>style</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The css inline style sheet.]]></description></attribute><attribute><name>styleClass</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The css class style sheet.]]></description></attribute><attribute><name>tableId</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The unique identifier for the table.]]></description></attribute><attribute><name>theme</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The theme to style the table. The default is eXtremeTable.]]></description></attribute><attribute><name>title</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The title of the table. The title will display above the table.]]></description></attribute><attribute><name>var</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[The name of the variable to hold the current row bean.]]></description></attribute><attribute><name>view</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Generates the output. The default is the HtmlView to generate the HTML. Also used by the exports to generate XLS-FO, POI, and CSV.]]></description></attribute><attribute><name>width</name><required>false</required><rtexprvalue>true</rtexprvalue><description><![CDATA[Width of the table.]]></description></attribute></tag>

从上面我们可以看到,先定义了table标签的实现类:org.extremecomponents.table.tag.TableTag,其作用是:

The container which holds all the main table information. Will also hold global information if needed. The table tag is copied into the Table and encapsulated in the Model.

一句话:保存table的信息及一些全局信息,通过table封装到Model中。

然后定义了table的一些属性,这些属性和org.extremecomponents.table.bean.Table一致。

public class Table extends Attributes {private TableModel model;private String action;private Boolean autoIncludeParameters;private String border;private Boolean bufferView;private String cellpadding;private String cellspacing;private Boolean filterable;private String filterRowsCallback;private String form;private String imagePath;private String interceptor;private Object items;private String locale;private int maxRowsDisplayed;private int medianRowsDisplayed;private String method;private String onInvokeAction;private String retrieveRowsCallback;private int rowsDisplayed;private Boolean saveFilterSort;private String scope;private Boolean showExports;private Boolean showPagination;private Boolean showStatusBar;private Boolean showTitle;private Boolean showTooltips;private String sortRowsCallback;private Boolean sortable;private String state;private String stateAttr;private String style;private String styleClass;private String tableId;private String title;private String theme;private String var;private String view;private String width;public Table(TableModel model) {this.model = model;}
// setter and getter
}

2. TableTag实现

我们来看一下TableTage如何实现table标签?首先:TableTage继承了TagSupport:

web容器执行自定义标签的过程如下
初始化时调用setPageContent()方法,完了在调用setParent方法
2.1  web容器首先执行自定义标签的开始标记,同时调用doStartTag方法。
2.2  如果doStartTag方法返回EVAL_BODY_INCLUDE,web容器在执行完标签体的内容后,会调用标签类得doAfterBody方法;
  如果doStartTag方法返回SKIP_BODY,doAfterBody方法不会调用,web容器会直接调用标签类得doEndTag方法
2.3 如果doAfterBody方法被调用,并且方法返回EVAL_BODY_AGIN,web容器会再次执行标签体的内容;
  如果doAfterBody方法返回SKIP_BODY,web容器会调用标签类的doEndTag方法
2.4 如果doEndTag方法返回EVAL_PAGE,web容器会执行标签后面的内容;
  如果doEndTag方法返回SKIP_PAGE,web容器会忽略自定义标签后面的内容

 public int doStartTag() throws JspException {try {// initialize the attributesiterator = null;pageContext.setAttribute(TableConstants.ROWCOUNT, "0");// fire up the model with the context, preferences and messagesmodel = new TableModelImpl(new JspPageContext(pageContext), TagUtils.evaluateExpressionAsString("locale", this.locale, this, pageContext));// make the tableTable table = new Table(model);table.setAction(TagUtils.evaluateExpressionAsString("action", action, this, pageContext));table.setAutoIncludeParameters(TagUtils.evaluateExpressionAsBoolean("autoIncludeParameters", this.autoIncludeParameters, this, pageContext));table.setBorder(TagUtils.evaluateExpressionAsString("border", this.border, this, pageContext));table.setBufferView(TagUtils.evaluateExpressionAsBoolean("bufferView", this.bufferView, this, pageContext));table.setCellpadding(TagUtils.evaluateExpressionAsString("cellpadding", this.cellpadding, this, pageContext));table.setCellspacing(TagUtils.evaluateExpressionAsString("cellspacing", this.cellspacing, this, pageContext));table.setFilterable(TagUtils.evaluateExpressionAsBoolean("filterable", this.filterable, this, pageContext));table.setFilterRowsCallback(TagUtils.evaluateExpressionAsString("filterRowsCallback", this.filterRowsCallback, this, pageContext));table.setForm(TagUtils.evaluateExpressionAsString("form", this.form, this, pageContext));table.setImagePath(TagUtils.evaluateExpressionAsString("imagePath", this.imagePath, this, pageContext));table.setInterceptor(TagUtils.evaluateExpressionAsString("interceptor", this.interceptor, this, pageContext));table.setItems(TagUtils.evaluateExpressionAsObject("items", this.items, this, pageContext));table.setLocale(TagUtils.evaluateExpressionAsString("locale", this.locale, this, pageContext));table.setMethod(TagUtils.evaluateExpressionAsString("method", this.method, this, pageContext));table.setOnInvokeAction(TagUtils.evaluateExpressionAsString("onInvokeAction", this.onInvokeAction, this, pageContext));table.setRetrieveRowsCallback(TagUtils.evaluateExpressionAsString("retrieveRowsCallback", this.retrieveRowsCallback, this, pageContext));table.setRowsDisplayed(TagUtils.evaluateExpressionAsInt("rowsDisplayed", this.rowsDisplayed, this, pageContext));table.setScope(TagUtils.evaluateExpressionAsString("scope", scope, this, pageContext));table.setShowExports(TagUtils.evaluateExpressionAsBoolean("showExports", this.showExports, this, pageContext));table.setShowPagination(TagUtils.evaluateExpressionAsBoolean("showPagination", this.showPagination, this, pageContext));table.setShowStatusBar(TagUtils.evaluateExpressionAsBoolean("showStatusBar", this.showStatusBar, this, pageContext));table.setShowTitle(TagUtils.evaluateExpressionAsBoolean("showTitle", this.showTitle, this, pageContext));table.setShowTooltips(TagUtils.evaluateExpressionAsBoolean("showTooltips", this.showTooltips, this, pageContext));table.setSortRowsCallback(TagUtils.evaluateExpressionAsString("sortRowsCallback", this.sortRowsCallback, this, pageContext));table.setSortable(TagUtils.evaluateExpressionAsBoolean("sortable", this.sortable, this, pageContext));table.setState(TagUtils.evaluateExpressionAsString("state", this.state, this, pageContext));table.setStateAttr(TagUtils.evaluateExpressionAsString("stateAttr", this.stateAttr, this, pageContext));table.setStyle(TagUtils.evaluateExpressionAsString("style", style, this, pageContext));table.setStyleClass(TagUtils.evaluateExpressionAsString("styleClass", this.styleClass, this, pageContext));table.setTableId(TagUtils.evaluateExpressionAsString("tableId", tableId, this, pageContext));table.setTheme(TagUtils.evaluateExpressionAsString("theme", this.theme, this, pageContext));table.setTitle(TagUtils.evaluateExpressionAsString("title", this.title, this, pageContext));table.setVar(TagUtils.evaluateExpressionAsString("var", this.var, this, pageContext));table.setView(TagUtils.evaluateExpressionAsString("view", this.view, this, pageContext));table.setWidth(TagUtils.evaluateExpressionAsString("width", this.width, this, pageContext));addTableAttributes(model, table);model.addTable(table);} catch (Exception e) {throw new JspException("TableTag.doStartTag() Problem: " + ExceptionUtils.formatStackTrace(e));}return EVAL_BODY_INCLUDE;}/*** Two things need to be accomplished here. First, need to iterate once over* the columns to load up all the attributes. Second, need to iterate over* the columns as many times as specified by the rowsDisplayed attribute so* the columns row can be resolved. On each iteration over the columns the* current bean in the collection is passed via the pageScope.*/public int doAfterBody() throws JspException {try {if (iterator == null) { iterator = model.execute().iterator();}if (iterator != null && iterator.hasNext()) {Object bean = iterator.next();model.setCurrentRowBean(bean);return EVAL_BODY_AGAIN;}} catch (Exception e) {throw new JspException("TableTag.doAfterBody() Problem: " + ExceptionUtils.formatStackTrace(e));}return SKIP_BODY;}public int doEndTag() throws JspException {try {pageContext.getOut().println(model.getViewData());} catch (Exception e) {throw new JspException("TableTag.doEndTag() Problem: " + ExceptionUtils.formatStackTrace(e));}return EVAL_PAGE;}

3. 深入追踪到TableModel

在doAfterBody()方法中调用了TableModel的excute方法:

 public Collection execute() throws Exception {      //1. 查询记录Collection rows = TableModelUtils.retrieveRows(this);rows = new ArrayList(rows); // copy for thread safetythis.collectionOfBeans = rows;//2. 过滤和排序记录rows = TableModelUtils.filterRows(this, rows);rows = TableModelUtils.sortRows(this, rows);this.collectionOfFilteredBeans = rows;// 3. 获取记录总数和pagesizeInteger totalRows = getTableHandler().getTotalRows();    int defaultRowsDisplayed = getTableHandler().getTable().getRowsDisplayed();if (totalRows != null) {       //4. 设置记录总数和默认pagesize limit.setRowAttributes(totalRows.intValue(), defaultRowsDisplayed);} else {limit.setRowAttributes(rows.size(), defaultRowsDisplayed);}if (logger.isDebugEnabled()) {logger.debug(limit.toString());}//5. 获取本次显示的记录rows = TableModelUtils.getCurrentRows(this, rows);this.collectionOfPageBeans = rows;//6. 视图显示 viewHandler.setView();return rows;}

4. 视图显示

 默认定义了三种视图模式:extremetable.properties

table.view.compact=org.extremecomponents.table.view.CompactView
table.view.limit=org.extremecomponents.table.view.LimitView
table.view.html=org.extremecomponents.table.view.HtmlView

    public void setView() throws Exception {boolean isExported = model.getLimit().isExported();String currentView = null;if (isExported) {currentView = model.getExportHandler().getCurrentExport().getView();String preference = model.getPreferences().getPreference(PreferencesConstants.EXPORT_VIEW + currentView);if (StringUtils.isNotBlank(preference)) {currentView = preference;}} else {currentView = model.getTableHandler().getTable().getView();String preference = model.getPreferences().getPreference(PreferencesConstants.TABLE_VIEW + currentView);if (StringUtils.isNotBlank(preference)) {currentView = preference;}}Class classDefinition = Class.forName(currentView);this.view = (View) classDefinition.newInstance();getView().beforeBody(model);}

调用抽象类的beforeBody方法:

    public final void beforeBody(TableModel model) {this.model = model;bufferView = model.getTableHandler().getTable().isBufferView();if (bufferView) {html = new HtmlBuilder();} else {html = new HtmlBuilder(model.getContext().getWriter());}formBuilder = new FormBuilder(html, model);init(html, model);formBuilder.formStart();tableBuilder.themeStart();   beforeBodyInternal(model);}

调用HtmlView的beforeBodyInternal处理

    protected void beforeBodyInternal(TableModel model) {toolbar(getHtmlBuilder(), getTableModel());getTableBuilder().tableStart();getTableBuilder().theadStart();statusBar(getHtmlBuilder(), getTableModel());getTableBuilder().filterRow();getTableBuilder().headerRow();getTableBuilder().theadEnd();getTableBuilder().tbodyStart();}

工具栏:

    protected void toolbar(HtmlBuilder html, TableModel model) {    //layout 布局new DefaultToolbar(html, model).layout();}

左右布局格式:

    public void layout() {if (!showLayout(model)) {return;}html.table(0).border("0").cellPadding("0").cellSpacing("0");Table table = model.getTableHandler().getTable();html.width(table.getWidth()).close();html.tr(1).close();// layout area leftcolumnLeft(html, model);// layout area right
        columnRight(html, model);html.trEnd(1);html.tableEnd(0);html.newline();}

布局的实现:

protected void columnLeft(HtmlBuilder html, TableModel model) {html.td(2).close();new TableBuilder(html, model).title();html.tdEnd();}protected void columnRight(HtmlBuilder html, TableModel model) {boolean showPagination = BuilderUtils.showPagination(model);boolean showExports = BuilderUtils.showExports(model);ToolbarBuilder toolbarBuilder = new ToolbarBuilder(html, model);html.td(2).align("right").close();html.table(2).border("0").cellPadding("0").cellSpacing("1").styleClass(BuilderConstants.TOOLBAR_CSS).close();html.tr(3).close();if (showPagination) {html.td(4).close();toolbarBuilder.firstPageItemAsImage();html.tdEnd();html.td(4).close();toolbarBuilder.prevPageItemAsImage();html.tdEnd();html.td(4).close();toolbarBuilder.nextPageItemAsImage();html.tdEnd();html.td(4).close();toolbarBuilder.lastPageItemAsImage();html.tdEnd();html.td(4).close();toolbarBuilder.separator();html.tdEnd();html.td(4).style("width:20px").close();html.newline();html.tabs(4);toolbarBuilder.rowsDisplayedDroplist();html.img();html.src(BuilderUtils.getImage(model, BuilderConstants.TOOLBAR_ROWS_DISPLAYED_IMAGE));html.style("border:0");html.alt("Rows Displayed");html.xclose();html.tdEnd();if (showExports) {html.td(4).close();toolbarBuilder.separator();html.tdEnd();}}if (showExports) {Iterator iterator = model.getExportHandler().getExports().iterator();for (Iterator iter = iterator; iter.hasNext();) {html.td(4).close();Export export = (Export) iter.next();toolbarBuilder.exportItemAsImage(export);html.tdEnd();}}html.trEnd(3);html.tableEnd(2);html.newline();html.tabs(2);html.tdEnd();}

状态栏和工具栏类似,就不一一赘述了。

5. 动作触发

以下一页来理解ectable中是如何触发事件的:

public void nextPageItemAsImage() {
ImageItem item = new ImageItem();
item.setTooltip(messages.getMessage(BuilderConstants.TOOLBAR_NEXT_PAGE_TOOLTIP));
item.setDisabledImage(BuilderUtils.getImage(model, BuilderConstants.TOOLBAR_NEXT_PAGE_DISABLED_IMAGE));
item.setImage(BuilderUtils.getImage(model, BuilderConstants.TOOLBAR_NEXT_PAGE_IMAGE));
item.setAlt(messages.getMessage(BuilderConstants.TOOLBAR_NEXT_PAGE_TEXT));
item.setStyle("border:0");
ToolbarItemUtils.buildNextPage(html, model, item);
}

下一页的构建

    public static void buildNextPage(HtmlBuilder html, TableModel model, ToolbarItem item) {int page = model.getLimit().getPage();String action = new TableActions(model).getPageAction(page + 1);item.setAction(action);int totalPages = BuilderUtils.getTotalPages(model);if (!BuilderUtils.isNextPageEnabled(page, totalPages)) {item.disabled(html);} else {item.enabled(html, model);}}

触发动作,js实现

    public String getPageAction(int page) {StringBuffer action = new StringBuffer("javascript:");action.append(getClearedExportTableIdParameters());action.append(getFormParameter(TableConstants.PAGE, "" + page));action.append(getOnInvokeAction());return action.toString();}

一个完整的table示例如下:

<table border="0"  cellpadding="0"  cellspacing="0"  width="60%" ><tr><td><span class="title" >persons</span></td><td align="right" ><table border="0"  cellpadding="0"  cellspacing="1"  class="toolbar" ><tr><td><img src="/address-book/public/images/table/firstPageDisabled.gif"  style="border:0"  alt="第一页" /></td><td><img src="/address-book/public/images/table/prevPageDisabled.gif"  style="border:0"  alt="上一页" /></td><td><img src="/address-book/public/images/table/nextPageDisabled.gif"  style="border:0"  alt="下一页" /></td><td><img src="/address-book/public/images/table/lastPageDisabled.gif"  style="border:0"  alt="最后页" /></td><td><img src="/address-book/public/images/table/separator.gif"  style="border:0"  alt="Separator" /></td><td style="width:20px" ><select name="ec_rd"  onchange="javascript:document.forms.ec.ec_crd.value=this.options[this.selectedIndex].value;document.forms.ec.ec_p.value='1';document.forms.ec.setAttribute('action','/address-book/person/list');document.forms.ec.setAttribute('method','post');document.forms.ec.submit()" ><option value="5"  selected="selected">5</option><option value="50" >50</option><option value="100" >100</option></select><img src="/address-book/public/images/table/rowsDisplayed.gif"  style="border:0"  alt="Rows Displayed" /></td></tr></table></td></tr>
</table>

6. 小结:

eXtremeComponents为jsp开发table提供了比较好的支持,它的源码可以作为学习jsp tag的一个很好示例,研究该源码可以加深对jsp的理解,通过对上述源码进行合适的扩展后可以作为组件库使用。

参考文献:

1. http://liuna718-163-com.iteye.com/blog/1318991

2. http://www.51cto.com/specbook/11/57761.htm

转载于:https://www.cnblogs.com/davidwang456/p/4401742.html

extremeComponents(ec)源码分析相关推荐

  1. ceph bluestore 源码分析:刷缓存(trim)逻辑

    环境 ceph版本:12.2.1 部署模式:ec 2+1 osd: 3个 且资源池已经有数据 执行命令:ceph daemon osd.0 flush_store_cache 进行刷缓存.即将dump ...

  2. 《Ceph源码分析》——第1章,第5节RADOS

    本节书摘来自华章出版社<Ceph源码分析>一书中的第1章,第1.5节RADOS,作者常涛,更多章节内容可以访问云栖社区"华章计算机"公众号查看 1.5 RADOS RA ...

  3. 【Zookeeper】源码分析之持久化(三)之FileTxnSnapLog

    一.前言 前面分析了FileSnap,接着继续分析FileTxnSnapLog源码,其封装了TxnLog和SnapShot,其在持久化过程中是一个帮助类. 二.FileTxnSnapLog源码分析 2 ...

  4. 【akka】Akka源码分析-local-DeathWatch

    1.概述 转载自己学习,建议直接看原文:Akka源码分析-local-DeathWatch 生命周期监控,也就是死亡监控,是akka编程中常用的机制.比如我们有了某个actor的ActorRef之后, ...

  5. JS/Jquery版本的俄罗斯方块(附源码分析)

    转载于 http://blog.csdn.net/unionline/article/details/63250597 且后续更新于此 1.前言 写这个jQuery版本的小游戏的缘由在于我想通过从零到 ...

  6. ceph 代码分析 读_Ceph源码分析

    Ceph源码分析 作者:常涛 编著 出版日期:2016年10月 文件大小:2.34M 支持设备: ¥40.00在线试读 适用客户端: 言商书局 iPad/iPhone客户端:下载 Android客户端 ...

  7. 《Ceph源码分析》——导读

    本节书摘来自华章出版社<Ceph源码分析>一书中的导读,作者常涛,更多章节内容可以访问云栖社区"华章计算机"公众号查看 目 录 序言 第1章 Ceph整体架构 1.1 ...

  8. 以太坊DPOS源码分析

    2019独角兽企业重金招聘Python工程师标准>>> 一.前言: 任何共识机制都必须回答包括但不限于如下的问题: 下一个添加到数据库的新区块应该由谁来生成? 下一个块应该何时产生? ...

  9. [前沿技术] AMD FSR 1.0源码分析(二)

    FSR技术分析 前文:[前沿技术] AMD FSR 1.0源码分析(一) 2. EASU源码分析 2.3 FsrEasuF分析 1️⃣首先,就参数而言,主要是: void FsrEasuF(out A ...

  10. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

最新文章

  1. C++、嵌入式软开之指针
  2. android平台水波效果 源码
  3. 中国科学院院士张钹:人工智能目前只能在某些行为上尽量接近人
  4. dede首页调用栏目内容{dedefield.content}的方法
  5. oracle分页性能不同,oracle高效分页
  6. php提交后清楚表单缓存,PHP提交表单后如何控制缓存 | 学步园
  7. 三维重建:QT+OpenNI+Kinect图像校正
  8. linux下的bc计算器设置scale精度
  9. vlan为什么能隔离广播域_路由交换技术-VLAN原理及配置
  10. C/C++程序员必须熟悉的开源库
  11. 腾讯云linux服务器怎么使用图形化界面_winscp使用方法,winscp使用方法详细说明...
  12. JUnit5 @Tag注解示例
  13. 树莓派 Learning 001 装机 ---之 1 安装NOOBS系统
  14. C#中WinForm 父窗体和子窗体传值
  15. oracle递归树查询
  16. C语言课程设计——25道蓝桥杯练习题
  17. freemarker 数组转字符串_freemarker list转json
  18. 商圈研究方案-调研内容及方法
  19. 正则表达式的基本原理
  20. java mybatis优点_mybatis优缺点是什么?有哪些优点和缺点?

热门文章

  1. 违反了primarykey约束怎么解决_前期物业服务合同对主业有约束力吗?
  2. c 定义结构体时提示应输入声明_C语言结构体的坑很多,这6大方法千万要记住!...
  3. Shell中的常用操作
  4. linux 设备驱动 百度,Linux设备驱动之input子系统
  5. dw做php怎么做表格透明,DW做的简单PHP管理
  6. mysql根据bin log恢复_MySQL 通过 binlog 恢复数据
  7. bean加载时调用@value时会出现空指针异常_SpringMVC全局异常处理机制
  8. 独占电脑装linux,旧电脑如何处理?装Tiny Core,极致精简,超低CPU占用,你敢试吗...
  9. linux的ip地址是127,Linux的IP地址显示127.0.0.1的解决办法
  10. 一套完整的导视设计案例_经验分享 | 我的一套完整的硬件电路设计方案