[转载]ASP.NET MVC 小牛之路05 - 在ASP.NET MVC中使用Ninject - Liam Wang - 博客园

mikel阅读(1095)

[转载][ASP.NET MVC 小牛之路]05 – 在ASP.NET MVC中使用Ninject – Liam Wang – 博客园.

在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来演示Ninject在ASP.NET MVC中的应用。

为了更好的理解和撑握本文内容,强烈建议初学者阅读本文前先阅读依赖注入(DI)和Ninject

本文目录:

1.准备工作

2.创建Controller Factory

3.添加Domain Model

4.添加Repository

5.添加绑定

6.显示列表

准备工作

新建一个名为BookShop的空白解决方案。在该解决方案中分别添加一个名为BookShop.WebUI的MVC空应用程序,和一个名为BookShop.Domain的类库工程。目录结构如下:

两个工程添加完后,在BookShop.WebUI工程下添加BookShop.Domain工程的引用。

使用NuGet分别为BookShop.WebUI工程和BookShop.Domain工程安装Ninject包(NuGet的介绍请阅读依赖注入(DI)和Ninject)。可以通过可视化窗口安装,也可以打开Package Manager Console(视图->其他窗口->Package Manager Console)执行下面命令安装:
Install-Package Ninject -Project BookShop.WebUI
Install-Package Ninject -Project BookShop.Domain
下图说明安装成功:

创建Controller Factory

我们知道,在ASP.NET MVC中,一个客户端请求是在特定Controller的Action中进行处理的。 默认情况下,ASP.NET MVC使用内置的Controller工厂类 DefaultControllerFactory来创建某个请求对应的Controller实例。有时候默认的Controller工厂不能满足我们实 际的需求,我们就需要对这种默认行为进行扩展,即创建一个继承自DefaultControllerFactory类的自定义Controller工厂类 并重写其中的一些方法。为此,我们在BookShop.WebUI工程下创建一个名为Infrastructure的文件夹,在该文件夹中添加一个名为 NinjectControllerFactory的工厂类,代码如下:

public class NinjectControllerFactory : DefaultControllerFactory {
    private IKernel ninjectKernel;

    public NinjectControllerFactory() {
        ninjectKernel = new StandardKernel();
        AddBindings();
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
        return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
    }

    private void AddBindings() {
        // todo:后面再来添加绑定
    }
}

上面代码中 的 ninjectKernel.Get(controllerType) 可获取到一个Controller实例。在这里如果手动实例化Controller类是一个非常复杂的过程,我们不知道Controller类有没有带参 数的构造函数,也不知道构造函数的参数是什么类型。而使用Ninject只需要使用上面的一个Get方法就可以,Ninject内部会自动处理所有的依赖 关系,智能地创建我们需要的对象。

Controller工厂类创建好后,我们就需要告诉MVC用我们的NinjectControllerFactory类来创建Controller对象,为此,需在Global.asax文件的Application_Start方法中添加下面代码:

protected void Application_Start() {
    ......

    //设置Controller工厂
    ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}

这里我们暂且不去关心上面这段代码是什么原理,知道设置自定义的Controller工厂必须要在这注册就行了,有空的话我会在后续博文对这部分内容进行更深入的讲解。

添加Domain Model

在MVC应用程序中,一切都是围绕Domain Model(领域模型)来的。 所以我们在BookShop.Domain工程中专门建一个名为Entities的文件夹,用来存放领域实体模型。作为一个电子商务类的网上书店,当然最 重要的一个领域实体就是Book了。由于只是为了演示,我们简单定义一个Book类,并在Entities文件夹中添加该类,代码如下:

public class Book {
    public int ID { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
    public string Summary { get; set; }
    public string Author { get; set; }
    public string Thumbnail { get; set; }
    public double Price { get; set; }
    public DateTime Published { get; set; }
}

添加Repository

我们知道,我们肯定需要一种方式来从数据库中读取Book数据。在这我们不防为数据的使用者(这里指Controller)提供一个 IBookRepository接口,在这个接口中声明一个IQueryable<Book>类型的属性Books。这样,通过该接口使用依 赖注入,使用者就可以拿到Books数据集合,而不用关心数据是如何得到的。为此,我们在BookShop.Domain工程中添加一个名为 Abstract的文件夹,在该文件夹中添加我们的IBookRepository接口文件,代码如下:

public interface IBookRepository {
    IQueryable<Book> Books { get; }
}

在MVC中我们一般会用仓储模式(Repository Pattern)把数据相关的逻辑和领域实体模型分离,这样对于使用者来说,通过调用仓储对象,使用者可以直接拿到自己想要的数据,而完全不必关心数据具 体是如何来的。我们可以把仓储比喻成一个超市,超市已经为消费者供备好了商品,消费者只管去超市选购自己需要的商品,而完全不必关心这些商品是从哪些供应 商怎么样运输到超市的。但对于仓储本身,必须要实现读取数据的“渠道”。

在BookShop.Domain工程中添加一个名为Concrete文件夹用于存放具体的类。我们在Concrete文件夹中添加一个实现了 IBookRepository接口的BookRepository类来作为我们的Book数据仓储。BookRepository类代码如下:

public class BookRepository : IBookRepository {

    public IQueryable<Book> Books {
        get { return GetBooks().AsQueryable(); }
    }

    private static List<Book> GetBooks() {  
        //为了演示,这里手工造一些数据,后面会介绍使用EF从数据库中读取。
        List<Book> books = new List<Book>{
            new Book { ID = 1, Title = "ASP.NET MVC 4 编程", Price = 52},
            new Book { ID = 2, Title = "CLR Via C#", Price = 46},
            new Book { ID = 3, Title = "平凡的世界", Price = 37}
        };
        return books;
    }
}

为了演示,上面是手工造的一些数据,后面的文章我将介绍使用Entity Framwork从数据库中读取数据。对于刚接触ORM框架的朋友可能对这里IQueryable感到奇怪,为什么用IQueryable作为返回类型, 而不用IEnumerable呢?后面有机会讲Entity Framwork的时候再讲。

添加绑定

打开之前我们在BookShop.WebUI工程创建的NinjectControllerFactory类,在AddBindings方法中添加如下代码:

private void AddBindings() {
    ninjectKernel.Bind<IBookRepository>().To<BookRepository>();
}

这句代码,通过Ninject把IBookRepository接口绑定到BookRepository,当IBookRepository接口的实现被请求时,Ninject将自动创建BookRepository类的实例。

到这里,Ninject的使用步骤就结束了,接下来我们把本示例剩余的步骤完成。

显示列表

右击BookShop.WebUI工程的Controllers文件夹,添加一个名为Book的Controller,按下面代码对其进行编辑:

public class BookController : Controller {
    private IBookRepository repository;

