博客换主题啦!!!

feed订阅 腾讯微博 你好,欢迎光临! 

读写HTML代码类型配置信息的思考

2008.10.3 , , 1 条评论 , 672 浏览

昨天写了那个 [自定义配置文件] ,今天就又碰到问题了。如果我们定义的这个配置信息要能够支持HTML代码呢?比如要能够直接支持保存超级链接,统计代码啦诸如此类,那可就会爆出问题来。
例如,我们现在要保存一段51啦的统计代码:
<scrip tlanguage="javascript" type="text/javascript" src="http://js.users.51.la/1642363.js"></script>
<noscript>
<a href="http://www.51.la/?1642363" target="_blank"><img alt="&#x6211;&#x8981;&#x5566;&#x514D;&#x8D39;&#x7EDF;&#x8BA1;" src="http://img.users.51.la/1642363.asp" style="border:none" /></a>
</noscript>
将它保存的时候是不会出错的,保存到配置文件中会是这样的:

Const ZC_BLOG_COPYRIGHT="<scrip tlanguage="javascript"
type="text/javascript"src="http://js.users.51.la/1642363.js"></script><noscript><a href="http://www.51.la/?1642363" target="_blank"><img alt="&#x6211;&#x8981;&#x5566;&#x514D;&#x8D39;&#x7EDF;&#x8BA1;" src="http://img.users.51.la/1642363.asp" style="border:none" /></a></noscript>";

当我们第二次读取它的时候,按照我们上次的方法(截取“=”号和“;”之间部分)就出错啦。来看看它给我们截出来的是什么吧,先找到“=”紧接着找第一个“;”,然后把它们之间的截取出来,那就是:

<scrip tlanguage="javascript" type="text/javascript" src="http://js.users.51.la/1642363.js"></script>
<noscript><a href="http://www.51.la/?1642363" target="_blank"><img alt="&#x621

这不就完全错了吗,根本就不是我们想要得到的那段代码。怎么办?
首先,从“=”开始截取我们不用修改,我们要让它截取到该行的最后一个“;”,这样以来截取出来的就是我们想要的了,代码只需将int end = line.indexOf(";");修改为:int end = line.lastIndexOf(";");这样就OK了。
接下来还有一个问题,我们的配置文件的格式这这样的Const ZC_BLOG_COPYRIGHT="HTML代码";如果直接将“HTML代码”替换成上面的统计代码,虽然在我们修改读取的时候不会有问题,但是如果在网页的脚本中需要用的话那就出错了,为什么呢?因为统计代码中有“"”。
这个又要如何修改呢?也很简单,我们在写入代码到配置文件中之前先使用
copyRight = copyRight.replace('\"','\'');
将其中所有的双引号都替换为单引号,而取值修改的时候我们再反过来
copyRight = copyRight.replace('\'','\"');
把读取出来的代码中的所有单引号替换为双引号,这样用户在修改的时候看到的就和原来的一样了,而实际上的配置文件中却不是这样的,有点障眼法的意思,呵呵。

JSP读取自定义配置文件

2008.10.2 , , 2 条评论 , 1,633 浏览

在J2EE的Web开发中(其他的也有),有时我们需要存储一些常量类型的配置信息,而这些信息是在不查询数据库的时候就要能够使用的,我就只想到了两个方法。
一个是存储在XML文件中,使用的时候用AJAX来获取,可是这样需要在客户端写大量的JavaScript代码,如果我们在写Jsp脚本的时候也需要这些信息呢?AJAX也没办法了吧?而且,XML文件是可以直接从URL来访问查看的,虽说不一定是重要的信息,但是能够被人随意看那也不好吧。
第二个方法就是,写在Jsp脚本里面,读取的时候我们可以通过
<%@ include file="" %>这样的[JSP指令] 或者<jsp:include flush="" page="" />[标准动作] 把它包含进当前脚本页即可直接访问它的值。需要修改的时候那就只能用IO流来写进去了。
经过再三斟酌,我决定使用第二个方法。那么,既然是配置信息,那就必须有它的规则(格式),若随便写,那读取起来就不好办了。这里举个实例,比如尼克技术博客使用这个ZBLOG程序,在它的根目录下就有一个类似这样的配置文件c_custom.asp,其代码如下:

 
  1. <%
  2. '网站基本设置
  3. Const ZC_DATABASE_PATH="data/#%206438769b7b43fa552613.mdb"
  4. Const ZC_BLOG_HOST="http://localhost/"
  5.  
  6. '--------------------------------------------------------------------
  7. Const ZC_BLOG_TITLE="Your Blog"
  8. Const ZC_BLOG_SUBTITLE="Good Luck To You!"
  9. Const ZC_BLOG_NAME="你的Blog名称"
  10. Const ZC_BLOG_SUB_NAME="欢迎使用Z-Blog,有问题或意见请到Zblogger.BBS社区反馈,谢谢您的参与使用。"
  11. Const ZC_BLOG_CSS="default"
  12. Const ZC_BLOG_COPYRIGHT="Copyright xxxx-xxxx Your WebSite. Some Rights Reserved."
  13. Const ZC_BLOG_MASTER="neeke"
  14. '--------------------------------------------------------------------
  15.  
  16. Const ZC_BLOG_THEME="default"
  17.  
  18. %>

 

