首页 文章 精选 留言 我的

精选列表

搜索[源码学习],共10000篇文章
优秀的个人博客,低调大师

hive变量传递的源码实现

用过hive的人都知道,可以通过在cli向hive传递参数,变量等,这里其实是通过下面两个类实现的。 1 2 org.apache.hadoop.hive.ql.processors.SetProcessor类 org.apache.hadoop.hive.ql.parse.VariableSubstitution类 其中SetProcessor类定义了对set 命令的处理,VariableSubstitution类负责把变量值进行转换。 VariableSubstitution用来实现在解析hive命令时把特殊字符进行转换,如果是以!开头的shell命令的话,直接在CliDriver类的processCmd方法中做转换 1 2 3 else if (cmd_trimmed.startsWith( "!" )){ Stringshell_cmd=cmd_trimmed.substring( 1 ); shell_cmd= new VariableSubstitution().substitute(ss.getConf(),shell_cmd); 其他的命令会在具体的CommandProcessor实现类中做转换。关于CommandProcessor类这里简单说下,后面会相信分析: CommandProcessor的调用是在在CliDriver类的processLocalCmd方法中发生的。 1 int processLocalCmd(Stringcmd,CommandProcessorproc,CliSessionStatess) 这里传入一个CommandProcessor的实例,函数中会判断具体的实现类。如果实现类是Driver类(即执行的命令是sql),会调用Driver的run方法。 1 2 3 4 if (proc instanceof Driver){ Driverqp=(Driver)proc; ..... ret=qp.run(cmd).getResponseCode(); 如果是其他实现类(即执行的命令是set/add/compile等),会调用对应实现类(commandprocessor相关类)的run方法。 下面分析下VariableSubstitution的具体实现: VariableSubstitution类有两个控制参数 1 2 hive.variable.substitute控制是否打开Substitution功能,默认是 true hive.variable.substitute.depth,控制可以匹配到几层,默认是 40 主要有getSubstitute和substitute方法。 方法的调用顺序是 1 substitute----->getSubstitute 其中substitute方法如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public Stringsubstitute(HiveConfconf,Stringexpr){ if (conf.getBoolVar(ConfVars.HIVEVARIABLESUBSTITUTE)){ //判断hive.variable.substitute是否设置true l4j.debug( "Substitutionison:" +expr); } else { return expr; } if (expr== null ){ return null ; } Matchermatch=varPat.matcher( "" ); Stringeval=expr; for ( int s= 0 ;s<conf.getIntVar(ConfVars.HIVEVARIABLESUBSTITUTEDEPTH);s++){ match.reset(eval); if (!match.find()){ //判断输入的命令是否匹配"\\$\\{[^\\}\\$\u0020]+\\}",如果不匹配直接返回 return eval; } Stringvar=match.group(); var=var.substring( 2 ,var.length()- 1 ); //remove${..} Stringval=getSubstitute(conf,var); if (val== null ){ l4j.debug( "Interpolationresult:" +eval); return eval; //returnliteral,nosubstitutionfound } //substitute eval=eval.substring( 0 ,match.start())+val+eval.substring(match.end()); //完成替换 } throw new IllegalStateException( "Variablesubstitutiondepthtoolarge:" +conf.getIntVar(ConfVars.HIVEVARIABLESUBSTITUTEDEPTH)+ "" +expr); } 其中getSubstitute会调用SetProcessor类,来解析命令。 比如,以hiveconf:开头的命令会经过如下的处理: 1 2 3 if (var.startsWith(SetProcessor.HIVECONF_PREFIX)){ val=conf.get(var.substring(SetProcessor.HIVECONF_PREFIX.length())); } 但是对于使用命名空间如hiveconf,system,env的,前缀则不可少,hivevar可以不需要前缀。 1 2 3 4 5 6 7 if (val== null ){ if (var.startsWith(SetProcessor.HIVEVAR_PREFIX)){ //这里HIVEVAR_PREFIX的值是hivevar: val=SessionState.get().getHiveVariables().get(var.substring(SetProcessor.HIVEVAR_PREFIX.length())); } else { val=SessionState.get().getHiveVariables().get(var); } } 这里有个例子: 1 2 setsystem:testdate= 20140816 ; select*fromchinacache_logwheredt>= '${system:testdate}' limit 5 ; 1)第一个set命令在经过processLocalCmd方法处理之后,传入substitute的expr是20140816 (取=号之后的数据) 因为不能匹配到正则,直接回返回。 1 2 3 4 5 Stringeval=expr; ..... if (!match.find()){ return eval; } 2)第2条sql 1 select*fromxxxxwheref1>= '${system:testdate}' 由Driver处理后,传入的expr是 1 select*frompeter001wheref1>= '${system:testdate}' 由match.group()匹配到${system:testdate},然后通过 1 var.substring( 2 ,var.length()- 1 ) 去除掉${},并调用getSubstitute获取设置的变量值,并最终生成一个有效的sql。 最终由 1 eval.substring( 0 ,match.start())+val+eval.substring(match.end()) 返回的值是 1 select*frompeter001wheref1>= '20140816' 完成了变量的替换。 本文转自菜菜光 51CTO博客,原文链接:http://blog.51cto.com/caiguangguang/1541758,如需转载请自行联系原作者

优秀的个人博客,低调大师

android 开发之电子钢琴 源码

这个小例子主要用到android手势部分和Mediaplayer部分的知识。 手势部分没啥问题,我们可以通过MotionEvent中定义的Event Code来判断当前手势的状态(按下或者释放等) imageButton_white1.setOnTouchListener(new View.OnTouchListener() {public boolean onTouch(View view, MotionEvent motionEvent) {if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { play(R.raw.white1);//这个时候创建播放要用的资源文件 imageButton_white1.setImageResource(R.drawable.whiteback1); }if (motionEvent.getAction() == MotionEvent.ACTION_UP) { imageButton_white1.setImageResource(R.drawable.white1); }return false; } }); Mediaplayer部分目前还有个问题没有解决: 每次按下键盘时我都要调用相应的音符 mediaPlayer01 = MediaPlayer.create(Piano.this, resource); 随着按键次数的增加create的次数也随着增加。 只要create的次数到了32次之后,再按键盘就不会响了,这个时候只要改变一下屏幕的方向程序就可以继续运行。 我的理解是create后的资源没有被释放导致的。 但我在代码中也加入了 mediaPlayer01.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {public void onCompletion(MediaPlayer arg0) { mediaPlayer01.release(); Toast.makeText(Piano.this, "资源释放了!", Toast.LENGTH_SHORT).show(); } }); 这样的监听代码。在资源文件播放完成后释放。但运行过程中这部分没有起作用(因为Toast部分没有执行)。 目前还不知道是什么原因造成的。 PS: 今天找到一个解决方法 不使用mediaplayer的监听事件来释放mediaplayer资源了。直接在play的时候先release一次,然后create资源文件。 不过这种做法稍微有点不大合理 为什么资源文件在事件触发的时候才create就不会被正常监听到呢。如果哪位同学知道原因的请帮忙解答下 源文件在这里MyPiano.rar 本文转自qianqianlianmeng博客园博客,原文链接:http://www.cnblogs.com/aimeng/archive/2011/11/17/2253123.html ,如需转载请自行联系原作者

优秀的个人博客,低调大师

Alisql源码编译安装(详细篇)

前言 AliSQL 在 2016 云栖大会宣布开放源代码之后,迅速就获得了广泛的关注,目前(2016-10-27) star 数目已达 1187,欢迎访问 AliSQL GitHub 项目关注。社区反应也非常活跃,在 Issue 中提了不少反馈建议,其中有一部分是和编译安装相关的,因为官方目前并没有提供 binary,有同学可能没有 GNU/Linux 环境下编译代码的经验,导致不能直接使用。针对这个问题,本文提供一个非官方 (unofficial) 的编译指导,希望对大家有所帮助 编译需要准备的环境CentOS 6.5+(阿里云服务器) 编译需要gcc >= 4.7, cmake >= 2.8 1.安装yum源【此步骤可以省略,我用的阿里云的镜像】 rpm -ivh "http://vault.centos.org/6.6/updates/x86_64/Packages/scl-utils-20120927-27.el6_6.x86_64.rpm" #安装scl rpm -ivh "https://www.softwarecollections.org/repos/rhscl/devtoolset-3/epel-6-x86_64/noarch/rhscl-devtoolset-3-epel-6-x86_64-1-2.noarch.rpm" #安装yum源 2.安装如下环境 yum install centos-release-scl -y yum install devtoolset-4-gcc-c++ devtoolset-4-gcc -y yum install cmake git -y yum install ncurses-devel openssl-devel bison -y 提示:由于是国外的网站 ,,所以速度可能有点慢 大家需要耐心等待 ,,现在我们来获取下Alisql 的源代码包******* ps:可能其他服务器会需要执行:yum install devtoolset-3 wget -c https://github.com/alibaba/AliSQL/archive/master.zip 创建用户和所属组 [root@spade ~]# groupadd mysql [root@spade ~]# useradd -M -s/sbin/nologin -g mysql -r mysql 解压 并且进入 [root@spade ~]# unzip AliSQL-master.zip [root@spade ~]# cd AliSQL-master 改变并且使用devtoolset-4 里面的GCC 套装 [root@spade AliSQL-master ~]# scl enable devtoolset-4 bash [root@spade AliSQL-master ~]# gcc -v gcc version 5.2.1 20150902 (Red Hat 5.2.1-2) (GCC) ##现在已经达到编译安装环境所需要的要求了 编译参数 ‘’大家可以自行根据mysql 5.6 官方的编译参数,,也可以参考我的。。谢谢‘’ cmake . \ -DCMAKE_BUILD_TYPE="Release" \ -DCMAKE_INSTALL_PREFIX="/usr/local/mysql" \ -DWITH_EMBEDDED_SERVER=0 \ -DWITH_EXTRA_CHARSETS=all \ -DWITH_MYISAM_STORAGE_ENGINE=1 \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_PARTITION_STORAGE_ENGINE=1 \ -DWITH_CSV_STORAGE_ENGINE=1 \ -DWITH_ARCHIVE_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITH_FEDERATED_STORAGE_ENGINE=1 \ -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \ 编译安装(根据CPU来进行调整j参数) [root@spade AliSQL-master]# make -j4 &&make install *****等待时间可能会有点长 耐心等待。。。。 配置并且启动 [root@spade AliSQL-master]# cd /usr/local/mysql [root@spade alisql]# ./scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data ##这一步是为了初始时数据库 [root@spade alisql]# cp ./support-files/my-default.cnf /etc/my.cnf [root@spade alisql]# cp ./support-files/mysql.server /etc/init.d/mysqld [root@spade alisql]# chmod +x /etc/init.d/mysqld [root@spade alisql]# chowd -R mysql:mysql /usr/local/mysql ##这一步很重要 注意看清楚***** [root@spade alisql]# echo "export PATH=$PATH:/usr/local/mysql/bin">>/etc/profile [root@spade alisql]# source /etc/profile [root@spade alisql]# service mysqld start Starting MySQL.. [确定] 常见错误分析 [root@spade alisql]# service mysqld start Starting MySQL…….The server quit without updating PID f[失败]usr/local/mysql/spade.pid). 解决原因是: ① /usr/local/mysql跟目录需要赋予mysql权限 根据日志文件显示,首先检查运行权限,再看一下/usr/local/mysql/mysql.sock,发现/usr/local/mysql目录下并没有该文件,是否是没有权限写目录? 看到/usr/local/mysql目录是root用户,所以赋予mysql操作权限。 chown -R mysql.mysql /usr/local/mysql ② 关闭防火墙 ③ 关闭selinux ps :// 很多时候都是我们没有仔细赋予权限导致的 祝愿大家玩的开心~~~~

优秀的个人博客,低调大师

SpringMVC源码分析(8)剖析ViewResolver

ViewResolver很简单,通过名称(name),获取View视图的。 View视图 其实就是对应MVC中的"V" 1.ViewResolver 结构图 2.BeanNameViewResolver 通过把返回的逻辑视图名称去匹配定义好的视图bean对象。 @Test publicvoidtestBeanNameViewResolver()throwsServletException{ StaticWebApplicationContextwac=newStaticWebApplicationContext(); wac.setServletContext(newMockServletContext()); MutablePropertyValuespvs1=newMutablePropertyValues(); pvs1.addPropertyValue(newPropertyValue("url","/example1.jsp")); wac.registerSingleton("example1",InternalResourceView.class,pvs1); BeanNameViewResolvervr=newBeanNameViewResolver(); vr.setApplicationContext(wac); wac.refresh(); Viewview=vr.resolveViewName("example1",Locale.getDefault()); assertEquals("Correctviewclass",InternalResourceView.class,view.getClass()); assertEquals("CorrectURL","/example1.jsp",((InternalResourceView)view).getUrl()); } 3.XmlViewResolverXmlViewResolver这个视图解析器跟 BeanNameViewResolver 有点类似,也是通过把返回的逻辑视图名称去匹配定义好的视图 bean 对象。 3.1 配置XML <?xmlversion="1.0"encoding="UTF-8"?> <!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN""http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <beanid="example1"class="org.springframework.web.servlet.view.ViewResolverTests$TestView"> <propertyname="url"><value>/example1.jsp</value></property> <propertyname="attributesMap"> <map> <entrykey="test1"><value>testvalue1</value></entry> <entrykey="test2"><refbean="testBean"/></entry> </map> </property> <propertyname="location"><value>test</value></property> </bean> </beans> 3.2 测试用例 @Test publicvoidtestXmlViewResolver()throwsException{ StaticWebApplicationContextwac=newStaticWebApplicationContext(); wac.registerSingleton("testBean",TestBean.class); wac.setServletContext(newMockServletContext()); wac.refresh(); TestBeantestBean=(TestBean)wac.getBean("testBean"); XmlViewResolvervr=newXmlViewResolver(); vr.setLocation(newClassPathResource("org/springframework/web/servlet/view/views.xml")); vr.setApplicationContext(wac); Viewview1=vr.resolveViewName("example1",Locale.getDefault()); assertTrue("Correctviewclass",TestView.class.equals(view1.getClass())); assertTrue("CorrectURL","/example1.jsp".equals(((InternalResourceView)view1).getUrl()));BeanNameViewResolver VS XmlViewResolver 1. BeanNameViewResolver 要求视图 bean 对象都定义在 Spring 的 application context 中,而 XmlViewResolver 是在指定的配置文件中寻找视图 bean 对象, 2. XmlViewResolver是 AbstractCachingViewResolver的子类,支持缓存; BeanNameViewResolver 不会进行视图缓存。4.ResourceBundleViewResolver 和 XmlViewResolver 一样它也需要有一个配置文件来定义逻辑视图名称和真正的 View 对象的对应关系,不同的是 ResourceBundleViewResolver 的配置文件是一个属性文件,而且必须是放在 classpath 路径下面的,默认情况下这个配置文件是在 classpath 根目录下的 views.properties 文件,如果不使用默认值的话,则可以通过属性 baseName 或 baseNames 来指定。 4.1 配置文件testviews_fr.properties debugView.(class)=org.springframework.web.servlet.view.InternalResourceView debugView.url=jsp/debug/deboug.jsp debugView.contentType=text/xml;charset=ISO-8859-1 4.2 测试用例 publicclassResourceBundleViewResolverTestsextendsTestCase{ /**Comesfromthispackage*/ privatestaticStringPROPS_FILE="org.springframework.web.servlet.view.testviews"; privateResourceBundleViewResolverrb; privateStaticWebApplicationContextwac; protectedvoidsetUp()throwsException{ rb=newResourceBundleViewResolver(); rb.setBasename(PROPS_FILE); rb.setCache(getCache()); rb.setDefaultParentView("testParent"); wac=newStaticWebApplicationContext(); wac.setServletContext(newMockServletContext()); wac.refresh(); //Thiswillbepropagatedtoviews,soweneedit. rb.setApplicationContext(wac); } publicvoidtestDebugViewFrench()throwsException{ Viewv=rb.resolveViewName("debugView",Locale.FRENCH); assertTrue("FrenchdebugViewmustbeoftypeInternalResourceView",vinstanceofInternalResourceView); InternalResourceViewjv=(InternalResourceView)v; assertTrue("FrenchdebugViewmusthavecorrectURL","jsp/debug/deboug.jsp".equals(jv.getUrl())); assertTrue( "Correctoverridden(XML)contenttype,not'"+jv.getContentType()+"'", jv.getContentType().equals("text/xml;charset=ISO-8859-1")); } } 在ResourceBundleViewResolver第一次进行视图解析的时候会先new一个BeanFactory对象,然后把properties文件中定义好的属性按照它自身的规则生成一个个的bean对象注册到该BeanFactory中,之后会把该BeanFactory对象保存起来,所以ResourceBundleViewResolver缓存的是BeanFactory,而不是直接的缓存从BeanFactory中取出的视图bean。然后会从bean工厂中取出名称为逻辑视图名称的视图bean进行返回。接下来就讲讲Spring通过properties文件生成bean的规则。它会把properties文件中定义的属性名称按最后一个点“.”进行分割,把点前面的内容当做是bean名称,点后面的内容当做是bean的属性。这其中有几个特别的属性,Spring把它们用小括号包起来了,这些特殊的属性一般是对应的attribute,但不是bean对象所有的attribute都可以这样用。其中(class)是一个,除了(class)之外,还有(scope)、(parent)、(abstract)、(lazy-init)。而除了这些特殊的属性之外的其他属性,Spring会把它们当做bean对象的一般属性进行处理,就是bean对象对应的property。所以根据上面的属性配置文件将生成如下两个bean对象: from http://elim.iteye.com/blog/1770554 5.UrlBasedViewResolver 它是对ViewResolver的一种简单实现,而且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。 5.2 重要属性 publicclassUrlBasedViewResolverextendsAbstractCachingViewResolverimplementsOrdered{ /** *PrefixforspecialviewnamesthatspecifyaredirectURL(usually *toacontrollerafteraformhasbeensubmittedandprocessed). *Suchviewnameswillnotberesolvedintheconfigureddefault *waybutratherbetreatedasspecialshortcut. */ publicstaticfinalStringREDIRECT_URL_PREFIX="redirect:"; /** *PrefixforspecialviewnamesthatspecifyaforwardURL(usually *toacontrollerafteraformhasbeensubmittedandprocessed). *Suchviewnameswillnotberesolvedintheconfigureddefault *waybutratherbetreatedasspecialshortcut. */ publicstaticfinalStringFORWARD_URL_PREFIX="forward:"; //Settheviewclassthatshouldbeusedtocreateviews. privateClassviewClass; //SettheprefixthatgetsprependedtoviewnameswhenbuildingaURL. privateStringprefix=""; //thesuffixthatgetsappendedtoviewnameswhenbuildingaURL. privateStringsuffix=""; //viewnames;suchthat'my*','*Report'and'*Repo*' privateString[]viewNames=null; //contenttypeforallviews. privateStringcontentType; //UrlBasedViewResolver的redirectContextRelative的默认值为true, //这意味着,只要重定向的资源以/开头,那么spring会帮你添加contextPath privatebooleanredirectContextRelative=true; //whetherredirectsshouldstaycompatiblewithHTTP1.0clients privatebooleanredirectHttp10Compatible=true; //thenameoftheRequestContextattributeforallviews privateStringrequestContextAttribute; privateintorder=Integer.MAX_VALUE; /**Mapofstaticattributes,keyedbyattributename(String)*/ privatefinalMap<String,Object>staticAttributes=newHashMap<String,Object>(); ... } 5.3 createView方法 publicstaticfinalStringREDIRECT_URL_PREFIX="redirect:"; protectedViewcreateView(StringviewName,Localelocale)throwsException{ //Ifthisresolverisnotsupposedtohandlethegivenview, //returnnulltopassontothenextresolverinthechain. if(!canHandle(viewName,locale)){ returnnull; } //Checkforspecial"redirect:"prefix. if(viewName.startsWith(REDIRECT_URL_PREFIX)){ StringredirectUrl=viewName.substring(REDIRECT_URL_PREFIX.length()); returnnewRedirectView(redirectUrl,isRedirectContextRelative(),isRedirectHttp10Compatible()); } //Checkforspecial"forward:"prefix. if(viewName.startsWith(FORWARD_URL_PREFIX)){ StringforwardUrl=viewName.substring(FORWARD_URL_PREFIX.length()); returnnewInternalResourceView(forwardUrl); } //Elsefallbacktosuperclassimplementation:callingloadView. returnsuper.createView(viewName,locale); } URLBasedViewResolver发现返回的视图名称包含”redirect:”前缀,于是把返回的视图名称前缀”redirect:”去掉,取后面的test.do组成一个RedirectView,RedirectView中将把请求返回的模型属性组合成查询参数的形式组合到redirect的URL后面,然后调用HttpServletResponse对象的sendRedirect方法进行重定向。同样URLBasedViewResolver还支持forword:前缀,对于视图名称中包含forword:前缀的视图名称将会被封装成一个InternalResourceView对象,然后在服务器端利用RequestDispatcher的forword方式跳转到指定的地址。使用UrlBasedViewResolver的时候必须指定属性viewClass,表示解析成哪种视图,一般使用较多的就是InternalResourceView,利用它来展现jsp,但是当我们使用JSTL的时候我们必须使用JstlView。 5.4 一段UrlBasedViewResolver的定义 <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <propertyname="prefix"value="/WEB-INF/"/> <propertyname="suffix"value=".jsp"/> <propertyname="viewClass"value="org.springframework.web.servlet.view.InternalResourceView"/> </bean> 6.InternalResourceViewResolver 内部资源视图解析器 InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。 6.1最熟悉的一段配置 <beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"> <propertyname="prefix"value="/WEB-INF/"/> <propertyname="suffix"value=".jsp"></property> </bean> 总结 ViewResolver解决的事情很单一 通过配置,根据不同策略,找出匹配的JSP(也可以是其他)。 适当添加缓存处理 根据策略不同,返回不同的VIEW,降低耦合度。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册