zoukankan      html  css  js  c++  java
  • LoadRunner性能测试系统学习教程:Vuser发生器(上)

    引言

    Vuser发生器(VisualUserGenerator,简称为VuGen)主要通过捕获客户端向服务器发送的HTTP请求,将这些请求录制成脚本,在回放时将捕获的HTTP请求再次发送,以达到模拟客户的行为的目的,所以Vuser主要是用来捕获最终用户业务流程和创建自动化测试脚本,即生成测试脚本。VuGen是录制测试脚本、编辑与完善测试脚本的一个平台,支持C语言语法。

    主要包括以下内容:

    脚本录制

    Recording Options设置

    Run-Time Settings设置

    脚本完善

    脚本录制

    启动VisualUserGenerator,创建一个新的脚本,开始录制脚本,在录制脚本过程中,VuGen会自动捕获操作过程中客户端与服务器端进行通信的所有数据。这里涉及的关键点是如何选择录制协议。  

    脚本开发主要包括四大步骤:计划、录制脚本、脚本增强和单机调试脚本,如图所示。

    如何选择协议

    在创建一个新的脚本时,首先会弹出一个对话框,在该对话框中选择录制时需要的协议,这步非常重要,选择的协议将直接影响到录制后的脚本是否理想,如何选择录制协议是录制前必须要解决的问题。  

    各种协议和相关头文件的对应关系如图所示。  

    协议

    头文件

    AJAX(Click&Script)

    web_ajax.h

    Citrix

    ctrxfuncs.h

    COM/DCOM

    lrc.h

    Database

    lrd.h

    FTP

    mic_ftp.h

    General C function

    lrun.h

    IMAP

    mic_imap.h

    LDAP

    mic_midap.h

    MAPI

    mic_mapi.h

    Oracle NCA

    orafuncs.h

    POP3

    mic_pop3.h

    ROP

    lrrdp.h

    SAPGUI

    as_sapgui.h

    SAP(Click&Script)

    sap_api.h

    Siebel

    lrdsiebel.h

    SMTP

    mic_smtp.h

    Terminal Emulator

    lrrte.h

    WAP

    as_wap.h

    Web(HTMLHTTP)

    as_wab.h

    Web(Click&Script)

    web_api.h

    Web Services

    wssoap.h

    Windows Sockets

    lrs.h

    选择协议的常用方法主要有以下几种:  

    1.最简单的方法就是向开发工程师确认数据通信所采用的协议,因为开发工程师最清楚应用程序采用的是何种通信协议。  

    2.没有开发工程师支持时,可以通过概要或详细设计手册获知所使用的协议。  

    3.使用协议分析工具捕获通信时的数据包并进行分析,然后确定被测对象所使用的协议。在使用协议分析工具分析协议过程中一定要摒除底层协议,不要被底层协议所迷惑。  

    4.根据以往测试经验来判断被测试对象采用的协议,这种方法具有猜测性,有时候不一定准确。  

    在LoadRunner新的版本中有一个协议分析的工具(ProtocolAdvisor),通过该工具可以分析当前系统所使用的协议。协议分析工具的使用步骤如下:  

    1.在【WelcometotheVirtualUserGenerator】界面单击【ProtocolAdvisor】按钮,如图所示。

    2.弹出【ProtocolAdvisor】对话框,如图所示。

    Applicationtype:选择应用程序的类型,被测试的应用程序类型主要包括两类:InternetApplictions和Win32Applications,也即通常说的B/S和C/S框架的两类应用程序。  

    Programtoanalyze:分析的程序,如果选择的应用程序类型为InternetApplications那么,该选项为MicrosoftInternetExplorer,即IE浏览器,因为LoadRunner在录制时默认启动IE浏览器进行录制;如果选择的应用程序类型为Win32Applications,那么该选项为需要测试的应用程序的路径。  

    URLAddress:即需要分析的网页地址;  

    Workingdirectory:工作目录,默认的为LoadRunner所在路径的bin目录。  

    3.设置待分析程序的路径或URL地址,单击【OK】按钮,即开始分析应用程序,通常分析一个简单的业务即可停止分析。  

    4.单击浮动框中的【StopAnalyzing】按钮,停止分析应用程序,并产生分析后的结果。  

    LoadRunner提供了多种协议,具体的协议分类见表。

    1.单协议脚本:创建单协议Vuser脚本,在对话框中选择录制时需要的协议,如图所示。创建新脚本时,会弹出一个对话框,LoadRunner提供三种选择协议的方式:单协议脚本、多协议脚本和最近使用过的协议。  

    2.多协议脚本:创建多协议Vuser脚本。在AvailableProtocols中选择一个或多个协议,点击右箭头,将其移入到SelectedProtocols部分中,同样,在SelectedProtocols中选择一个或多个协议,点击左箭头可以移除选中的协议,如图所示。

    3.最近使用过的协议:从最近录制脚本的协议列表中,选择一种协议进行录制,如图所示

    开始录制脚本  

    协议选择好后可以开始录制脚本。这里以Web(HTTP/HTML)协议为例进行录制。  

    VuGen录制浏览器主要是通过代理的方式来实现的。开始录制时,VuGen打开浏览器(默认使用Mircosoft自带的IE浏览器,使用其它浏览器录制容易出现HTTP请求被丢失的现象,所以尽量使用IE浏览器进行录制),并以VuGen作为代理来访问目标服务器。这样,VuGen就可以捕获客户端与服务器之间通过的数据包,如图所示。

    在使用VuGen进行录制用户操作时,VuGen会对捕获的数据进行分析,并将其还原成对应协议的由API组成的脚本。同时,VuGen会将这些函数生成的脚本插入到VuGen编辑器中,以创建原始的Vuser脚本。  

    录制时系统弹出一个录制窗口,如图所示。

    在URLAddress中输入要录制的站点地址。RecordintoAction选项表示将录制的代码放到哪个部分。LoadRunner生成的代码由三部分组成:vuser_init、Action和vuser¬_end。  

    注意:一般情况下都是将生成的代码放在Action部分,因为vuser_init和vuser¬_end两部分的代码只会执行一次,这样会出现这种问题,客户的并发虚拟用户只执行一次,执行完成一次后再也不执行,这样就没有HTTP请求给服务器,也即服务器没有压力。如下例子,图是每秒点击率的值。

    从图中可以看出,在场景执行到25秒后,客户端的点击率为0,即25秒后客户端没有提交任何请求,这就是典型的由于将脚本放在vuser_init引起的,因为脚本放在vuser_init中,导致每个虚拟用户只会执行一次这部分的脚本,当用户加载完成后,再也不行,所以看到后期的点击率都为0。  

    Recordtheapplicationstartup选项表示应用程序一旦启动,VuGen就立即开始录制;如果不选中,应用程序启动后,VuGen会弹出如图所示的对话框,并且暂时不会进行录制,当用户操作应用程序到需要录制的地方时,点击Record按钮,VuGen才开始录制。默认情况下Recordtheapplicationstartup是选中的状态。点击Record按钮开启录制。

    在录制前还需要注意在RecordinOptions设置对话框中,设计脚本录制的方式,关于脚本的录制方式将在3.2.1小节中详细介绍。  

    开始录制后,会出现如图所示的工具栏 

    该工具条从左到右依次代表开始录制、暂停录制、停止录制、新建Action、在脚本与录制界面之间切换、添加开始事务标识、添加结束事务标识、设置集合点和添加注释。  

    录制过程中,LoadRunner会自动记录用户的操作。录制完成后,点击“停止录制”按钮结束录制,这时VuGen会自动生成一个脚本,如图所示。

    这是一个比较简单的脚本,但可以看出LoadRunner生成的脚本都是由函数组成。

    Recording Options设置

    在进行录制时,首先要对录制的一些参数进行设置,只有将这些参数设置好,才能录制并生成需要的脚本。  

    首先是RecordingOptions设置,需要注意的设置项有:Recording选项卡、Advanced选项卡和Correlation选项卡。  

    在Tools菜单中选择RecordingOptions或直接按快捷键Ctrl+F7进入参数设置对话框,如图所示。

    Recording选项卡

    在RecordingOptions对话框中,选择Recording选项卡。RecordingLevel包含两种录制模式:HTML-basedscript和URL-basedscript,如图所示,默认情况下选中HTML-basedscript录制方式。当然,两种录制模式也存在差别  

    单击【HTMLAdvanced…】按钮,弹出【AdvancedHTML】对话框,如图所示,在该对话框中关于HTML-basedscript脚本方式又有两种:“Ascriptdescribinguseractions”和“Ascriptcontainingexplicit”。

    Ascriptdescribinguseractions:模拟用户行为录制,即GUI录制,把用户每一步的操作显示出来,最后生成的脚本非常直观并且会将上下文的一些敏感信息记录下来。它创建URL(web_url)、link(web_link)、image(web_image)和提交表单(web_submit_form)。  

    下面以Ascriptdescribinguseractions方式录制一个登录的功能,录制后的代码如下:  

    web_url("WebTours",  

    "URL=http://127.0.0.1:1080/WebTours/",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=",  

    "Snapshot=t1.inf",  

    "Mode=HTML",  

    LAST);  

    lr_think_time(4);  

    web_submit_form("login.pl",  

    "Snapshot=t2.inf",  

    ITEMDATA,  

    "Name=username","Value=test1",ENDITEM,  

    "Name=password","Value=1",ENDITEM,  

    "Name=login.x","Value=65",ENDITEM,  

    "Name=login.y","Value=8",ENDITEM,  

    LAST);  

    return0;  

    从生成的代码中可以看到,在录制时只做了两个操作,生成的代码也只有两个函数,也即这种录制模式只录制用户的操作,其它的内容不会被录制。使用的提交信息函数为web_submit_form()。  

    AscriptcontaningexplictURLsonly:录制所有links(链接)、images(图片)和URL(web_url),但不创建web_link、web_image和提交表单(web_submit_form)。这种录制方式生成的脚本不直观。  

    下面以AscriptcontaningexplictURLSonly方式录制一个登录的功能,录制后的代码如下:

    web_url("WebTours",  

    "URL=http://127.0.0.1:1080/WebTours/",  

    "TargetFrame=",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=",  

    "Snapshot=t1.inf",  

    "Mode=HTML",  

    LAST);  

    web_submit_data("login.pl",  

    "Action=http://127.0.0.1:1080/WebTours/login.pl",  

    "Method=POST",  

    "TargetFrame=body",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",  

    "Snapshot=t2.inf",  

    "Mode=HTML",  

    ITEMDATA,  

    "Name=userSession","Value=108748.859052248ffQDHzQptDHfDDfzcpzVzzcf",ENDITEM,  

    "Name=username","Value=test1",ENDITEM,  

    "Name=password","Value=1",ENDITEM,  

    "Name=JSFormSubmit","Value=off",ENDITEM,  

    "Name=login.x","Value=53",ENDITEM,  

    "Name=login.y","Value=10",ENDITEM,  

    LAST);  

    return0; 

    从生成的代码中可以看到,同样的提交登录的信息但使用的函数为web_submit_data(),不再以表单的方式提交,而web_submit_form()函数则是以表单的信息进行提交的,该函数运行时,首先在页面上去查找表单,再提交数据,而web_submit_data()则不需要,直接向服务器发送要提交的数据。  

    但在录制过程中很可能会录制到一些非HTML的元素(如Java小程序、XML、ActiveX元素、JavaScript),这些非HTML元素主要用于包含或去获取自己的一些资源,例如,JavaScript的JS文件用于调用加载多个图片。对于这类非HTML的元素,录制时有三种方式:  

    Recordwithinthecurrentscriptstep:在录制时对于非HTML资源并不会生成一个新的功能。它列出所有相关资源的参数,如web_url、web_link和web_submit_data。这些web功能的参数使用EXTRARES标示。  

    如以下代码: 

    web_url("index.asp",  

    "URL=http://www.daisy.com/index.asp",  

    "TargetFrame=",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=",  

    "Snapshot=t2.inf",  

    "Mode=HTML",  

    EXTRARES,  

    "Url=http://www.daisy.com/ScrollApplet.class","Referer=",ENDITEM,  

    "Url=http://www.daisy.com/board.txt","Referer=",ENDITEM,  

    "Url=http://www.daisy.com/nav_login1.gif",ENDITEM,  

    ...  

    LAST);  

    Recordinseparatestepsanduseconcurrentgroups:在一个组中记录这些单独的步骤,为每个非HTML资源创建一个新的功能(但不包括一些页面的功能,如web_url、web_link等)。所有的web_url资源都将放置并行组中(并行组由web_concurrent_start和web_concurrent_end进行标示)。  

    如以下代码: 

    web_url("index.asp",  

    "URL=http://www.daisy.com/index.asp",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=",  

    "Snapshot=t2.inf",  

    "Mode=HTML",  

    LAST);  

    web_concurrent_start(NULL);  

    web_url("ScrollApplet.class",  

    "URL=http://www.daisy.com/ScrollApplet.class",  

    "Resource=1",  

    "RecContentType=application/octet-stream",  

    "Referer=",  

    LAST);  

    web_url("board.txt",  

    "URL=http://www.daisy.com/board.txt",  

    "Resource=1",  

    "RecContentType=text/plain",  

    "Referer=",  

    LAST);  

    web_concurrent_end(NULL);  

    Donotrecord:不记录,对于非HTML元素不记录。  

    注意:使用HTML-Based模式录制时,VuGen插入目标帧到web_url函数中时,VuGen会在run-time运行的浏览器中和结果报告中显示页面的正确性。  

    如以下代码:

    web_url("buttonhelp.gif",  

    "URL=http://www.hplab.com/home?com/rstr?BV_EngineID...,  

    "TargetFrame=main",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://www.hplab.com/home?...  

    "Snapshot=t5.inf",  

    "Mode=HTML",  

    LAST); 

    URL-basedscript方式:将每条客户端发出的请求录制成一条语句,对LoadRunner来说,在该模式下,一条语句只能建立一个到服务器的连接,并将通信过程中的很多隐藏的信息都录制出来(如session、cookie)。LoadRunner提供了web_concurrent_start()和web_concurrent_end()函数模拟URL-basedscript的工作方式。  

    下面以URL-basedscript方式录制一个登录的功能,录制后的代码如下:

    web_url("WebTours",  

    "URL=http://127.0.0.1:1080/WebTours/",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=",  

    "Snapshot=t1.inf",  

    "Mode=HTTP",  

    LAST);  

    web_concurrent_start(NULL);  

    web_url("header.html",  

    "URL=http://127.0.0.1:1080/WebTours/header.html",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/",  

    "Snapshot=t2.inf",  

    "Mode=HTTP",  

    LAST);  

    web_url("welcome.pl",  

    "URL=http://127.0.0.1:1080/WebTours/welcome.pl?signOff=true",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/",  

    "Snapshot=t4.inf",  

    "Mode=HTTP",  

    LAST);  

    web_concurrent_end(NULL);  

    web_concurrent_start(NULL);  

    web_url("hp_logo.png",  

    "URL=http://127.0.0.1:1080/WebTours/images/hp_logo.png",  

    "Resource=1",  

    "RecContentType=image/png",  

    "Referer=http://127.0.0.1:1080/WebTours/header.html",  

    "Snapshot=t3.inf",  

    LAST);  

    web_url("webtours.png",  

    "URL=http://127.0.0.1:1080/WebTours/images/webtours.png",  

    "Resource=1",  

    "RecContentType=image/png",  

    "Referer=http://127.0.0.1:1080/WebTours/header.html",  

    "Snapshot=t5.inf",  

    LAST);  

    web_concurrent_end(NULL);  

    web_concurrent_start(NULL);  

    web_url("home.html",  

    "URL=http://127.0.0.1:1080/WebTours/home.html",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/welcome.pl?signOff=true",  

    "Snapshot=t6.inf",  

    "Mode=HTTP",  

    LAST);  

    web_url("nav.pl",  

    "URL=http://127.0.0.1:1080/WebTours/nav.pl?in=home",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/welcome.pl?signOff=true",  

    "Snapshot=t7.inf",  

    "Mode=HTTP",  

    LAST);  

    web_concurrent_end(NULL);  

    web_url("mer_login.gif",  

    "URL=http://127.0.0.1:1080/WebTours/images/mer_login.gif",  

    "Resource=1",  

    "RecContentType=image/gif",  

    "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",  

    "Snapshot=t8.inf",  

    LAST);  

    web_submit_data("login.pl",  

    "Action=http://127.0.0.1:1080/WebTours/login.pl",  

    "Method=POST",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/nav.pl?in=home",  

    "Snapshot=t9.inf",  

    "Mode=HTTP",  

    ITEMDATA,  

    "Name=userSession","Value=108749.254191981ffQDHiQpHzcfDDfzcpHDifHf",ENDITEM,  

    "Name=username","Value=test1",ENDITEM,  

    "Name=password","Value=1",ENDITEM,  

    "Name=JSFormSubmit","Value=off",ENDITEM,  

    "Name=login.x","Value=63",ENDITEM,  

    "Name=login.y","Value=9",ENDITEM,  

    LAST);  

    web_concurrent_start(NULL);  

    web_url("nav.pl_2",  

    "URL=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/login.pl",  

    "Snapshot=t10.inf",  

    "Mode=HTTP",  

    LAST);  

    web_url("login.pl_2",  

    "URL=http://127.0.0.1:1080/WebTours/login.pl?intro=true",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://127.0.0.1:1080/WebTours/login.pl",  

    "Snapshot=t12.inf",  

    "Mode=HTTP",  

    LAST);  

    web_concurrent_end(NULL);  

    web_concurrent_start(NULL);  

    web_url("flights.gif",  

    "URL=http://127.0.0.1:1080/WebTours/images/flights.gif",  

    "Resource=1",  

    "RecContentType=image/gif",  

    "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",  

    "Snapshot=t11.inf",  

    LAST);  

    web_url("itinerary.gif",  

    "URL=http://127.0.0.1:1080/WebTours/images/itinerary.gif",  

    "Resource=1",  

    "RecContentType=image/gif",  

    "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",  

    "Snapshot=t13.inf",  

    LAST);  

    web_url("signoff.gif",  

    "URL=http://127.0.0.1:1080/WebTours/images/signoff.gif",  

    "Resource=1",  

    "RecContentType=image/gif",  

    "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",  

    "Snapshot=t14.inf",  

    LAST);  

    web_url("in_home.gif",  

    "URL=http://127.0.0.1:1080/WebTours/images/in_home.gif",  

    "Resource=1",  

    "RecContentType=image/gif",  

    "Referer=http://127.0.0.1:1080/WebTours/nav.pl?page=menu&in=home",  

    "Snapshot=t15.inf",  

    LAST);  

    web_concurrent_end(NULL);  

    return0;

    选择URL-basedscript选择,单击【URLAdvanced…】,弹出【AdvancedURL】对话框。关于URL的高级设置有两种方式:“CreateconcurrentgroupsforresourcestheirsourceHTMLpage”和“Useweb_custom_requestonly”。  

    CreateconcurrentgroupsforresourcestheirsourceHTMLpage:将捕获所有HTML页面的资源,并将其保存在并发组中(并发组使用web_concurrent_start和web_concurrent_endstatements两个函数标识),如果不选中该选项时,HTML页面资源将会分成独立的、单独的web_url步骤,但并不放入并行组中。  

    如以下代码: 

    web_concurrent_start(NULL);  

    ...  

    web_url("ClickHereForAdditionalRestrictions",  

    "URL=http://www.hplab.com/restrictions.html",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://www.hplab.com/home?...  

    "Snapshot=t4.inf",  

    "Mode=HTTP",  

    LAST);  

    web_url("buttonhelp.gif",  

    "URL=http://www.hplab.com/home?com/rstr?BV_EngineID...,  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=http://www.hplab.com/home?...  

    "Snapshot=t5.inf",  

    "Mode=HTTP",  

    LAST);  

    ...  

    web_concurrent_end(NULL);  

    Useweb_custom_requestonly:如果录制的是非浏览器的应用程序,可以设置VuGen自定义HTTP请求,在LoadRunner中使用web_custom_reques函数来实现,不管内容如何。  

    如以下代码:

    web_custom_request("www.hplab.com",  

    "URL=http://www.hplab.com/",  

    "Method=GET",  

    "Resource=0",  

    "RecContentType=text/html",  

    "Referer=",  

    "Snapshot=t1.inf",  

    "Mode=HTTP",  

    LAST); 

    选择HTML-basedscript还是URL-basedscript,应该根据实际需要进行,下面是一些常见的参考原则:  

    1.基于浏览器的应用程序推荐使用HTML-basedscript。  

    2.不是基于浏览器的应用程序推荐使用URL-basedscript。  

    3.如果基于浏览器的应用程序中包含了JavaScript,并且该脚本向服务器发送了请求,比如DataGrid的分页按钮等,推荐使用URL-basedscript。  

    4.基于浏览器的应用程序中使用了HTTPS安全协议,建议使用URL-basedscript。如果使用HTML-basedscript模式录制后不能成功回放,可以考虑改用URL-basedscript模式来录制。因为这种情况多是由上面所列举的原因所引起的。

    Advanced选项卡

    Advanced选项是设置脚本回放的高级选项,如图所示。

    Savesnapshotresourceslocally:表示运行结果中保存一个快照。  

    AddcommentstoscriptforHTTPerrorswhilerecording表示出现错误时会自动添加注释。  

    点击Headers…按钮,会弹出HTTPHeaders配置对话框,如图所示。在该对话框中可以选择需要录制的Headers,以便服务器能够正确处理编辑信息。需要注意的是Accept-Language选项,像Websphere这类服务器会根据HTTP请求中的Header来确定编码。

    Correlation选项卡

    Correlation选项卡用来对脚本中的关联属性进行设置,如图3-19所示。LoadRunner包括两种规则:一是内建规则;二是:自定义的规则;LoadRunner会默认自带一些内建规格。在录制时选中需要的关联规则,录制脚本过程中LoadRunner会自动匹配需要关联的规格,并生成关联函数。如果当前的这些关联规则无法满足录制的需求,那么可以点击【NewApplication】按钮来新建一个关联,再点击【NewRule】按钮为该关联新建一个规则。

    如果您看了本篇博客,觉得对您有所收获,请点击右下角的[推荐]. 如果您想转载本博客,请注明出处, 如果您对本文有意见或者建议,欢迎留言. 感谢您的阅读,请关注我的后续博客!
  • 相关阅读:
    两个有序链表的合并
    阶乘求和优化思考
    ### Error building SqlSession. ### The error may exist in SQL Mapper Configuration ### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibat
    ### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.
    Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'ItemsCustom' in 'class com.pojo.OrderDetailCustom
    org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.lang.NumberFormatException: For input string: "W%" ### Cause: java.lang.NumberFormatException: For input s
    java发送http的get、post请求
    Echarts 中当y轴有负数时,让x轴下落在y轴最小值
    Echarts数据可视化grid直角坐标系(xAxis、yAxis)详解:
    Echarts datazoom数据区域缩放
  • 原文地址:https://www.cnblogs.com/chuansinfo/p/13528114.html
Copyright © 2011-2022 走看看