我们看到它的定义是这样的:

数据类型 关键字名称 = "配置信息"

那么我我们也可以相应的写一个自己的配置文件。

 
  1. <%@ page contentType="text/html; charset=GBK" %>
  2. <%
  3. String NK_BLOG_TITLE="Your Blog";
  4. String NK_BLOG_SUBTITLE="Good Luck To You!";
  5. String NK_BLOG_NAME="你的Blog名称";
  6. String NK_BLOG_SUB_NAME="欢迎使用NK-Blog!";
  7. String NK_BLOG_COPYRIGHT="Copyright xxxx-xxxx Your WebSite. Some Rights Reserved.";
  8. %>

如果在Jsp脚本中需要用他们的时候,我们可以在页头使用<%@ include file="" %>包含这个文件,之后我们就可以直接使用<%=NK_BLOG_TITLE %>来输出“Your Blog”这条信息。修改的时候我们可以使用IO流每次读取其中一行若该行包含有NK_BLOG_TITLE这样的关键字则截取它对应的值,如何截取呢?找每行都有的特征出来,最容易看出来的应该就是双引号啦(""),不过我们不这样截,我们从等号(=)开始截取到分号(;)完,然后替换成新的数据再写入到文件中就OK了!下面就来写具体的实现代码。

读取配置信息:

 
  1. public static BlogSetting getBaseSetting(String custom) {
  2.         BlogSetting bset = new BlogSetting();
  3.         //用于存放每行的信息
  4.      &nbs
    p;  String line = 
    "";
  5.         //用于存储配置信息
  6.         String[] lines = new String[5];
  7.         try {
  8.             //开始读取配置信息
  9.             FileReader fr = new FileReader(custom);
  10.             BufferedReader br = new BufferedReader(fr);
  11.             while ((line = br.readLine()) != null) {
  12.                 //keyWords为预定义的特征字符数组
  13.                 for (int i = 0; i < keyWords.length; i++) {
  14.                     if (line.contains(keyWords[i])) {
  15.                         int begin = line.indexOf("=");
  16.                         int end = line.indexOf(";");
  17.                         //截取配置信息
  18.                         String key = line.substring(begin + 2, end - 1);
  19.                         //存储
  20.                         lines[i] = key;
  21.                     }
  22.                 }
  23.             }
  24.             //关闭文件流
  25.             br.close();
  26.             fr.close();
  27.         } catch (FileNotFoundException ex) {
  28.             ex.printStackTrace();
  29.         } catch (IOException ex) {
  30.             ex.printStackTrace();
  31.         }
  32.         bset.title = lines[0];
  33.         bset.subTitle = lines[1];
  34.         bset.name = lines[2];
  35.         bset.subName = lines[3];
  36.         bset.copyRight = lines[4];
  37.         return bset;
  38.     }