    public BookController(IBookRepository bookRepository) {
        repository = bookRepository;
    }
}

在这,BookController的构造函数接受了一个IBookRepository参数,当BookController被实例化的时 候,Ninject就为其注入了BookRepository的依赖。接下来我们为这个Controller添加一个名为List的Action,用来呈 现Book列表。代码如下:

public class BookController : Controller {
    ...

    public ViewResult List() {
        return View(repository.Books);
    }
}

当然我们需要添加一个View。右击上面的List方法,选择添加视图,在弹出的窗口进行如下配置:

然后我们在List.cshtml中用foreach循环来列举书本信息,代码如下:

@model IEnumerable<BookShop.Domain.Entities.Book>

@{
    ViewBag.Title = "Books";
}

@foreach (var p in Model) {  
    <div class="item" style="border-bottom:1px dashed silver;"> 
        <h3>@p.Title</h3> 
        <p>价格:@p.Price.ToString("c") </p>   
    </div>     
}

最后我们还需要修改一下默认路由,让系统运行后直接导向到我们的{controller = “Book”, action = “List”},打开Global.asax文件,找到RegisterRoutes方法,进行如下修改:

public static void RegisterRoutes(RouteCollection routes) {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name 
        "{controller}/{action}/{id}", // URL with parameters 
        new { controller = "Book", action = "List", id = UrlParameter.Optional }
    );
}

到这,我们的程序可以运行了,效果如下:

 

结束语:

本文是Ninject在ASP.NET MVC中使用的一个简单示例,目的是让大家了解Ninject在MVC中的使用方法。当然,Ninject的强大之处不仅限于本文所演示的,相信当你熟悉 了Niject之后,在搭建MVC应用程序时,你一定会喜欢上它的。至于本文的示例BookShop,我会在后续博文中慢慢完善,让它看起来像个像样的网 上书店。

 

参考:

《Pro ASP.NET MVC 4》

[转载]Struts迭代器(iterator)遍历List常用的4种例子 - 冯世杰 - 博客园

mikel阅读(1076)

[转载]Struts迭代器(iterator)遍历List常用的4种例子 – 冯世杰 – 博客园.

【摘要】本文主要介绍及演示了Struts迭代器(iterator)遍历List常用的4种例子,基于MyEclipse开发环境,重点关注前后端代码的实现,给出后端java代码、前段struts标签代码,主要有如下4个例子:

1. 遍历List<String>

2. 遍历List<List<String>>
3. 遍历UserEntity
4. 遍历List<UserEntity>

例子的详细代码请参考附件1,给出两个4个例子的运行截图(如下图1):
图1:遍历Listd的4个例子运行结果
图1:遍历Listd的4个例子运行结果
关键词:Struts标签,iterator迭代器,List<String>,List<List<String>>

1、遍历List<String>  

(1)后台TestAction.java 部分代码:

复制代码
1         // TODO 给list赋值
2         if (list==null) {
3             list=new ArrayList<String>();
4             list.add("刘备");
5             list.add("关羽");
6             list.add("张飞");
7             list.add("赵云");
8         }
复制代码

(2)前台jsp+s标签部分源代码:

复制代码
 1                     <%--List<String>遍历--%>
 2                     <table width="242" height="256" border="1" cellpadding="1"
 3                         cellspacing="1">
 4                         <caption>
 5                             List&ltString&gt遍历
 6                         </caption>
 7                         <tr>
 8                             <%--
 9                         说明:<s:iterator id="别名" value="后台List变量名">
10                               <s:if test="#别名!=null">
11                             --%>
12                             <s:iterator id="li" value="list">
13                                 <td>
14                                     <s:if test="#li!=null">
15                                         <s:property />
16                                     </s:if>
17                                 </td>
18                             </s:iterator>
19                         </tr>
20                     </table>
复制代码

注:遍历List<String>运行结果参考上图1(左上)

2、遍历List<List<String>>

(1)后台TestAction.java 部分代码:

复制代码
 1         // TODO 给listList赋值(二维列表List)
 2         if (listList==null) {
 3             listList=new ArrayList<List<String>>();
 4             List<String> li=new ArrayList<String>();
 5             li.add("姓名");
 6             li.add("势力");
 7             li.add("职务");
 8             listList.add(li);
 9             /*List为引用类型(以地址方式保存一维List对象),
10             添加不同List到二维列表需再实例化    */        
11             li=new ArrayList<String>();
12             li.add("刘备");
13             li.add("蜀");
14             li.add("老大");
15             listList.add(li);
16             li=new ArrayList<String>();
17             li.add("关羽");
18             li.add("蜀");
19             li.add("老2");
20             listList.add(li);
21             li=new ArrayList<String>();
22             li.add("张飞");
23             li.add("蜀");
24             li.add("老3");
25             listList.add(li);
26             li=new ArrayList<String>();
27             li.add("赵云");
28             li.add("蜀");
29             li.add("大将");
30             listList.add(li);
复制代码

(2)前台jsp+s标签部分源代码:

复制代码
 1     <%--List<List<String>>遍历--%>
 2                     <table width="242" height="256" border="1" cellpadding="1"
 3                         cellspacing="1">
 4                         <caption>
 5                             List&ltList&ltString&gt&gt遍历如下:
 6                         </caption>
 7                         <s:iterator value="#request.listList" status="st">
 8                             <tr>
 9                                 <s:iterator value="#request.listList.get(#st.index)">
10                                     <td valign="middle" align="center">
11                                         <s:property />
12                                     </td>
13                                 </s:iterator>
14                             </tr>
15                         </s:iterator>
16                     </table>
复制代码

注:遍历List<List<String>>运行结果参考上图1(右上)

3、遍历UserEntity

(1)后台TestAction.java 部分代码:

1 // TODO 给UserEntity赋值
2             if (userEntity==null) {
3                 userEntity=new UserEntity("诸葛亮","男",37);
4             }

(2)前台jsp+s标签部分源代码:

复制代码
 1                     <%--UserEntity遍历如下:--%>
 2                     <table width="242" height="256" border="1" cellpadding="1"
 3                         cellspacing="1">
 4                         <caption>
 5                             UserEntity遍历如下:
 6                         </caption>
 7                         <tr>
 8                             <%--<td><s:property value="#变量名.属性名" /></td>--%>
 9                             <td>
10                                 <s:property value="userEntity.name" />
11                             </td>
12                             <td>
13                                 <s:property value="userEntity.sex" />
14                             </td>
15                             <td>
16                                 <s:property value="userEntity.age" />
17                             </td>
18                         </tr>
19                     </table>
复制代码

注:遍历UserEntity运行结果参考上图1(左下)

4、遍历List<UserEntity>

(1)后台TestAction.java 部分代码:

复制代码
 1 // TODO 给List<UserEntity>赋值
 2     if (users==null) {
 3         users=new ArrayList<UserEntity> ();
 4         UserEntity user=new UserEntity("张飞","男",18);
 5         users.add(user);
 6         user=new UserEntity("李斯","男",19);
 7         users.add(user);
 8         user=new UserEntity("王武","男",20);
 9         users.add(user);
10         user=new UserEntity("小乔","女",21);
11         users.add(user);
12     }
复制代码

(2)前台jsp+s标签部分源代码:

复制代码
 1 <%-- List<UserEntity>遍历如下:--%>
 2                     <table width="242" height="256" border="1" cellpadding="1"
 3                         cellspacing="1">
 4                         <caption>
 5                             List&ltUserEntity&gt遍历如下:
 6                         </caption>
 7                         <tr>
 8                             <th>
 9                                 姓名
10                             </th>
11                             <th>
12                                 性别
13                             </th>
14                             <th>
15                                 年龄
16                             </th>
17                         </tr>
18                         <s:iterator id="u" value="users">
19                             <%--
20         <s:iterator  id="別名"  value="要遍历的集合">
21         users:对应后台Action类的List<UserEntity> users;
22         --%>
23                             <tr>
24                                 <%--<td><s:property value="#別名.实体类属性名" /></td>--%>
25                                 <td>
26                                     <s:property value="#u.name" />
27                                 </td>
28                                 <td>
29                                     <s:property value="#u.sex" />
30                                 </td>
31                                 <td>
32                                     <s:property value="#u.age" />
33                                 </td>
34                             </tr>
35                         </s:iterator>
36                     </table>
复制代码

注:遍历List<UserEntity>运行结果参考上图1(右下)

5、用法比较

(1)比较List<String>和UserEntity

它们遍历显示效果类似,但是细心的朋友会发现,它们主要有以下区别:
区别1:List<String>的遍历需要iterator迭代器如<s:iterator id=”别名” value=”后台List变量名”>,且不需要value属性直接用<s:property />获取列表元素;
区别2:UserEntity刚相反,不需要iterator迭代器,但需要value属性<s:property value=”#变量名.属性名” />来获取列表元素。

(2)比较List<List<String>>和List<UserEntity>

它们遍历显示效果也类似,它们也有以下区别:
  区别1:List<List<String>>由于列表没有属性需要借助迭代器的属性status=”st”,
如:

复制代码
<s:iterator value="#request.listList" status="st">
  <tr>
    <s:iterator value="#request.listList.get(#st.index)">
        <td valign="middle" align="center">
          <s:property />
        </td>
</s:iterator>
</tr>
</s:iterator>
复制代码

区别2:List<UserEntity>则简单多,借用迭代器iterator的id、value属性,再用<s:property value=”#別名.实体类属性名” />获取

  如:

复制代码
<s:iterator id="u" value="users">
   <tr>
       <td>
         <s:property value="#u.name" />
       </td>
       <td>
         <s:property value="#u.sex" />
       </td>
       <td>
         <s:property value="#u.age" />
       </td>
   </tr>
</s:iterator>
复制代码

  综合以上的对比分析:遍历方法各有长短,若不是多表联接查询、显示表格的列数已经固定一般用实体类(UserEntity)迭代的方式。相反,显示的数据表格行和列不确定,此时用实体类(UserEntity)迭代的方式很难实现,只能用List<String>或List<List<String>>实现了。

[转载]string中Insert与Format效率对比、String与List中Contains与IndexOf的效率对比 - alert(dong) - 博客园

mikel阅读(1071)

[转载]string中Insert与Format效率对比、String与List中Contains与IndexOf的效率对比 – alert(dong) – 博客园.

 

 

总结:

1.这点效率问题对于某些人来说可能无所谓,但是我觉得更重要的是编码习惯的养成问题。

2.能用Contains的地方还是尽量使用Contains(发现我改的代码中有不少同事直接用了”IndexOf(value)”),当然会有特殊的例外场景,这里不罗嗦。
3.关于Insert,我编写了两个扩展方法,如下(方法虽简单,但是给代码带来了更大的优雅性)

复制代码
        public static string InsertLast(this string source, string str)
        {
            return source.Insert(source.Length, str);
        }

        public static string InsertFirst(this string source, string str)
        {
            return source.Insert(0, str);
        }
复制代码

 

 

最后本人不是什么资深狼友,将不会提供任何福利图片作别,抱歉!!

 


分割线:我的个人原创,请认准 http://freedong.cnblogs.com/ (转摘不标原文出处可耻)

[转载]SQLSERVER用无中生有的思想来替代游标 - 桦仔 - 博客园

mikel阅读(1136)

[转载]SQLSERVER用无中生有的思想来替代游标 – 桦仔 – 博客园.

 
我这个SQL语句也需要拼接SQL来达到LZ想要的效果

不过这篇文章的重点不是拼接SQL


重点是怎麽模仿游标

其实这个方法是最原始的方法,之前解决论坛问题的时候用过,想不到这次也能用上

关键代码有以下几句

复制代码
 1 CREATE TABLE #ttt (ID INT IDENTITY(1,1), pay_cost INT )
 2 
 3 SELECT  IDENTITY( INT,1,1 ) AS ID, * INTO    #temptb FROM  t1
 4 
 5 --获取#t1表的总行数
 6 SELECT  @COUNT = COUNT(*) FROM    [#temptb]
 7 WHILE @i <= @COUNT 
 8 SELECT  @pay_level = [pay_level] FROM    [#temptb] WHERE   id = @i
 9 SET @i = @i + 1
10 ----------------------------------
11 SELECT  A.[client], A.[pay_level], B.[pay_cost]
12 FROM    [#temptb] AS A
13 INNER JOIN [#ttt] AS B ON A.[ID] = B.[ID]
14 ORDER BY A.[ID] ASC
复制代码

 

原表是没有自增id的,我建一个临时表#temptb,临时表有一个自增id,并把原表的数据全部放入临时表

获取临时表的行数,用于循环

每次执行的时候根据 WHERE   id = @i 来逐行逐行获取值,变量@i每次循环都递增1

将获取到的值都插入到#ttt这个临时表里面,然后根据ID的值做两表连接就可以得到LZ的结果

我说的无中生有就是“在原表里增加一个自增id方便循环,既简单又容易理解o(∩_∩)o ”

 


判断

我这里还用了一句

1 IF 'pay_lv_' + CAST(@pay_level AS VARCHAR(200)) IN ( SELECT   NAME FROM     SYS.[syscolumns] )

用于判断要获取值的pay_lv_列是否存在,如果存在就插入pay_lv_列的值,如果不存在就插入0


总结

其实如果觉得某样东西很难去实现,能不能用一个变通的方法呢?多动脑筋,办法会有的

[转载]web form中自定义HttpHandler仿mvc - ahl5esoft - 博客园

mikel阅读(921)

[转载]web form中自定义HttpHandler仿mvc – ahl5esoft – 博客园.

前言

  在mvc大行其道的今天,仍然有不少公司的项目还是使用web form来实现的(其实mvc也是基于web form的),如果要在项目中引入mvc,不得不新建一个mvc的项目,然后将当前项目的功能一点点的转移过去,实在是很麻烦的一件事情,而且项目的改造 周期也会加长,更别说一边改造一边添加新功能了,那么如果中间出现那么一点点的小差错,那么开发人员和测试人员估计想死的心都有了。

  基于以上的情景,我们可以通过自定义HttpHandler来仿造mvc的模式,大概的实现思路如下:

  1. 给页面提供一个PageBase<TModel>的类来继承,中间类似于mvc中存放Model的容器
  2. 通过类似/mvc/controller/action方式的url对于Controller内Action的调用(之前《C#实现简易ajax调用后台方法》这篇文章有简单介绍过)
  3. 不同的action返回不同的ActionResult(如文本、Json等)
  4. 将自定义的MvcHandler在web.config中进行配置并引用相关的库即可

实现

  首先我们需要自定义一个IHttpHandler来处理我们定义的mvc规则,并对其进行解析,其实原理就是上面提到的文章,只是Controller的Action会跟mvc的相似,返回ActionResult,代码大致如下:

publicabstractclassActionResult{publicabstractvoidExecuteResult(HttpContext context);}publicclassMvcHandler:IHttpHandler,IRequiresSessionState{publicconststring PREFIX ="/mvc/";//其他代码略publicvoidProcessRequest(HttpContext context){string path = context.Request.AppRelativeCurrentExecutionFilePath.Substring(PREFIX.Length);Int32 index = path.LastIndexOf("/");string route = path.Substring(0, index).ToLower();string actionName = path.Substring(index +1);//反射获取Controller和Actionvar controller =null;var action =null;var actionParamters = action.GetParameters();object[] parameters =Array.ConvertAll(actionParamters, p =>{if(p.ParameterType==typeof(HttpPostedFile)){return context.Request.Files[p.Name];}returnConvert.ChangeType(collection[key], type);});var result = action.Invoke(controller, parameters,null)asActionResult;if(result !=null)
            result.ExecuteResult(context);}  

  然后在web.config内的HttpHandlers内添 加<add path=”/mvc/*/*” type=”Infrastructure.MvcHandler” verb=”POST,GET”/>,规则可以任意定制,但是得注意url的格式,如果定义成了*/*/*那么多拦截到全部的请求,那么难度就增加 了。

  接下来是页面,与以往aspx页面不同的是,我们需要在页面上调用到相应的Model,那么对于PageBase<TModel>就需要一个可以get Model的属性,代码如下:

publicclassDynamicPageBase:Page{public T Model{protectedget;set;}}

  但是由于我们在页面内调用Model之前,是要对其赋值的,因此就需要一个接口,代码改造如下:

publicinterfaceIMvcPage{voidSetModel(object model);}publicclassDynamicPageBase:Page,IMvcPage{private T m_Model =default(T);protected T Model{get{return m_Model;}}publicvoidSetModel(object model){if(model !=null)
            m_Model =(T)model;}}

  在页面上,我们就可以使用<%=Model.XXX%>的方式来获取Model内的相关属性了,对于页面的改造大致已经完成了

  那么我们怎么样像mvc那样通过/controller/action的方式来返回html呢,使用过mvc的朋友应该知道,我们的view是要放在一些特定的位置下的,如相应的Controller文件夹内包含着相应的Action aspx页面或razor页面

  因此我们也可以在Web Form的目录下创建一个Views的文件夹,专门用来存放所有对应的Action页面,然后通过对url的解析来获取相应的页面,并将页面转化为html返回给客户端,ViewResult大致代码如下:

string html ="";try{string childPath = context.Request.AppRelativeCurrentExecutionFilePath.Replace(MvcHandler.PREFIX,string.Empty);string virtualPath =string.Format("~/Views/{0}.aspx", childPath);IMvcPage page =PageParser.GetCompiledPageInstance(virtualPath, context.Server.MapPath(virtualPath), context)asIMvcPage;if(page !=null)
        page.SetModel(m_model);using(StringWriter sw =newStringWriter()){
        context.Server.Execute(page, sw,false);
        html = sw.ToString();}}catch(Exception){
    html ="无法访问该视图";}
context.Response.Write(html);

  其他的ActionResult都是根据返回类型的不同而有不同的实现,我就不详细列举出来了。

扩展

  相信留意过老赵博客的朋友都看过《技巧:使用User Control做HTML生成》《方案改进:直接通过User Control生成HTML》这 两篇关于UserControl的文章,那么我们可以参考里面的实现来对页面也添加相似的功能,并整合两种方案,让你的ViewResult可以生成 aspx或ascx的html,我自己实现的规则是在页面不存在的情况下,则查找对应的UserControl是否存在,如果存在则返回 UserControl的html,不存在的话则返回以上的无法访问视图的提示,代码改造大致如下:

//MvcHandler内string pageVirtualPath ="页面虚拟路径";string controlVirtualPath ="用户控件虚拟路径";//aspxif(File.Exists(context.Server.MapPath(pageVirtualPath))){var page = manager.LoadPage(pageVirtualPath)asIMvcPage;if(page !=null)
        page.SetModel(m_model);
    html = manager.RenderView();}//ascxelseif(File.Exists(context.Server.MapPath(controlVirtualPath))){var control = manager.LoadControl(controlVirtualPath);
    html = manager.RenderView();}else{
    html ="无法访问该视图";}publicclassViewManager{//其他代码略publicPageLoadPage(string virtualPath){
        m_page =PageParser.GetCompiledPageInstance(virtualPath, m_context.Server.MapPath(virtualPath), m_context)asPage;
        s_cache.SetViewPropertyValue(m_page, m_context.Request);return m_page;}publicControlLoadControl(string virtualPath){
        m_page =newPage();
        m_control = m_page.LoadControl(virtualPath);
        m_page.Controls.Add(m_control);
        s_cache.SetViewPropertyValue(m_control, m_context.Request);return m_control;}}

  对于MvcHandler而言,我们可以将部分的可变参数抽离出去,然后额外的进行实现,那么仿mvc的代码就可以整理到一个dll中,可以让其他的项目重用了。

  然后就是可以在MvcHandler内再添加一些Filter的功能,抽离出过滤的接口,来对于一些请求的过滤,那么功能上就可以被进一步的扩展了。

结尾

  由于以往在 写文章的时候,都会提供详细的实现源码,但是后来发现这样并不能给其他人自己实现的机会,因此这次就不提供源码了,大部分重点的想法已经在文章中了,大家 可以尝试自己去实现,由于写的文章也不多,如果有阅读上的困难,请告诉我,我会发源码给各位,文章中如有任何错误和遗漏请大家指出,谢谢大家。

[转载]lucene-3.5.0 IKIKAnalyzer3.2.5Stable_bin 中文分词建立索引和检索 - 裴东辉 - 博客园

mikel阅读(1075)

[转载]lucene-3.5.0 IKIKAnalyzer3.2.5Stable_bin 中文分词建立索引和检索 – 裴东辉 – 博客园.

基本环境:

ext_stopword.dic和IKAnalyzer.cfg.xml放到classpath下面

引入jar包:IKAnalyzer3.2.5Stable.jar   lucene-core-3.5.0.jar

基本程序:

1、中文分词建立索引

package testlucene.index;
import java.io.File;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;
import testlucene.util.FileUtil;
//import org.apache.lucene.search.IndexSearcher;
public class TxtFileIndexer {
public static void main(String args[]) throws Exception {
//索引位置
   File indexDir = new File(“E:/eclipse_research/fetchnews/ILucene-3.5.0/src/lucenesource/index”);
   //数据位置
   File dataDir  = new File(“E:/eclipse_research/fetchnews/ILucene-3.5.0/src/lucenesource/data”);
   //使用IKAnalyzer中文分词工具
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35,new IKAnalyzer());
FSDirectory directory = FSDirectory.open(indexDir);
IndexWriter indexWriter = new IndexWriter(directory, iwc);
        //接着程序遍历了目录下面的所有文本文档,并为每一个文本文档创建了一个 Document 对象。
        //然后把文本文档的两个属性:路径和内容加入到了两个 Field 对象中,接着在把这两个 Field 对象加入到 Document 对象中
        //最后把这个文档用 IndexWriter 类的 add 方法加入到索引中去。
        //这样我们便完成了索引的创建。接下来我们进入在建立好的索引上进行搜索的部分。
   File[] dataFiles  = dataDir.listFiles();
   String name=””,path=””,content=””;
for(File file:dataFiles){
if(file.isFile() && file.getName().endsWith(“.txt”)){
System.out.println(“Indexing file ” + file.getCanonicalPath());
 
/*Step 1. Prepare the data for indexing. Extract the data. */
name =file.getName();
               path=file.getCanonicalPath();

content=FileUtil.parsefiletostring(file);

 
                /*Step 2. Wrap the data in the Fields and add them to a Document */

Document doc = new Document();doc.add(new Field(“name”,name,Field.Store.YES,Field.Index.NOT_ANALYZED));doc.add(new Field(“path”,path,Field.Store.YES,Field.Index.NOT_ANALYZED));doc.add(new Field(“content”,content,Field.Store.NO,Field.Index.ANALYZED));

 
                /*Step 3: Add this document to Lucene Index.*/

indexWriter.addDocument(doc);

}
}
indexWriter.close();
}
}

 2、中文分词 搜索

package testlucene.search;

import java.io.File;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKQueryParser;
import org.wltea.analyzer.lucene.IKSimilarity;
@SuppressWarnings(“resource”)
public class TxtFileSearcher {
public static void main(String[] args) {
try{
//index索引位置生成Reader流
   File indexDir = new File(“E:/eclipse_research/fetchnews/ILucene-3.5.0/src/lucenesource/index”);
   FSDirectory directory = FSDirectory.open(indexDir);
IndexReader reader = IndexReader.open(directory);
//创建Searcher
IndexSearcher indexSearcher = new IndexSearcher(reader);
indexSearcher.setSimilarity(new IKSimilarity());
//查询关键词
String keyWords = “是一个开放源代码的全文检索引擎工具包 “;
//IKAnalyzer中文分词生成查询
Query query = IKQueryParser.parse(“content”, keyWords);
TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE);
System.out.println(topDocs.totalHits);
//对获取到的文档进行解析输出
       ScoreDoc[] scoreDosArray = topDocs.scoreDocs;
       for(ScoreDoc scoredoc: scoreDosArray){
         Document doc = indexSearcher.doc(scoredoc.doc);
         System.out.println(“name: “+doc.getFieldable(“name”).stringValue());
         System.out.println(“path: “+doc.getFieldable(“path”).stringValue());
       }
}catch(Exception e){
e.printStackTrace();
}
}
}

3、工具类

package testlucene.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class FileUtil {
/**
* parse the file to string
* @param file
* @return
*/
public static String parsefiletostring(File file) {
String strresult=””,tmp=””;
BufferedReader br=null;
try{
br=new BufferedReader(new FileReader(file));
while((tmp=br.readLine())!=null){
strresult+=tmp;
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(null!=br){
try {br.close();} catch (IOException e) {e.printStackTrace();}
}
}
System.out.println(strresult);
return strresult;
}
}

 

[转载]jQuery LigerUI V1.2.2 (包括API和全部源码) 发布 - 谢略 - 博客园

mikel阅读(1182)

[转载]jQuery LigerUI V1.2.2 (包括API和全部源码) 发布 – 谢略 – 博客园.

前言

这次版本主要对树进行了加载性能上面的优化,并解决了部分兼容性的问题,添加了几个功能点。

欢迎使用反馈。

相关链接

API:         http://api.ligerui.com/

演示地址:  http://demo.ligerui.com/

源码下载:  http://git.oschina.net/ligerui/LigerUI/ (源码托管)

      http://pan.baidu.com/share/link?shareid=206890659&uk=2318736180 (V1.2.2)

技术支持: http://www.cnblogs.com/leoxie2011/

更新记录

[需求]优化了加载数据的能力
[需求]增加isExpand(支持灵活地控制展开/收缩状态)
[需求]增加delay(支持延迟加载数据)

表格

[需求]对表格分页条数增加缓存处理
[需求]增加参数toolbarShowInLeft(控制工具条显示在左边还是右边)

表单

[需求]验证部分增加对旧版本的兼容处理

工具条

增加方法removeItem、setEnabled、setDisabled、isEnable

Tab

ListBox

V1.2.1更新记录

核心

[需求]表单、表格编辑器的统一化处理

[BUG]支持JQuery高版本

[BUG]改善layout、dialog在ie下的拖拽操作体验

表单

[需求]表单内置验证支持

[需求]相关表单元素增加参数valueFieldCssClass(隐藏域css样式)

[需求]相关表单元素参数parms支持运行时动态获取

[需求]下拉框组件增加参数alwayShowInTop,增加方法reload、getSelected

[需求]listBox组件增加selectAll方法

[需求]popupEdit增加parms参数

[需求]文本框数值类型默认右对齐

[需求] 表单增加getData setData方法

表格

[需求]优化表格工具条的显示位置,并增加工具条标题的支持

[需求]表格树支持线性数据结构

[需求]表格 列支持auto

[BUG]修复grid不能确定取得更新数据的错误

[BUG]修复grid编辑器位置在显示标题出现错位的情况

[BUG]修改grid排序事件没有起效的问题

[需求]tree增加ajaxType、render(自定义html)、selectable(可选择判断函数)参数

[转载]基于MongoDB打造.Net的分布式Session子系统 - Aaron Dai - 博客园

mikel阅读(974)

[转载]基于MongoDB打造.Net的分布式Session子系统 – Aaron Dai – 博客园.

Taobao有她自己的分布式session框架,.net阵营也不能落后了,在下做了个基于MongoDB的支持最多26台MongoDB的分布式Session框架。

先看看配置文件:

复制代码
<?xml version="1.0" encoding="utf-8" ?>
<MongoDBSession>
  <DbName>SessionDB</DbName>
  <IdentityMap Identity="A">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="B">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="C">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="D">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="E">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="F">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="G">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="H">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="I">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="J">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="K">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="L">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="M">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="N">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="O">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="P">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="Q">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="R">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="S">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="T">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="U">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="V">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="W">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="X">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="Y">mongodb://localhost</IdentityMap>
  <IdentityMap Identity="Z">mongodb://localhost</IdentityMap>
</MongoDBSession>
复制代码

从Identity A一直到Z,默认分成了26个Map,具体的C#应用代码:

复制代码
protected void btnTest_Click(object sender, EventArgs e)
        {
            Session["A"] = DateTime.Now;
            Session["B"] = 1111111111111;
            Session["C"] = "fffffffffffffff";
        }

        protected void btnGetSession_Click(object sender, EventArgs e)
        {
            Response.Write(Session["A"].ToString());
            Response.Write("<br />");
            Response.Write(Session["B"].ToString());
            Response.Write("<br />");
            Response.Write(Session["C"].ToString());
        }
        protected void btnAbandon_Click(object sender, EventArgs e)
        {
            Session.Abandon();
        }
复制代码

呵呵,就是普通的Session用法。

这个要配置web.config:

复制代码
<system.web>
    <sessionState mode="Custom" customProvider="A2DSessionProvider" sessionIDManagerType="A2DFramework.SessionService.MongoDBSessionIDManager">
      <providers>
        <add name="A2DSessionProvider" type="A2DFramework.SessionService.MongoDBSessionStateStore"/>
      </providers>
    </sessionState>
  </system.web>
复制代码

这里会牵扯出2个类:

  1. A2DFramework.SessionService.MongoDBSessionIDManager
  2. A2DFramework.SessionService.MongoDBSessionStateStore

MongoDBSessionIDManager

  • 自定义生成的cookie值(也就是SessionID),在这个sample中,会生成如“E.asadfalkasdfjal”这样的SessionID,其中前缀E代表这个Session的信息会映射到哪台MongoDB上。
  • 关键代码
  • 复制代码
    public class MongoDBSessionIDManager : SessionIDManager
        {
            private Random rnd = new Random();
            private object oLock = new object();
    
            public override string CreateSessionID(System.Web.HttpContext context)
            {
                int index = 0;
                lock(this.oLock)
                {
                    index = rnd.Next(SessionConfiguration.SessionServerIdentities.Length);
                }
                string sessionId = string.Format("{0}.{1}", SessionConfiguration.SessionServerIdentities[index], base.CreateSessionID(context));
                return sessionId;
            }
    
            public override string Encode(string id)
            {
                return DESEncryptor.Encode(id, SessionConfiguration.DESKey);
            }
            public override string Decode(string id)
            {
                return DESEncryptor.Decode(id, SessionConfiguration.DESKey);
            }
    
            public override bool Validate(string id)
            {
                string prefix;
                string realId;
    
                if (!Helper.ParseSessionID(id, out prefix, out realId))
                    return false;
    
                return base.Validate(realId);
            }
        }
    复制代码

     

MongoDBSessionStateStore

  • 自定义Session过程中最核心的一个类,代码如下(较多):
  • 复制代码
    public sealed class MongoDBSessionStateStore : SessionStateStoreProviderBase
        {
            private SessionStateSection pConfig;
            private string pApplicationName;
    
            public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
            {
                base.Initialize(name, config);
    
                pApplicationName =System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
                System.Configuration.Configuration cfg = WebConfigurationManager.OpenWebConfiguration(pApplicationName);
                pConfig =(SessionStateSection)cfg.GetSection("system.web/sessionState");
            }
    
            public override SessionStateStoreData CreateNewStoreData(System.Web.HttpContext context, int timeout)
            {
                return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout);
            }
    
            public override void CreateUninitializedItem(System.Web.HttpContext context, string id, int timeout)
            {
                //insert to db
                MongoDBSessionEntity session = new MongoDBSessionEntity();
                session.ApplicationName = this.pApplicationName;
                session.SessionId = id;
                session.Created = DateTime.Now;
                session.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.Minutes);
                session.LockDate = DateTime.Now;
                session.LockId = 0;
                session.Timeout = timeout;
                session.Locked = false;
                session.Flags = (int)SessionStateActions.InitializeItem;
    
                MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id);
                collection.Save(session);
            }
    
            public override void Dispose()
            {
            }
    
            public override void EndRequest(System.Web.HttpContext context)
            {
            }
    
            public override SessionStateStoreData GetItem(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
            {
                return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actions);
            }
    
            public override SessionStateStoreData GetItemExclusive(System.Web.HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
            {
                return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actions);
            }
    
            public override void InitializeRequest(System.Web.HttpContext context)
            {
            }
    
            public override void ReleaseItemExclusive(System.Web.HttpContext context, string id, object lockId)
            {
                //update locked=0, expired=, where lockId=?
                MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id);
    
                var query = Query.And(  Query.EQ("LockId", int.Parse(lockId.ToString())),
                                        Query.EQ("_id", id), 
                                        Query.EQ("ApplicationName", pApplicationName));
                var update = Update.Set("Locked", false)
                                    .Set("Expires", DateTime.Now.AddMinutes(pConfig.Timeout.Minutes));
    
                collection.Update(query, update);
            }
    
            public override void RemoveItem(System.Web.HttpContext context, string id, object lockId, SessionStateStoreData item)
            {
                //delete where sessionId=? and lockId=? and applicationname=?
                MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id);
    
                var query = Query.And(Query.EQ("LockId", int.Parse(lockId.ToString())),
                                        Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName));
                collection.Remove(query);
            }
    
            public override void ResetItemTimeout(System.Web.HttpContext context, string id)
            {
                //update expire date
                MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id);
    
                var query = Query.And(Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName));
                var update = Update.Set("Expires", DateTime.Now.AddMinutes(pConfig.Timeout.Minutes));
                collection.Update(query, update);
            }
    
            public override void SetAndReleaseItemExclusive(System.Web.HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
            {
                MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id);
                if (newItem)
                {
                    //delete expired items
                    var query = Query.And(Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName),
                                        Query.LT("Expires", DateTime.Now));
    
                    collection.Remove(query);
    
                    //insert new item
                    MongoDBSessionEntity session = new MongoDBSessionEntity();
                    session.ApplicationName = this.pApplicationName;
                    session.SessionId = id;
                    session.Created = DateTime.Now;
                    session.Expires = DateTime.Now.AddMinutes(pConfig.Timeout.Minutes);
                    session.LockDate = DateTime.Now;
                    session.LockId = 0;
                    session.Timeout = item.Timeout;
                    session.Locked = false;
                    session.Flags = (int)SessionStateActions.None;
                    session.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items);
    
                    collection.Save(session);
                }
                else
                {
                    //update item
                    var query = Query.And(Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName),
                                        Query.EQ("LockId", int.Parse(lockId.ToString())));
                    MongoDBSessionEntity entity= collection.FindOne(query);
                    entity.Expires = DateTime.Now.AddMinutes(item.Timeout);
                    entity.SessionItems = Helper.Serialize((SessionStateItemCollection)item.Items);
                    entity.Locked = false;
                    collection.Save(entity);
                }
            }
    
            public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
            {
                return false;
            }
    
            private SessionStateStoreData GetSessionStoreItem(bool lockRecord, System.Web.HttpContext context, 
                                                                string id,
                                                                out bool locked,
                                                                out TimeSpan lockAge,
                                                                out object lockId,
                                                                out SessionStateActions actions)
            {
                SessionStateStoreData item = null;  
                lockAge = TimeSpan.Zero;
                lockId = null;
                locked = false;
                actions = 0;
    
                bool foundRecord = false;
                bool deleteData = false;
    
                MongoCollection<MongoDBSessionEntity> collection = Helper.GetMongoDBCollection(id);
    
                if (lockRecord)
                { 
                    //update db, set locked=1, lockdate=now
                    var query1 = Query.And(Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName),
                                        Query.EQ("Locked", MongoDB.Bson.BsonValue.Create(false)),
                                        Query.GT("Expires", DateTime.UtcNow));
    
                    long count = collection.Find(query1).Count();
                    if (count == 0)
                    {
                        locked = true;
                    }
                    else
                    {
                        var update = Update.Set("Locked", true).Set("LockDate", DateTime.Now);
                        collection.Update(query1, update);
                        locked = false;
                    }
                }
                //get item by id
                var query2 = Query.And(Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName));
                MongoDBSessionEntity entity=collection.FindOne(query2);
                if (entity != null)
                {
                    if (entity.Expires < DateTime.Now)
                    {
                        locked = false;
                        deleteData = true;
                    }
                    else
                    {
                        foundRecord = true;
                    }
                }
    
                //delete item if session expired
                if (deleteData)
                {
                    var query3 = Query.And(Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName));
                    collection.Remove(query3);
                }
    
                if (!foundRecord)
                    locked = false;
    
                if (foundRecord && !locked)
                {
                    if (lockId == null)
                        lockId = 0;
                    lockId = (int)lockId + 1;
    
                    var query4 = Query.And(Query.EQ("_id", id),
                                        Query.EQ("ApplicationName", pApplicationName));
                    var update4 = Update.Set("LockId", (int)lockId)
                                            .Set("Flags", (int)SessionStateActions.None);
                    collection.Update(query4, update4);
    
                    if (actions == SessionStateActions.InitializeItem)
                        item = CreateNewStoreData(context, pConfig.Timeout.Minutes);
                    else
                        item = Helper.Deserialize(context, entity.SessionItems, entity.Timeout);
                }
                return item;
            }
        }
    复制代码

     

