首页 文章 精选 留言 我的

精选列表

搜索[智能问数],共10011篇文章
优秀的个人博客,低调大师

面试常问的Java Web题集

对于我们大部分人而言,在进入自己心仪的公司之前少不了准备工作,有一份全面细致面试题将帮助我们减少许多麻烦。之前给大家整理了一些Java基础方面常见的面试题,现在再整理一些JavaWeb方面常见的面试题,一方面帮助自己巩固下基础,另一方面也希望帮助想要换工作的朋友,看完之后如果你有更好的总结欢迎留言讨论分享。 01说一说selvet的生命周期 servlet 有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。 这个生存期由 javax.servlet.Servlet 接口的 init,service 和 destroy 方法表达。 Servlet 被服务器实例化后,容器运行其 init 方法,请求到达时运行其 service 方法,service 方法自动派遣运行与请求对应的 doXXX 方法(doGet,doPost)等,当服务器决定将实例 销毁的时候调用其 destroy 方法。 web 容器加载 servlet,生命周期开始。通过调用 servlet 的 init()方法进行 servlet 的初始化。通过调用 service()方法实现,根据请求的不同调用不同的do***()方法。结束服务,web 容 器调用 servlet的 destroy()方法 02 forward 和 redirect的区别 forward 是服务器请求资源,服务器直接访问目标地址的 URL,把那个 URL 的响应内容读 取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的, 所以它的地址栏中还是原来的地址。 redirect 就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来 说浏览器会用刚才请求的所有参数重新请求,所以 session,request参数都可以获取。 03 Spring MVC 整合 1.首先,要在web.xml里面配置SpringMVC的核心控制器,DispatcherServlet,对指定的后缀请求进行拦截。 2.Controller层要加@Controller注解,表明该类是MVC的控制层。 3.创建Service接口,给接口加上注解@Component或者@Service表明这是Service业务处理层 4.在Controller层声明Service变量(属性),给变量(属性)加上@Autowired注解,通过自动绑定机制将Service注入到Controller。 (注:@Autowired默认是ByType,如果想根据属性名注入,那么就再加上注解 @Resource(name="属性名")) 5.在Controller层的方法上加上注解@RequestMapping("requestAddress")表明该方法的请求地址 6.Dao层要加上注解@Repository表明这是数据库持久层 7.同样将dao实例注入到service层中。 8.配置视图解析器“InternalResourceViewResolver” 对于处理后的跳转进行统一配置 04 JSP和 Servlet有哪些相同点和不同点 JSP 是 Servlet技术的扩展,本质上是 Servlet 的简易方式,更强调应用的外表表达。JSP 编译后是"类 servlet"。Servlet 和 JSP 最主要的不同点在于,Servlet 的应用逻辑是在 Java 文件中,并且完全从表示层中的 HTML 里分离开来。而 JSP 的情况是 Java 和 HTML 可以 组合成一个扩展名为.jsp 的文件。JSP 侧重于视图,Servlet主要用于控制逻辑。 05 MVC的各个部分都有那些技术来实现 MVC 是 Model-View-Controller的简写。 Model 代表的是应用的业务逻辑(通过 JavaBean,EJB 组件实现) View 是应用的表示面(由 JSP 页面产生) Controller是提供应用的处理过程控制(一般是一个 Servlet) 通过这种设计模型把应用逻辑,处理过程和显 示逻辑分成不同的组件实现。这些组件可以进行交互和重用。 06 JSP隐视对象中四个作用域的作用范围 四个作用域从大到小的顺序为: appliaction>session>request>page application:全局作用范围,整个应用程序共享.生命周期为:应用程序启动到停止。 session:会话作用域,当用户首次访问时,产生一个新的会话,以后服务器就可以记住这个会话状态。 request:请求作用域,就是客户端的一次请求。 page:一个JSP页面。 以上作用范围使越来越小, request和page的生命周期都是短暂的 他们之间的区别就是:一个request可以包含多个page页(include,forward)。 07 项目的生命周期 1.需求分析 2.概要设计 3.详细设计(用例图,流程图,类图) 4.数据库设计(powerdesigner) 5.代码开发(编写) 6.单元测试(junit 白盒测试)(开发人员) svn版本管理工具(提交,更新代码,文档) 7.集成测试 (黑盒测试,loadrunner(编写测试脚本)(高级测试)) 8.上线试运行 (用户自己体验) 9.压力测试(loadrunner) 10.正式上线 11.维护 08 session和cookie的区别 session是存储在服务器端,cookie是存储在客户端的,所以安全来讲session的安全性要比cookie高,然后我们获取session里的信息是通过存放在会话cookie里的sessionid获取的。又由于session是存放在服务器的内存中,所以session里的东西不断增加会造成服务器的负担,所以会把很重要的信息存储在session中,而把一些次要东西存储在客户端的cookie里。 cookie确切的说分为两大类分为会话cookie和持久化cookie,会话cookie确切的说是存放在客户端浏览器的内存中,所以说他的生命周期和浏览器是一致的,浏览器关了会话cookie也就消失了,然而持久化cookie是存放在客户端硬盘中,而持久化cookie的生命周期就是我们在设置cookie时候设置的那个保存时间,然后我们考虑一问题当浏览器关闭时session会不会丢失,从上面叙述分析session的信息是通过sessionid获取的,而sessionid是存放在会话cookie当中的,当浏览器关闭的时候会话cookie消失所以我们的sessionid也就消失了,但是session的信息还存在服务器端,这时我们只是查不到所谓的session但它并不是不存在。那么,session在什么情况下丢失,就是在服务器关闭的时候,或者是sessio过期,再或者调用了invalidate()的或者是我们想要session中的某一条数据消失调用session.removeAttribute()方法,然后session在什么时候被创建呢,确切的说是通过调用session.getsession来创建,这就是session与cookie的区别。 原文发布时间为:2018-09-14 本文作者:全栈开发者社区 本文来自云栖社区合作伙伴“全栈开发者社区”,了解相关信息可以关注“全栈开发者社区”。

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