存储配置信息:

 
  1. public span> boolean BaseSettingSave(String custom) {
  2.         boolean ok = true;
  3.         //待保存的配置信息
  4.         String[] Words = new String[] {this.title, this.subTitle, this.name,
  5.                             this.subName,
  6.                             this.copyRight};
  7.         try {
  8.             //开始读取原配置信息
  9.             FileReader fr = new FileReader(custom);
  10.             BufferedReader br = new BufferedReader(fr);
  11.             String line = "";
  12.             String lines = "";
  13.             while ((line = br.readLine()) != null) {
  14.                 for (int i = 0; i < keyWords.length; i++) {
  15.                     //keyWords为预定义好的特特征字符数组
  16.                     if (line.contains(keyWords[i])) {
  17.                         int begin = line.indexOf("=");
  18.                         int end = line.indexOf(";");
  19.                         //截取出要替换掉的配置信息
  20.                         String key = line.substring(begin + 2, end - 1);
  21.                         //开始替换
  22.                         line = line.replaceAll(key, Words[i]);
  23.                     }
  24.                 }
  25.                 //新的配置信息字符串
  26.                 lines += line+"\r\n";//*****需要换行符
  27.             }
  28.             //关闭文件流
  29.             br.close();
  30.             fr.close();
  31.             //开始写入新的配置信息
  32.             FileWriter fw = new FileWriter(custom);
  33.             BufferedWriter bw = new BufferedWriter(fw);
  34.             bw.write(lines);
  35.             bw.flush();
  36.             //关闭文件流
  37.             bw.close();
  38.             fw.close();
  39.         } catch (FileNotFoundException ex) {
  40.             ok = false;
  41.             ex.printStackTrace();
  42.         } catch (IOExc
    eption ex) {
  43.             ok = false;
  44.             ex.printStackTrace();
  45.         }
  46.         return ok;
  47.     }

为什么要写这个呢?因为这个也是我这次J2EE项目中的一部分,JAVA真的忘得差不多了,想到了方法但是如何使用IO流就给忘了,结果翻书找到...温故而知新,写完后读取成功,修改成功,再读取就失败了~ - -!怎么回事呢?因为我修改写入的时候规则丢了,直接用bw.write(lines)写到一行了,第二次读取的时候它找不到规则当然错啦,然后给加上换行符搞定("\r\n")。贴出来以备将来书丢了的时候用,O(∩_∩)O哈哈~

 

如何从Servlet中获取物理路径

2008.10.1 , , 无评论 , 1,047 浏览

有个地方需要用到文件的物理路径,因为我需要调用方法来删除用户上传至服务器的文件。代码如下:

  1. /**
  2. * 用于删除上传的附件
  3. * @param url String
  4. * @return boolean
  5. */
  6. public static boolean deleteUploadFileByUrl(String url)
  7. {
  8. File file = new File(url);
  9. boolean ok = false;
  10. if(file.exists())
  11. {
  12. if(file.delete())
  13. {
  14. ok = true;
  15. }
  16. }
  17. return ok;
  18. }

可是直接传文件的相对路径当然不行啦。起初我想到的是request.getContextPath(),结果返回的是网站的相对根目录,没用,PASS掉!哎~忘了是用哪个了,我记得好像有个Server中的一个方法可以用来获取物理路径,晕~ASP.NET学时间长了,J2EE忘了差不多了...经过我分别对request和response的个个方法逐一查看(速度还是很快的)。终于被我给找到了。
request.getSession().getServletContext().getRealPath("");
这样就可以获得网站所在的物理路径了,OK问题解决,继续折腾...

HttpHandler—APS.NET最后一课

2008.09.30 , , 3 条评论 , 994 浏览

应该算是ACCP5.0 ASP.NET中的有技术含量的最后一课了吧,为什么要说是ACCP5.0 ASP.NET中的有技术含量的最后一课,因为知识无尽头嘛!嘿嘿~
打开VS2005新建一个Web站点,然后在“添加新项”中选择“一般处理程序”接着点击“添加”。HttpHandler程序是以ashx为后缀名的,新创建的HttpHandler的默认内容为:

 
  1. <%@ WebHandler Language="C#" Class="Handler" %>//WebHandler指令,标记该处理程序的语言和类名称
  2.  
  3. using System;
  4. using System.Web;
  5.  
  6. public class Handler : IHttpHandler {//继承自IHttpHandler接口
  7.     
  8.     public void ProcessRequest (HttpContext context) {//最终处理方法
  9.         context.Response.ContentType = "text/plain";
  10.         context.Response.Write("Hello World");
  11.     }
  12.  
  13.     public bool IsReusable {//是否用于其他的IHttpHandler的实例
  14.         get {
  15.             return false;
  16.         }
  17.     }
  18.  
  19. }

 这段代码说明了context对象可以用来控制输出的内容和类型。
