2015年6月30日星期二

XMPP使用简介--登录 - 杰瑞教育

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
XMPP使用简介--登录 - 杰瑞教育  阅读原文»

  在现阶段的通信服务中,各种标准都有,因此会出现无法实现相互连通,而XMPP(Extensible Message and presence Protocol)协议的出现,实现了整个及时通信服务协议的互通。有了这个协议之后,使用任何一个组织或者个人提供的即使通信服务,都能够无障碍的与其他的及时通信服务的用户进行交流。例如google 公司2005年推出的Google talk就是一款基于XMPP协议的即时通信软件。下面我们就谈论一下如何简单的使用XMPP

一、环境的搭建,本文采用的是openFire 服务器

  1、下载最新openfire for mac版 http://www.igniterealtime.org/downloads/index.jsp

  2、点击下面图标进行安装JDK 和服务器

  3、启动后,点击Open Admin Console按钮,自动在浏览器中打开本地web配置页面http://localhost:9090/setup/index.jsp然后进行服务器配置

  4、将语言设置为中文即可

  5、设置服务器地址为本机

  6、设置数据库

  在执行此步骤之前需要做一些准备工作,

1创建数据库 :create database openfire;2导入openfire资源文件夹 resources/database下的数据表:source /usr/local/openfire/resources/database/openfire_mysql.sql
7、特性设置

  8、设置openfire服务器管理员的帐号和密码

  9、安装完成,点击按钮登录

  登录后界面如下

  10、按照上面操作创建用户密码

  11、此时的准备工作基本完成

二 导入XMPP

  1、将XMPP全部导入工程

  2、导入依赖包

  由于动态库的存在因此需要做以下操作

三、到目前为止我们的XMPP成功导入到项目中,下面我们开始编码实现用户登录

  1、在代理里面引入包,并且定义流属性

  2、初始化并且添加代理