Android View事件机制21问21答

1.View的坐标参数 主要有哪些?分别有什么注意的要点? 答:Left,Right,top,Bottom 注意这4个值其实就是 view 和 他的父控件的 相对坐标值。 并非是距离屏幕左上角的绝对值,这点要注意。 此外,X和Y 其实也是相对于父控件的坐标值。 TranslationX,TranslationY 这2个值 默认都为0,是相对于父控件的左上角的偏移量。 换算关系: x=left+tranX,y=top+tranY. 很多人不理解,为什么事这样,其实就是View 如果有移动的话,比如平移这种,你们就要注意了,top和left 这种值 是不会变化的。 无论你把view怎么拖动,但是 x,y,tranX,tranY 的值是随着拖动平移 而变化的。想明白这点 就行了。 2.onTouchEvent和GestureDetector 在什么时候用哪个比较好? 答:只有滑动需求的时候 就用前者,如果有双击等这种行为的时候 就用后者。 3.Scroller 用来解决什么问题? 答:view的scrollTo和scrollBy 滑动效果太差了,是瞬间完成。而scroller可以配合view的computeScroll 来完成 渐变的滑动效果。体验更好。 4.ScrollTo和ScrollBy 有什么需要注意的? 答:前者是绝对滑动,后者是相对滑动。滑动的是view的内容 而不是view本身。这很重要。比如textview 调用这2个方法 滑动的就是显示出来的字的内容。 一般而言 我们用scrollBy会比较多一些。传值的话 其实 记住几个法则就可以了。 右-左 x为正 否则x为负 上-下 y为负,否则y为正。 可以稍微看一下 这2个的源码: publicvoidscrollTo(intx,inty){ if(mScrollX!=x||mScrollY!=y){ intoldX=mScrollX; intoldY=mScrollY; mScrollX=x; mScrollY=y; invalidateParentCaches(); onScrollChanged(mScrollX,mScrollY,oldX,oldY); if(!awakenScrollBars()){ postInvalidateOnAnimation(); } } } publicvoidscrollBy(intx,inty){ scrollTo(mScrollX+x,mScrollY+y); } 看到里面有2个变量 mScrollX 和mScrollY 这2个东西没,这2个单位的 值是像素,前者代表 view的左边缘和view内容左边缘的距离。 后者代表 view上边缘和view内容上边缘的距离。 5.使用动画来实现view的滑动 有什么后果? 答:实际上view动画 是对view的表面ui 也就是给用户呈现出的视觉效果 来做的移动,动画本身并不能移动view的真正位置。属性动画除外。动画播放结束以后,view最终还是会回到自己的位置的,。当然了你可以设置fillafter 属性 来让动画播放结束以后 view表象停留在 变化以后的位置。所以这会带来一个很严重的后果。比如你的button在屏幕的左边,你现在用个动画 并且设置了fillafter属性让他去了右边。你会发现 点击右边的button 没有click事件触发,但是点击左边的 却可以触发,原因就是右边的button 只是view的表象,真正的button 还在左边没有动过。你一定要这么做的话 可以提前在右边button移动后的位置放一个新的button,当你动画执行结束以后 把右边的enable 左边的让他gone就可以了。 这么做就可以规避上述问题。 6.让view滑动总共有几种方式,分别要注意什么?都适用于那些场景? 答:总共有三种: a:scrollto,scrollby。这种是最简单的,但是只能滑动view的内容 不可以滑动view本身。 b:动画。动画可以滑动view内容,但是注意非属性动画 就如我们问题5说的内容 会影响到交互,使用的时候要多注意。不过多数复杂的滑动效果都是属性动画来完成的,属于大杀器级别、 c:改变布局参数。这种最好理解了,无非是动态的通过java代码来修改 margin等view的参数罢了。不过用的比较少。我本人不怎么用这种方法。 7.Scroller是干嘛的?原理是什么? 答:Scroller就是用于 让view有滑动渐变效果的。用法如下: packagecom.example.administrator.motioneventtest; importandroid.content.Context; importandroid.util.AttributeSet; importandroid.widget.Scroller; importandroid.widget.TextView; /** *CreatedbyAdministratoron2016/2/2. */ publicclassCustomTextViewextendsTextView{ privateScrollermScroller; publicCustomTextView(Contextcontext){ super(context); mScroller=newScroller(context); } publicCustomTextView(Contextcontext,AttributeSetattrs){ super(context,attrs); mScroller=newScroller(context); } publicCustomTextView(Contextcontext,AttributeSetattrs,intdefStyleAttr){ super(context,attrs,defStyleAttr); mScroller=newScroller(context); } //调用此方法滚动到目标位置 publicvoidsmoothScrollTo(intfx,intfy){ intdx=fx-mScroller.getFinalX(); intdy=fy-mScroller.getFinalY(); smoothScrollBy(dx,dy); } //调用此方法设置滚动的相对偏移 publicvoidsmoothScrollBy(intdx,intdy){ //设置mScroller的滚动偏移量 mScroller.startScroll(mScroller.getFinalX(),mScroller.getFinalY(),dx,dy,4000); invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果 } //使用scroller最重要不要遗漏这个方法 @Override publicvoidcomputeScroll(){ if(mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); //这个方法不要忘记调用。 postInvalidate(); } super.computeScroll(); } } 其实上述代码 很多人应该都能搜到。我们这里主要讲一下 他的原理。 //参数很好理解前面滑动起始点中间滑动距离最后一个是渐变时间 //而且我们看到startScroll这个方法就是设置了一下参数并没有什么滑动的代码在 //回到前面的demo能看到我们通常调用完这个方法以后都会马上调用invalidate()方法 publicvoidstartScroll(intstartX,intstartY,intdx,intdy,intduration){ mMode=SCROLL_MODE; mFinished=false; mDuration=duration; mStartTime=AnimationUtils.currentAnimationTimeMillis(); mStartX=startX; mStartY=startY; mFinalX=startX+dx; mFinalY=startY+dy; mDeltaX=dx; mDeltaY=dy; mDurationReciprocal=1.0f/(float)mDuration; } //我们都知道invalidate会触发view的draw方法 //我们跟进去看会发现draw方法里会调用下面的代码: //也就是说会调用computeScroll方法而view本身这个方法 //是空的所以会留给我们自己实现 intsx=0; intsy=0; if(!drawingWithRenderNode){ computeScroll(); sx=mScrollX; sy=mScrollY; } //然后回到我们的customtextview可以看到我们实现的computeScroll方法如下: //你看在这个方法里我们调用了scrollTo方法来实现滑动,滑动结束以后再次触发view的重绘 //然后又会再次触发computeScroll实现一个循环。 publicvoidcomputeScroll(){ if(mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); //这个方法不要忘记调用。 postInvalidate(); } super.computeScroll(); } //返回true就代表滑动还没结束false就是结束了 //其实这个方法就跟属性动画里的插值器一样你在使用startScroll方法的时候会传一个事件的值, //这个方法就是根据这个事件的值来计算你每一次scrollx和scrolly的值 publicbooleancomputeScrollOffset(){ if(mFinished){ returnfalse; } inttimePassed=(int)(AnimationUtils.currentAnimationTimeMillis()-mStartTime); if(timePassed<mDuration){ switch(mMode){ caseSCROLL_MODE: finalfloatx=mInterpolator.getInterpolation(timePassed*mDurationReciprocal); mCurrX=mStartX+Math.round(x*mDeltaX); mCurrY=mStartY+Math.round(x*mDeltaY); break; caseFLING_MODE: finalfloatt=(float)timePassed/mDuration; finalintindex=(int)(NB_SAMPLES*t); floatdistanceCoef=1.f; floatvelocityCoef=0.f; if(index<NB_SAMPLES){ finalfloatt_inf=(float)index/NB_SAMPLES; finalfloatt_sup=(float)(index+1)/NB_SAMPLES; finalfloatd_inf=SPLINE_POSITION[index]; finalfloatd_sup=SPLINE_POSITION[index+1]; velocityCoef=(d_sup-d_inf)/(t_sup-t_inf); distanceCoef=d_inf+(t-t_inf)*velocityCoef; } mCurrVelocity=velocityCoef*mDistance/mDuration*1000.0f; mCurrX=mStartX+Math.round(distanceCoef*(mFinalX-mStartX)); //PintomMinX<=mCurrX<=mMaxX mCurrX=Math.min(mCurrX,mMaxX); mCurrX=Math.max(mCurrX,mMinX); mCurrY=mStartY+Math.round(distanceCoef*(mFinalY-mStartY)); //PintomMinY<=mCurrY<=mMaxY mCurrY=Math.min(mCurrY,mMaxY); mCurrY=Math.max(mCurrY,mMinY); if(mCurrX==mFinalX&&mCurrY==mFinalY){ mFinished=true; } break; } } else{ mCurrX=mFinalX; mCurrY=mFinalY; mFinished=true; } returntrue; } 8.view的滑动渐变效果总共有几种方法? 答:三种,第一种是scroller 也是使用最多的。问题7里有解释。还有一种就是动画,动画我就不多说了,不属于本文范畴。最后一种也是我们经常使用的就是用handler ,每隔一个时间间隔 来更新view的状态。 代码不写了很简单。 自行体会。 9.view的事件传递机制 如何用伪代码来表示? 答: /** *对于一个rootviewgroup来说,如果接受了一个点击事件,那么首先会调用他的dispatchTouchEvent方法。 *如果这个viewgroup的onInterceptTouchEvent返回true,那就代表要拦截这个事件。接下来这个事件就 *给viewgroup自己处理了,从而viewgroup的onTouchEvent方法就会被调用。如果如果这个viewgroup的onInterceptTouchEvent *返回false就代表我不拦截这个事件,然后就把这个事件传递给自己的子元素,然后子元素的dispatchTouchEvent *就会被调用,就是这样一个循环直到事件被处理。 * */ public booleandispatchTouchEvent(MotionEventev) { booleanconsume=false; if(onInterceptTouchEvent(ev)){ consume=onTouchEvent(ev); }else { consume=child.dispatchTouchEvent(ev); } returnconsume; } 10.view的onTouchEvent,OnClickListerner和OnTouchListener的onTouch方法 三者优先级如何? 答:onTouchListener优先级最高,如果onTouch方法返回 false ,那onTouchEvent就被调用了,返回true 就不会被调用。至于onClick 优先级最低。 11.点击事件的传递顺序如何? 答:Activity-Window-View。从上到下依次传递,当然了如果你最低的那个view onTouchEvent返回false 那就说明他不想处理 那就再往上抛,都不处理的话 最终就还是让Activity自己处理了。举个例子,pm下发一个任务给leader,leader自己不做 给架构师a,小a也不做 给程序员b,b如果做了那就结束了这个任务。 b如果发现自己搞不定,那就找a做,a要是也搞不定 就会不断向上发起请求,最终可能还是pm做。 //activity的dispatchTouchEvent方法一开始就是交给window去处理的 //win的superDispatchTouchEvent返回true那就直接结束了这个函数了。返回false就意味 //这事件没人处理,最终还是给activity的onTouchEvent自己处理这里的getwindow其实就是phonewindow publicbooleandispatchTouchEvent(MotionEventev){ if(ev.getAction()==MotionEvent.ACTION_DOWN){ onUserInteraction(); } if(getWindow().superDispatchTouchEvent(ev)){ returntrue; } returnonTouchEvent(ev); } //来看phonewindow的这个函数直接把事件传递给了mDecor @Override publicbooleansuperDispatchTouchEvent(MotionEventevent){ returnmDecor.superDispatchTouchEvent(event); } //devorview就是我们的rootview了就是那个framelayout我们的setContentView里面传递的那个layout //就是这个decorview的子view了 @Override publicfinalViewgetDecorView(){ if(mDecor==null){ installDecor(); } returnmDecor; } 12.事件分为几个步骤? 答:down事件开头,up事件结尾,中间可能会有数目不定的move事件。 13.ViewGroup如何对点击事件分发? 答: viewgroup就是在actionMasked==MotionEvent.ACTION_DOWN和mFirstTouchTarget!=null这两种情况来判断是否会进入拦截事件的流程 看代码可以知道如果是ACTION_DOWN事件那就肯定进入是否要拦截事件的流程 如果不是ACTION_DOWN事件那就要看mFirstTouchTarget!=null这个条件是否成立 这个地方有点绕但是也好理解,其实就是对于一个事件序列来说down是事件的开头所以肯定进入了这个事件是否拦截的流程也就是if括号内。 mFirstTouchTarget其实是一个单链表结构他指向的是成功处理事件的子元素。 也就是说如果有子元素成功处理了事件,那这个值就不为NULL。反过来说 只要viewgroup拦截了事件,mFirstTouchTarget就不为NULL,所以括号内就不会执行,也就侧面说明了一个结论: 某个view一旦决定拦截事件,那么这个事件所属的事件序列都只能由他来执行。并且onInterceptTouchEvent这个方法不会被调用了 finalbooleanintercepted; if(actionMasked==MotionEvent.ACTION_DOWN ||mFirstTouchTarget!=null){ finalbooleandisallowIntercept=(mGroupFlags&FLAG_DISALLOW_INTERCEPT)!=0; if(!disallowIntercept){ intercepted=onInterceptTouchEvent(ev); ev.setAction(action);//restoreactionincaseitwaschanged }else{ intercepted=false; } }else{ //Therearenotouchtargetsandthisactionisnotaninitialdown //sothisviewgroupcontinuestointercepttouches. intercepted=true; } 14.如果某个view 处理事件的时候 没有消耗down事件 会有什么结果? 答:假如一个view,在down事件来的时候 他的onTouchEvent返回false, 那么这个down事件 所属的事件序列 就是他后续的move 和up 都不会给他处理了,全部都给他的父view处理。 15.如果view 不消耗move或者up事件 会有什么结果? 答:那这个事件所属的事件序列就消失了,父view也不会处理的,最终都给activity 去处理了。 16.ViewGroup 默认拦截事件吗? 答:默认不拦截任何事件,onInterceptTouchEvent返回的是false。 17.一旦有事件传递给view,view的onTouchEvent一定会被调用吗? 答:是的,因为view 本身没有onInterceptTouchEvent方法,所以只要事件来到view这里 就一定会走onTouchEvent方法。 并且默认都是消耗掉,返回true的。除非这个view是不可点击的,所谓不可点击就是clickable和longgclikable同时为fale Button的clickable就是true 但是textview是false。 18.enable是否影响view的onTouchEvent返回值? 答:不影响,只要clickable和longClickable有一个为真,那么onTouchEvent就返回true。 19.requestDisallowInterceptTouchEvent 可以在子元素中干扰父元素的事件分发吗?如果可以,是全部都可以干扰吗? 答:肯定可以,但是down事件干扰不了。 20.dispatchTouchEvent每次都会被调用吗? 答:是的,onInterceptTouchEvent则不会。 21.滑动冲突问题如何解决 思路是什么? 答。要解决滑动冲突 其实最主要的就是有一个核心思想。你到底想在一个事件序列中,让哪个view 来响应你的滑动?比如 从上到下滑,是哪个view来处理这个事件,从左到右呢? 用业务需求 来想明白以后 剩下的 其实就很好做了。核心的方法 就是2个 外部拦截也就是父亲拦截,另外就是内部拦截,也就是子view拦截法。 学会这2种 基本上所有的滑动冲突 都是这2种的变种,而且核心代码思想都一样。 外部拦截法:思路就是重写父容器的onInterceptTouchEvent即可。子元素一般不需要管。可以很容易理解,因为这和android自身的事件处理机制 逻辑是一模一样的 @Override publicbooleanonInterceptTouchEvent(MotionEventev){ booleanintercepted=false; intx=(int)ev.getX(); inty=(int)ev.getY(); switch(ev.getAction()){ //down事件肯定不能拦截拦截了后面的就收不到了 caseMotionEvent.ACTION_DOWN: intercepted=false; break; caseMotionEvent.ACTION_MOVE: if(你的业务需求){ //如果确定拦截了就去自己的onTouchEvent里处理拦截之后的操作和效果即可了 intercepted=true; }else{ intercepted=false; } break; caseMotionEvent.ACTION_UP: //up事件我们一般都是返回false的一般父容器都不会拦截他。因为up是事件的最后一步。这里返回true也没啥意义 //唯一的意义就是因为父元素up被拦截。导致子元素收不到up事件,那子元素就肯定没有onClick事件触发了,这里的 //小细节要想明白 intercepted=false; break; default: break; } returnintercepted; } 内部拦截法:内部拦截法稍微复杂一点,就是事件到来的时候,父容器不管,让子元素自己来决定是否处理。如果消耗了 就最好,没消耗 自然就转给父容器处理了。 子元素代码: @Override publicbooleandispatchTouchEvent(MotionEventevent){ intx=(int)event.getX(); inty=(int)event.getY(); switch(event.getAction()){ caseMotionEvent.ACTION_DOWN: getParent().requestDisallowInterceptTouchEvent(true); break; caseMotionEvent.ACTION_MOVE: if(如果父容器需要这个点击事件){ getParent().requestDisallowInterceptTouchEvent(false); }//否则的话就交给自己本身view的onTouchEvent自动处理了 break; caseMotionEvent.ACTION_UP: break; default: break; } returnsuper.dispatchTouchEvent(event); } 父亲容器代码也要修改一下,其实就是保证父亲别拦截down: @Override publicbooleanonInterceptTouchEvent(MotionEventev){ if(ev.getAction()==MotionEvent.ACTION_DOWN){ returnfalse; } returntrue; } 本文作者:佚名 来源:51CTO

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

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

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

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

用户登录
用户注册