由于很多方法会用到MongoCollection,因此写了个static公用函数,如下:

复制代码
public static MongoCollection<MongoDBSessionEntity> GetMongoDBCollection(string sessionId)
        {
            IPartitionResolver resolver = new MongoDBSessionPartitionResolver();
            string mongoDbConnectionString = resolver.ResolvePartition(sessionId);

            MongoClient client = new MongoClient(mongoDbConnectionString);
            MongoServer srv = client.GetServer();
            MongoDatabase db = srv.GetDatabase(SessionConfiguration.MongoDBName);
            if (!db.CollectionExists(SessionConfiguration.MongoDBCollectionName))
                db.CreateCollection(SessionConfiguration.MongoDBCollectionName);

            MongoCollection<MongoDBSessionEntity> collection = db.GetCollection<MongoDBSessionEntity>(SessionConfiguration.MongoDBCollectionName);

            return collection;
        }
复制代码

 

运行效果:

点击Set Session后:

点击Get Session后:

点击Abandon后:

 

源代码已经更新到A2D Framework中了。

[转载]SVN版本管理教程 - 善小书 - 博客园

mikel阅读(1029)

[转载]SVN版本管理教程 – 善小书 – 博客园.

SVN版本管理教程

1、     先上SVN for Eclipse的地址

             http://subclipse.tigris.org/update_1.8.x

