首页 文章 精选 留言 我的

精选列表

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

Cassandra概念学习系列之Cassandra是什么?

不多说,直接上干货! http://cassandra.apache.org/ Apache Cassandra是一套开源分布式NoSQL数据库系统。它最初由Facebook开发,用于储存收件箱等简单格式数据,集Google BigTable的数据模型与Amazon Dynamo的完全分布式的架构于一身。Facebook于2008将 Cassandra 开源,此后,由于Cassandra良好的可扩放性,被Digg、Twitter等知名Web 2.0网站所采纳,成为了一种流行的分布式结构化数据存储方案。 它是一个开源的、分布式、无中心、支持水平扩展、高可用的KEY-VALUE类型的NOSQL数据库。 官网文档地址是在:http://cassandra.apache.org/doc/latest/ 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/8031459.html如需转载请自行联系原作者

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

ABP架构学习系列三:手工搭建ABP框架

由于公司的项目才接触到ABP这个框架,当时就觉得高大上,什么IOC、AOP、ddd各种专业词汇让人激情 澎湃,但在使用过程中碰到了许多坑,可能也许是没有去看源码导致的,但工作确实没有那么多时间让人去慢慢研究。很久之前想手动搭建这个框架了,但是各种理由,你懂的。但是要在技术上得到大的提升就得静的下心去研究,学到大神的思想和精髓,运用到实际中去,才能去体验更开阔的天地。 本文以创建博客为思路,一步步构建整个项目,在摸索中进步,也希望能够帮助到有需要的人。 一、基础架构 第一部分主要是搭建好整个项目的骨架,连通各个项目 创建MVC5项目(ZmBlog.Web),手动引入Abp、Abp.Web、Abp.Web.Mvc、Abp.Web.Api 详情请看上一篇第一部分: http://www.cnblogs.com/xcsn/p/7941541.html 接下来,继续创建其他类库ZmBlog.Core、ZmBlog.Infrastructure、ZmBlog.Application。 引入相关nuget包,所有项目引用abp,ZmBlog.Infrastructure引用 Abp.EntityFramework,web项目引用后两个 Install-Package Abp -Version 0.8.4 Install-Package Abp.EntityFramework -Version 0.8.4 Install-Package Abp.Web.Mvc -Version 0.8.4 Install-Package Abp.Web.Api -Version 0.8.4 二、ZmBlog.Core ZmBlog.Core是DDD的核心,实体、领域服务、事件等一般都写在这里,同时也定义了仓储的接口,但实现放在基础设施层。 首先,添加类ZmBlogCoreModule,如下 namespace ZmBlog.Core { public class ZmBlogCoreModule:AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } } ZmBlogCoreModule必须依赖于AbpModule,ZmBlogCoreModule是自定义模块第一个启动的,另外,ZmBlogCoreModule启动之前,abp会先启用内部的AbpKernelModule。 AbpKernelModule类是Abp框架自己的Module,它也跟所有其他的Module一样继承自AbpModule,重写PreInitialize,Initialize,PostInitialize三个主要成员。 更详细的请参考:https://www.cnblogs.com/Azula/archive/2015/11/23/4989157.html 现在,定义一个实体文章分类Category,继承自Entity<TPrimaryKey> public class Category: Entity<string> { public Category() { Id = Guid.NewGuid().ToString(); } /// <summary> /// 类别名称 /// </summary> public string Name { get; set; } /// <summary> /// 状态(0隐藏1显示) /// </summary> public int Status { get; set; } } 以下是Entity<TPrimaryKey>的成员,其中定义了主键Id(可重写) 接着,添加一个仓储接口ICategoryRepository public interface ICategoryRepository : IRepository<Category,string>{} 另外,还可以添加领域服务ICategoryDomainService、CategoryDomainService,对于业务简单的模块,可以去掉领域服务,直接在应用层处理。 public interface ICategoryDomainService:IDomainService{} public class CategoryDomainService : DomainService, ICategoryDomainService{} 三、ZmBlog.Infrastructure 1.定义模块 创建一个模块ZmBlogDataModule,依赖模块AbpEntityFrameworkModule会自动注册了所有仓储接口 [DependsOn(typeof(ZmBlogCoreModule),typeof(AbpEntityFrameworkModule))] public class ZmBlogDataModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } 2.使用EF作为orm 使用以下命令引入包 Install-Package EntityFramework -Version 6.1.3 Install-Package Castle.Windsor -Version 3.3.0 (1)创建ZmBlogDbContext public class ZmBlogDbContext: AbpDbContext { public ZmBlogDbContext() : base("DefaultConnection") { } public ZmBlogDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } //This constructor is used in tests public ZmBlogDbContext(DbConnection connection) : base(connection, true) { } public DbSet<Category> Categorys { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); modelBuilder.Configurations.Add(new CategoryCfg());//使用独立配置 } } DefaultConnection是连接字符串名称,在web项目添加或修改如下 <connectionStrings> <add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=ZmBlogDb;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings> CategoryCfg是对实体类型的配置,如设置Id为主键 public class CategoryCfg: EntityTypeConfiguration<Category> { public CategoryCfg() { HasKey(s => s.Id); } } (2)使用codefirst模式 1.启用迁移 启用:Enable-Migrations 自动生成配置文件:Configuration.cs 2.创建迁移 add-migration AddCategory 自动生成迁移文件:201712040256502_AddCategory 3.执行迁移 update-database -vebose 自动生成数据库ZmBlogDb、迁移记录表__MigrationHistory、表Categories (3)实现仓储 基础类BaseRepository,继承实现增删改查 public abstract class BaseRepository<TEntity, TPrimaryKey> :EfRepositoryBase<ZmBlogDbContext,TEntity,TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey> { protected BaseRepository(IDbContextProvider<ZmBlogDbContext> dbContextProvider) : base(dbContextProvider) { } //add common methods for all repositories } public abstract class BaseRepository<TEntity> : BaseRepository<TEntity, string> where TEntity : class, IEntity<string> { protected BaseRepository(IDbContextProvider<ZmBlogDbContext> dbContextProvider) : base(dbContextProvider) { } //do not add any method here, add to the class above (since this inherits it) } 自定义的实现类,如下 public class CategoryRepository : BaseRepository<Category, string>, ICategoryRepository { public CategoryRepository(IDbContextProvider<ZmBlogDbContext> dbContextProvider) : base(dbContextProvider) { } } 四、ZmBlog.Application 1.添加模块 添加模块ZmBlogApplicationModule namespace ZmBlog.Application { [DependsOn(typeof(ZmBlogCoreModule), typeof(ZmBlogDataModule))] public class ZmBlogApplicationModule:AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } } 2.创建服务 在项目下添加文件夹Categories,然后添加服务接口和实现类,如 ICategoryApp public interface ICategoryApp:IApplicationService { string GetCategoryName(string id); } CategoryApp namespace ZmBlog.Application.Categories { public class CategoryApp : ApplicationService, ICategoryApp { private readonly IRepository<Category, string> _categoryRepository; public CategoryApp(IRepository<Category, string> categoryRepository) { _categoryRepository = categoryRepository; } //private readonly ICategoryRepository _categoryRepository; //public CategoryApp(ICategoryRepository categoryRepository) //{ // _categoryRepository = categoryRepository; //} public string GetCategoryName(string id) { //var categoryData = _categoryRepository.GetAll().FirstOrDefault(s=>s.Name == "硬件"); var category = new Category() { Name = "硬件" + DateTime.Now.ToString("yy-MM-dd HH:mm:ss"), Status = 1 }; _categoryRepository.Insert(category); CurrentUnitOfWork.SaveChanges(); return category.Name; } } } 五、ZmBlog.Web修改 1.增加依赖 ZmBlogWebModule是web的模块,上一篇文章创建的,增加依赖ZmBlogApplicationModule [DependsOn(typeof(AbpWebMvcModule),typeof(ZmBlogApplicationModule))] public class ZmBlogWebModule:AbpModule { //... } 2.修改控制器 public class HomeController : AbpController { private ICategoryApp _categoryApp; public HomeController(ICategoryApp categoryApp) { _categoryApp = categoryApp; } public ActionResult Index() { try { ViewBag.Name = _categoryApp.GetCategoryName(""); } catch (Exception e) { ViewBag.Name = "默认分类"; throw; } return View(); } //.....省略 3.页面修改 @{ ViewBag.Title = "Home Page"; } <div class="jumbotron"> <h1>I Like @ViewBag.Name</h1> </div> 去掉没用的,直接展示效果 六、展示 运行起来的效果 数据库 由于时间原因,一些细节没有详细讲,如有不清楚请留言 源码下载:https://github.com/jackchn/cnblogs-xcsn-source下的ZmBlogStudy.rar

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

