词条统计
浏览次数:3294 次
编辑次数:1次 历史版本
最近更新:2013/6/20
创建者:掷鸡蛋者

本文来源:http://www.wojilu.com/forum1/topic/5111

我记录框架1.9对链接 Link 的生成方法进行了小幅重构。
在旧有的教程中,对这部分解释也许不够充分,所以趁新版发布,补充一下相关说明。

在阅读本文之前,请先确保已经了解过以前关于 Link 的说明:http://www.wojilu.com/Common/Page/91 

总的说来,链接的生成,可以分成4种方式:

1、在 controller 内部,直接使用 to( 参数 ) 方法
String url1 = to( List, 3 );
String url2 = to( new PostController().Index, 88 );

2、在 controller 之外,其他有 ctx 的地方,直接使用 ctx.link.to( 参数 ) 方法
String url = ctx.link.to( List, 3 )

3、在既没有 controller,也没有 ctx 的地方,使用 Link.To( 参数 ) 的静态方法
String url = Link.To( controller, action, id )

4、也可以自定义链接生成方法,也就是自己拼接字符串生成 url。

---------------------------------------

下面依次解释这4种生成方式。

1. 通用的链接生成方法

使用 Link.To( 参数 ) 静态方法,如下图所示——



2、在控制器中使用便捷方法  to( 参数 )



这些 to(参数) 方法其实是调用了 ctx.link 对象,它的内部,其实将当前 appId、当前 owner 等信息传递进去了,最终还是调用的 Link.To(参数) 方法,只不过少写了 appId, owner 等参数,更加简短、便捷一些。

补充:如果你只是使用 wojilu 框架(没有使用综合系统),那么可以忽略 appId/owner 这些参数。

3、在有 ctx 的地方使用 ctx.link.To( 参数) 生成链接

ctx.link 指向 CtxLink 对象,不是静态方法,因为这个对象封装了当前的 owner/appId 等信息。
下面是方法一览:



4、自定义链接生成方法

因为是自定义,所以你可以随心所欲,生成任意的链接。比如

public class MyLink {
    public static String ToPhoto() {
        return "my/photo" + MvcConfig.Instance.UrlEx;
    }
}

--------------------------------------------


常见问题1:IMember 参数是什么意思?
(如果你只是使用“wojilu framework”框架,不使用“综合系统”,其实不需要传递IMember参数,可以跳过下面的说明)

答:请先看这篇说明:http://www.wojilu.com/space/author/blog1/post/22 ,里面是多用户模型的说明。

我们知道,在“我记录综合系统”中,有一个无所不包的用户(Member)模型。这个模型模拟了现实社会,核心思想是:任何页面和数据,都属于特定的拥有者(IMember)。

在现实社会中,一般说来,社会参与的成员方 member, 可以分成三种类型:

1)个人/家庭;
2)政府;
3)其他组织单位。

任何物品或财产,都属于这3种成员(Member)。如果你在路上捡到一件没有主人的东西,或者郊外看到一片没人的荒地,实际上最终,是属于政府的,所谓“普天之下莫非王土”。重复一下:一件财物(或东西),它总有一个拥有者owner,这个owner,要么是个人,要么是某个“组织单位”,要么是政府。

在“我记录网站综合系统”中,IMember类型和“个人、政府、组织”也是对应的:
1)个人=>“个人用户”: User:IMember
2)政府=>“网站”:Site:IMember
3)组织=>“群组”:Group:IMember
(当然,你通过实现IMember扩展用户类型,比如创建一个 School:IMember 学校,或者扩展一个 Company:IMember 出来)

和现实社会一样,在“我记录网站综合系统”中,所有的页面或数据,都有一个拥有者owner(IMember),要么属于User,要么属于Group,要么属于Site