2、     将项目添加到SVN服务器

             右击项目—> Team —> Share Project….
选择SVN —> Next
 
选择创建新的资源库位置 —> Next
填入地址 —> Next

输入文件夹名  —>Finish

3、     从SVN获取项目

从SVN检出项目
 

Ok 以上就是这么简单,接下来才是本文的重点

——————-是不是这么割———————————————–
 
4、     协作开发
基本流程:
    * 各开发成员建立自己的分支,并在此分支上开发
    * 各开发成员把分支合并到主干上并形成较为稳定
    * 各个成员重新从主干上建立新的分支,在此分支上开发(即回到第一步)
    * 循环往复,直到工程结束

案例:
     *建立项目及其分支

浏览找到分支文件夹并输入分支名 命名规则: 负责人姓名大写_日期_后缀
输入好之后一路Next最后输入相关注释,Finish即可
各个分支负责人从SVN中获取相关的分支项目进行开发,开发完成提交即可

*合并
     合并指的的是将分支开发稳定的代码合并到主干中,所以第一步是将代码切换到主干代码。右击项目—> Team —> 切换

右击项目—> Team —> 合并
我们选择第二项将分支代码合并到主干
选择要合并进主干的分支 Finish
合并成功后提交一下。
 
*解决冲突
     同事修改了同一个文件就会出现冲突,有冲突的话合并的时候就会弹出这个对话框提示解决冲突的方式。我一般使用最后一个解决办法 “启动图形冲突决议编辑器”