ContentType用于设置程序的输出类型,这段代码可以在页面上出处一段文本“Hello World”(不禁悄悄问一句:为啥无论什么程序语言,写的第一个小程序都是输出Hello World?)且次ashx文件是可以直接访问的。
注意:
实现HttpHandler得功能就必须实现IHttpHandler接口,而且,任何实现了该接口的类都可以用于处理输入的HTTP请求。
从上面的代码我们可以看到,实现该接口需要实现IsReusable属性和ProcessRequest方法。
IsReusable可以用来设置是否可以重用此实例。
ProcessRequest方法是整个HTTP请求最终的处理方法。如下图所示:

这个方法需要一个HttpContext类型的参数,即“http上下文”。它封装了有关一些HTTP请求的所有HTTP特定的信息。在这里,它被用在不同的HttpModule和HttpHandler之间进行数据传递,也可以用于保持某一个完整的请求的相应的一些信息。

6步学会ASP.NET自定义验证码+水印控件

2008.09.28 , , 5 条评论 , 1,003 浏览

验证码大家应该经常看到吧,比如你在给网站留言,或者注册时就经常可以看到验证码的身影,验证码是很有必要的,因为现在灌水机,信息群发等严重扰乱正常的网站信息管理。
水印应该也都见过吧?它就好比一个我们日常生活中的印章印下的章子。它能够很好的保护发布人的著作权,防止他人盗用。这两个东西如此有用,你想不想知道如何自己动手做呢?想知道就继续看下去吧。
注:需要懂得ASP.NET技术。
1.首先使用VS2005新建一个WEB站点并添加Web用户控件(名为MyCode,语言选择Visual C#)。
2.进入MyCode.ascx文件的设计模式,分别拖入一个Image控件和一个LinkButton控件并将LinkButton控件的

Text属性改为:“我看不清,给我换一张”(你当然可以随便写什么)。
3.双击LinkButton控件进入后置代码中,在该文件中写一个私有的无返回类型的GetCode()方法,其代码如下:

 
  1. private void GetCode()
  2.     {
  3.         //创建验证码位图,宽为500个像素,高为150个像素
  4.         Bitmap myCode = new Bitmap(500, 150);
  5.         //获取位图物理路径
  6.         string codePath = Server.MapPath("~") + "\\code.jpg";
  7.         //创建随机数
  8.         Random rd = new Random();
  9.         //验证码字符串
  10.         string line = "";
  11.         for (int j = 0; j < 6; j++)
  12.         {
  13.             //随即产生大于等于0小于3的数
  14.             int i = rd.Next(3);
  15.             
  16.             if (i == 0)
  17.             {
  18.                 //若为0则生成A-Z的字符并追加到line
  19.                 line += char.ConvertFromUtf32(rd.Next(65, 92));
  20.             }
  21.             else if (i == 1)
  22.             {
  23.                 //若为1则生成a-z的字符串并追加到line
  24.                 line += char.ConvertFromUtf32(rd.Next(97, 123));
  25.             }
  26.             else
  27.             {
  28.                 //其他则生成0-9的数字并追加到line
  29.                 line += rd.Next(10);
  30.             }
  31.         }
  32.         //创建Graphics对象
  33.         Graphics g = Graphics.FromImage(myCode);
  34.         //画上字符串line,且字体随机,大小为90,采用红色实线,从位图的左上角开始画
  35.         g.DrawString(line, new Font(FontFamily.Families[rd.Next(2)], 90), new SolidBrush(Color.Red), 0, 0);
  36.         //给验证码画上10条随机线条加以干扰,黄绿实线,粗度为2,起始位置,终止位置均为不超过位图大小的随机数
  37.         for (int i = 0; i < 10; i++)
  38.         {
  39.             g.DrawLine(new Pen(new SolidBrush(Color.LightGreen), 3), new Point(rd.Next(500), rd.Next(150)), new Point(rd.Next(500), rd.Next(150)));
  40.         }
  41.         //获得水印图片
  42.       &
    nbsp; System.Drawing.Image water = System.Drawing.Image.FromFile(Server.MapPath(
    "~") + "\\water.jpg");
  43.         //将水印画至位图右下角
  44.         g.DrawImage(water, new Point(500-water.Width,150-water.Height));
  45.         //销毁Graphics
  46.         g.Dispose();
  47.         //保存验证码
  48.         myCode.Save(codePath, System.Drawing.Imaging.ImageFormat.Jpeg);
  49.         //销毁位图对象
  50.         myCode.Dispose();
  51.         //显示至网页
  52.         this.Image1.ImageUrl = "code.jpg";
  53.     }

4.在LinkButton1_Click事件中调用GetCode()方法,在Page_Load事件中写入:
if (!IsPostBack)
{
       GetCode();
}
其意是当第一次打开网页的时候调用GetCode()方法。
5.新建一个Web窗体文件TestMyCode.aspx并进入其设计模式,将刚才创建的用户控件MyCode.ascx文件拖入其中


6.运行TestMyCode.aspx文件即可看到如下图中的效果,当单击“我看不清,给我换一张”时便会更换一张新的

验证码。


注:code.jpg为位图文件由编写的代码生成,water.jpg文件为自备水印文件。

解决SQL 2005 中不允许远程连接的方法

2008.09.27 , 未分类 , 1 条评论 , 1,110 浏览

今天在SQL2000的基础上又装了SQL2005结果发现SQL2005不能使用SA登陆只能集成认证方式登陆,郁闷了~,找了点资料来按部就班搞定。

1、打开外围应用配置器——》服务和连接的外围应用配置器,作如下配置后重启服务:

 

2、打开SQL Server Configuration Manager——》SQLEXPRESS的协议,启用TCP/IP

 

3、右键点击TCP/IP——》属性——》IP地址,作如下设置并重启服务

 

注:IPALL中的TCP动态端口设置为0,系统会自动成2391

4、使用SQL Server Management Studio连接数据库
 在只装了SQL2005的情况下使用IP直接连接就行了,不需要加SQLEXPRESS,如127.0.0.1即可
 若同时装了SQL2000和SQL2005在需要连接2005的时候要在IP地址后面加上SQLEXPRESS,如127.0.0.1\SQLEXPRESS

什么是黑盒测试与白盒测试

2008.09.26 , , 无评论 , 711 浏览

1.黑盒测试(Black-box Tesing)
黑盒测试又称功能测试、数据驱动测试或基于规格说明书的测试。注重于测试软件的功能性需求。
采用这种测试方法,测试者把被测程序看成一个黑盒子,完全不要考虑程序的内部结构和特性,只知道该程序输入和输出之间的关系或程序功能,依靠能够反映这一关系和程序功能的需求规格说明书,来自确定测试用例和推断测试结果的正确性。例如:Windows计算其程序,我们如果输入3.14159并按sqrt键,就会得到结果1.772453102341。使用黑盒子测试方式,不管软件计算圆周率的平方根要经历多少复杂运算,只关心他的运行结果。
2.白盒测试(White-box Tesing)
白盒测试又称结构测试、逻辑驱动测试或基于程序本身的测试。测试者把被测程序看成一个盒子,而这个盒子是打开着的,以程序的内容来设计测试数据。采用这种测试方法,测试人员对被测试程序的内部结构是清楚的。从程序的内部逻辑结构入手,按照一定的原则设计测试用例,对软件的逻辑路径进行测试,在程序的不同点检查程序的状态,来判定其实际情况是否和预期的状态相一致。
白盒测试要求对某些程序的结构特性做到一定程度的覆盖,或者说是“基于覆盖率的测试”,并以此为目标,引导我们朝着提高覆盖覆盖率的方向努力,找出那些已被忽视的程序错误。最常见的程序结构覆盖有:
1)语句覆盖:程序中每一条语句至少被执行一次,这是最弱的逻辑覆盖准则。
2)分支覆盖或判断覆盖:程序中的每一个分支至少走查一次,即每一条分支语句的真值执行一次,假值也执行一次。
3)条件覆盖:当判定式中含有多个条件时,要求每个条件的取值均得到检验。
4)判断/条件覆盖:同时考虑条件的组合及判定结果的检验。
5)路径覆盖:使程序延所有可能的路径执行。