Centos 5.8 安装KVM虚拟机学习笔记

KVM虚拟机简介 KVM(Kernel-based Virtual Machine)的简称,是一个开源的全虚拟化的解决方案。自从Linux2.6.20之后集成在Linux的各个发行版中,KVM虚拟化运行在x86架构且需要硬件(Intel VT or AMD-V)的支持,它使用Linux自身的调度器进行管理,下面是在centos5.8上面详细安装Kvm虚拟机的详细步骤。 1.查看宿主机的cpu是否支持KVM,vmx表示CPU支持Intel VT技术,svm代表CPU支持AMD-v技术。 2.安装KVM软件包,yum groupinstall KVM。 3.安装桥接管理工具,yum install bridge-utils tunctl。 4.设置桥接网卡配置文件,先备份一下原来的配置文件。 4.1编辑ifcfg-eth0文件。 4.2编辑ifcfg-br0文件。 5.安装gui管理工具,yum install virt-manager virt-viewer。 6.1查看服务器的配置是否生效,KVM安装完成后需要重启(reboot)服务器后才能被内核加载。 6.2查看桥接网卡配置是否生效。 6.3查看内核是否加载KVM模块。 7.在服务器上面安装vncserver,以便通过vncerver来安装虚拟机。 7.1VNC环境需要安装KDE或者GNOME环境,生产环境的服务器都采用最小化安装,用yum grouplist可以查看系统安装了那些组件,这里安装KDE环境。 7.2安装vnc_server,yum install vnc-server。 7.3运行vncserver 添加客户端VNC登录需要的密码。 7.4修改配置文件/root/.vnc/xstartup,startkde &表示支持KDE组件。 7.5修改vncserver 配置文件/etc/sysconfig/vncservers,添加如下两行。 7.6重启VNC服务,/etc/init.d/vncserver restart。 8.1客户端用VNC_viewer连接到服务器,在开始-System-terminal开启终端,输入virt-manager调出虚拟系统管理器新建虚拟机。 8.2KVM支持全虚拟化,选择CPU架构和KVM管理程序。 8.3选择安装介质为本地ISO文件。 8.4选择ISO文件路径,此种方法要将ISO文件上传服务器上面。 8.5选择KVM虚拟机的磁盘空间,在新建虚拟机时候自动生成.img文件,可以用qemu-img创建。 8.6选择网络为共享的物理设备,即桥接。 8.7选择创建虚拟机的内存大小和虚拟cpu数。 8.8虚拟机创建完毕,后面安装系统部分省略了,和vmware安装虚拟机完全一致。 9)系统安装完毕以后,用virsh工具开启虚拟机。 10)然后通过VNC或者SSH可以远程管理虚拟机了。 总结:1)KVM虚拟机不仅需要CPU的支持,还需要在BOIS里面开启VT选项。 2)在终端用virsh list可以查看当前正在运行的虚拟机。 3)在virsh #模式下面,可以用start 机器名开启虚拟机,用shutdown 虚拟机名关闭虚拟机。 4)创建虚拟机,virt-install --name TEST001 --ram 1024 --vcpus=2 --disk path=/data/vps/TEST001.img,size=20 --bridge=br0 --accelerate --cdrom /opt/iso/CentOS-5.8-x86_64-bin-DVD.iso --vnc --vncport=-1。 5)移除虚拟机virsh undefine TEST001。 附件:http://down.51cto.com/data/2361999 本文转自 sfzhang 51CTO博客,原文链接:http://blog.51cto.com/sfzhang88/1093720,如需转载请自行联系原作者

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

Storm概念学习系列之storm核心组件

Storm核心组件 了解 Storm 的核心组件对于理解 Storm 原理非常重要,下面介绍 Storm 的整体,然后介绍 Storm 的核心。 Storm 集群由一个主节点和多个工作节点组成。主节点运行一个名为“Nimbus”的守护进程,工作节点都运行一个名为“Supervisor”的守护进程,两者的协调工作由 ZooKeeper 来完成, ZooKeeper 用于管理集群中的不同组件。 每一个工作节点上运行的 Supervisor 监听分配给它那台机器的工作,根据需要启动 / 关闭工作进程,每一个工作进程执行一个 Topology 的一个子集;一个运行的 Topology 由运行在很多机器上的很多工作进程 Worker 组成。那么Storm 的核心就是主节点(Nimbus)、工作节点(Supervisor)、协调器(ZooKeeper)、工作进程( Worker)、任务线程(Task)。 1、主节点 Nimbus 主节点通常运行一个后台程序——Nimbus,用于响应分布在集群中的节点,分配任务和监测故障,这类似于 Hadoop 中的 JobTracker。 Nimbus 进程是快速失败( fail-fast)和无状态的,所有的状态要么在 ZooKeeper 中,要么在本地磁盘上。可以使用 kill -9 来杀死 Nimbus 进程,然后重启即可继续工作。 2、工作节点 Supervisor 工作节点同样会运行一个后台程序——Supervisor,用于收听工作指派并基于要求运行工作进程。每个工作节点都是Topology中一个子集的实现。而Nimbus 和 Supervisor 之间的协调则通过 ZooKeeper 系统。同 样,Supervisor进程也是快速失败(fail-fast)和无状态的, 所有的状态要么在ZooKeeper中,要么在本地磁盘上,用kill -9来杀死Supervisor进程,然后重启就可以继续工作。 3、协调服务组件 ZooKeeper ZooKeeper 是完成 Nimbus 和 Supervisor 之间协调的服务。 Storm使用ZooKeeper 协调集群,由于ZooKeeper 并不用于消息传递,所以Storm给ZooKeeper 带来的压力相当低。在大多数情况下,单个节点的 ZooKeeper 集群足够胜任,不过为了确保故障恢复或者部署大规模Storm集群,可能需要更大规模的 ZooKeeper 集群。 Nimbus、 Supervisor 与 ZooKeeper 的关系如图 1 所示。 图 1 Nimbus、 Supervisor 与 ZooKeeper 关系图 4、其他核心组件 Storm 的组件不止上面的,还有一些组件也是 Storm 的核心,缺一不可。下面简单介绍Worker 和 Task。 1)具体处理事务进程 Worker:运行具体处理组件逻辑的进程。 2)具体处理线程 Task:Worker 中的每一个 Spout/Bolt 线程称为一个 Task。在 Storm 0.8之后,Task 不再与物理线程对应,同一个 Spout/Bolt 的 Task 可能会共享一个物理线程,该线程称为 Executor。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5989256.html,如需转载请自行联系原作者

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

【Android进阶学习】shape和selector的结合使用