比如这个页面:http://www.wojilu.com/space/author/blog1/post/22 从 url 字符串中可以看出,它隶属于 space/author 名下(space是User的别名),也就是说,这个博客是属于个人用户的;
再比如这个页面:http://www.wojilu.com/group/union/forum20/topic/1768 它隶属于 group/union 名下,是属于群组union的。
至于这个帖子:http://www.wojilu.com/forum1/topic/81 因为url中没有 owner 信息,所以默认属于Site(网站)。

当我们Link生成链接的时候,应该指明这个页面(数据)所属的拥有者。但大多数时候,我们可以省略掉:

在 http://www.wojilu.com/forum1/topic/81 页面中,通过 to(controller,action)生成的所有链接,默认就是 http://www.wojilu.com/forum1/topic/81 的owner,也就是Site;

在 http://www.wojilu.com/group/union/forum20/topic/1768 页面中,通过 to(controller,action)生成的所有链接,默认内部会传递group/union参数到url中,所以拥有者是 group/union;
……
当你在 to(controller,action) 中不指定IMember参数的时候,内部默认使用当前页面的拥有者。

如果你要在网站页面,比如 http://www.wojilu.com/forum1/topic/81 页面中,生成指向特定用户空间的链接(owner是User),因为owner不一样,所以必须明确指定 IMember 参数:


User user = getSomeUser( xxx );
String url =
Link.To( user, new xxxController().xxxAction )

再举几个例子:

1)比如,你在用户空间 /space/mike.aspx 中,使用 to( new PostController().List ),默认是指向用户空间的,生成的结果是:
/space/mike/Post/List.aspx
to() 方法内部调用 ctx.link,默认指定了当前的 owner 参数,在url 中对应着 /space/mike/ 这部分。

2)如果你在群组 /group/book.aspx 中,使用 to( new PostController().List ) ,因为默认的 owner 是 /group/book,所以生成的 url 是:
/group/book/Post/List.aspx

3)如果你在网站(Site) 中,
使用 to( new PostController(), List ) ,因为默认的 owner 是Site(对应的url默认没有前缀),所以生成的 url 是:
/Post/List.aspx

但是,如果和默认的owner不一致,比如你要在“用户空间”中生成指向“群组”、或者指向“空间”的链接,那么需要使用 Link.To() 方法,并显式指定owner参数:
Link.To( Site.Instance, new PostController().List )

总之,
1)你的程序总是运行在某个 owner 中的,要么在Site中,要么在User Space中,要么在Group中;
2)如果要生成指向其他 owner 的链接,必须提供 owner 参数。


常见问题2:纯字符串参数 To( String controller, String action ) 的第一个参数怎么表示?

答: controller 用斜杠分隔,而不是点号,比如:
String url = Link.To( "/Blog/Category", "List", 3 );


常见问题3:如何在 service 层生成链接?

链接方法 to(参数) 是表现层使用的方法,其内部依赖于 ctx 和 controller,它在 service 层的上面,service 层不应该依赖视图层,也就是说,在 service 里面无法直接使用 to(参数) 方法。

根本的原因在于,网站架构分层——
最底层一般是数据层,
再上面是业务逻辑层(往往和service是同一层),
再往上是视图表现层。

一般上层依赖下层,但却不应该让下面的层次依赖上面的层次。否则乱套了,背离了架构分层要低耦合的原则。

简单说来,不应该在 service 里面直接生成链接。更靠谱、更推荐的做法,是将 url 从视图层通过参数传递给 service 层。

比如,service层这么定义:

public class SomeService {
    public void SaveData( String postUrl ) {
    }
}

然后在 controller 中将 url 传递给 service:

public class SomeController {
    public void Index() {
        String postUrl = to( 参数 );
        someService.SaveData( postUrl );
    }
}

当然,如果一定要在 service 中生成链接,也不是不可以。这时候必须使用 Link.To(参数) 方法,而且还有限制:
1)无法直接引用 controller,像 Link.To( new Blog.PostController().List, 3 ) 这种强类型方式是不行的;
2)只能传递字符串参数,即只能这样: Link.To( "Blog/Post", "List", 3 )