首页 文章 精选 留言 我的

精选列表

搜索[翻译],共9615篇文章
优秀的个人博客,低调大师

[Android]异步 layout inflation(翻译)

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5829809.html 异步 layout inflation 原文:https://medium.com/@lupajz/asynchronous-layout-inflation-7cbca2653bf#.q22vpezg4 随着最近发布的Android Support Library, revision 24,Google开发者在v4包中增加了一个用来异步inflate layouts的帮助类。 进入 AsyncLayoutInflater 你会发现AsyncLayoutInflater可以使用在当你想要去懒加载你应用中部分UI或者用户行为的响应。这个帮助类将会允许你的UI线程在执行繁重的inflate时继续保持响应。 使用AsyncLayoutInflater你需要在你应用的UI线程创建一个它的实例。 假设下面部分代码是你Activity代码中的一部分(我将在这里使用Kotlin语法): val inflater = AsyncLayoutInflater(this) 然后现在可以通过这个实例inflate你的layout文件: inflater.inflate(resId: Int, parent: ViewGroup) 如你所见,inflate函数接收3个参数。第一个是你layout资源,第二个是可选的view作为预期inflated层次结构的parent,然后第三个是一个OnInflateFinishedListener,是一个回调,一旦layout被inflate完毕它就会被回调(例子中被lambda函数代替)。 比较基本的LayoutInflater的inflate函数,一般使用一个boolean作为第三个参数,它表示是否inflate层次结构应该附属岛一个root参数上面。在我们的inflate函数的异步版本中并没有这样一个参数,大多数情况下你会使用这种方式调用: inflater.inflate(resId: Int, parent: ViewGroup) { view, resid, parent -> parent.addView(view) } 使用AsyncLayoutInflater的缺点 当然它有如下一些缺点: parent的 generateLayoutParams() 函数必须是线程安全的。 所有正在构建的views一定不能创建任何 Handlers 或者调用 Looper.myLooper 函数。 不支持设置LayoutInflater.Factory也不支持LayoutInflater.Factory2 不支持包含Fragments的inflating layouts 如果我们尝试异步的方式去inflate的layout不支持这种方式,那么inflation处理将会自动回退到主线程中。 使用Kotlin Android Extensions 的 Kotlin的小例子 MainActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) loadFirst.setOnClickListener { loadAsync(R.layout.async) { second.text = "I am second TextView" } } } } fun MainActivity.loadAsync(@LayoutRes res: Int, action: View.() -> Unit) = AsyncLayoutInflater(this).inflate(res, frame) { view, resid, parent -> with(parent) { addView(view) action(view) } } activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/frame" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.cartoon.player.MainActivity"> <TextView android:id="@+id/loadFirst" android:layout_width="match_parent" android:layout_height="48dp" android:gravity="center" android:layout_marginBottom="16dp" android:text="Load f async"/> </LinearLayout> async.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/first" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:text="1"/> <TextView android:id="@+id/second" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:text="2"/> </LinearLayout>

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

