리프트 프레임 워크에서 URL처럼 RESTFul을 처리하는 올바른 방법입니까?

StackOverflow https://stackoverflow.com/questions/2036037

  •  19-09-2019
  •  | 
  •  

문제

URL과 같은 경우 http : // localhost/test/edit/{id} 그리고 {id} 변환을 URL 경로 부품 대신 매개 변수로 변환하려고합니다.

RewriteRequest로 메뉴를 만들어서 수행하는 것이 가장 좋은 방법입니까? 이와 같은 URL 패턴이 많이 있다면 약간의 보일러 플레이트를 발견했기 때문입니다.

val menu = Menu(new Loc[Unit] {

    override def name = "Test"
    override def text = "Test"
    override def link = (List ("Test"), true)
    override def params = Nil
    override def defaultValue = Full(())


    def isTarget (path: ParsePath) = path match {
        case ParsePath (List("Test", "edit", id), _, _, _) => true

        case _ => false
    }

    override def rewrite = Full ( NamedPF("Test") {
        case RewriteRequest (path, _, _) if isTarget(path) => 
             RewriteResponse(List("Test", "edit"),  
                             Map("id" -> "1024")) -> ()

    })
})
도움이 되었습니까?

해결책

boot.scala에서는 다음 (실제 작업 코드에서)이 필요합니다 (실제 작업 코드에서) 각 rewriterponse 경로는 사이트 맵에 있어야합니다.

LiftRules.rewrite.append {
  case RewriteRequest(ParsePath(List("shopInfo", "view", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "view" :: Nil, Map("id" -> id))
  case RewriteRequest(ParsePath(List("shopInfo", "orders", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "orders" :: Nil, Map("id" -> id))
  case RewriteRequest(ParsePath(List("shopInfo", "sync", id), _, _, _), _, _) => RewriteResponse("shopInfo" ::  "sync" :: Nil, Map("id" -> id))
  case RewriteRequest(ParsePath(List("shopInfo", "delete", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "delete" :: Nil, Map("id" -> id))
  case RewriteRequest(ParsePath(List("shopInfo", "edit", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "edit" :: Nil, Map("id" -> id))
}

다른 팁

모든 답변에 감사드립니다.

내가 가장 원하는 것은이 물건을 메뉴와 단단히 결합하여 Crudify 특성과 같은 모델 클래스에서만 설정할 수 있다는 것입니다.

결국, 나는 이러한 재 작성 규칙을 처리하기 위해 LOC의 서브 클래스를 직접 만들었고, 그것이 잘 작동하고 적어도 나에게 훨씬 더 간단한 일을한다는 것을 알았으므로 여기에 코드를 게시했습니다.

누군가가 필요한 경우 자유롭게 복사하십시오

/**
 *  A RESTful-like URL handling Loc
 *
 *  If you have the following templates:
 *
 *    * webapps/item/edit.html
 *    * webapps/item/view.html
 *  
 *  You want the following URL map to corresponding template with 
 *  last path component as a S parameter.
 *
 *    http://localhost/item/edit/1  to  http://localhost/item/edit
 *    http://localhost/item/view/1  to  http://localhost/item/view
 *
 *  You could create a Menu with this Loc class in your Model object.
 *
 *  <code>
 *  object Item extends Item with LongKeyedMetaMapper[Item] 
 *  {
 *      // Other methods here...
 *
 *      def menu () {  
 *
 *          // What methods do we have?
 *          val methods = List ("view", "edit")
 *
 *          val parameterName = "itemID"
 *          val itemLoc = new RESTfulLoc("Item", List("item"), "Item", 
 *                                       methods, parameterName)
 *
 *          Menu (itemLoc)
 *      }
 *  }
 *  </code>
 *
 *  Now add the menu to SiteMap in Boot.boot
 *
 *  <code>
 *  class Boot {
 *      def boot () {
 *          
 *          val entries = Item.menu ::  Nil
 *
 *          LiftRules.setSiteMap(SiteMap(entries:_*))
 *      }
 *  }
 *  </code>
 *
 *
 *  Finally, You could access the parameter in your snippet with 
 *  S.param("itemID")
 *
 */
class RESTfulLoc (val name: String, val path: List[String],
                  val text: LinkText[Unit], val methods: List[String],
                  val parameterName: String,
                  val locParams: LocParam[Unit]*) extends Loc[Unit] 
{
    override val defaultValue = Full(())
    override val params = locParams.toList
    override val link: Link[Unit] = (List(path.first), true)

    def this (name: String, path: List[String], text: LinkText[Unit], 
              methods: List[String], locParams: LocParam[Unit]*) = 
    {
        this (name, path, text, methods, "id", locParams:_*)
    }

    private def isTarget (path: ParsePath) = 
    {
        path.partPath -- this.path match {
            case List (action, id) => {
                (methods contains action) && id != "index"
            }
            case _ => false
        }
    }

    override def rewrite = Full (NamedPF("RESTfulLoc") 
    {
        case RewriteRequest (path, _, _) if isTarget(path) => {
             val parameter = path.partPath.last
             val action    = path.partPath.init
             val data      = Map (parameterName -> parameter)

             RewriteResponse(action, data) -> ()
        }
    })
}

같은 질문이 있었기 때문에이 게시물을 우연히 발견했습니다. Jim Barrows의 답변은 정확하고 가장 쉬운 일이지만, 설명 없이는 그 코드가 수행하는 일을 어렵게 만들기가 어려웠습니다. Jim의 솔루션 작품이 왜 Lift Book Online에서 찾을 수 있는지에 대한 자세한 설명 (http://groups.google.com/group/the-lift-book). "URL Rewriting"이라는 제목의 섹션 3.12를 확인하여 편안한 URL을 구축하는 방법에 대한 단계별로 안내합니다.

어쨌든 원하는 효과를 달성하기 위해 맞춤형 LOC를 작성할 필요가 없어야합니다.

행운을 빌어 요!

죄송합니다. 위의 의견은 거친 지저분합니다.

문제는 webapp/test에서 edit.html이라는 템플릿이있는 경우 항목을 편집하는 데 사용하는 템플릿입니다.

다음과 같은 메뉴 인스턴스가 있습니다.

Menu (Loc("Test", List("Test") -> true, "Test"))

URL처럼 일치합니다 http : // localhost/test/edit, 같은 것은 아닙니다 http : // localhost/test/edit/1

쿼리로 변경하려는 이유는 무엇입니까? 기술적 또는 프레임 워크 이유입니까?

{id}는 URI 경로에 대한 내 견해에 속하며 고유 한 리소스를 식별 하며이 정보를 경로 안에 보관하고 싶습니다. URI는 모든 종류의 문자열이 될 수 있지만 (따라서 쿼리 매개 변수도 작동합니다) URI를 가능한 한 밀접한 자원 ID 준수로 모델링 할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top