shape和selector是Android UI设计中经常用到的,比如我们要自定义一个圆角Button,点击Button有些效果的变化,就要用到shape和selector。可以这样说,shape和selector在美化控件中的作用是至关重要的。 1.Shape 简介 作用:XML中定义的几何形状 位置:res/drawable/文件的名称.xml 使用的方法: Java代码中:R.drawable.文件的名称 XML中:android:background="@drawable/文件的名称" 属性: <shape>android:shape=["rectangle" | "oval" | "line" | "ring"] 其中rectagle矩形,oval椭圆,line水平直线,ring环形 <shape>中子节点的常用属性: <gradient> 渐变 android:startColor 起始颜色 android:endColor 结束颜色 android:angle 渐变角度,0从上到下,90表示从左到右,数值为45的整数倍默认为0; android:type 渐变的样式 liner线性渐变 radial环形渐变 sweep <solid > 填充 android:color 填充的颜色 <stroke > 描边 android:width 描边的宽度 android:color 描边的颜色 android:dashWidth 表示'-'横线的宽度 android:dashGap 表示'-'横线之间的距离 <corners> 圆角 android:radius 圆角的半径 值越大角越圆 android:topRightRadius 右上圆角半径 android:bottomLeftRadius 右下圆角角半径 android:topLeftRadius 左上圆角半径 android:bottomRightRadius 左下圆角半径 2.Selector 简介 位置:res/drawable/文件的名称.xml 使用的方法: Java代码中:R.drawable.文件的名称 XML中:android:background="@drawable/文件的名称" <?xmlversion="1.0"encoding="utf-8"?> <selectorxmlns:android="http://schemas.android.com/apk/res/android"> <!--默认时的背景图片--> <itemandroid:drawable="@drawable/pic1"/> <!--没有焦点时的背景图片--> <item android:state_window_focused="false" android:drawable="@drawable/pic_blue" /> <!--非触摸模式下获得焦点并单击时的背景图片--> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/pic_red" /> <!--触摸模式下单击时的背景图片--> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pic_pink" /> <!--选中时的图片背景--> <item android:state_selected="true" android:drawable="@drawable/pic_orange" /> <!--获得焦点时的图片背景--> <item android:state_focused="true" android:drawable="@drawable/pic_green" /> </selector> 第一个例子:圆角的Button http://liangruijun.blog.51cto.com/3061169/630051 第二个例子:shape+selector综合使用的例子 漂亮的ListView 先看看这个例子的结构: selector.xml <?xmlversion="1.0"encoding="utf-8"?> <selectorxmlns:android="http://schemas.android.com/apk/res/android"> <itemandroid:state_selected="true"> <shape> <gradientandroid:angle="270"android:endColor="#99BD4C" android:startColor="#A5D245"/> <sizeandroid:height="60dp"android:width="320dp"/> <cornersandroid:radius="8dp"/> </shape> </item> <itemandroid:state_pressed="true"> <shape> <gradientandroid:angle="270"android:endColor="#99BD4C" android:startColor="#A5D245"/> <sizeandroid:height="60dp"android:width="320dp"/> <cornersandroid:radius="8dp"/> </shape> </item> <item> <shape> <gradientandroid:angle="270"android:endColor="#A8C3B0" android:startColor="#C6CFCE"/> <sizeandroid:height="60dp"android:width="320dp"/> <cornersandroid:radius="8dp"/> </shape> </item> </selector> list_item.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/selector" > <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="20dp" /> <TextView android:text="data" android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:textSize="14sp" android:textStyle="bold" android:textColor="@color/black" > </TextView> </LinearLayout> main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#253853" > <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#00000000" android:divider="#2A4562" android:dividerHeight="3px" android:listSelector="#264365" android:drawSelectorOnTop="false" > </ListView> </LinearLayout> colors.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <colorname="white">#FFFFFFFF</color> <colorname="transparency">#00000000</color> <colorname="title_bg">#1C86EE</color> <colorname="end_color">#A0cfef83</color> <colorname="black">#464646</color> </resources> MainActivity.xml packagecom.lingdududu.customlist; importjava.util.ArrayList; importjava.util.HashMap; importxb.customlist.R; importandroid.R.array; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.ArrayAdapter; importandroid.widget.ListView; importandroid.widget.SimpleAdapter; publicclassMainActivityextendsActivity{ ListViewlist; Stringdata[]=newString[]{ "China","UK","USA","Japan","German","Canada","ET","Narotu" }; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); list=(ListView)findViewById(R.id.list); SimpleAdapteradapter=newSimpleAdapter(this,getData(),R.layout.list_item, newString[]{"title","img"},newint[]{R.id.title,R.id.img}); list.setAdapter(adapter); } privateArrayList<HashMap<String,Object>>getData(){ ArrayList<HashMap<String,Object>>dlist=newArrayList<HashMap<String,Object>>(); for(inti=0;i<data.length;i++){ HashMap<String,Object>map=newHashMap<String,Object>(); map.put("title",data[i]); map.put("img",R.drawable.item_left2); dlist.add(map); } returndlist; } } 效果图: 上面的例子中用到很多关于颜色RGB的参数,对RGB不熟悉的,可以参照我博客的一篇文章 http://liangruijun.blog.51cto.com/3061169/629276 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/732310

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

Android开发学习笔记:数据存取之SQLite浅析