Live long and process (#LLAP) 翻译

Live long and process (#LLAP) sershe, sseth, hagleitn, 2014-08-27. Overview综述 Hive has become significantly faster thanks to various features and improvementsthat were built by the community over the past two years. Keeping themomentum, here are some examples of what we think will take us to the nextlevel: asynchronous spindle-aware IO, pre-fetching and caching of column chunks,and multi-threaded JIT-friendly operator pipelines. 得益于在过去两年里社区提交的各种特性和改进,Hive能够显著的变快。 为保持这一势头,这里有一些示例,被认为能够带领我们(将Hive)提升到下一个水平:异步主轴感知IO、预取、缓存列块、多线程运行时友好的操作管道。In order to achieve this we are proposing a hybrid execution model which consistsof a long-lived daemon replacing direct interactions with the HDFS DataNode and atightly integrated DAG-based framework. Functionality such as caching,pre-fetching, some query processing and access control will move into thedaemon. Small/short queries can be largely processed by this daemon directly,while any heavy lifting will be performed in standard YARN containers. 为了实现这些,我们提出一种混合执行模型,它由一个替代直接与HDFS DataNode交互的长期存活的守护进程、一个基于DAG紧密集成的框架组成。诸如缓存caching、预取pre-fetching、一些查询处理和访问控制将会被移动到守护进程。小的或短的查询主要被该守护进程直接处理,同时任何繁重的工作将会在标准的Yarn容器中执行。 Similar to the DataNode, LLAP daemons can be used by other applications as well,especially if a relational view on the data is preferred over file-centric processing.We’re thus planning to open the daemon up through optional APIs (e.g.:InputFormat) that can be leveraged by other data processing frameworks as abuilding block.与DataNode一样,LLAP守护进程也能够被其它应用使用,特别是优先于以文件为中心处理的数据之上关系型视图。因此我们打算通过可选的api(比如InputFormat)打开这个守护进程,可以利用其他数据处理框架作为构建块。Last, but not least, fine-grained column-level access control -- a key requirementfor mainstream adoption of Hive -- fits nicely into this model.最后但也是最重要的,细粒度的列级访问控制,Hive主流应用的一个关键需求,很好地符合这个模型。 Example of execution with #LLAP. Tez AM orchestrates overallexecution. Initial stage of query is pushed into #LLAP, largeshuffle is performed in their own containers. Multiple queriesand applications can access #LLAP concurrently.LLAP执行示例:Tez AM统筹总体执行。查询的初级阶段被推进到LLAP,较大的shuffle在它们自己的容器中执行。多种查询或应用能够在LLAP中并行执行。 Persistent daemon 持续的守护进程 To facilitate caching, JIT optimization and to eliminate most of the startup costs,we will run a daemon on the worker nodes on the cluster. The daemon will handleI/O, caching, and query fragment execution.为促进缓存、运行时优化,同时为消除大部分启动开销,我们将会在集群中的一些工作节点上运行一个守护进程。这个守护进程将会处理I/O、缓存和查询片段的执行。● These nodes will be stateless. Any request to an #LLAP node will containthe data location and metadata. It will process local and remote locations;locality will be the caller’s responsibility (YARN).这些节点将会是无状态的。任何发往LLAP节点的请求将会包含数据位置和元数据信息。它将会处理本地和远程位置,位置将是调用者的责任。 ● Recovery/resiliency. Failure and recovery is simplified because any datanode can still be used to process any fragment of the input data. The TezAM can thus simply rerun failed fragments on the cluster.恢复/弹性。故障和恢复被简化,因为任何数据节点仍然可以用于处理输入数据的任何片段。Tez AM可以简单地在集群上重新运行失败的碎片。 ● Communication between nodes. #LLAP nodes will be able to share data(e.g., fetching partitions, broadcasting fragments). This will be realizedwith the same mechanisms used today in Tez.节点间通信。LLAP节点能够共享数据(比如加载分区、广播片段等)。现在这将在使用Tez通过相同的途径实现。 Working within existing execution model 在现有的执行模型中工作 #LLAP will work within existing, process-based Hive execution to preserve thescalability and versatility of Hive. It will not replace the existing execution modelbut enhance it.LLAP能够工作在现有的基于进程的hive执行模型,以此来保护Hive的可扩展性和多功能性。它不会替代现有的执行模型,反而会提升它。 ● The daemons are optional. Hive will continue to work without them andwill also be able to bypass them even if they are deployed and operational.Feature parity with regard to language features will be maintained.守护进程是可选的。没有守护进程Hive仍将继续工作,并且即使守护进程被部署和运作,hive仍可以绕过它们。关于语言的特性仍然被保留。 ● External orchestration and execution engines. #LLAP is not anexecution engine (like MR or Tez). Overall execution will be scheduled andmonitored by existing Hive execution engine such as Tez; transparentlyover both #LLAP nodes, as well as regular containers. Obviously, #LLAPlevel of support will depend on each individual execution engine (startingwith Tez). MapReduce support is not planned, but other engines may beadded later. Other frameworks like Pig will also have the choice of using#LLAP daemons.外部协调和执行引擎。LLAP不是一个执行引擎(像MR或Tez)。总的执行将会被现有的Hive执行引擎比如Tez调度和监控。在LLAP节点和常规容器间透明。明显的,LLAP支持水平将取决于每个执行引擎(随Tez启动)。MapReduce的支持目前没有计划,但是其它引擎可能在随后添加。其它框架比如Pig等也会添加使用LLAP守护进程的选项。 ● Partial execution. The result of the work performed by an #LLAP daemoncan either form part of the result of Hive query, or be passed on to externalHive tasks, depending on the query.部分执行。LLAP守护进程执行的工作结果,即可能是Hive查询的部分结果,也可能是被传递给外部依赖查询的Hive任务。 ● Resource management. YARN will remain responsible for themanagement and allocation of resources. The YARN container delegationmodel will be used for users to transfer allocated resources to #LLAP. Toavoid the limitations of JVM memory settings, we will keep cached data, aswell as large buffers for processing (e.g., group by, joins), off-heap. Thisway, the daemon can use a small amount of memory, and additionalresources (i.e., CPU and memory) will be assigned based on workload.资源管理。Yarn仍将负责资源的管理和分配。Yarn容器代理模型将被用户用来传递被分配的资源到LLAP。为避免JVM内存设置的局限性,我们将把缓存的数据、为处理数据而设置的缓冲区(比如group by、joins等)保持在堆外内存。这种方式,守护进程能够使用少量的内存,其它附加资源(比如CPU、内存)将根据工作负载分配。 Query fragment execution 查询分片执行 For partial execution as described above, #LLAP nodes will execute “queryfragments” such as filters, projections, data transformations, partial aggregates,sorting, bucketing, hash joins/semi-joins, etc. Only Hive code and blessed UDFswill be accepted in #LLAP. No code will be localized and executed on the fly. Thisis done for stability and security reasons.对于上面提到的分片查询,LLAP节点将会执行查询的片段,比如过滤器、预测、数据转换、部分聚集、排序、分桶、哈希join、semi-joins等。仅仅是Hive代码、UDFs将会被LLAP接受。● Parallel execution. The node will allow parallel execution for multiplequery fragments from different queries and sessions.并行执行。该节点将允许不同查询和会话的多种查询片段的并行执行。 ● Interface. Users can access #LLAP nodes directly via client API. They willbe able to specify relational transformations and read data viarecord-oriented streams.接口。用户可以直接通过客户端API访问LLAP节点。它们能够列举关系转换,并且能够通过面向记录的流读取数据。 I/O 输入/输出 The daemon will off-load I/O and transformation from compressed format toseparate threads. The data will be passed on to execution as it becomes ready, sothe previous batches can be processed while the next ones are being prepared.The data will be passed to execution in a simple RLE-encoded columnar formatthat is ready for vectorized processing; this will also be the caching format, andintends to minimize copying between I/O, cache, and execution.守护进程将摆脱I/O,和从压缩格式转换到单独的线程。数据在准备好后将被传递到执行,前面的batchs被处理,同时下一组batchs也已准备好。数据将会以简单的RLE列编码格式被传递以执行,以备向量化处理。这也将会是缓存格式、打算减少I / O之间的复制、缓存和执行。 ● Multiple file formats. I/O and caching depend on some knowledge of theunderlying file format (especially if it is to be done efficiently). Therefore,similar to Vectorization work, different file formats will be supportedthrough plugins specific to each format (starting with ORC). Additionally, ageneric, less-efficient plugin may be added that supports any Hive inputformat. The plugins have to maintain metadata and transform the raw datato column chunks. 多种文件格式。I/O和缓存依赖于底层的文件格式的一些知识(特别是如果要有效地完成)。因此,类似向量化工作,不同的文件格式将通过针对每种文件格式的插件来支持(从ORC开始)。此外,一种一般的,低效的,能够支持任何Hive输入格式的插件会被添加。插件必须保持元数据,并将行数据转换成列块。 ● Predicates and bloom filters. SARGs and bloom filters will be pusheddown to storage layer, if they are supported. 谓词和布隆过滤器。如果他们支持的话,查询参数和布隆过滤器将会被下推到存储层。 Caching 缓存 The daemon will cache metadata for input files, as well as the data. The metadataand index information can be cached even for data that is not currently cached.Metadata will be stored in process in Java objects; cached data will be stored in theformat described in the I/O section, and kept off-heap (see Resourcemanagement).守护进程将会缓存输入文件的元数据、数据。元数据和索引信息甚至可以缓存当前没有缓存的数据。元数据将会存储在进程的java对象中,缓存的数据将被以I/O section格式描述形式存储,并保持在堆外,即非堆存储。● Eviction policy. The eviction policy will be tuned for analytical workloadswith frequent (partial) table-scans. Initially, a simple policy like LRFU willbe used. The policy will be pluggable.回收策略。回收策略将会根据为分析工作(而进行的)频繁的或者部分的表扫描而调整。最初,一个简单的LRU回收策略将会被使用。回收策略是可以插件化的。 ● Caching granularity. Column-chunks will be the unit of data in the cache.This achieves a compromise between low-overhead processing and storageefficiency. The granularity of the chunks depends on particular file formatand execution engine (Vectorized Row Batch size, ORC stripe, etc.).缓存粒度。缓存中数据的单位是列块。这将在低开销处理和存储效率方面实现一种平衡(妥协)。块的粒度取决于特定的文件格式和执行引擎(向量化行批处理大小、ORC stripe等)。 Workload Management 工作负载管理 YARN will be used to obtain resources for different workloads. Once resources(CPU, memory, etc) have been obtained from YARN for a specific workload, theexecution engine can choose to delegate these resources to #LLAP, or to launchHive executors in separate processes. Resource enforcement via YARN has theadvantage of ensuring that nodes do not get overloaded, either by #LLAP or byother containers. The daemons themselves will be under YARN’s control.Yarn将被用于为不同的负载获取资源。一种资源(CPU、内存等)为专门的工作负载而从Yarn获取,执行引擎可以选择将这些资源委托给LLAP,或者在分离的进程中执行Hive操作。通过Yarn获取的资源永远能够保证节点不会超负荷的优势,不管是对LLAP还是其它容器。守护进程自己也会在Yarn的控制下。 Acid 事务 #LLAP will be aware of transactions. The merging of delta files to produce acertain state of the tables will be performed before the data is placed in cache.Multiple versions are possible and the request will specify which version is to beused. This has the benefit of doing the merge async and only once for cached data,thus avoiding the hit on the operator pipeline.LLAP将会了解事务。为表产生一定状态的差异文件的合并,将会在数据被放置到缓存之前执行。可能存在多个版本,请求将指定使用哪个版本。这样做的好处是异步合并,且只有一次数据缓存,这样就避免了操作管道的热点问题。 Security 安全性 #LLAP servers are a natural place to enforce access control at a more fine-grainedlevel than “per file”. Since the daemons know which columns and records areprocessed, policies on these objects can be enforced. This is not intended toreplace the current mechanisms, but rather to enhance and open them up to otherapplications as well.LLAP服务器是一个(实现)比每个文件更细粒度水平的强制访问控制的合适的地方。由于守护进程知道哪些列和记录能够被处理,这些对象之上的策略可以被强制执行。这不是为了替代当前的机制,而是使其对其他应用程序来说更加强大和开放。

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

【翻译】split lock检测与处理

本文在解读 https://lwn.net/Articles/790464/ 的基础上,加入自己理解,与原文存在差异。 从地址不对齐访问到split lock Intel CPU微架构允许不对齐的内存访问,但ARM、RISC-V等架构却不允许。在众多的不对齐中,一个特殊的场景是:原子操作的操作数(由于地址不对齐)跨越两个cache lines,Intel将之叫做split lock。它有两个特征: 原子操作,即汇编指令包含Lock前缀; 操作数地址不对齐,还跨越两个cache lines; 其实大部分吃瓜群众都不知道这个特性,但是它却对应用性能影响极大。最近,Intel工程师Fenghua Yu同学正在开发一组内核补丁,用于检测和处理split lock,现在已经发出了第8版code review。阿里巴巴在多年前就意识到split loc

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

[翻译]高阶Python一学就会

高阶Python一学就会 在前一篇文章中,我们学习了几个一般来说比较有用的Python语言的特性。 考虑到这篇文章是前一篇文章的续集,在这里我们进一步延伸一些显式使用装饰器的概念,我们并没有扰乱前一篇文章的内容。 装饰器 装饰器的概念展现了python领域内最漂亮和最强大的设计可能性之一,这不仅仅是在Python编程中,也在整个软件设计领域。本质上来说,装饰器就是一种包装,主要是想在不改变被包装的原代码的原则下,实现延伸代码功能性的目的。为了能让这个概念更清晰易懂,我们来从最基础的内容开始。 函数亦称为第一类对象 函数简单来说就是基于给定的自变量返回一个值。在python中,这些函数还有另外一种荣誉称号,叫作第一类对象。考虑到函数可以被像普通的对象一样被作为自变量传递,函数荣膺这项称号还真的是恰如其分。比如说,它们可以被作为自变量传递给其它函数,同时也可以被用做一个函数返回值。 作为自变量的函数 def greet(name): print ('Hello ' + name) def send_greetings(fun, name): fun(name) send_greetings(greet, 'John') 闭包函数 闭包函数是定义在其它函数内部的函数。这使得:闭包函数只有在其父函数被调用时才会被定义,或者说闭包函数的作用域仅存在于父函数内部,亦或者说闭包函数只是作为父函数的一个局域变量存在的。 def send_greetings(name): def greet_message(): return ‘Hello ‘ result = greet_message() + name print (result) send_greetings(‘John’) 从函数中返回函数 Python还允许你将一个函数作为返回值传给另一个函数。本质上来讲,我们只是将内部函数的引用传回以待后续的调用。 def classify(element): def even_number(): print ('Element is even.') def odd_number(): print ('Element is odd.') if element%2 == 0: return even_number else: return odd_number classify(2)() 装饰器 现在,有了上面所有这些基本概念的经验之后,我们来这些概念串起来组成一个完整的图像。 def my_decorator(fun): def wrapper(): print (‘Before calling the function…’) fun() print (‘After calling the function…’) return wrapper def say_hello(): print (‘Hello!’) say_hello = my_decorator(say_hello) 就是这样!!! 这就是我们能得到的最简单的装饰器。我们把到前面学到的东西一个个的都用进来了。所以装饰器其实就是 一个把另一个函数作为自变量的函数,它生成了一个新的函数,同时对原先的函数扩展了功能性,它最终返回的是生成的新的函数,这样我们可以在其他地方使用它。 另外,python让编程者可以非常整洁漂亮地创建并使用装饰器。 def my_decorator(fun): def wrapper(): print (‘Before calling the function…’) fun() print (‘After calling the function…’) return wrapper @my_decorator def say_hello(): print (‘Hello!’) 上下文环境管理 简单来说吧,上下文管理是一种资源的获取和释放机制,它避免了资源泄露并确保即使在遇到一些糟糕的异常情况后仍能完成恰当的清理工作。比如说,保证文件在打开之后的关闭,锁在获得之后的释放。这个概念在大量其他编程语言中有清楚地表述和恰当地使用,比如说C++ 中的RAII。 技术上来说,它是一个对象需要去遵循的通讯协议。这个协议要求,对象要像一个上下文管理器一样,要执行 __enter__ 和 __exit__ 方法。 __enter__ 返回要被管理的资源,而 __exit__ 完成任何可能出现的清理工作并且什么也不返回。 class File: def __init__(self, name): self.name = name def __enter__(self): self.file = open(self.name, 'w') return self.file def __exit__(self, type, value, trace_back): if self.file: self.close() 现在,上面这个类可以在with语句中被安全地使用。更一般地,使用with,我们可以调用任何东西并返回一个上下文管理器。 with File('example.txt') as f: f.write('Hey hello') f.write('See you later. Bye!!!') __enter__在with语句被调用的时候被执行。当代码块的语句执行完了的时候 __exit__ 方法会被调用。 上下文管理器还可以被用在更复杂的问题中。我们看另一个上下文管理器几乎不可避免的例子。这个问题中的资源就是锁,我们可以避免的问题就是死锁。 from threading import Lock lock = Lock() def do_something(): lock.acquire() raise Exception('Oops I am sorry. I have to raise it!') lock.release() try: do_something() except: print ('Got an exception.') 注意,在释放锁之前会报异常。这会导致一个明显的副作用,那就是所有调用do_something的其它线程会永远地出现拥堵从而导致系统死锁。使用上下文管理器,我们可以避免这种尴尬的情况。 from threading import Lock lock = Lock() def do_something(): with lock: raise Exception('Oops I am sorry. I have to raise it!') try: do_something() except: print ('Got an exception.') 哇塞!看到没,即使遇到一些异常情况,代码也能恰当地完成清理工作。很明显,在任何可能的情况下都不会出现使用了上下文管理器来获得锁,而还没有释放锁就结束的情形。它就应该是这样。 连锁的异常 设想一种情况,因为除以零而使得方法抛出ZeroDivisionError的异常。显然,在python中我们有很好的一组工具能够来处理异常。然而,如果异常的原因是因为这个函数所调用的一些其它函数中出现了TypeError呢。仅仅报告最顶层的异常是不够,这样我们会丢失原始的异常信息和一连串异常的主要原因。 为了演示这个问题中的概念,我们举个简单的例子。 def chained_exceptions(): try: raise ValueError(17) except Exception as ex: raise ValueError(23) from ex if __name__ == "__main__": chained_exceptions() 在python 2.0中,上述情况会导致后面的异常被抛出而前面的会丢失,像下面这样。 Traceback (most recent call last): File “test.py”, line 3, in chained_exceptions raise ValueError(23) ValueError: 23 很明显,我们丢失了信息中有价值的那部分,因为我们丢失了异常导致的真正的起因。然而,在python3.0中运行同样的脚本,我们可以看到完整的异常栈跟踪的信息。 Traceback (most recent call last): File “test.py”, line 3, in chained_exceptions raise ValueError(17) ValueError: 17 The above exception was the direct cause of the following exception: Traceback (most recent call last): File “test.py”, line 8, in <module> chained_exceptions() File “test.py”, line 5, in chained_exceptions raise ValueError(23) from ex ValueError: 23 如果对您对本文的内容有任何的修改或者改进的意见,请在评论中让我看到。(原文链接:https://medium.com/quick-code/advanced-python-made-easy-2-d5a7ffb4e658)

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

【翻译】Awesome Asyncio 中文版

本文来自云栖社区官方钉群“Python技术进阶”,了解相关信息可以关注“Python技术进阶”。 Python Asyncio 精选资源列表,囊括了网络框架,库,软件等资源。 Awesome-asyncio是 Timo Furrer 发起并维护的 Python Asyncio 资源列表。本项目是其中文版,在这里,收集了大量的 Asyncio 的最棒、最新的资源,供大家探索 Python 异步编程世界。 Python 3.4 引入了 Asyncio 模块作为标准库,通过协程、多路 I/O 访问 Socket 和其他资源来编写单线程并发代码,并在网络客户端与服务器上运行。Asyncio 内置了对异步 I/O 的支持,其编程模型类似于消息循环,从 Asyncio 模块可以直接获取 EventLoop 引用,再把需要执行的协程放到 EventL

资源下载

更多资源
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应用均可从中受益。

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部分的功能。

用户登录
用户注册