#pragma mark 初始化
- (void)setUpStream{

if (_stream==nil) {

//1 初始化stream
_stream=[[XMPPStream alloc] init];

//2 添加代理
[_stream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

}

}

  3、建立连接

#pragma mark 建立链接
//建立连接
- (void) connect{

//1 初始化
[self setUpStream];

//2 制定服务器地址,用户名,密码
NSString * userName=@"jereh@jereh.local";
NSString
* hostName=@"jereh.local";

//3 设置JID和主机
XMPPJID * jid=[XMPPJID jidWithString:userName];

[self.stream setMyJID:jid];
[self.stream setHostName:hostName];

//4 开始连接
NSError * error;
[self.stream connectWithTimeout:XMPPStreamTimeoutNone error:
&error];

if (error) {
NSLog(
@"发送连接请求失败");
}
else{
NSLog(
@"发送连接请求成功");
}

}

  5、进行密码验证,通过代理方法返回结果

#pragma mark 验证身份请求
-(void)xmppStreamDidConnect:(XMPPStream *)sender{

NSLog(
@"链接成功");

//发送身份验证请求
NSString * pwd=@"jereh123";
[self.stream authenticateWithPassword:pwd error:nil];
}制作在线简历(三)――技能介绍 - 咖啡机(K.F.J)  阅读原文»

一、结构

结构还是很朴素的,星星是在font-awsome选的一符号,整个结构又是用一张table表格来搭的,选了两种底色作为顶部和左边的底色。

这里由于使用了自定义字体,就碰到了个问题,就是当点到这张星星页面的时候,字体还没加载进来,这个时候星星的位置要么是乱码要么是没有的,后面就去找了个解决方法,使用webfont loader,在字体加载成功的回调函数中再应用相应的font-family的CSS样式。

<script src="js/webfontloader.js"></script>
<script>
WebFont.load({
custom: {
families: [

2015年6月28日星期日

ASP.NET MVC 自定义错误页面心得 - kavensu

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
ASP.NET MVC 自定义错误页面心得 - kavensu  阅读原文»

自定义错误页面的目的,就是为了能让程序在出现错误/异常的时候,能够有较好的显示体验。

所以,首先要先了解,我们可以在哪里捕获异常。

当程序发生错误的时候,我们可以在两个地方捕获:

  1. Global里面的Application_Error 。
  2. HandleErrorAttribute 中的OnException。(需要新建一个类,继承HandleErrorAttribute)

那我们到底应该在哪里处理错误好呢?下面我来给大家说说他们的区别。

Application_Error

程序中发生的所有异常,都可以在这里捕获。但是有一个不足的地方,那就是,如果我们在这里捕获异常之后,需要显示错误页面,那么浏览器上的地址是会改变的,已经被重定向了。也就是说,浏览器上显示的地址,并不是真正发生错误的地址,而是仅仅是显示错误信息的页面地址。这个不足,跟在Web.config的customError中配置错误页面是一样的。

很多时候,我们是希望在访问某个URL后发生了错误,显示错误页面之后,URL还是不变。因此,在这里处理异常并不能满足这种需求。

OnException。(继承HandleErrorAttribute)

MVC的特点就是,每一个请求都对应一个Controller,当在某个Controller中发生异常时,我们都可以在OnException中捕获。但是,如果根本就找不到这个Controller,那么这种错误OnException就无能为力了。举个例子:

假设有个Controller叫About,当访问http://host/About/Index发生错误时,是可以在OnException中捕获的。但如果我访问http://host/Aboute/Index的时候,因为根本不存在Aboute控制器,所以这种错误是无法在OnException捕获的,如果要捕获这种错误,只能在Application_Error中处理。虽然OnException不能捕获所有的错误,但是,它可以解决Application_Error错误页面重定向的问题,在显示错误页面的时候,URL保持不变。

执行顺序

如果发生了错误,会先执行OnException,如果设置 filterContext.ExceptionHandled = true; 则说明该错误已被错误,不会再执行Application_Error,否则会继续执行Application_Error。

参考代码

protected void Application_Error(Object sender, EventArgs e)
{
//当路径出错,无法找到控制器时,不会执行FilterConfig中的OnException,而会在这里捕获。
//当发生404错误时,执行完OnException后,还会执行到这里。
//当发生其他错误,会执行OnException,但在base.OnException中已经处理完错误,不会再到这里执行。
var lastError = Server.GetLastError();
if (lastError != null)
{
var httpError = lastError as HttpException;

if (httpError != null)
{
//Server.ClearError();
switch (httpError.GetHttpCode())
{
case 404:
Response.Redirect(
"/Views/Static/404.html");
break;
}
}
}
}

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class LogExceptionAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
HandleErrorInfo info
= new HandleErrorInfo(filterContext.Exception, controllerName, actionName);

HttpRequestBase request
= filterContext.RequestContext.HttpContext.Request;
string broser = request.Browser.Browser;
string broserVersion = request.Browser.Version;
string system = request.Browser.Platform;
string errBaseInfo = string.Format("UserId={0},Broser={1},BroserVersion={2},System={3},Controller={4},Action={5}", AuthAttribute.GetUserId(), broser, broserVersion, system, controllerName, actionName);
LogUtil.Error(errBaseInfo, filterContext.Exception, Website.LOG_ID);

if (!filterContext.ExceptionHandled)
{
if (filterContext.HttpContext.IsCustomErrorEnabled)
{
filterContext.HttpContext.Response.Clear();
HttpException httpex
= filterContext.Exception as HttpException;
if (httpex != null)
{
filterContext.HttpContext.Response.StatusCode
= httpex.GetHttpCode();
// info = new HandleErrorInfo(ex, controllerName, actionName);
//switch (httpex.GetHttpCode())
//{
// case 403:
// break;
// case 404:
// break;
// default:
// base.OnException(filterContext);
// break;
//}
}
else
{
filterContext.HttpContext.Response.StatusCode
= 500;
}

filterContext.Result
= new ViewResult() { ViewName = "/Views/Shared/Error.cshtml", ViewData = new ViewDataDictionary<HandleErrorInfo>(info) };
filterContext.ExceptionHandled
= true;
Scala学习(六)---Scala对象 - sunddenly  阅读原文»

Scala中的对象

摘要:

在本篇中,你将会学到何时使用Scala的object语法结构。在你需要某个类的单个实例时,或者想为其他函数找一个可以挂靠的地方时,你就会用到它。本篇的要点包括:

1. 用对象作为单例或存放工具方法

2. 类可以拥有—个同名的伴生对象

3. 对象可以扩展类或特质

4. 对象的apply方法通常用来构造伴生类的新实例

5. 如果不想显式定义main方法,可以用扩展App特质的对象

6. 你可以通过扩展Enumeration对象来实现枚举

单例对象

Scala没有静态方法静态字段,你可以用object这个语法结构来达到同样目的。对象定义了某个类的单个实例,包含了你想要的特性。例如:

object Accounts {

private var lastNumber=0

def newUniqueNumber() = { lastNumber+=1, lastNumber}

}

当你在应用程序中需要一个新的唯一账号时,调用Accounts.newUniqueNumber()即可。对象的构造器在该对象第一次被使用时调用。在本例中,Accounts的构造器在Accounts.newUniqueNumber()的首次调用时执行。如果一个对象从未被使用,那么其构造器也不会被执行。

对象本质上可以拥有类的所有特性,它甚至可以扩展其他类或特质。只有一个例外:你不能提供构造器参数。对于任何你在Java或C++中会使用单例对象的地方,在Scala中都可以用对象来实现:

■ 作为存放工具函数常量的地方

■ 高效地共享单个不可变实例

■ 需要用单个实例来协调某个服务时,可参考单例模式

注意:很多人都看低单例模式。Scala提供的是工具,可以做出好的设计,也可以做出糟糕的设计,你需要做出自己的判断。

伴生对象

在Java或C++中,你通常会用到既有实例方法又有静态方法的类。在Scala中,你可以通过和与类同名的"伴生"对象来达到同样的目的。例如:

class Account {

val id=Account.newUniqueNumber()

private var balance =0

def deposit (amount: Double) { balance+=amount }

}

object Account{ // 伴生对象

private var lastNumber=0

private def newUniqueNumber() = { lastNumber+=1;lstNumber }

}

和它的伴生对象可以相互访问私有特性。它们必须存在于同一个源文件中这说明了类的伴生对象可以被访问,但并不在作用域当中。举例来说,Account类必须通过Account.newUniqueNumber()而不是直接用newUniqueNumber()来调用伴生对象的方法。

扩展类或特质的对象

一个object可以扩展类以及一个多个特质,其结果是一个扩展了指定类以及特质类的对象,同时拥有在对象定义中给出的所有特性。一个有用的使用场景是给出可被共享的缺省对象。举例来说,考虑在程序中引入一个可撤销动作的类:

abstract class UndoableAction (val description: String) {

def undo() : Unit

def redo() : Unit

}

默认情况下可以是"什么都不做"。当然了,对于这个行为我们只需要一个实例即可:

object DoNothingAction extends UndoableAction("Do nothing") {

override def undo () {}

override def redo () {}

}

DoNothingAction对象可以被所有需要这个缺省行为的地方共用。

val actions=Map( "open" -> DoNothingAction,"save" -> DoNothingAction,…) // 打开和保存功能尚未实

apply方法

apply含义

我们通常会定义和使用对象的apply方法。当遇到如下形式的表达式时,apply方法就会被调用:

Object(参数1,…,参数N)

通常,这样—个apply方法返回的是伴生类的对象举例来说,Array对象定义了apply方法,让我们可以用下面这样的表达式来创建数组:

Array("Mary", "had", "a", "little", "lamb")

为什么不用构造器呢?对于嵌套表达式而言,省去new关键字会方便很多,例如:

Array (Array (1, 7),Array (2, 9))

注意:Array(100)和new Array(100)很容易搞混。前一个表达式调用的是apply(100),输出一个单元素整数100的Array。而第二个表达式调用的是构造器this(100),结果是Array[Nothing],包含了100个null元素。

apply示例

这里有一个定义apply方法的示例:

class Account private (val id: Int, initialBalance: Double) {

private var balance=initiaIBalance

………

}

object Account { //伴生对象

def apply (initialBalance: Double) =

new Account (newUniqueNumber(), initialBalance)

}

这样一来你就可以用如下代码来构造账号了:

val acct = Account (1000.0)

应用程序对象

main方法

每个Scala程序都必须从一个对象的main方法开始,这个方法的类型为Array[String]=> Unit:

object Hello{

def main (args: Array[String]) {

println("Hello, World! ")

}

}

扩展App特质

除了每次都提供自己的main方法外,你也可以扩展App特质,然后将程序代码放人构造器方法体内:

object Hello extends App{

println("Hello, World! ")

}

命令行参数

如果你需要命令行参数,则可以通过args属性得到:

object Hello extends App{

if (args.length > 0)

println("Hello, "+args (0))

else

println("Hello, World! ")

}

时间特质

如果你在调用该应用程序时设置了scala.time选项的话,程序退出时会显示逝去的时间

scalac Hello.scala

scala -Dscala.time Hello Fred

Hello, Fred

[total 4ms]

所有这些涉及一些小小的魔法。App特质扩展自另一个特质Dela

阅读更多内容

2015年6月25日星期四

一条诡异的insert语句 - 天士梦

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
一条诡异的insert语句 - 天士梦  阅读原文»

问题背景

有同事反馈在mysql上面执行一条普通的insert语句,结果报错,
execute failed due to >>> Incorrect string value: '\xA1;offl...' forcolumn 'biz_info' at row 1

经过半天的折腾,终于搞清楚了来龙去脉,这里简单给大家分享下。为了方便说明,我将测试例子中的表和语句简化,但不影响问题重现。

问题复现

连接字符集:UTF8

表结构:

CREATE TABLE `ggg` (
`id` int(11) DEFAULT NULL,
`c` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

root@test 06:13:48>insert into gggvalues(1,concat('cardName:校园网',char(59),'offlineCardType:campus'));

Query OK, 1 row affected, 1 warning (2.51sec)

root@test 06:14:36>show warnings\G

*************************** 1. row***************************

Level: Warning

Code: 1366

Message: Incorrect string value:'\x91;offl...' for column 'c' at row 1

查看结果

root@test 06:16:06>select * from gggwhere id=1;

*************************** 1. row***************************

id: 1

c: cardName:�″�缃

问题分析

从报错的结果来看,感觉是字符集转换引起的问题,而且由于连接串的字符集是UTF8,表的字符集是GBK,更容易引起怀疑。但是,即使是字符集转换,也不应该导致插入报错,因为语句中的中文字符“校园网"都是普通汉字,UTF8->GBK不应该存在问题。那我们在回过头来看看insert语句,唯一特殊的是使用了concat和char两个函数。会不会跟这两个函数有关系?char(59)实际是字符“;”,为了验证想法,做了两个实验:

  1. 将char(59)替换成';'

insert into ggg values(1,concat('cardName:校园网',';','offlineCardType:campus'));

2.设置连接串字符集为GBK

insert into gggvalues(1,concat('cardName:校园网',char(59),'offlineCardType:campus'));

果然,两种情况执行结果都是OK的,查询结果如下:

root@test 09:22:32>select * fromggg\G

*************************** 1. row***************************

id: 1
c: cardName:�″�缃

*************************** 2. row***************************

id: 1
c: cardName:校园网;offlineCardType:campus

*************************** 3. row***************************

id: 1
c: cardName:校园网;offlineCardType:campus

跟踪了下源代码,找到了原因。char()函数返回的是一个binary类型字符串,在进行concat时,会导致'cardName:校园网'字符串到binary的转换。转换前,mysql将字符串‘cardName:校园网’看作是9个英文字符和3个汉字字符;转换后,mysql将其看作是18个字节的二进制串,其中,UTF8字符集的三个汉字“校园网”占了9个字节。由于目标表字符集是GBK,因此在入库时,还会发生一次binary到GBK的转码,“校园网”的二级制编码是E6A0A1 E59BAD E58DA1,在转码过程中,由于GBK字符集只包含一个字节(编码值<128)和二个字节的字符(汉字和特殊字符),“校园网”的二进制串会按照两个字节拆分E6A0 A1E5 9BAD E58D A1,前面四个变为“�″�缃”,解析到A1时,由于A1既不是单字节字符,又不能与后面的字节组成一个合法的GBK字符,导致转换出错。
现在就很好解释为啥改变语句后,两种情况都OK了。第一种情况,将char(59)直接替换成‘;’,由于不涉及UF8到binary的转换,只有utf8到gbk转码的过程,这个转换是OK的,不会出现乱码;第二种情况,将连接串的字符集设置为GBK,那么会涉及GBK到binary的转换,然后再从binary转换到GBK,由于整个转换过程并没有二进制数据丢失,所以也是OK的。

问题产生的两个关键点

  1. 连接字符集与表字符集不匹配
  2. 使用了char函数

解决办法

1.char函数提供了using语法来实现返回特定字符集的字符串,比如:char(59 using utf8)

2.保证连接字符集与表字符集一致。




本文链接:一条诡异的insert语句,转载请注明。

从手工测试转型web自动化测试继而转型成专门做自动化测试的学习路线。 - 又是你  阅读原文»

在开始之前先自学两个工具
商业web自动化测试工具请自学QTP;QTP的学习可以跳过,我是跳过了的。
开源web自动化测试工具请自学Selenium;我当年是先学watir(耗时1周),再学selenium(也耗时1周)。

这里主要讲一些能让读者和普通菜鸟区别开来的东西,这些请和上面的两个工具穿插地学:

基础:
1.浏览器前端相关的简单技术基础:就是那些什么html、xml、css、javascript、等等,详见w3c教程网站

2.学习使用一个单元测试框架或者叫做测试执行器,建议testNG,学完testNG,你应该具备了3小时学会任何一个测试执行器的能力,我用过的有testNG/Junit/Nunit/ruby unit test/python test unit/visual studio里的测试执行器、等等;

3.学习一个语言的基本语法:
静态语言建议java、动态语言建议python;只需要学基本语法,一般三个月之内都可以学完。我顺便学了一些ruby、groovy、shell脚本等。
4.学习一两个版本控制工具的使用:
svn和git; 我那时候还顺便学了hg,不过现在没多少人用了
只要使用,很简单,请自己找资料
5.学习page object设计模式:
selenium官网有例子,极其简单; 理解这个设计模式花了一两天。用这个模式改写一个网站的全套回归测试用例花了我一个月。
6.学习jenkins的使用:
只要使用,很简单,请自己找资料; 这一点大概花费一个下午时间。
7.学习自动化构建工具的使用:
至少学ant和maven; 这个在学testNG时顺便掌握,只需要简单应用。

提高:
1.浏览器是怎么工作的:
How browsers work

2.学习了解一个关键字驱动的测试执行器,建议robot
Robot Framework 有前面的基础,这个大概学一个下午可简单掌握,深入掌握清熟读官方文档。
3.学习了解一个BDD业务驱动的测试执行器,建议cucmber
Cucumber 个人对BDD持保留意见,有testNG的基础学这个大概一两个下午(这个是用ruby的,我假设你顺便学了ruby语法)。另外我顺便花了一两个下午看了看JBehave(Java的)、Spock(groovy的)。
4.学习几个数据库的简单使用:
mysql,mongodb; 这个w3cschool有教程。自己找。我其实还没看。
5.学习服务器端的操作系统简单使用:
linux,unix及shell脚本之类的; 这个比较费时间,推荐鸟哥的linux私房菜系列。
6.学习其他的商业工具或自动化测试工具
原理都是差不多的,大概有几十种可以学,但都差不多。这个我断断续续把网上能找到都看了看,大概看了几十种吧。其中不乏很奇葩的产品比如fit和fitness
7.继续扩展学习各种开发框架、网络协议等。如果你想去巨头互联网公司做测试开发,学完这条才是刚刚开始;这也是为什么转型做专职的自动化测试、测试开发人员对很多手工测试人员而言这么困难。

当然互联网公司的测试开发前面的很多东西可以跳过不学。有的人跳过的东西太多了,就会开发出各种奇葩的测试框架/工具,但他反正可以做到这个职位了。

8.扩展到其他方向如app自动化、性能等等。如果想去新创业的互联网公司做测试开发,app的自动化肯定要学,但有前面的基础,学这个易如反掌。

其他可有可无的知识(主要用途是吹牛逼、给别人讲课、写文章吹牛逼):

1.黑盒测试理论;一周入门,三个月精通。大部分人学到三个月就够了。觉得自己很懂的同学其实要知道你还不是很懂。因为这块挖深了可以挖出很多神奇但对找份好工作没多大用的理论知识。建议你到架构师层次再来深入学习这些理论以便更好地给人讲课、吹牛逼。

2.白盒测试理论;这个建议还是要懂一点的。比如桩啊驱动啊,覆盖率啊;工具方面可以自学sonar,并尝试和jenkins一起用,集成进一个小项目中。工具不学也没关系因为很少有公司用。个把月可以掌握。但一般在前述很多东西学习时顺便掌握。

3.自动化测试理论;这个N多的人其实压根都不懂。比如你跟他说个数据驱动、业务逻辑和测试实现分离、False alarm误报之类的自动化测试的专有名词他都不知道你说什么鬼。但这种人也可以做自动化测试,做测试开发,所以这个也就是可有可无的了。当然我建议还是要有。顺便你可以看下别人研究的自动化测试ROI的错误计算方法(因为大部分计算方法都是错误的)、自动化测试和手工测试的区别等等。还有什么基于模型的自动化测试设计理论、正交设计法和全配对(pariwise)设计法的异同等等。这些学了之后可以用于吹牛逼和给别人讲课。

4.测试管理理论、项目管理知识:你学了如果没机会也做不了管理。你不学有机会了也可以坐上管理的位子。


本文链接:从手工测试转型web自动化测试继而转型成专门做自动化测试的学习路线。,转载请注明。

阅读更多内容

2015年6月23日星期二

思科路由器PPOE client+NAT解决地址回流问题测试

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
思科路由器PPOE client+NAT解决地址回流问题测试  阅读原文»

一.测试拓扑:
wKiom1WH46fhBjvJAADX2zoss3k937.jpg
二.测试思路:
A.通过不设置方向的ip nat enable解决

---这种方式可以直接用公网IP地址访问,也可以用域名方式访问

---不幸的是思科不同的IOS,有的虽然有ip nat enable,但是实现不了同样的功能

---在有的版本中接口下干脆就不能输入ip nat enable

B.通过设置DNS域名为内网实际地址解决

---这种方式只适用于使用域名访问的方式

---如果是ASA防火墙可以通过NAT添加DNS参数,让修改DNS回包为内网地址解决

---如果客户端DNS为内部服务器,可以直接修改内部服务器DNS记录

---如果没有内部DNS服务器,可以让路由器同时作为DNS代理服务器,同时在它上面配置记录,将域名指向内部服务器的实际地址
三.基本配置:
A.R1:
interface Ethernet0/0
ip address 202.100.1.1 255.255.255.0
no shutdown
ip route 0.0.0.0 0.0.0.0 202.100.1.2
B.R2:
1.接口配置:

interface Ethernet0/0
ip address 202.100.1.2 255.255.255.0
no shutdown
interface Ethernet0/1
no ip address
no shutdown

2.DNS 服务器:

ip dns server

ip host R4.yuntian.cn 202.100.2.4

ip host R1.yuntian.cn 202.100.1.1

3.PPPOE Server配置:
aaa new-model
aaa authentication ppp default local
username cisco password 0 cisco


ip dhcp excluded-address 202.100.2.2

ip dhcp excluded-address 202.100.2.4

ip dhcp pool ppoe
network 202.100.2.0 255.255.255.0
default-router 202.100.2.2

bba-group pppoe TEST
virtual-template 1

interface Virtual-Template1
ip address 202.100.2.2 255.255.255.0
peer default ip address dhcp-pool ppoe
ppp authentication chap callin

ppp ipcp dns 202.100.2.2
interface Ethernet0/1
pppoe enable group TEST
C.R3:
1.接口配置:

interface Ethernet0/0
no ip address
no shutdown
interface Ethernet0/1
ip address 192.168.1.3 255.255.255.0
no shutdown
2.PPPOE Client配置:
interface e0/0
pppoe enable group global
pppoe-client dial-pool-number 1
interface Dialer0
mtu 1492
ip address negotiated
encapsulation ppp
dialer pool 1
ppp chap hostname cisco
ppp chap password 0 cisco

3.DHCP服务器:

ip dhcp excluded-address 192.168.1.3
ip dhcp excluded-address 192.168.1.4

ip dhcp pool client
network 192.168.1.0 255.255.255.0
dns-server 202.100.2.2

D.R4:

interface Ethernet0/0
ip address 192.168.1.4 255.255.255.0
no shutdown

ip route 0.0.0.0 0.0.0.0 192.168.1.3

E.R5:

interface Ethernet0/0
ip address DHCP
no shutdown

---接口IP,默认网关,DNS都由DHCP分配

四.解决地址回流

---都是在R3上面配置

A.方法一:NVI
1.动态PAT配置:
ip access-list extended PAT
permit ip 192.168.1.0 0.0.0.255 any

ip nat source list PAT interface Dialer0 overload

interface Ethernet0/1
ip nat enable

interface Dialer0

ip nat enable

2.静态NAT配置:

ip nat source static 192.168.1.4 202.100.2.4 extendable

3.测试:

---R5能通过R4映射后的公网地址访问R4

R5#telnet 202.100.2.4
Trying 202.100.2.4 ... Open


User Access Verification

Password:
R4>show users
Line User Host(s) Idle Location
0 con 0 UNKNOWN 00:00:16
*130 vty 0 idle 00:00:00 202.100.2.3

Interface User Mode Idle Peer Address

R4>

---R4也能通过R4映射后的公网地址访问R4

R4#telnet 202.100.2.4
Trying 202.100.2.4 ... Open


User Access Verification

Password:
R4>show users
Line User Host(s) Idle Location
0 con 0 202.100.2.4 00:00:00
*131 vty 1 idle 00:00:00 202.100.2.4

Interface User Mode Idle Peer Address

R4>

---通过域名访问时会自动修改DNS记录回包(类似ASA的dns rewrite)

R5#ping R4.yuntian.cn

Translating "R4.yuntian.cn"...domain server (202.100.2.2) [OK]

Translating "R4.yuntian.cn"...domain server (202.100.2.2) [OK]

Translating "R4.yuntian.cn"...domain server (202.100.2.2) [OK]

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.1.4, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 8/32/52 ms
R5#
*Mar 1 02:13:40.991: ICMP: echo reply rcvd, src 192.168.1.4, dst 192.168.1.5
*Mar 1 02:13:41.047: ICMP: echo reply rcvd, src 192.168.1.4, dst 192.168.1.5
*Mar 1 02:13:41.087: ICMP: echo reply rcvd, src 192.168.1.4, dst 192.168.1.5
*Mar 1 02:13:41.095: ICMP: echo reply rcvd, src 192.168.1.4, dst 192.168.1.5
*Mar 1 02:13:41.139: ICMP: echo reply rcvd, src 192.168.1.4, dst 192.168.1.5
R5#

通过不同位置的抓包可以看出,路由器R3修改了DNS的回包,把公网地址修改为内网地址:

--在R2连接R3的接口抓包,可以看到DNS回复的是公网地址

wKioL1WH5X3S3UP2AAKaktHWSuc708.jpg

--但是在R3内网接口抓包,可以看到公网地址已经被修改为内网地址

UITableView代理cellForRowAtIndexPath不执行的相关解决方案  阅读原文»

UITableView代理cellForRowAtIndexPath不执行的相关解决方案

郝萌主倾心贡献,尊重作者的劳动成果,请勿转载。

如果文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额随意,重在心意^_^

我要捐赠:点击捐赠

Cocos2d-X源码下载:点我传送


1、是否设置代理与数据源

[table setDelegate:self];

[table setDataSource:self];

2、numberOfSectionsInTableView是否设置

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

return 1;

}

3、numberOfRowsInSection方法返回值是否正确,如果不正确就不会执行 cellForRowAtIndexPath。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

return1;

}

4、检查Table是否被其他View遮挡

5、还有可能是autolayout引起的,autolayout约束不对,也会导致tableview显示不出来,

cellForRowAtIndexPath是在显示到界面的时候才调用,正确的设置autolayout就会执行该方法。

6、如果纯代码实现,并使用VFL布局参考以下写法

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-64-[table]-50-|" options:0 metrics:nil views:constraintsView ]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[table]-0-|" options:0 metrics:nil views:constraintsView ]];


郝萌主倾心贡献,尊重作者的劳动成果,请勿转载。

如果文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额随意,重在心意^_^

我要捐赠:点击捐赠

Cocos2d-X源码下载:点我传送

本文出自 "郝萌主YuriyHao" 博客,请务必保留此出处http://haomengzhu.blog.51cto.com/1036740/1664340

每日博报 精彩不止一点

阅读更多内容

[.NET领域驱动设计实战系列]专题十:DDD扩展内容:全面剖析CQRS模式实现 - Learning hard

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
[.NET领域驱动设计实战系列]专题十:DDD扩展内容:全面剖析CQRS模式实现 - Learning hard  阅读原文»

一、引言

  前面介绍的所有专题都是基于经典的领域驱动实现的,然而,领域驱动除了经典的实现外,还可以基于CQRS模式来进行实现。本专题将全面剖析如何基于CQRS模式(Command Query Responsibility Segregation,命令查询职责分离)来实现领域驱动设计。

二、CQRS是什么?

  在介绍具体的实现之前,对于之前不了解CQRS的朋友来说,首先第一个问题应该是:什么是CQRS啊?你倒是详细介绍完CQRS后再介绍具体实现啊?既然大家会有这样的问题,所以本专题首先全面介绍下什么是CQRS。

  2.1 CQRS发展历程

  在介绍CQRS之前,我觉得有必要先了解一下CQS(即Command Query Separation,命令查询分离)模式。我们可以理解CQRS是在DDD的实践中基于CQS理论而出现的一种体系结构模式。CQS模式最早由软件大师Bertrand Meyer(Eiffel语言之父,面向对象开-闭原则OCP提出者)提出,他认为,对象的行为仅有两种:命令和查询,不存在第三种情况。根据CQS的思想,任何方法都可以拆分为命令和查询两部分。例如下面的方法:

private int _number = 0;
public int Add(int factor)
{
_number +
= factor;
return _number;
}

  在上面的方法中,执行了一个命令,即对变量_number加上一个因子factor,同时又执行了一个查询,即查询返回_number的值。根据CQS的思想,该方法可以拆成Command和Query两个方法:

private int _number = 0;
private void AddCommand(int factor)
{
_number
+= factor;
}

private int QueryValue()
{
return _number;
}

  命令和查询分离使得我们可以更好地把握对象的细节,更好地理解哪些操作会改变系统的状态。从而使的系统具有更好的扩展性,并获得更好的性能。

  CQRS根据CQS思想,并结合领域驱动设计思想,由Grey Young在CQRS, Task Based UIs, Event Sourcing agh! 这篇文章中提出。CQRS将之前只需要定义一个对象拆分成两个对象,分离的原则按照对象中方法是执行命令还是执行查询来进行拆分的。

  2.2 CQRS结构

  由前面的介绍可知,采用CQRS模式实现的系统结构可以分为两个部分:命令部分和查询部分。其系统结构如下图所示:

  从上面系统结构图可以发现,采用CQRS实现的领域驱动设计与经典DDD有很大的不同。采用CQRS实现的DDD结构大体分为两部分,查询部分和命令部分,并且维护着两个数据库实例,一个专门用来进行查询,另一个用来响应命令操作。然后通过EventHandler操作将命令改变的状态同步到用来查询的数据库实例中。从这个描述中,我们可能会联想到数据库级别主从读写分离。然而数据读写分离是在数据库层面来实现读写分离的机制,而CQRS是在业务逻辑层面来实现读写分离机制。两者是站在两个不同的层面对读写分离进行实现的。

三、为什么需要引入CQRS模式

  前面我们已经详细介绍了CQRS模式,相信经过前面的介绍,大家对CQRS模式一定有一些了解了,但为什么要引入CQRS模式呢?

  在传统的实现中,对DB执行增、删、改、查所有操作都会放在对应的仓储中,并且这些操作都公用一份领域实体对象。对于一些简单的系统,使用传统的设计方式并没有什么不妥,但在一些大型复杂的系统中,传统的实现方式也会存在一些问题:

  • 使用同一个领域实体来进行数据读写可能会遇到资源竞争的情况。所以经常要处理锁的问题,在写入数据的时候,需要加锁,读取数据的时候需要判断是否允许脏读。这样使得系统的逻辑性和复杂性增加,并会影响系统的吞吐量。
  • 在大数据量同时进行读写的情况下,可能出现性能的瓶颈。
  • 使用同一个领域实体来进行数据库读写可能会太粗糙。在大多是情况下,比如编辑操作,可能只需要更新个别字段,这时却需要将整个对象都穿进去。还有在查询的时候,表现层可能只需要个别字段,但需要查询和返回整个领域实体,再把领域实体对象转换从对应的DTO对象。
  • 读写操作都耦合在一起,不利于对问题的跟踪和分析,如果读写操作分离的话,如果是由于状态改变的问题就只需要去分析写操作相关的逻辑就可以了,如果是关于数据的不正确,则只需要关心查询操作的相关逻辑即可。

  针对上面的这些问题,采用CQRS模式的系统都可以解决。由于CQRS模式中将查询和命令进行分析,所以使得两者分工明确,各自负责不同的部分,并且在业务上将命令和查询分离能够提高系统的性能和可扩展性。既然CQRS这么好,那是不是所有系统都应该基于CQRS模式去实现呢?显然不是的,CQRS也有其使用场景:

  1. 系统的业务逻辑比较复杂的情况下。因为本来业务逻辑就比较复杂了,如果再把命令操作和查询操作绑定同一个业务实体的话,这样会导致后期的需求变更难于进行扩展下去。
  2. 需要对系统中查询性能和写入性能分开进行优化的情况下,尤其读/写比例非常高的情况下。例如,在很多系统中读操作的请求数远大于写操作,此时,就可以考虑将写操作抽离出来进行单独扩展。
  3. 系统在将来随着时间不断变化的情况下。

  然而,CQRS也有其不适用的场景:

  • 业务逻辑比较简单的情况下,此时采用CQRS反而会把系统搞的复杂。
  • 系统用户访问量都比较小的情况下,并且需求以后不怎么会变更的情况下。针对这样的系统,完全可以用传统的实现方式快速将系统实现出来,没必要引入CQRS来增加系统的复杂度。

四、事件溯源

  在CQRS中,查询方面,直接通过方法查询数据库,然后通过DTO将数据返回,这个方面的操作相对比较简单。而命令方面,是通过发送具体Command,接着由CommandBus来分发到具体的CommandHandle来进行处理,CommandHandle在进行处理时,并没有直接将对象的状态保存到外部持久化结构中,而仅仅是从领域对象中获得产生的一系列领域事件,并将这些事件保存到Event Store中,同时将事件发布到事件总线Event Bus进行下一步处理;接着Event Bus同样进行协调,将具体的事件交给具体的Event Handle进行处理,最后Event Handler再把对象的状态保存到对应Query数据库中。

  上面过程正是CQRS系统中的调用顺序。从中可以发现,采用CQRS实现的系统存在两个数据库实例,一个是Event Store,该数据库实例用来保存领域对象中发生的一系列的领域事件,简单来说就是保存领域事件的数据库。另一个是Query Database,该数据库就是存储具体的领域对象数据的,查询操作可以直接对该数据库进行查询。由于,我们在Event Store中记录领域对象发生的所有事件,这样我们就可以通过查询该数据库实例来获得领域对象之前的所有状态了。所谓Event Sourcing,就是指的的是:通过事件追溯对象的起源,它允许通过记录下来的事件,将领域模型恢复到之前的任意一个时间点。

  通过Event来记录领域对象所发生的所有状态,这样利用系统的跟踪并能够方便地回滚到某一历史状态。经过上面的描述,感觉事件溯源一般用于系统的维护。例如,我们可以设计一个同步服务,该服务程序从Event Store数据库查询出领域对象的历史数据,从而打印生成一个历史报表,如历史价格报表等。但正是的CQRS系统中如何使用Event Sourcing的呢?

  在前面介绍CQRS系统的调用顺序中,我们讲到,由Event Handler将对象的状态保存到对应的Query数据库中,这里有一个问题,对象的状态怎么获得呢?对象状态的获得正是由Event sourcing机制来获得,因为用户发送的仅仅是Command,Command中并不包含对象的状态数据,所以此时需要通过Event Sourcing机制来查询Event Store来还原对象的状态,还原根据就是对应的Id,该Id是通过命令传入的。Event Sourcing的调用需要放在CommandHandle中,因为CommandHandle需要先获得领域对象,这样才能把领域对象与命令对象来进行对比,从而获得领域对象中产生的一系列领域事件。

五、快照

  然而,当随着时间的推移,领域事件变得越来越多时,通过Event Sourcing机制来还原对象状态的过程会非常耗时,因为每一次都需要从最早发生的事件开始。那有没有好的一个方式来解决这个问题呢?答案是肯定的,即在Event Sourcing中引入快照(Snapshots)实现。实现原理就是——没产生N个领域事件,则对对象做一次快照。这样,领域对象溯源的时候,可以先从快照中获得最近一次的快照,然后再逐个应用快照之后所有产生的领域事件,而不需要每次溯源都从最开始的事件开始对对象重建,这样就大大加快了对象重建的过程。

六、CQRS模式实现和剖析

  前面介绍了那么多CQRS的内容,下面就具体通过一个例子来演示下CQRS系统的实现。

  命令部分的实现

堆表上的转发记录 - woodytu  阅读原文»

今天这篇文章我想谈下堆表上特有的性能问题:转发记录(Forwarding Records)。首先我们要澄清下什么是堆表:堆表就是没有聚集索引定义的表。它对插入新记录非常快,但当你读取数据时非常慢。读取数据会在你的存储子系统上引入随机存取(random I/O) 有时候当你碰到转发记录,它会进一步降低你的读取性能。

为什么会有转发记录?

当堆表里的记录需要移动到不同的物理位置时,SQL Server使用转发记录。假设你有一个变长列的表,首先你在堆表里插入一些记录,这个时候你没有在变长列里存储任何数据:

1 -- Create a table to demonstrate forwarding records
2 CREATE TABLE HeapTable
3 (
4 Col1 INT IDENTITY(1, 1),
5 Col2 CHAR(2000),
6 Col3 VARCHAR(1000)
7 )
8 GO
9
10 -- Insert 4 records - those will fit into one page
11 INSERT INTO HeapTable VALUES
12 (
13 REPLICATE('1', 2000),
14 ''
15 ),
16 (
17 REPLICATE('2', 2000),
18 ''
19 ),
20 (
21 REPLICATE('3', 2000),
22 ''
23 ),
24 (
25 REPLICATE('4', 2000),
26 ''
27 )
28 GO

当你在变长列执行UPDATE语句时,想象下会发生什么?在那个情况下SQL Server可能需要扩展这个记录,因为记录大小更长了,其他记录必须从同个数据页移走。

1 -- Let's update the table and expand each row of the table
2 UPDATE HeapTable
3 SET Col3 = REPLICATE('5', 1000)
4 GO

在那个情况下,SQL Server在原始位置留下称为转发记录,它指向记录最终存储的新位置。

SQL Server需要使用这个方法来避免更新同个表上所有非聚集索引。你可能知道,当你在堆表上创建非聚集索引时,在叶子层,非聚集索引指向记录数据存储的物理位置。没有抓发记录的话,所有这些指针都要改变,这会大幅度降低你的性能。

如何修正转发记录?

为了找出表里是否包含转发记录,你可以使用DMF sys.dm_db_index_physical_stats。当你在堆表上调用这个函数并传入DETAILED模式,SQL Server通过forwarded_record_count列告诉你表上的转发记录数。

1 -- Check the forwarding record count through sys.dm_db_index_physical_stats
2 SELECT
3 index_type_desc,
4 page_count,
5 avg_page_space_used_in_percent,
6 avg_record_size_in_bytes,
7 forwarded_record_count
8 FROM sys.dm_db_index_physical_stats
9 (
10 DB_ID('ALLOCATIONDB'),
11 OBJECT_ID('HeapTable'),
12 NULL,
13 NULL,
14 'DETAILED'
15 )
16 GO

可以看到,表上有2条转发记录,在4条记录之外。为了去掉这些转发记录,你可以重建表。

1 -- Rebuild the heap table to get rid of the Forwarding Records
2 ALTER TABLE HeapTa

阅读更多内容

2015年6月21日星期日

Java知多少(100)图像处理基础 - Coda

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
Java知多少(100)图像处理基础 - Coda  阅读原文»

图像是由一组像素构成,用二进制形式保存的图片。java语言支持GIF、JPEG和BMP这3种主要图像文件格式。java语言的图像处理功能被封装在Image类中。

图像载入和输出

在java程序中,图像也是对象,所以载入图像时,先要声明Image对象,然后,利用getImage()方法把Image对象与图像文件联系起来。载入图像文件的方法有两个:

  • Image getImage(URL url),url指明图像所在位置和文件名。
  • Image getImage(URL url,String name),url指明图像所在位置,name是文件名。


例如,以下代码声明Image对象,并用getImage()对象与图像文件联系起来:

1 Image img = getImage(getCodeBase(),”family.jpg”);

URL(uniform Resource Location 统一资源定位符)对象用于标识资源的名字和地址,在WWW客户机访问Internet网上资源时使用。确定图像位置的方法有两种:绝对位置与相对位置。取相对位置的方法有:

  • URL getCodeBase(),取小应用程序文件所在的位置。
  • URL getDocumentBase(),取HTML文件所在的位置。


例如,代码:

1 URL picURLA = new URL(getDocumentBase(),”imageSample1.gif”),
2 picURLB = new URL(getDocumentBase(),”pictures/imageSample.gif”);
3 Image imageA = getImage(picURLA),imageB = getImage(picURLB);

获取图像信息(属性)的方法有:

  • getWidth(ImageObserver observer):取宽度;
  • getHeight(ImageObserver observer):取高度。


输出图像的代码写在paint()方法中,有4种显示图像的方法:

  • boolean drawImage(Image img,int x,int y,ImageObserver observer)
  • boolean drawImage(Image img,int x,int y,Color bgcolor,ImageObserver observer)
  • boolean drawImage(Image img,int x,int y,int width,int height,ImageObsever observer)
  • boolean drawImage(Image img,int x,int y,int width,int height,Color bgcolor,ImageObsever observer)

参数img是Image对象,x,y是绘制图像矩形的左上角位置,observer是加载图像时的图像观察器,bgcolor是显示图像用的底色,width和height是显示图像的矩形区域,当这个区域与图像的大小不同时,显示图像就会有缩放处理。

Applet类也实现ImageObserver接口,常用this作为实参。参见以下代码及注释:

  • (1) g.drawImage(image1,0,0,this);//原图显示
  • (2) g.drawImage(image2,10,10,Color.red,this);//图形加底色显示
    注意:如原图的大小与给定的范围不同,系统会自动缩放
  • (3) g.drawImage(labImag,0,0,this);// 原图显示
  • (4) g.grawImage(labImag,0,120,100,100,this);//缩放显示
  • (5) g.grawImage(labImag,0,240,500,100,this);//缩放显示


【例 12-5】小应用程序用init()或start()方法下载(获取)图像,用paint()方法显示得到的图像。

1 import java.applet.*;import java.awt.*;
2 public class Example7_5 extends Applet{
3 Image myImag;
4 public void start(){
5 myImag = getImage(getCodeBase(),”myPic.jpg”);
6 }
7 public void paint(Graphics g){
8 g.drawImage(myImg,2,2,this);
9 }
10 }

由于在Frame、JFrame和JPanel等类中没有提供getImage()方法,它们载入图像需要使用java.awt.Toolkit中的Toolkit抽象类,该类有载入图像文件的方法:

  • Image.getImage(String name):按指定的文件名载入图像文件。
  • Image.getImage(URL url):统一资源定位符载入图像文件。


这样,各种组件可以用getToolkit()方法得到Toolkit对象,然后在组件的paint()方法中通过Toolkit对象显示图像。以下代码示意这样的用法:

1 Toolkit tool = getToolkit();
2 URL url = new URL(http://www.weixueyuan.net/image.gif);
3 Image img = tool.getImage(url);

组件也可以使用Toolkit提供的静态方法getDefaultToolkit()获得一个缺省的Toolkit对象,并用它加载图像。此时,载入图像的代码常写成这样:

Image img = Toolkit.getDefaultToolkit().getImage(url);

系列文章:

上周热点回顾(6.15-6.21) - 博客园团队  阅读原文»

热点随笔:

· 找女神要QQ号码奔跑的Man
· 聊一下C#开发者如何过渡到JAVA 开发者codesnippet.info
· 打车软件烧钱背后的商业逻辑马非码
· 对程序员说点实在话foreach_break
· 网站接入支付宝疯吻IT
· .NET平台下的微信SDK(Rabbit.WeiXin)开源发布KAnts
· EasyUI实战经验总结,给有需要的人淮左
· 程序员"青春饭"问题之我见hzg1981
· 如何实现:录制视频聊天的全过程? 【低调赠送:QQ高仿版GG 4.3 最新源码】GG2014
· 即使用ADO.NET,也要轻量级动态生成更新SQL,比Ormlite性能更高Tony Tan
· .NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)DotNet开源大本营
· 移动开发中Fiddler的那些事儿咖啡机(K.F.J)

热点新闻:

· 让程序员跳槽的非钱原因
· 免费Windows 10虽好 但微软的做法太蠢
· 微软的“特洛伊木马” 前诺基亚CEO埃洛普竟然从微软离职了!
· 世界第一的人脸检测技术背后的四个 90 后美女学霸
· 女学霸获26份大学录取通知书 奖学金1860万
· 程序员是怎样一群人
· “伟大”的新商业模式:如何优雅地骗傻子钱?
· 秒杀磁悬浮的交通方式超级高铁要来了 北京到上海1小时
· 刘姝威评贾跃亭减持套现25亿:钱来的太容易
· 吴晓波:关于手机我不明白的事
· 诺基亚半成品Meltemi OS工程样机曝光
· 面试前妹妹过世,美国男子收到谷歌的慰问信


本文链接:上周热点回顾(6.15-6.21),转载请注明。

阅读更多内容

2015年6月20日星期六

Matlab实现二进制矩阵转换为十进制 - DM张朋飞

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
Matlab实现二进制矩阵转换为十进制 - DM张朋飞  阅读原文»

一.问题描述  

  [1 1 1 0 1

  0 1 1 0 1

  0 0 1 1 0]

每两位3转换为一个十进制数,共5列,那么转换后是ceil(5/3)=2列。

  [7 1

  6 1

  1 2]

二.问题分析

  1.每八个字符划分为一个十进制,nwords=ceil(size(b,2)/8)

  2.按列处理每行的字符,只不过1到8是一组,为第一列;9到17是二组,为第2列。

  cb = zeros(,'uint8')

  for(j=1:size(b,2))

  {

    w = ceil(j/8);

    //用bitset(A,bit,Value),bit没组都是1到8

    cb(:,w) = bitset(cb(:,w),mod(j-1,8)+1,b(:,j))

  }

三.实现

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function cb = compactbit(b)
%
% b = bits array
% cb = compacted string of bits (using words of 'word' bits)

[nSamples nbits] = size(b);
nwords = ceil(nbits/8);%向上取整(正无穷方向)压缩bit->word.
cb = zeros([nSamples nwords], 'uint8');

for j = 1:nbits
w = ceil(j/8);
cb(:,w) = bitset(cb(:,w), mod(j-1,8)+1, b(:,j));
end


本文链接:Matlab实现二进制矩阵转换为十进制,转载请注明。

linq分页扩展 - 漫漫洒洒  阅读原文»

直接上代码了

public static List<T> ToPagedList<T>(this IEnumerable<T> allItems, int pageIndex, int pageSize, Expression<Func<T, int>> keySelector)
{
var itemList = allItems.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}
public static List<T> ToPagedList<T>(this IEnumerable<T> allItems, int pageIndex, int pageSize, Expression<Func<T, bool>> keySelector)
{
var itemList = allItems.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}
public static List<T> ToPagedList<T>(this IEnumerable<T> allItems, int pageIndex, int pageSize, Expression<Func<T, string>> keySelector)
{
var itemList = allItems.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}
public static List<T> ToPagedList<T>(this IEnumerable<T> allItems, int pageIndex, int pageSize, Expression<Func<T, DateTime>> keySelector)
{
var itemList = allItems.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}
public static List<T> ToPagedList<T>(this IQueryable<T> allItems, int pageIndex, int pageSize, Expression<Func<T,int>> keySelector)
{
var itemList = allItems.OrderBy(keySelector).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}
public static List<T> ToPagedList<T>(this IQueryable<T> allItems, int pageIndex, int pageSize, Expression<Func<T, bool>> keySelector)
{
var itemList = allItems.OrderBy(keySelector).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}
public static List<T> ToPagedList<T>(this IQueryable<T> allItems, int pageIndex, int pageSize, Expression<Func<T, string>> keySelector)
{
var itemList = allItems.OrderBy(keySelector).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}
public static List<T> ToPagedList<T>(this IQueryable<T> allItems, int pageIndex, int pageSize, Expression<Func<T, DateTime>> keySelector)
{
var itemList = allItems.OrderBy(keySelector).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
return itemList;
}


本文链接:linq分页扩展,转载请注明。

阅读更多内容