ASP.NET使用正则表达式屏蔽垃圾信息

2008.09.25 , , 1 条评论 , 572 浏览

找资料,看看如何实现使用正则表达式屏蔽垃圾信息,找来找去找出来的都不怎么好,有不详细的,有代码缺失的。最后还是找到了微软,先摘过来,大概思路已经有了,只需把下面微软给的样例代码修改一下即可,具体能不能行还不知道,先睡一觉,起来再慢慢研究。
Regex 类
表示不可变的正则表达式。

命名空间:System.Text.RegularExpressions

Regex 类包含若干 static(在 Visual Basic 中为 Shared)方法,使您无需显式创建 Regex 对象即可使用正

则表达式。在 .NET Framework 2.0 版中,将缓存通过调用静态方法而编译的正则表达式,而不会缓存通过调

用实例方法而编译的正则表达式。默认情况下,正则表达式引擎将缓存 15 个最近使用的静态正则表达式。因

此,在过度地依赖一组固定的正则表达式来提取、修改或验证文本的应用程序中,您可能更愿意调用这些静态

方法,而不是其相应的实例方法。IsMatch、Match、Matches、Replace 和 Split 方法的静态重载可用。

 
  1. using System;
  2. using System.Text.RegularExpressions;
  3.  
  4. public class Test
  5. {
  6.    public static void Main ()
  7.    {
  8.       // Define a regular expression for currency values.
  9.          Regex rx = new Regex(@"^-?\d+(\.\d{2})?$");
  10.           
  11.          // Define some test strings.
  12.          string[] tests = {"-42""19.99""0.001""100 USD"
  13.                            ".34""0.34""1,052.21"};
  14.           
  15.          // Check each test string against the regular expression.
  16.          foreach (string test in tests)
  17.          {
  18.             if (rx.IsMatch(test))
  19.             {
  20.                Console.WriteLine("{0} is a currency value.", test);
  21.             }
  22.             else
  23.             {
  24.                Console.WriteLine("{0} is not a currency value.", test);
  25.             }
  26.          }
  27.    }    
  28. }

 