一.SQLite的介绍 1.SQLite简介 SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入 式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持 Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl、PHP、Java、C++、.Net等,还有ODBC接口,同样比起 Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。 2.SQLite的特点: 轻量级 SQLite和C/S模式的数据库软件不同,它是进程内的数据库引擎,因此不存在数据库的客户端和服务器。使用SQLite一般只需要带上它的一个动态 库,就可以享受它的全部功能。而且那个动态库的尺寸也挺小,以版本3.6.11为例,Windows下487KB、Linux下347KB。 不需要"安装" SQLite的核心引擎本身不依赖第三方的软件,使用它也不需要"安装"。有点类似那种绿色软件。 单一文件 数据库中所有的信息(比如表、视图等)都包含在一个文件内。这个文件可以自由复制到其它目录或其它机器上。 跨平台/可移植性 除了主流操作系统 windows,linux之后,SQLite还支持其它一些不常用的操作系统。 弱类型的字段 同一列中的数据可以是不同类型 开源 这个相信大家都懂的! 3.SQLite数据类型 一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断。SQLite具有以下五种常用的数据类型: NULL: 这个值为空值 VARCHAR(n):长度不固定且其最大长度为 n 的字串,n不能超过 4000。 CHAR(n):长度固定为n的字串,n不能超过 254。 INTEGER: 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8. REAL: 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号. TEXT: 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE). BLOB: 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式。 DATA :包含了 年份、月份、日期。 TIME:包含了 小时、分钟、秒。 相信学过数据库的童鞋对这些数据类型都不陌生的!!!!!!!!!! 二.SQLiteDatabase的介绍 Android提供了创建和是用SQLite数据库的API。SQLiteDatabase代表一个数据库对象,提供了操作数据库的一些方法。在Android的SDK目录下有sqlite3工具,我们可以利用它创建数据库、创建表和执行一些SQL语句。下面是SQLiteDatabase的常用方法。 SQLiteDatabase的常用方法 方法名称 方法描述 openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory) 打开或创建数据库 insert(String table,String nullColumnHack,ContentValues values) 添加一条记录 delete(String table,String whereClause,String[] whereArgs) 删除一条记录 query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy) 查询一条记录 update(String table,ContentValues values,String whereClause,String[] whereArgs) 修改记录 execSQL(String sql) 执行一条SQL语句 close() 关闭数据库 1、打开或者创建数据库 在Android 中以使用SQLiteDatabase的静态方法openOrCreateDatabase(String path,SQLiteDatabae.CursorFactory factory)打开或者创建一个数据库。它会自动去检测是否存在这个数据库,如果存在则打开,不存在则创建一个数据库;创建成功则返回一个SQLiteDatabase对象,否则抛出异常FileNotFoundException。 下面是创建名为“stu.db”数据库的代码: db=SQLiteDatabase.openOrCreateDatabase("/data/data/com.lingdududu.db/databases/stu.db",null); 2、创建表 创建一张表很简单。首先,编写创建表的SQL语句,然后,调用SQLiteDatabase的execSQL()方法来执行SQL语句便可以创建一张表了。 下面的代码创建了一张用户表,属性列为:_id(主键并且自动增加)、sname(学生姓名)、snumber(学号) privatevoidcreateTable(SQLiteDatabasedb){ //创建表SQL语句 Stringstu_table="createtableusertable(_idintegerprimarykeyautoincrement,snametext,snumbertext)"; //执行SQL语句 db.execSQL(stu_table); } 3、插入数据 插入数据有两种方法: ①SQLiteDatabase的insert(String table,String nullColumnHack,ContentValues values)方法,参数一是表名称,参数二是空列的默认值,参数三是ContentValues类型的一个封装了列名称和列值的Map; ②编写插入数据的SQL语句,直接调用SQLiteDatabase的execSQL()方法来执行 第一种方法的代码: privatevoidinsert(SQLiteDatabasedb){ //实例化常量值 ContentValuescValue=newContentValues(); //添加用户名 cValue.put("sname","xiaoming"); //添加密码 cValue.put("snumber","01005"); //调用insert()方法插入数据 db.insert("stu_table",null,cValue); } 第二种方法的代码: privatevoidinsert(SQLiteDatabasedb){ //插入数据SQL语句 Stringstu_sql="insertintostu_table(sname,snumber)values('xiaoming','01005')"; //执行SQL语句 db.execSQL(sql); } 4、删除数据 删除数据也有两种方法: ①调用SQLiteDatabase的delete(String table,String whereClause,String[] whereArgs)方法,参数一是表名称,参数二是删除条件,参数三是删除条件值数组; ②编写删除SQL语句,调用SQLiteDatabase的execSQL()方法来执行删除。 第一种方法的代码: privatevoiddelete(SQLiteDatabasedb){ //删除条件 StringwhereClause="_id=?"; //删除条件参数 String[]whereArgs={String.valueOf(2)}; //执行删除 db.delete("stu_table",whereClause,whereArgs); } 第二种方法的代码: privatevoiddelete(SQLiteDatabasedb){ //删除SQL语句 Stringsql="deletefromstu_tablewhere_id=6"; //执行SQL语句 db.execSQL(sql); } 5、修改数据 修改数据有两种方法: ①调用SQLiteDatabase的update(String table,ContentValues values,String whereClause, String[] whereArgs)方法。参数是表名称,参数是更行列ContentValues类型的键值对(Map),参数是更新条件(where字句),参数是更新条件数组。 ②编写更新的SQL语句,调用SQLiteDatabase的execSQL执行更新。 第一种方法的代码: privatevoidupdate(SQLiteDatabasedb){ //实例化内容值 ContentValuesvalues=newContentValues(); //在values中添加内容 values.put("snumber","101003"); //修改条件 StringwhereClause="id=?"; //修改添加参数 String[]whereArgs={String.valuesOf(1)}; //修改 db.update("usertable",values,whereClause,whereArgs); } 第二种方法的代码: privatevoidupdate(SQLiteDatabasedb){ //修改SQL语句 Stringsql="updatestu_tablesetsnumber=654321whereid=1"; //执行SQL db.execSQL(sql); } 6、查询数据 在Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下: public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit); 各个参数的意义说明: ①table:表名称 ②columns:列名称数组 ③selection:条件字句,相当于where ④selectionArgs:条件字句,参数数组 ⑤groupBy:分组列 ⑥having:分组条件 ⑦orderBy:排序列 ⑧limit:分页查询限制 ⑨Cursor:返回值,相当于结果集ResultSet Cursor是一个游标接口,提供了遍历查询结果的方法,如移动指针方法move(),获得列值方法getString()等. Cursor游标常用方法 方法名称 方法描述 getCount() 获得总的数据项数 isFirst() 判断是否第一条记录 isLast() 判断是否最后一条记录 moveToFirst() 移动到第一条记录 moveToLast() 移动到最后一条记录 move(int offset) 移动到指定记录 moveToNext() 移动到下一条记录 moveToPrevious() 移动到上一条记录 getColumnIndexOrThrow(String columnName) 根据列名称获得列索引 getInt(int columnIndex) 获得指定列索引的int类型值 getString(int columnIndex) 获得指定列缩影的String类型值 下面就是用Cursor来查询数据库中的数据,具体代码如下: privatevoidquery(SQLiteDatabasedb) { //查询获得游标 Cursorcursor=db.query("usertable",null,null,null,null,null,null); //判断游标是否为空 if(cursor.moveToFirst(){ //遍历游标 for(inti=0;i<cursor.getCount();i++){ cursor.move(i); //获得ID intid=cursor.getInt(0); //获得用户名 Stringusername=cursor.getString(1); //获得密码 Stringpassword=cursor.getString(2); //输出用户信息 System.out.println(id+":"+sname+":"+snumber); } } } 7、删除指定表 编写插入数据的SQL语句,直接调用SQLiteDatabase的execSQL()方法来执行 privatevoiddrop(SQLiteDatabasedb){ //删除表的SQL语句 Stringsql="DROPTABLEstu_table"; //执行SQL db.execSQL(sql); } 三.SQLiteOpenHelper 该类是SQLiteDatabase一个辅助类。这个类主要生成一 个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法getWritableDatabase()或者 getReadableDatabase()方法的时候,如果当时没有数据,那么Android系统就会自动生成一个数据库。 SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里面的3个函数: 1.onCreate(SQLiteDatabase) 在数据库第一次生成的时候会调用这个方法,也就是说,只有在创建数据库的时候才会调用,当然也有一些其它的情况,一般我们在这个方法里边生成数据库表。 2. onUpgrade(SQLiteDatabase,int,int) 当数据库需要升级的时候,Android系统会主动的调用这个方法。一般我们在这个方法里边删除数据表,并建立新的数据表,当然是否还需要做其他的操作,完全取决于应用的需求。 3. onOpen(SQLiteDatabase): 这是当打开数据库时的回调函数,一般在程序中不是很常使用。 写了这么多,改改用实际例子来说明上面的内容了。下面这个操作数据库的实例实现了创建数据库,创建表以及数据库的增删改查的操作。 SQLiteActivity.java packagecom.lingdududu.testSQLite; importcom.lingdududu.testSQLiteDb.StuDBHelper; importandroid.app.Activity; importandroid.content.ContentValues; importandroid.database.Cursor; importandroid.database.sqlite.SQLiteDatabase; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; /* *@authorlingdududu */ publicclassSQLiteActivityextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ //声明各个按钮 privateButtoncreateBtn; privateButtoninsertBtn; privateButtonupdateBtn; privateButtonqueryBtn; privateButtondeleteBtn; privateButtonModifyBtn; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //调用creatView方法 creatView(); //setListener方法 setListener(); } //通过findViewById获得Button对象的方法 privatevoidcreatView(){ createBtn=(Button)findViewById(R.id.createDatabase); updateBtn=(Button)findViewById(R.id.updateDatabase); insertBtn=(Button)findViewById(R.id.insert); ModifyBtn=(Button)findViewById(R.id.update); queryBtn=(Button)findViewById(R.id.query); deleteBtn=(Button)findViewById(R.id.delete); } //为按钮注册监听的方法 privatevoidsetListener(){ createBtn.setOnClickListener(newCreateListener()); updateBtn.setOnClickListener(newUpdateListener()); insertBtn.setOnClickListener(newInsertListener()); ModifyBtn.setOnClickListener(newModifyListener()); queryBtn.setOnClickListener(newQueryListener()); deleteBtn.setOnClickListener(newDeleteListener()); } //创建数据库的方法 classCreateListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ //创建StuDBHelper对象 StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可读的SQLiteDatabase对象 SQLiteDatabasedb=dbHelper.getReadableDatabase(); } } //更新数据库的方法 classUpdateListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ //数据库版本的更新,由原来的1变为2 StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,2); SQLiteDatabasedb=dbHelper.getReadableDatabase(); } } //插入数据的方法 classInsertListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getWritableDatabase(); //生成ContentValues对象//key:列名,value:想插入的值 ContentValuescv=newContentValues(); //往ContentValues对象存放数据,键-值对模式 cv.put("id",1); cv.put("sname","xiaoming"); cv.put("sage",21); cv.put("ssex","male"); //调用insert方法,将数据插入数据库 db.insert("stu_table",null,cv); //关闭数据库 db.close(); } } //查询数据的方法 classQueryListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getReadableDatabase(); //参数1:表名 //参数2:要想显示的列 //参数3:where子句 //参数4:where子句对应的条件值 //参数5:分组方式 //参数6:having条件 //参数7:排序方式 Cursorcursor=db.query("stu_table",newString[]{"id","sname","sage","ssex"},"id=?",newString[]{"1"},null,null,null); while(cursor.moveToNext()){ Stringname=cursor.getString(cursor.getColumnIndex("sname")); Stringage=cursor.getString(cursor.getColumnIndex("sage")); Stringsex=cursor.getString(cursor.getColumnIndex("ssex")); System.out.println("query------->"+"姓名:"+name+""+"年龄:"+age+""+"性别:"+sex); } //关闭数据库 db.close(); } } //修改数据的方法 classModifyListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getWritableDatabase(); ContentValuescv=newContentValues(); cv.put("sage","23"); //where子句"?"是占位符号,对应后面的"1", StringwhereClause="id=?"; String[]whereArgs={String.valueOf(1)}; //参数1是要更新的表名 //参数2是一个ContentValeus对象 //参数3是where子句 db.update("stu_table",cv,whereClause,whereArgs); } } //删除数据的方法 classDeleteListenerimplementsOnClickListener{ @Override publicvoidonClick(Viewv){ StuDBHelperdbHelper=newStuDBHelper(SQLiteActivity.this,"stu_db",null,1); //得到一个可写的数据库 SQLiteDatabasedb=dbHelper.getReadableDatabase(); StringwhereClauses="id=?"; String[]whereArgs={String.valueOf(2)}; //调用delete方法,删除数据 db.delete("stu_table",whereClauses,whereArgs); } } } StuDBHelper.java packagecom.lingdududu.testSQLiteDb; importandroid.content.Context; importandroid.database.sqlite.SQLiteDatabase; importandroid.database.sqlite.SQLiteDatabase.CursorFactory; importandroid.database.sqlite.SQLiteOpenHelper; importandroid.util.Log; publicclassStuDBHelperextendsSQLiteOpenHelper{ privatestaticfinalStringTAG="TestSQLite"; publicstaticfinalintVERSION=1; //必须要有构造函数 publicStuDBHelper(Contextcontext,Stringname,CursorFactoryfactory, intversion){ super(context,name,factory,version); } //当第一次创建数据库的时候,调用该方法 publicvoidonCreate(SQLiteDatabasedb){ Stringsql="createtablestu_table(idint,snamevarchar(20),sageint,ssexvarchar(10))"; //输出创建数据库的日志信息 Log.i(TAG,"createDatabase------------->"); //execSQL函数用于执行SQL语句 db.execSQL(sql); } //当更新数据库的时候执行该方法 publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){ //输出更新数据库的日志信息 Log.i(TAG,"updateDatabase------------->"); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/createDatabase" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="创建数据库" /> <Button android:id="@+id/updateDatabase" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="更新数据库" /> <Button android:id="@+id/insert" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="插入数据" /> <Button android:id="@+id/update" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="更新数据" /> <Button android:id="@+id/query" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="查询数据" /> <Button android:id="@+id/delete" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="删除数据" /> </LinearLayout> 程序运行的效果图: 当点击创建数据库按钮: LogCat窗口输出的信息为: 当点击更新数据库按钮: LogCat窗口输出的信息为: 当点击查询数据库按钮: LogCat窗口输出的信息为: 使用adb命令查看数据库: 1.在命令行窗口输入adb shell回车,就进入了Linux命令行,现在就可以使用Linux的命令了。 2.ls回车,显示所有的东西,其中有个data。(ls:显示所有,cd:进入) 3.cd data回车,再ls回车,cd data回车,ls回车后就会看到很多的com.。。。,那就是系统上的应用程序包名,找到你数据库程序的包名,然后进入。 4.进去后在查看所有,会看到有databases,进入databases,显示所有就会发现你的数据库名字,这里使用的是"stu_db"。 5.sqlite3 stu_db回车就进入了你的数据库了,然后“.schema”就会看到该应用程序的所有表及建表语句。 6.之后就可以使用标准的SQL语句查看刚才生成的数据库及对数据执行增删改查了。 #sqlite3 stu_dbsqlite3 stu_dbSQLite version 3.6.22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite>.schema.schema CREATE TABLE android_metadata (locale TEXT); CREATE TABLEstu_table(id int,sname varchar(20),sage int,ssex varchar(10));--->创建的表 sqlite>select * from stu_table; select * from stu_table; 1|xiaoming|21|male sqlite> 插入数据 sqlite>insert into stu_table values(2,'xiaohong',20,'female'); 插入的数据记得要和表中的属性一一对应 insert into stu_table values(2,'xiaohong',20,'female'); sqlite> select * from stu_table; select * from stu_table; 1|xiaoming|21|male 2|xiaohong|20|female--------------> 插入的数据sqlite> 当点击修改数据的按钮时候 sqlite> select * from stu_table; select * from stu_table; 1|xiaoming|23|male-------------->年龄被修改为232|xiaohong|20|female sqlite> 当点击删除数据的按钮 sqlite> select * from stu_table; select * from stu_table; 1|xiaoming|23|maleid=2的数据已经被删除 总之,我们可以在代码中执行数据库的增删改查,也可以在adb命令行下实现。不过因为SQLite没有客户端,不能直接的查看数据库变化后的信息,所以常用adb命令行查看数据库改变后的信息。 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/663686

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

Android开发学习笔记:BroadcastReceiver简介和注册方式

一.BroadcastReceiver简介 BraodcastReceiver(广播接收器)是为了实现系统广播而提供的一种组件,它和事件处理机制类似,但是事件处理机制是程序组件级别的,而广播事件处理机制是系统级别的。比如,我们可以发出一种广播来测试手机电量的变化,这时候就可以定义一个BraodcastReceiver来接受广播,当手机电量较低时提示用户。我们既可以用Intent来启动一个组件,也可以用sendBroadcast()方法发起一个系统级别的事件广播来传递消息。我们同样可以在自己的应用程序中实现BroadcastReceiver来监听和响应广播的Intent。 在程序中使用BraodcastReceiver是比较简单的。首先要定义一个类继承BraodcastReceiver,并且覆盖onReceiver()方法来响应事件。然后注册在程序中BraodcastReceiver。最后构建Intent对象调用sendBroadcast()方法将广播发出。 二.BroadcastReceiver的注册方式 1.静态注册方式 静态注册方式是在AndroidManifest.xml的application里面定义receiver并设置要接收的action。静态注册方式的特点:不管改应用程序是否处于活动状态,都会进行监听,比如某个程序时监听 下面是具体的例子: MainActivity.java packagecom.android.broadcast; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ //定义action常量 protectedstaticfinalStringACTION="com.android.broadcast.RECEIVER_ACTION"; //定义Button对象 privateButtonbtnBroadcast; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btnBroadcast=(Button)findViewById(R.id.btnBroadcast); //为按钮设置单击监听器 btnBroadcast.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //实例化Intent Intentintent=newIntent(); //设置Intent的action属性 intent.setAction(ACTION); //发出广播 sendBroadcast(intent); } }); } } 在“com.android.broadcast”包中定义一个MyReceiver类,继承于BroadcastReceiver,覆盖onReceive()方法。 MyReceiver.java packagecom.android.broadcast; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.util.Log; publicclassMyReceiverextendsBroadcastReceiver{ //定义日志标签 privatestaticfinalStringTAG="Test"; @Override publicvoidonReceive(Contextcontext,Intentintent){ //输出日志信息 Log.i(TAG,"MyReceiveronReceive--->"); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/btnBroadcast" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送Broadcast" /> </LinearLayout> 在AndroidManifest.xml配置文件中16~20行声明receiver <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.broadcast" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <receiverandroid:name="MyReceiver"> <intent-filter> <actionandroid:name="com.android.broadcast.RECEIVER_ACTION"/> </intent-filter> </receiver> </application> </manifest> 效果图: 当我们点击按钮的时候,程序会调用onReceive()方法,LogCat输出信息如下: 2.动态注册方式 动态注册方式在activity里面调用函数来注册,和静态的内容差不多。一个形参是receiver,另一个是IntentFilter,其中里面是要接收的action。动态注册方式特点:在代码中进行注册后,当应用程序关闭后,就不再进行监听。 下面是具体的例子: MainActivity.java packagecom.android.broadcast; importandroid.app.Activity; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ //定义Action常量 protectedstaticfinalStringACTION="com.android.broadcast.RECEIVER_ACTION"; privateButtonbtnBroadcast; privateButtonregisterReceiver; privateButtonunregisterReceiver; privateMyReceiverreceiver; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btnBroadcast=(Button)findViewById(R.id.btnBroadcast); //创建事件监听器 btnBroadcast.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ Intentintent=newIntent(); intent.setAction(ACTION); sendBroadcast(intent); } }); registerReceiver=(Button)findViewById(R.id.btnregisterReceiver); //创建事件监听器 registerReceiver.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ receiver=newMyReceiver(); IntentFilterfilter=newIntentFilter(); filter.addAction(ACTION); //动态注册BroadcastReceiver registerReceiver(receiver,filter); } }); unregisterReceiver=(Button)findViewById(R.id.btnunregisterReceiver); //创建事件监听器 unregisterReceiver.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ //注销BroadcastReceiver unregisterReceiver(receiver); } }); } } 在“com.android.broadcast”包中定义一个MyReceiver类,继承于BroadcastReceiver,覆盖onReceive()方法。 MyReceiver.java packagecom.android.broadcast; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.util.Log; publicclassMyReceiverextendsBroadcastReceiver{ //定义日志标签 privatestaticfinalStringTAG="Test"; @Override publicvoidonReceive(Contextcontext,Intentintent){ //输出日志信息 Log.i(TAG,"MyReceiveronReceive--->"); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/btnBroadcast" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送广播" /> <Button android:id="@+id/btnregisterReceiver" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注册广播接收器" /> <Button android:id="@+id/btnunregisterReceiver" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注销广播接听器" /> </LinearLayout> 效果图: ①当我们首先点击按钮的时候,因为程序没有注册BraodcastReceiver,所以LogCat没有输出任何信息。 ②当我们先点击再点击按钮的时候,这时程序会动态的注册BraodcastReceiver,之后会调用onReceive()方法,LogCat输出信息如下: ③当我们点击按钮的时候,这时程序会注销BraodcastReceiver,再点击,LogCat没有输出任何信息。 三.BroadcastReceiver的生命周期 一个BroadcastReceiver 对象只有在被调用onReceive(Context, Intent)的才有效的,当从该函数返回后,该对象就无效的了,结束生命周期。 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/655885

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

Android开发学习笔记:浅谈Tab选项卡

Tab选项卡是一个非常方便的组件。 一.使用Tab组件的步骤: 1.在布局文件中使用FrameLayout列出Tab组件以及Tab中的内容组件 2.Activity要继承TabActivity 3.调用TabActivity的getTabHost( )方法来获得TabHost对象 4.通过TabHost创建Tab选项 二.实现不同Tab里面的内容有两种方式: 1.切换不同的Tab时候,不同Tab里面的内容在同一个Activity显示,主要是通过修改布局文件里面的id来实现的。下面是一个具体的例子: MainActivity.java packagecom.android.tab.activity; importandroid.app.TabActivity; importandroid.os.Bundle; importandroid.view.LayoutInflater; importandroid.widget.TabHost; publicclassMainActivityextendsTabActivity{ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //获得TabHost对象 TabHosttah=getTabHost(); //from(this)从TabActivity获取LayoutInflater //R.layout.main存放Tab布局 //通过TabHost获得存放Tab标签页内容的FrameLayout //是否将inflate加到根布局元素上 LayoutInflater.from(this).inflate(R.layout.main,tah.getTabContentView(),true); //设置Tab标签的内容和显示内容 tah.addTab(tah.newTabSpec("tab1").setIndicator("图片1").setContent(R.id.TextView01)); tah.addTab(tah.newTabSpec("tab2").setIndicator("图片2").setContent(R.id.TextView02)); tah.addTab(tah.newTabSpec("tab3").setIndicator("图片3").setContent(R.id.TextView03)); } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/FrameLayout01" android:layout_width="wrap_content" android:layout_height="wrap_content" > <TabHost android:id="@+id/TabHost01" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/TextView01" android:background="@drawable/pic1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/TextView02" android:background="@drawable/pic2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/TextView03" android:background="@drawable/pic3" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </FrameLayout> 效果图: 1.切换不同的Tab时候,不同Tab里面的内容在不同的Activity显示 先创建三个类FirstActivity.java,SecondActivity.java,ThirdActivity.java,都是继承Activity FirstActivity.java packagecom.android.tabtest.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.TextView; publicclassFirstActivityextendsActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TextViewtextview=newTextView(this); textview.setText("这是Tab1"); setContentView(textview); } } SecondActivity.java packagecom.android.tabtest.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.TextView; publicclassSecondActivityextendsActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TextViewtextview=newTextView(this); textview.setText("这是Tab2"); setContentView(textview); } } ThirdActivity.java packagecom.android.tabtest.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.TextView; publicclassThirdActivityextendsActivity{ publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TextViewtextview=newTextView(this); textview.setText("这是Tab3"); setContentView(textview); } } 在layout文件夹中对main.xml进行修改 <?xmlversion="1.0"encoding="utf-8"?> <TabHostandroid:id="@android:id/tabhost"android:layout_width="fill_parent" android:layout_height="fill_parent"xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp" /> </LinearLayout> </TabHost> 新建一个测试Tab的类TabDemo.java,继承于TabActivity类 packagecom.android.tabtest.activity; importandroid.app.TabActivity; importandroid.content.Intent; importandroid.content.res.Resources; importandroid.os.Bundle; importandroid.widget.TabHost; importandroid.widget.TabHost.TabSpec; publicclassTabDemoextendsTabActivity{ /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main);//这里使用了上面创建的xml文件(Tab页面的布局) Resourcesres=getResources();//ResourceobjecttogetDrawables TabHosttabHost=getTabHost();//TheactivityTabHost TabSpecspec; Intentintent;//ReusableIntentforeachtab //第一个Tab intent=newIntent(this,FirstActivity.class);//新建一个Intent用作Tab1显示的内容 spec=tabHost.newTabSpec("tab1")//新建一个Tab .setIndicator("Tab1",res.getDrawable(android.R.drawable.ic_media_play))//设置名称以及图标 .setContent(intent);//设置显示的intent,这里的参数也可以是R.id.xxx tabHost.addTab(spec);//添加进tabHost //第二个Tab intent=newIntent(this,SecondActivity.class);//第二个Intent用作Tab1显示的内容 spec=tabHost.newTabSpec("tab2")//新建一个Tab .setIndicator("Tab2",res.getDrawable(android.R.drawable.ic_menu_edit))//设置名称以及图标 .setContent(intent);//设置显示的intent,这里的参数也可以是R.id.xxx tabHost.addTab(spec);//添加进tabHost //第三个Tab intent=newIntent(this,SecondActivity.class);//第二个Intent用作Tab1显示的内容 spec=tabHost.newTabSpec("tab2")//新建一个Tab .setIndicator("Tab3",res.getDrawable(android.R.drawable.ic_menu_help))//设置名称以及图标 .setContent(intent);//设置显示的intent,这里的参数也可以是R.id.xxx tabHost.addTab(spec);//添加进tabHost tabHost.setCurrentTab(0);//设置当前的选项卡,这里为Tab1 } } 在AndroidManifest.xml里加入9~29行的声明代码 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.tabtest.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".TabDemo" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activityandroid:name=".FirstActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activityandroid:name=".SecondActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest> 效果图: 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/643043

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

CentOS 6.5 LVM磁盘管理学习笔记

在系统运维和服务器管理过程中,经常遇到服务器磁盘容量不足,需要在线扩容的情况。普通磁盘分区的管理方式在逻辑分区划好之后就无法改变其大小。而LVM可以实现Linux服务器下面磁盘空间的在线扩容和动态管理,相对于普通的磁盘分区有很大的灵活性。 一、LVM简介 LVM是Logical VolumeManager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制,它由Heinz Mauelshagen在Linux 2.4内核上实现。LVM将一个或多个硬盘的分区在逻辑上进行组合,做为一个大的硬盘空间来使用,当硬盘的剩余空间不够的时候,可以将其它的硬盘加入到分区当中,这样可以实现磁盘空间的动态管理。 二、LVM基本术语 物理卷(physical volume,PV):物理卷就是指硬盘分区,也可以是整个硬盘或已创建的RAID,是LVM的基本存储设备,与普通物理存储介质的区别是该设备包含有LVM相关的管理参数。 卷组(volume group,VG):卷组是由一个或多个物理卷所组成的存储池,在卷组上能创建一个或多个“LVM分区”(逻辑卷)。 逻辑卷(logical volume,LV):LVM的逻辑卷类似于非LVM系统中的硬盘分区,它建立在卷组之上,是一个标准的块设备,在逻辑卷之上可以建立文件系统。 物理块(physical extent,PE):物理卷以大小相等的物理块为存储的基本单位,同时也是LVM寻址的最小单元。 逻辑块(logical extent,LE):逻辑卷以大小相等的逻辑块为存储的基本单位,在同一个卷组中,LE的大小和PE是相等的,并且一一对应。 三、通过LVM分区方式安装Centos 1.选择安装类型,选择最后一个复选框,即创建自定义布局。 2.首先划分/boot分区,/boot分区建议使用物理分区。 3.将剩余空间划分为一个物理卷(PV)。 4.创建一个卷组(VG)。默认卷组名为VolGroup00,修改卷组名为vg51cto_lv。 5.在VG上面创建逻辑卷(LV)。逻辑卷默认为LogVol00,LogVol01……末两位由00开始依次递增。 6.LVM分区完成。 7.df -h查看磁盘空间。 1 2 3 4 5 6 7 8 [root@hadoop01~] #df-h FilesystemSizeUsedAvailUse%Mountedon /dev/mapper/vg51cto_lv-LogVol01 9.9G1.2G8.2G13%/ tmpfs495M0495M0% /dev/shm /dev/sda1 194M29M155M16% /boot /dev/mapper/vg51cto_lv-LogVol03 20G172M19G1% /data /dev/mapper/vg51cto_lv-LogVol02 5.0G138M4.6G3% /home /dev/mapper/vg51cto_lv-LogVol04 23G173M22G1% /usr/local 四、LVM管理 第一部分:卷组(volume group,VG)相关的操作。 1.查看卷组(VG)名,卷组名为vg51cto_lv。 1 2 3 [root@hadoop01~] #vgscan Readingallphysicalvolumes.Thismaytakeawhile... Foundvolumegroup "vg51cto_lv" usingmetadata type lvm2 2.查看卷组(VG)包含的PV、LV信息。 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 [root@hadoop01~] #vgdisplay-vvg51cto_lv Usingvolumegroup(s)on command line Findingvolumegroup "vg51cto_lv" ---Volumegroup--- VGNamevg51cto_lv SystemID Formatlvm2 MetadataAreas1 MetadataSequenceNo6 VGAccess read /write VGStatusresizable MAXLV0 CurLV5 OpenLV5 MaxPV0 CurPV1 ActPV1 VGSize59.80GiB PESize4.00MiB TotalPE15309 AllocPE /Size 15309/59.80GiB FreePE/Size0/0 VGUUIDuF4S1y-21AZ-KOfs-rNIF-lFmN-wQ75-2sX7F1 ---Logicalvolume--- LVPath /dev/vg51cto_lv/LogVol04 LVNameLogVol04 VGNamevg51cto_lv LVUUIDrvOZeO-Oz2G-wx7Z-u0b6-CvXj-FKEj-RwCLXO LVWriteAccess read /write LVCreationhost, time hadoop01,2015-11-0517:30:51+0800 LVStatusavailable #open1 LVSize22.80GiB CurrentLE5837 Segments1 Allocationinherit Readaheadsectorsauto -currentlysetto256 Blockdevice253:2 ---Logicalvolume--- LVPath /dev/vg51cto_lv/LogVol01 LVNameLogVol01 VGNamevg51cto_lv LVUUIDd6YKrd-fWMJ-x61I-cfWG-v2me-Hn8V-xdm96L LVWriteAccess read /write LVCreationhost, time hadoop01,2015-11-0517:30:56+0800 LVStatusavailable #open1 LVSize10.00GiB CurrentLE2560 Segments1 Allocationinherit Readaheadsectorsauto -currentlysetto256 Blockdevice253:0 ---Logicalvolume--- LVPath /dev/vg51cto_lv/LogVol00 LVNameLogVol00 VGNamevg51cto_lv LVUUIDhSyH2r-mvMV-th7q-geKg-sVpm-O1zJ-D6DwT8 LVWriteAccess read /write LVCreationhost, time hadoop01,2015-11-0517:30:58+0800 LVStatusavailable #open1 LVSize2.00GiB CurrentLE512 Segments1 Allocationinherit Readaheadsectorsauto -currentlysetto256 Blockdevice253:1 ---Logicalvolume--- LVPath /dev/vg51cto_lv/LogVol03 LVNameLogVol03 VGNamevg51cto_lv LVUUIDgKHLfz-O5Lm-TGMq-2LcF-xcH1-ASea-QCVVNc LVWriteAccess read /write LVCreationhost, time hadoop01,2015-11-0517:30:58+0800 LVStatusavailable #open1 LVSize20.00GiB CurrentLE5120 Segments1 Allocationinherit Readaheadsectorsauto -currentlysetto256 Blockdevice253:3 ---Logicalvolume--- LVPath /dev/vg51cto_lv/LogVol02 LVNameLogVol02 VGNamevg51cto_lv LVUUIDlkqKmO-Dt0u-3CnB-UqeD-d6gc-2rmP-gWtKVp LVWriteAccess read /write LVCreationhost, time hadoop01,2015-11-0517:31:00+0800 LVStatusavailable #open1 LVSize5.00GiB CurrentLE1280 Segments1 Allocationinherit Readaheadsectorsauto -currentlysetto256 Blockdevice253:4 ---Physicalvolumes--- PVName /dev/sda2 PVUUIDpKC6SA-fkfe-OAl2-scVr-tq0h-EAXD-AWpwgX PVStatusallocatable TotalPE /Free PE15309/0 3.修改卷组名,由vg51cto_lv修改成vg51cto。 1)修改卷组名的命令为vgrename,语法如下: vgrename OldVolumeGroupNameNew VolumeGroupName 1 2 [root@hadoop01~] #vgrenamevg51cto_lvvg51cto Volumegroup "vg51cto_lv" successfullyrenamedto "vg51cto" 2)修改/etc/fstab配置文件,把vg51cto_lv修改成vg51cto。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@hadoop01~] #vim/etc/fstab # #/etc/fstab #CreatedbyanacondaonThuNov517:33:462015 # #Accessiblefilesystems,byreference,aremaintainedunder'/dev/disk' #Seemanpagesfstab(5),findfs(8),mount(8)and/orblkid(8)formoreinfo # /dev/mapper/vg51cto-LogVol01 /ext4defaults11 UUID=9c02e519-3b85-4918-b9fd-395535cab496 /boot ext4defaults12 /dev/mapper/vg51cto-LogVol03 /data ext4defaults12 /dev/mapper/vg51cto-LogVol02 /home ext4defaults12 /dev/mapper/vg51cto-LogVol04 /usr/local ext4defaults12 /dev/mapper/vg51cto-LogVol00 swapswapdefaults00 tmpfs /dev/shm tmpfsdefaults00 devpts /dev/pts devptsgid=5,mode=62000 sysfs /sys sysfsdefaults00 proc /proc procdefaults00 3)修改grub.conf配置文件,把vg51cto_lv修改成vg51cto。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@hadoop01~] #vim/etc/grub.conf #grub.confgeneratedbyanaconda # #Notethatyoudonothavetorerungrubaftermakingchangestothisfile #NOTICE:Youhavea/bootpartition.Thismeansthat #allkernelandinitrdpathsarerelativeto/boot/,eg. #root(hd0,0) #kernel/vmlinuz-versionroroot=/dev/mapper/vg51cto_lv-LogVol01 #initrd/initrd-[generic-]version.img #boot=/dev/sda default=0 timeout=5 splashimage=(hd0,0) /grub/splash .xpm.gz hiddenmenu titleCentOS(2.6.32-431.el6.x86_64) root(hd0,0) kernel /vmlinuz-2 .6.32-431.el6.x86_64roroot= /dev/mapper/vg51cto-LogVol01 rd_NO_LUKSrd_LVM_LV=vg51cto /LogVol01 rd_LVM_LV=vg51cto /LogVol00 rd_NO_MDcrashkernel=autoLANG=zh_CN.UTF-8KEYBOARDTYPE=pcKEYTABLE=usrd_NO_DMrhgbquiet initrd /initramfs-2 .6.32-431.el6.x86_64.img 4)reboot重启后用df -h查看。 1 2 3 4 5 6 7 8 [root@hadoop01~] #df-h FilesystemSizeUsedAvailUse%Mountedon /dev/mapper/vg51cto-LogVol01 9.9G1.2G8.2G13%/ tmpfs495M0495M0% /dev/shm /dev/sda1 194M29M155M16% /boot /dev/mapper/vg51cto-LogVol03 20G172M19G1% /data /dev/mapper/vg51cto-LogVol02 5.0G138M4.6G3% /home /dev/mapper/vg51cto-LogVol04 23G173M22G1% /usr/local 第二部分:逻辑卷(logical volume,LV)相关的操作。 1.查看逻辑卷(LV)名。 使用LVM安装系统时,默认的卷组名为VolGroup00,卷组内的逻辑卷为LogVol00,LogVol01……末两位由00开始依次递增。 1 2 3 4 5 6 [root@hadoop01~] #lvscan ACTIVE '/dev/vg51cto/LogVol04' [22.80GiB]inherit ACTIVE '/dev/vg51cto/LogVol01' [10.00GiB]inherit ACTIVE '/dev/vg51cto/LogVol00' [2.00GiB]inherit ACTIVE '/dev/vg51cto/LogVol03' [20.00GiB]inherit ACTIVE '/dev/vg51cto/LogVol02' [5.00GiB]inherit 2.查看逻辑卷详细信息 lvdisplay命令查看所有逻辑卷的详细信息 lvdisplay 逻辑卷名称 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@hadoop01~] #lvdisplay/dev/vg51cto/LogVol00 ---Logicalvolume--- LVPath /dev/vg51cto/LogVol00 LVNameLogVol00 VGNamevg51cto LVUUIDhSyH2r-mvMV-th7q-geKg-sVpm-O1zJ-D6DwT8 LVWriteAccess read /write LVCreationhost, time hadoop01,2015-11-0517:30:58+0800 LVStatusavailable #open1 LVSize2.00GiB CurrentLE512 Segments1 Allocationinherit Readaheadsectorsauto -currentlysetto256 Blockdevice253:1 3.修改逻辑卷名 1)修改逻辑卷命令为lvrename,语法如下: 1 2 3 4 5 6 7 8 9 10 11 lvrenameOldLogicalVolumePathNewLogicalVolumePath [root@hadoop01~] #lvrename/dev/vg51cto/LogVol00/dev/vg51cto/lv_swap Renamed "LogVol00" to "lv_swap" in volumegroup "vg51cto" [root@hadoop01~] #lvrename/dev/vg51cto/LogVol01/dev/vg51cto/lv_root Renamed "LogVol01" to "lv_root" in volumegroup "vg51cto" [root@hadoop01~] #lvrename/dev/vg51cto/LogVol02/dev/vg51cto/lv_home Renamed "LogVol02" to "lv_home" in volumegroup "vg51cto" [root@hadoop01~] #lvrename/dev/vg51cto/LogVol03/dev/vg51cto/lv_data Renamed "LogVol03" to "lv_data" in volumegroup "vg51cto" [root@hadoop01~] #lvrename/dev/vg51cto/LogVol04/dev/vg51cto/lv_usr Renamed "LogVol04" to "lv_usr" in volumegroup "vg51cto" 2)修改/etc/fstab配置文件。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@hadoop01~] #vim/etc/fstab # #/etc/fstab #CreatedbyanacondaonThuNov517:33:462015 # #Accessiblefilesystems,byreference,aremaintainedunder'/dev/disk' #Seemanpagesfstab(5),findfs(8),mount(8)and/orblkid(8)formoreinfo # /dev/mapper/vg51cto-lv_root /ext4defaults11 UUID=9c02e519-3b85-4918-b9fd-395535cab496 /boot ext4defaults12 /dev/mapper/vg51cto-lv_data /data ext4defaults12 /dev/mapper/vg51cto-lv_home /home ext4defaults12 /dev/mapper/vg51cto-lv_usr /usr/local ext4defaults12 /dev/mapper/vg51cto-lv_swap swapswapdefaults00 tmpfs /dev/shm tmpfsdefaults00 devpts /dev/pts devptsgid=5,mode=62000 sysfs /sys sysfsdefaults00 proc /proc procdefaults00 3)修改grub.conf配置文件。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@hadoop01~] #vim/etc/grub.conf #grub.confgeneratedbyanaconda # #Notethatyoudonothavetorerungrubaftermakingchangestothisfile #NOTICE:Youhavea/bootpartition.Thismeansthat #allkernelandinitrdpathsarerelativeto/boot/,eg. #root(hd0,0) #kernel/vmlinuz-versionroroot=/dev/mapper/vg51cto_lv-LogVol01 #initrd/initrd-[generic-]version.img #boot=/dev/sda default=0 timeout=5 splashimage=(hd0,0) /grub/splash .xpm.gz hiddenmenu titleCentOS(2.6.32-431.el6.x86_64) root(hd0,0) kernel /vmlinuz-2 .6.32-431.el6.x86_64roroot= /dev/mapper/vg51cto-lv_root rd_NO_LUKSrd_LVM_LV=vg51cto /lv_root rd_LVM_LV=vg51cto /lv_swap rd_NO_MDcrashkernel=autoLANG=zh_CN.UTF-8KEYBOARDTYPE=pcKEYTABLE=usrd_NO_DMrhgbquiet initrd /initramfs-2 .6.32-431.el6.x86_64.img 第三部分:物理卷(physical volume,PV)相关操作。 1.查看物理卷(PV)名,这里为/dev/sda2,linux中SCSI的第1块硬盘为/dev/sda,第2块硬盘为/dev/sdb,依此类推。 1 2 3 [root@hadoop01~] #pvscan PV /dev/sda2 VGvg51ctolvm2[59.80GiB/0 free ] Total:1[59.80GiB]/ in use:1[59.80GiB]/ in noVG:0[0] 2.查看物理卷详细信息。 1 2 3 4 5 6 7 8 9 10 11 [root@hadoop01~] #pvdisplay ---Physicalvolume--- PVName /dev/sda2 VGNamevg51cto PVSize59.80GiB/notusable3.00MiB Allocatable yes (butfull) PESize4.00MiB TotalPE15309 FreePE0 AllocatedPE15309 PVUUIDpKC6SA-fkfe-OAl2-scVr-tq0h-EAXD-AWpwgX 四、LVM空间管理 1.LVM减少LV空间 举例:减少/data空间,从20G减少到10G。 1)卸载设备(Unmount thefilesystem) 1 [root@hadoop01~] #umount/data/ 2)e2fsck命令检查文件系统(Checkthe filesystem) 1 2 3 4 5 6 7 8 [root@hadoop01~] #e2fsck-f/dev/mapper/vg51cto-lv_data e2fsck1.41.12(17-May-2010) 第一步:检查inode,块,和大小 第二步:检查目录结构 第3步:检查目录连接性 Pass4:Checkingreferencecounts 第5步:检查簇概要信息 /dev/mapper/vg51cto-lv_data :11 /1310720files (0.0%non-contiguous),126289 /5242880 blocks 3)resize2fs命令调整lv大小,10G表示调整后/data剩余空间。 1 2 3 4 [root@hadoop01~] #resize2fs/dev/mapper/vg51cto-lv_data10G resize2fs1.41.12(17-May-2010) Resizingthefilesystemon /dev/mapper/vg51cto-lv_data to2621440(4k)blocks. Thefilesystemon /dev/mapper/vg51cto-lv_data isnow2621440blockslong. 4)lvreduce命令减少文件系统大小(Resizethe filesystem),表示将/data的空间减少9G。 1 2 3 4 5 6 [root@hadoop01~] #lvreduce-L-9G/dev/mapper/vg51cto-lv_data WARNING:Reducingactivelogicalvolumeto11.00GiB THISMAYDESTROYYOURDATA(filesystemetc.) Doyoureallywanttoreducelv_data?[y /n ]:y Reducinglogicalvolumelv_datato11.00GiB Logicalvolumelv_datasuccessfullyresized 5)vgs命令查看卷组剩余空间为9G。 6)mount文件系统并查看磁盘空间剩余空间。 2.LVM增加LV空间 举例:将刚才9G空间增加到/home分区。 1)vgs命令查看是否有空闲空间可以扩容。 1 2 3 [root@hadoop01~] #vgs VG #PV#LV#SNAttrVSizeVFree vg51cto150wz--n-59.80g9.00g 2)df -h查看当前磁盘空间 3)lvextend命令将home分区空间增加9G。 1 2 3 4 5 6 7 8 [root@hadoop01~] #lvextend-L+9G-f-r/dev/mapper/vg51cto-lv_home Extendinglogicalvolumelv_hometo14.00GiB Logicalvolumelv_homesuccessfullyresized resize2fs1.41.12(17-May-2010) Filesystemat /dev/mapper/vg51cto-lv_homeis mountedon /home ;on-lineresizingrequired olddesc_blocks=1,new_desc_blocks=1 Performinganon-lineresizeof /dev/mapper/vg51cto-lv_home to3670016(4k)blocks. Thefilesystemon /dev/mapper/vg51cto-lv_home isnow3670016blockslong. 4)查看分区是否增加成功。 五、LVM在线扩容 服务器磁盘空间不足,添加新的硬盘后,需要把空间添加当前分区当中。 linux中SCSI的第1个硬盘/dev/sda,第2个硬盘/dev/sdb依此类推。其中服务器第一块硬盘/dev/sda已经划分为LVM分区。/dev/sdb是新加的硬盘。 1)用pvcreate /dev/sdb命令初始化分区sdb为物理卷(PV)。 1 2 [root@hadoop01~] #pvcreate/dev/sdb Physicalvolume "/dev/sdb" successfullycreated 2)pvdisplay命令显示物理卷的信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [root@hadoop01~] #pvdisplay ---Physicalvolume--- PVName /dev/sda2 VGNamevg51cto PVSize59.80GiB/notusable3.00MiB Allocatable yes (butfull) PESize4.00MiB TotalPE15309 FreePE0 AllocatedPE15309 PVUUIDpKC6SA-fkfe-OAl2-scVr-tq0h-EAXD-AWpwgX "/dev/sdb" isanewphysicalvolumeof "40.00GiB" ---NEWPhysicalvolume--- PVName /dev/sdb VGName PVSize40.00GiB AllocatableNO PESize0 TotalPE0 FreePE0 AllocatedPE0 PVUUIDdMeOLS-Sks3-8k3q-pVWp-Iuz2-0Hh2-8njjhY 3)vgextend命令将pv加入到vg,vgcreate命令为新创建vg(vgcreate vg51cto /dev/sdb),这里的vg51cto已经存在,只需要用vgextend加入即可。 1 2 [root@hadoop01~] #vgextendvg51cto/dev/sdb Volumegroup "vg51cto" successfullyextended 4)用vgdisplay命令查看vg信息,看到已经有40G空闲PE。 5)lvextend命令扩展分区,将40G空间全部添加到/data分区。 直接增加40G空间不足,报下面的错误,因此添加39.9G的空间。 Insufficient free space:10240 extents needed, but only 10239 available 1 2 3 4 [root@hadoop01~] #lvextend-L+39.99G/dev/mapper/vg51cto-lv_data Roundingsizetoboundarybetweenphysicalextents:39.99GiB Extendinglogicalvolumelv_datato50.99GiB Logicalvolumelv_datasuccessfullyresized 6)上一步操作只是增加了逻辑卷的大小,用resize2fs命令重新定义文件系统的大小。 1 2 3 4 5 6 [root@hadoop01~] #resize2fs/dev/mapper/vg51cto-lv_data resize2fs1.41.12(17-May-2010) Filesystemat /dev/mapper/vg51cto-lv_datais mountedon /data ;on-lineresizingrequired olddesc_blocks=1,new_desc_blocks=4 Performinganon-lineresizeof /dev/mapper/vg51cto-lv_data to13367296(4k)blocks. Thefilesystemon /dev/mapper/vg51cto-lv_data isnow13367296blockslong. 7)查看磁盘在线扩容是否正常。 总结: 1)/分区不能umount,说明/分区只能扩容,不能减少/分区的空间。 2)减少分区的时候需要卸载分区,进行umount操作。 3)扩容的分区的时候不需要卸载分区。 4)重命名vg,lv命名后,需要修改/etc/fstab和/etc/grub.conf引导文件。 本文转自 sfzhang 51CTO博客,原文链接:http://blog.51cto.com/sfzhang88/1710059,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

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

Nacos

Nacos

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

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

用户登录
用户注册