首页 文章 精选 留言 我的

精选列表

搜索[c 14],共10015篇文章
优秀的个人博客,低调大师

2018-08-14

AIDL 创建一个接口,再里面定义方法 package com.example.taidl; interface ICalcAIDL { int add(int x , int y); int min(int x , int y ); } build一下gen目录下会生成ICalcAIDL.java文件 /* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/dream/Downloads/android/androidProject/TAIDL/src/com/example/taidl/ICalcAIDL.aidl */ package com.example.taidl; public interface ICalcAIDL extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.example.taidl.ICalcAIDL { private static final java.lang.String DESCRIPTOR = "com.example.taidl.ICalcAIDL"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.example.taidl.ICalcAIDL interface, * generating a proxy if needed. */ public static com.example.taidl.ICalcAIDL asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.example.taidl.ICalcAIDL))) { return ((com.example.taidl.ICalcAIDL)iin); } return new com.example.taidl.ICalcAIDL.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_add: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); int _result = this.add(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); return true; } case TRANSACTION_min: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); int _result = this.min(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.example.taidl.ICalcAIDL { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public int add(int x, int y) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(x); _data.writeInt(y); mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public int min(int x, int y) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(x); _data.writeInt(y); mRemote.transact(Stub.TRANSACTION_min, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_min = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public int add(int x, int y) throws android.os.RemoteException; public int min(int x, int y) throws android.os.RemoteException; } 新建一个Service package com.example.taidl; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class CalcService extends Service{ private static final String TAG = "server"; public void onCreate() { Log.e(TAG, "onCreate"); } public IBinder onBind(Intent t) { Log.e(TAG, "onBind"); return mBinder; } public void onDestroy() { Log.e(TAG, "onDestroy"); super.onDestroy(); } public boolean onUnbind(Intent intent) { Log.e(TAG, "onUnbind"); return super.onUnbind(intent); } public void onRebind(Intent intent) { Log.e(TAG, "onRebind"); super.onRebind(intent); } private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub() { @Override public int min(int x, int y) throws RemoteException { return x + y; } @Override public int add(int x, int y) throws RemoteException { // TODO Auto-generated method stub return x - y; } }; } 创建了一个mBinder对象,并在Service的onBind方法中返回 注册: <service android:name="com.example.taidl.CalcService"> <intent-filter> <action android:name="com.example.taidl.calc" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> 我们一会会在别的应用程序中通过Intent来查找此Service;这个不需要Activity,所以我也就没写Activity,安装完成也看不到安装图标,悄悄在后台运行着。服务端编写完毕。下面开始编写客户端: package com.example.tclient; import com.example.taidl.ICalcAIDL; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { private ICalcAIDL mCalcAidl; private ServiceConnection mServiceConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.e("client", "onServiceDisconnected"); mCalcAidl = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e("client", "onServiceConnected"); mCalcAidl = ICalcAIDL.Stub.asInterface(service); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /** * 点击BindService按钮时调用 * @param view */ public void bindService(View view) { Intent intent = new Intent(); intent.setAction("com.example.taidl.calc"); bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE); } /** * 点击unBindService按钮时调用 * @param view */ public void unbindService(View view) { unbindService(mServiceConn); } /** * 点击12+12按钮时调用 * @param view */ public void addInvoked(View view) throws Exception { if (mCalcAidl != null) { int addRes = mCalcAidl.add(12, 12); Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "服务器被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT) .show(); } } /** * 点击50-12按钮时调用 * @param view */ public void minInvoked(View view) throws Exception { if (mCalcAidl != null) { int addRes = mCalcAidl.min(50, 12); Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "服务器未绑定或被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT) .show(); } } } 将服务端的aidl文件完整的复制过来,包名一定要一致。 分析AIDL生成的代码 服务端 private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub() { @Override public int add(int x, int y) throws RemoteException { return x + y; } @Override public int min(int x, int y) throws RemoteException { return x - y; } }; ICalcAILD.Stub来执行的,让我们来看看Stub这个类的声明: public static abstract class Stub extends android.os.Binder implements com.zhy.calc.aidl.ICalcAIDL 清楚的看到这个类是Binder的子类,是不是符合我们文章开通所说的服务端其实是一个Binder类的实例 接下来看它的onTransact()方法: @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_add: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); int _result = this.add(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); return true; } case TRANSACTION_min: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); int _result = this.min(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } 文章开头也说到服务端的Binder实例会根据客户端依靠Binder驱动发来的消息,执行onTransact方法,然后由其参数决定执行服务端的代码。 可以看到onTransact有四个参数 code , data ,replay , flags code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法 data客户端传递过来的参数 replay服务器返回回去的值 flags标明是否有返回值,0为有(双向),1为没有(单向) 我们仔细看case TRANSACTION_min中的代码 data.enforceInterface(DESCRIPTOR); 与客户端的writeInterfaceToken对用,标识远程服务的名称 int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); 接下来分别读取了客户端传入的两个参数 int _result = this.min(_arg0, _arg1); reply.writeNoException(); reply.writeInt(_result); 然后执行this.min,即我们实现的min方法;返回result由reply写回。 add同理,可以看到服务端通过AIDL生成Stub的类,封装了服务端本来需要写的代码。 客户端 客户端主要通过ServiceConnected与服务端连接 private ServiceConnection mServiceConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.e("client", "onServiceDisconnected"); mCalcAidl = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e("client", "onServiceConnected"); mCalcAidl = ICalcAIDL.Stub.asInterface(service); } }; 如果你比较敏锐,应该会猜到这个onServiceConnected中的IBinder实例,其实就是我们文章开通所说的Binder驱动,也是一个Binder实例 在ICalcAIDL.Stub.asInterface中最终调用了: return new com.zhy.calc.aidl.ICalcAIDL.Stub.Proxy(obj); 这个Proxy实例传入了我们的Binder驱动,并且封装了我们调用服务端的代码,文章开头说,客户端会通过Binder驱动的transact()方法调用服务端代码 直接看Proxy中的add方法 @Override public int add(int x, int y) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(x); _data.writeInt(y); mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } 首先声明两个Parcel对象,一个用于传递数据,一个用户接收返回的数据 _data.writeInterfaceToken(DESCRIPTOR);与服务器端的enforceInterfac对应 _data.writeInt(x); _data.writeInt(y);写入需要传递的参数 mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0); 终于看到了我们的transact方法,第一个对应服务端的code,_data,_repay分别对应服务端的data,reply,0表示是双向的 _reply.readException(); _result = _reply.readInt(); 最后读出我们服务端返回的数据,然后return。可以看到和服务端的onTransact基本是一行一行对应的。 我们已经通过AIDL生成的代码解释了Android Binder框架的工作原理。Service的作用其实就是为我们创建Binder驱动,即服务端与客户端连接的桥梁。

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

第 14 章 FAQ

目录 14.1. ImportError: No module named 'zlib' 14.2. UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb2 in position 679: invalid start byte 14.1.ImportError: No module named 'zlib' 问题:编译安装的python3.4.2使用中提示 ImportError: No module named 'zlib' 原因:这个原因是你没有安装zlib 解决方法:安装 zlib-devel 后重新编译安装 yum install zlib-devel ./configure --prefix=/srv/python-3.4.2 make -j8 make install 原文出处:Netkiller 系列 手札 本文作者:陈景峯 转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。

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

Spring Boot(14)——使用WebClient

使用WebClient WebClient是Spring WebFlux模块提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具,从Spring5.0开始提供。Spring Boot应用中添加如下依赖将自动添加Spring WebFlux依赖,从而可以使用WebClient。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> Spring Boot的org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration.会自动配置一个WebClient.Builder类型的bean。在需要使用WebClient的时候在程序中注入一个WebClient.Builder对象,通过对它进行自定义来生成对应的WebClient对象,从而作为客户端进行Web请求。下面是一个简单的示例。 @Service public class WebClientService { private final WebClient webClient; public WebClientService(WebClient.Builder builder) { this.webClient = builder.baseUrl("http://localhost:8081").build(); } public String getJson() { return this.webClient.get().uri("hello/json").retrieve().bodyToMono(String.class).block(); } } WebClientCustomizer Spring Boot提供了org.springframework.boot.web.reactive.function.client.WebClientCustomizer接口定义,它允许我们通过实现该接口对WebClient进行一些通用的自定义,然后将该接口的实现类定义为Spring bean。Spring Boot在创建WebClient实例时会在bean容器中寻找WebClientCustomizer类型的bean,一一调用它们的customize()方法以便对WebClient进行一些自定义。下面的代码中就对WebClient添加了一个默认的Cookie和一个默认的Header。 @Component public class MyWebClientCustomizer implements WebClientCustomizer { @Override public void customize(Builder webClientBuilder) { webClientBuilder.defaultCookie("cookieName", "cookieValue").defaultHeader("headerName", "headerValue"); } } CodecCustomizer 如果需要定义自己的编解码工具,则可以实现org.springframework.boot.web.codec.CodecCustomizer接口,把它定义为Spring bean,通过其customize()方法可以获取到org.springframework.http.codec.CodecConfigurer对象,从而可以注册新的编解码工具,或对现有的编解码工具进行替换等。 本文主要介绍在Spring Boot工程中如何应用WebClient,关于WebClient的基本用法可以参考http://elim.iteye.com/blog/2427658。 (注:本文基于Spring Boot 2.0.3所写)

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

第 14 章 ITSM 实践

目录 14.1. 组织架构 14.2. Help Desk / Service Desk 14.3. Problem Management(问题管理) 14.3.1. 故障树分析(Fault Tree Analysis,FTA) 14.3.2. 员工手册 14.4. Incident Management(突发事件管理) 14.4.1. 突发事件处理流程 14.5. Change Management(变更管理) 14.6. Release Management(发布管理) 14.7. 内部培训 14.8. IT资源管理 14.8.1. 设备采购 14.8.1.1. 招标采购流程 14.8.2. 合同管理 14.8.3. 周期性时间管理 14.8.3.1. 合同到期与续约 14.8.3.2. SSL 证书 14.8.4. IDC 设备管理 14.8.4.1. 资产管理 14.8.4.2. 图表管理 14.8.4.3. 进出IDC机房 14.8.4.4. 设备上下架 14.8.4.5. 如何维护设备 14.9. 桌面支持 14.9.1. Office 基础设施及周边设备管理 14.9.1.1. 固定资产管理 14.9.1.2. 电脑设备 14.9.1.3. 打印机设备 14.9.1.4. 电脑设备采购 14.9.1.5. 电脑升级 14.9.1.6. 报修流程 14.9.1.7. 报废流程 14.9.2. 网络用户管理 14.9.2.1. 用户分配 14.9.2.2. 邮箱分配 14.9.2.3. 权限分配 14.9.3. 网络安全保密管理 14.9.3.1. 系统杀毒 14.9.3.2. 系统帐号 14.9.4. 信息存储备份管理 14.9.4.1. 邮件备份 14.9.4.2. 图片备份 14.9.4.3. 文档备份 14.9.5. 网络操作系统管理 14.9.5.1. 域控制器 14.9.5.2. 文件存储服务器 14.9.6. 网络应用系统管理 14.9.6.1. MIS 系统 14.9.6.2. ERP 系统 14.9.6.3. OA/CRM... 系统 14.9.7. 网络机房管理 14.9.7.1. 网络拓扑图 14.9.7.2. 机柜机架 14.9.7.3. Router 14.9.7.4. Switch 14.1.组织架构 Please enable JavaScript to view the &lt;a href="http://disqus.com/?ref_noscript"&gt;comments powered by Disqus.&lt;/a&gt;comments powered by Disqus 原文出处:Netkiller 系列 手札 本文作者:陈景峯 转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。

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

Android API 中文(14) —— ViewStub

前言 关键字: android.view.ViewStub,版本为Android 2.2 r1 本章翻译来自唐明,这里本博负责整理和发布,欢迎其他译者一起参与Android API 的中文翻译行动,联系我over140@gmail.com。 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民伯伯: http://www.cnblogs.com/over140/ 正文 一、结构 public final classViewStub extendsView java.lang.Object android.view.View android.view.ViewStub 二、类概述 ViewStub 是一个隐藏的,不占用内存空间的视图对象,它可以在运行时延迟加载布局资源文件。当ViewStub可见,或者调用 inflate()函数时,才会加载这个布局资源文件。 该ViewStub在加载视图时在父容器中替换它本身。因此,ViewStub会一直存在于视图中,直到调用setVisibility(int) 或者inflate()为止。ViewStub的布局参数会随着加载的视图数一同被添加到ViewStub父容器。同样,你也可以通过使用 inflatedId属性来定义或重命名要加载的视图对象的Id值。例如: 通过"stud"id可以找到被定义的ViewStub对象。加载布局资源文件"mySubTree "后, ViewStub对象从其父容器中移除。可以通过id"subTree"找到由布局资源"mySubTree"创建的View。这个视图对象最后被指定为 宽120dip,高40dip。执行加载布局资源文件的推荐方式如下: 当inflate()被调用, 这个ViewStub被加载的视图替代并且返回这个视图对象。这使得应用程序不需要额外执行findViewById()来获取加载视图的引用。 (译者注:这个类大概意思是用ViewStub类和在XML文件里面指定的布局资源文件关联起来,让布局资源文件在需要使用的时候再加载上去。主要 作用是性能优化,什么时候用什么时候加载,不用在开始启动的时候一次加载,既可以加快程序的启动速度,又可以节省内存资源。) 三、嵌套类 接口 ViewStub.OnInflateListener 一个用于接收ViewStub已经成功加载布局资源文件的通知的监听器。 四、XML属性 属性名称 相关方法 描述 android:inflatedId setInflatedId(int) 覆盖待加载视图的id值。 android:layout setLayoutResource(int) 为待加载的资源视图提供一个标识,在ViewStub变为可见或获取焦点时使用它。(译者注:要引用的布局资源文件id) 五、构造函数 ViewStub(Context context, int layoutResource) 创建一个与指定的布局资源文件关联的ViewStub对象。 参数 layoutResource要加载的布局资源文件的id值。 六、公共方法 public void draw (Canvas canvas) 手动在指定的画布绘制这个视图(及所有其子视图)。这个视图必须在调用这个函数之前做好了整体布局。当要自己实现一个视图时,不要重载这个方法;相反,你应该重载onDraw(Canvas)方法。(译者注:主要用于自定义的视图组件的方法。) 参数 canvas 这个画布传到那个已渲染的视图对象。 public int getInflatedId () 返回加载的布局资源文件的ID,如果加载的布局资源文件的id是NO_ID,那么这个加载的View将保留它原来的id值。 相关XML属性 android:inflatedId 返回值 一个正整数来标识这个要加载的视图或者NO_ID将保持加载视图原来的id。 参见 setInflatedId(int) public int getLayoutResource () 返回加载的布局资源文件的id值。 相关XML属性 android:layout 返回值 加载到视图对象的布局资源文件id值。 参见 setLayoutResource(int) setVisibility(int) inflate() public View inflate () 加载getLayoutResource()方法标识的布局资源,并通过加载布局资源替换父容器中它自己。 返回值 这个已加载的布局资源文件. public void setInflatedId (int inflatedId) 设置加载视图的ID。如果这个id为NO_ID,这个加载视图保持它原来的id不变。 相关XML属性 android:inflatedId 参数 inflatedId 一个正整数来标识这个加载视图或者NO_ID将保持加载视图原来的id。 参见 getInflatedId() public void setLayoutResource (int layoutResource) 设置待加载的布局资源文件,当ViewStub被设置为visible或invisible或调用inflate()时使用。这个在加载布局资源文件时创建的视图用来在父容器中替换它自己。 相关XML属性 android:layout 参数 layoutResource 一个有效的布局资源文件id值(不等于0)。 参见 getLayoutResource() setVisibility(int) inflate() public void setOnInflateListener (ViewStub.OnInflateListener inflateListener) 设置成功加载布局资源文件后事件通知的监听器。 参数 inflateListener 该OnInflateListener在成功加载后得到事件通知。 参见 ViewStub.OnInflateListener public void setVisibility (int visibility) 当可见性设置为VISIBLE或INVISIBLE,inflate()将被调用,并且加载视图资源在父容器中替换ViewStub。 参数 visibility设置为VISIBLE(显示), INVISIBLE(隐藏),或 GONE(完全隐藏,不暂用布局位置). 参见 inflate() 七、受保护方法 protected void dispatchDraw (Canvas canvas) 调用这个函数去绘制这个控件的子视图。可以通过派生类重写在绘制子类之前获取控制(但是是在他自己的视图已经被绘制完之后) 参数 canvas 这个画布传到那个已渲染的视图对象。 protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) 测量这个视图以确定其内容的高度和宽度。通过measure(int, int)来调用这个方法,并且应该由子类重写以提高内容测量的效率和精确度。 约定:当该方法被重写时,你必须调用setMeasuredDimension(int, int)来存储已测量视图的高度和宽度。否则将通过measure(int, int)抛出一个IllegalStateException异常。调用父类的onMeasure(int, int)方法是一个有效的办法。 父类的实现是以背景大小为默认大小,除非MeasureSpec(测量细则)允许更大的背景。为了更好测量内容子类应该重写onMeasure(int, int)。 如果这个方法被重写,子类有责任确保测量它的高度和宽度至少是视图的最小宽度和高度(getSuggestedMinimumHeight()和getSuggestedMinimumWidth())。 参数 widthMeasureSpec 由于父类有横向空间要求,参见View.MeasureSpec。 heightMeasureSpec 由于父类有纵向空间要求,参见View.MeasureSpec。 八、下载 CSDN:http://download.csdn.net/source/2764163 九、补充 文章链接 【译】使用ViewStub(Layout Tricks: Using ViewStubs) 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/5386614.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

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

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等操作系统。

用户登录
用户注册