【问题标题】:Create "pretty" user profile URLs in Grails application在 Grails 应用程序中创建“漂亮”的用户配置文件 URL
【发布时间】:2013-04-11 22:35:35
【问题描述】:

任何已经使用 Grails 实现过类似功能的人都可以告诉我,在 Facebook、Twitter、Linkedin 中创建格式为“http://www.myservice.com/username”的用户个人资料 URL 有哪些好的做法(如果有的话)?

我正在尝试通过 UrlMappings 来实现它,在我看来,我需要打破代码约定,至少对于控制器而言。

所以,欢迎任何建议,谢谢。

更新 1

当我提到我对违反代码约定的担忧时,我的意思是我想使用此映射显示用户配置文件,但我的应用程序中确实有其他对象,我想使用默认值访问映射:

"/$controller/$action?/$id?"()

解决方案

感谢我在这里收到的巨大贡献,我想出了这个解决方案,它解决了我的问题。

正如所指出的,要进行这种映射,我需要更密切地控制我的请求的处理方式。这意味着我需要告诉 Grails 我不想将哪些控制器映射到“用户名”规则。

因为这将是一项非常乏味的任务(因为我有多个控制器),所以我这样做是为了使其自动化:

UrlMappings.groovy

static mappings = {
     getGrailsApplication().controllerClasses.each{ controllerClass ->
     "/${controllerClass.logicalPropertyName}/$action?/$id?"(controller: controllerClass.logicalPropertyName)
     }
     "/$username/$action?"(controller: "user", action: "profile")
     }
     ...
 }

当然,我需要在我的用户注册过程中执行类似的操作,以避免用户名与某些控制器名称相同。

就是这样,谢谢大家。

【问题讨论】:

  • this tutorial 做了一些非常相似的事情,我想你可以从中得到一些指导。 (部分Displaying entries by author)
  • 谢谢,但这不是我所需要的。本教程处理映射问题,但通过添加前缀“/blog/”来避免与 URL 的多个可能匹配。

标签: grails seo url-mapping


【解决方案1】:

假设您有一个 UserController 并且您要将任何 domain.com/username 映射到用户控制器的 show 操作,您的 url 映射可能是这样的: 在我的示例中,名称将成为您的参数中的参数。 更多详情请参考here

希望这会有所帮助。

static mappings = {
    "/$name"(controller: "user", action: "show")

    ...
}

【讨论】:

  • 谢谢!你的假设都是正确的,这正是我正在做的。但这会导致一些不良的附带影响。最烦人的是,在应用这个映射之前,我可以使用example.com/controllername 获得控制器的默认操作。这就是为什么我要问是否有更好的方法,或者这是唯一的方法,我必须处理它。
  • 如果我理解正确,你不想在你的 url 中使用任何控制器名称。如果是这种情况 "/$name"(controller: "user", action: "show") 不需要任何 url,它会将 www.domain.com/Uilian 路由到用户控制器分配用于处理您的任何操作请求,在我的示例中为“显示”
  • 你说得对@alidad,我想使用你提出的这个映射来显示用户配置文件,但是我的应用程序中确实有其他对象,我想使用默认映射访问这些对象。我会用这些信息更新我的问题,谢谢。
  • 我明白了,你也可以在那里有其他映射,你可以保留传统的控制器/动作之一,也可以添加你自己的。 Grails 将尝试匹配模式,因此您需要确保您没有与模式重叠。
【解决方案2】:

根据您的要求,http://yourdomain.com/ 之后的所有内容都可以是用户名或您的其他控制器之一,这可能会产生不良影响,具体取决于首先定义的 url 映射(例如用户控制器与非用户控制器)。但很可能非用户控制器列表将是较小的列表,因此您应该首先放置它并对其进行过滤,然后将所有其他 url 映射视为用户映射。

这是一个例子:

static mapping = {
  "/$controller/$action?/$id?" {
    constraints {
      controller inList: ['nonUserController1', 'nonUserController2',...]
    }
  }

  //this should work for /username and /username/whateveraction
  "/$username/$action?"(controller: 'user')
}

这里有几点需要注意:

  • 您需要首先放置非用户控制器 url 映射,因为 http://yourdomain.com/ 之后的所有其他内容都可能是用户名 - 对吗?
  • 其次,您需要设置一个约束来捕获所有非用户控制器,同时忽略用户 url 映射
  • 您还需要防止用户使用与您的非用户控制器之一匹配的用户名进行注册

【讨论】:

  • 是的,我认为你是对的。我只是不确定是否通过 UrlMappings 优先规则,第二个(旨在匹配用户名)将不会结束第一个要评估的,因为它具有较少的通配符。但我真的很喜欢这种方法,它比我做的要干净得多,谢谢!
  • 好的,我已经测试了你的解决方案,正如我所怀疑的,由于优先规则,所有请求都被映射到“/username/$action?”。但是你的建议确实很有帮助,我想出了一个解决方案,我会用它来更新我的问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-07-05
  • 2013-05-25
  • 1970-01-01
  • 2017-09-08
  • 2012-07-20
  • 2017-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多