冲突编辑器如下
 
在这里手动编辑即可,是覆盖还是附加具体要看代码和分支负责人商量着来
编辑完成即可保存关闭,弹出完成对话框。选择yes
 
有时候合并也会出现以下两种错误,不必紧张Update以下就行了
没有最新更新的版本
版本没有提交
 
OK SVN的版本管理我了解到的就这些,不足之处望补充学习一下。

[转载]Android 自动化测试——Monkey测试 - 泡泡糖 - 博客园

mikel阅读(848)

[转载]Android 自动化测试——Monkey测试 – 泡泡糖 – 博客园.

 Android自带了很多方便的测试工具和方法,包括我们常用的单元测试、 Robotium测试、Monkey测试、MonkeyRunner测试、senevent模拟等。这些方法对于我们编写高质量的APP十分有用。也可以 提前暴露我们程序的隐藏问题。今天给大家讲一下Monkey测试,Monkey测试可以说是我上面提到过的测试方法里面最简单的。

(PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)

  

1、Monkey测试简介

  Monkey主要应用在压力和可靠性测试上,运行该命令可以随机地向目标程序发送各种模拟键盘事件流,并且可以自己定义发送的次数,以此观察被测应用程序的稳定性和可靠性,应用起来也比较简单,记住那几个命令就行了。

  • Monkey程序由Android系统自带,使用Java语言写成,在Android文件系统中的存放路径是:/system/framework/monkey.jar
  • Monkey.jar程序是由一个名为“monkey”的Shell脚本来启动执行,shell脚本在Android文件系统中的存放路径是:/system/bin/monkey

 