实践理解流式布局

2008.09.24 , , 1 条评论 , 1,005 浏览

自从我给尼克技术博客换上J-Spring模板加上了点小修改后在IE核心的浏览器下都很正常,自己也没有装FF就没注意去测试是否效果一样好。多亏长河同学的提醒,FF下文章排行严重错位了,在此感谢一下长河同学,哎~突然不禁感慨,每天来我这里的人也上百人呢,怎么按说用FF来的应该也不少(从流量统计能看到),怎么就没人给我提醒一下呢?郁闷~
牢骚发完了,我们看看是怎么个回事,为什么IE下显示正常,而FF下就严重错位了。学过HTML的人应该都知道网页默认情况下是流式布局的—从上到下,从左到右。
现在来看看我原先的模板代码:

 
  1. <ul class="msg trackback">
  2.     <li class="tbname">文章排行:</li>
  3. <div class="function">
  4.    <h3>最新文章</h3>
  5.    <ul id="ulRandomsortnew">
  6.    <script language="JavaScript" type="text/javascript">strBatchInculde+="ulRandomsortnew=randomsortnew,"</script>
  7.    </ul>
  8. </div>
  9.  
  10. <div class="function">
  11.    <h3>评论排行</h3>
  12.    <ul id="ulRandomsortcommonth">
  13.    <script language="JavaScript" type="text/javascript">strBatchInculde+="ulRandomsortcommonth=randomsortcommonth,"</script>
  14.    </ul>
  15. </div>
  16.  
  17. <div class="function">
  18.    <h3>随机推荐</h3>
  19.    <ul id="ulRandomsortallrand">
  20.    <script language="JavaScript" type="text/javascript">strBatchInculde+="ulRandomsortallrand=randomsortallrand,"</script>
  21.    </ul>
  22. </div>
  23. </ul>
  24.  
  25. <ul class="msg mutuality">
  26.     <li class="tbname"><#ZC_MSG231#>:</li>
  27.     <li class="msgarticle"><#template:article_mutuality#></li>
  28. </ul>

试了好几下终于找到了办法,把<ul class="msg trackback">...</ul>这段HTML标签用<div style="float:right"></div>套起来,这样一来文章排行就会靠右漂浮,将<ul class="msg mutuality">挤下去并靠左,于是乎FF下也都整齐了。

软件测试活动

2008.09.21 , , 无评论 , 693 浏览

软件测试活动包括:制定测试计划、测试设计和开发、执行测试、评估测试。那么这些活动的具体内容包括什么呢?下面我们来分别说明。