2、Monkey的基本用法

$ adb shell monkey [options]

  如果不指定options,Monkey将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部包。下面是一个常见用法的示例,它启动指定的应用程序,并向其发送100个伪随机事件:

$ adb shell monkey -p package_name -v 100

 

3、Monkey测试例子

上面就是一个使用Monkey测试Launcher的例子,因为对某个APP进行测试的时候,需要指定APP的包名,我们可以先进入data\data目录下面,看看有哪些APP包。

 

4、Monkey测试停止条件

Monkey Test执行过程中在下列三种情况下会自动停止:

  • 如果限定了Monkey运行在一个或几个特定的包上,那么它会监测试图转到其它包的操作,并对其进行阻止。
  • 如果应用程序崩溃或接收到任何失控异常,Monkey将停止并报错。
  • 如果应用程序产生了应用程序不响应(application not responding)的错误,Monkey将会停止并报错。

 

 

5、Monkey详细参数

  下面是Monkey的详细参数表,图片是从CSDN一位开发者的博客上截取的。

图片来源:http://blog.csdn.net/linghu_java/article/details/6732895

 

6、结语

   Monkey测试是Android自动化测试里面使用比较简单的方法,可以很大程度检验我们的程序是否稳定,能否经得起压力测试,可以根据实际情况调整测 试的强度和测试重点。这个也是我在开发APP的时候最常用的方法,基本上每个版本发布之前,我都会进行比较高强度的Monkey测试,就像我每次发布 Launcher之前都会进行1W次Monkey测试。系统集成后,再进行整体的压力测试。

  最后说一句,Monkey测试只是一个模拟测试,很多时候跟实际情况时有差别的。所以这个只能是其中一个辅助测试,后面有空再讲解其他的自动化测试方法。

 

2013-8-16 

Edited by 泡泡糖

参考网址:http://developer.android.com/tools/help/monkey.html