Spring으로 선택적 경로 변수를 만들 수 있습니까?


187

Spring 3.0에서 선택적 경로 변수를 가질 수 있습니까?

예를 들어

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @PathVariable String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

여기서 나는 같은 방법을 원 /json/abc하거나 /json호출하고 싶습니다 .
한 가지 확실한 해결 방법 type은 요청 매개 변수로 선언합니다 .

@RequestMapping(value = "/json", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @RequestParam(value = "type", required = false) String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

그때 /json?type=abc&track=aa또는 /json?track=rr작동합니다

답변:


194

선택적 경로 변수를 가질 수는 없지만 동일한 서비스 코드를 호출하는 두 가지 컨트롤러 메소드를 가질 수 있습니다.

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
        HttpServletRequest req,
        @PathVariable String type,
        @RequestParam("track") String track) {
    return getTestBean(type);
}

@RequestMapping(value = "/json", method = RequestMethod.GET)
public @ResponseBody TestBean testBean(
        HttpServletRequest req,
        @RequestParam("track") String track) {
    return getTestBean();
}

5
@ Shamik : 이것은 내 의견으로는 경로 변수를 사용 하지 않는 매력적인 이유 입니다. 조합 확산은 빠르게 벗어날 수 있습니다.
skaffman 2019

9
선택적 구성 요소로 채워지는 동안 경로가 그렇게 복잡 할 수 없기 때문에 실제로는 아닙니다. 하나 또는 최대 두 개의 선택적 경로 요소가있는 경우 매개 변수를 요청하기 위해 몇 가지 경로 요소를 심각하게 전환해야합니다.
Patrick Cornelissen

1
예를 들어 서로 다른 매개 변수는 다른 수단에 의해 제공 될 수 있는지 그리고 어떤 사람들을 위해, 두 번째 컨트롤러 메소드 호출을 첫 번째 컨트롤러 방식을 가진 것은 아니라 작동 할 수
chrismarx

3
최신 버전의 Spring에서 두 가지 컨트롤러 메소드를 만드는 대신 답을 업데이트하십시오 @RequestMapping. stackoverflow.com/questions/17821731/…
csharpfolk

이 끝점을 어떻게 유지해야합니까? 그리고 하나의 경로 변수 대신 5를 가지고 있다면 수학을 수행하십시오. 끝점은 몇 개입니까? 나에게 부탁을하고 교체하십시오 @PathVariable@RequestParam
Guilherme Alencar의

113

Spring 4.1과 Java 8을 사용한다면 java.util.Optional 있는 지원되는 @RequestParam, @PathVariable, @RequestHeader@MatrixVariable스프링 MVC에서 -

@RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
    @PathVariable Optional<String> type,
    @RequestParam("track") String track) {      
    if (type.isPresent()) {
        //type.get() will return type value
        //corresponds to path "/json/{type}"
    } else {
        //corresponds to path "/json"
    }       
}

이것이 효과가 있다고 확신합니까? 자신의 답은 여기 {타입} 경로에없는 경우 컨트롤러가 충돌되지 않는다는 것을 의미한다. PathVariable Map이 더 나은 접근 방식이거나 별도의 컨트롤러를 사용하는 것으로 생각합니다.
Anshul Tiwari

4
예, 방금 가지고 "/json/{type}"있고 유형이 없으면 내 링크 된 답변이 제안하는 것처럼 맞지 않지만 여기에 있습니다 value = {"/json/{type}", "/json" }. 따라서 컨트롤러 메소드와 일치하는 것이 있으면 히트합니다.
Aniket Thakur

같은 값 등의 유형이 RequestParam 및 RequestParam 일 수도 있습니까?
zygimantus

그것은 작동하지만 어쨌든 컨트롤러의 기능은 매개 변수를 기대하기 때문에 호출되지 않습니다
EliuX

15
이것은 작동하며 Spring 4.3.3부터 @PathVariable(required = false)변수가 없으면 null을 얻을 수 있습니다 .
Nicolai Ehemann

76

@PathVariable 주석을 사용하여 경로 변수의 맵을 삽입 할 수도 있다는 것은 잘 알려져 있지 않습니다. 이 기능을 Spring 3.0에서 사용할 수 있는지 또는 나중에 추가했는지 확실하지 않지만 다음 예제를 해결하는 다른 방법이 있습니다.

@RequestMapping(value={ "/json/{type}", "/json" }, method=RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
    @PathVariable Map<String, String> pathVariables,
    @RequestParam("track") String track) {

    if (pathVariables.containsKey("type")) {
        return new TestBean(pathVariables.get("type"));
    } else {
        return new TestBean();
    }
}

1
나는 항상 그것을 사용합니다. 이것은 하나의 메소드가 다른 URI 유형을 처리하는 단일 방법을 원할 때 편리합니다. {type} / {abc} ","/ json / {type} / {abc} / {something} ","/ json "}
Vaibs

25

당신은 사용할 수 있습니다 :

@RequestParam(value="somvalue",required=false)

경로가 아닌 선택적 매개 변수의 경우


1
이것은 버전에 따라 다릅니다. 봄 3
Stu Thompson

5
현재 스프링 3.1 프로젝트 에이 방법을 사용하고 있으며 문서는 2.5 이상에서 작동하므로 Spring 3에서는 확실히 작동한다고 말합니다 . EDIT : source .
Evan B.

22
사실이지만 이것은 문제가 아닙니다. 요청 매개 변수를 사용하는 것은 실제로 질문에서 "하나의 확실한 해결 방법" 으로 언급 되었지만 질문 자체는 경로 매개 변수 에 관한 것입니다 . 선택적 경로 매개 변수에 대한 솔루션이 아닙니다.
Arjan

9
PathVariable과 RequestParam이 다릅니다.
Timeless

10

Spring 5 / Spring Boot 2 예제 :

블로킹

@GetMapping({"/dto-blocking/{type}", "/dto-blocking"})
public ResponseEntity<Dto> getDtoBlocking(
        @PathVariable(name = "type", required = false) String type) {
    if (StringUtils.isEmpty(type)) {
        type = "default";
    }
    return ResponseEntity.ok().body(dtoBlockingRepo.findByType(type));
}

반응성

@GetMapping({"/dto-reactive/{type}", "/dto-reactive"})
public Mono<ResponseEntity<Dto>> getDtoReactive(
        @PathVariable(name = "type", required = false) String type) {
    if (StringUtils.isEmpty(type)) {
        type = "default";
    }
    return dtoReactiveRepo.findByType(type).map(dto -> ResponseEntity.ok().body(dto));
}

6

Nicolai Ehmann의 의견과 wildloop의 답변 (Spring 4.3.3 이상에서 작동)의 단순화 된 예, 기본적으로 다음을 사용할 수 있습니다 required = false.

  @RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
  public @ResponseBody TestBean testAjax(@PathVariable(required = false) String type) {
    if (type != null) {
      // ...
    }
    return new TestBean();
  }



-5
$.ajax({
            type : 'GET',
            url : '${pageContext.request.contextPath}/order/lastOrder',
            data : {partyId : partyId, orderId :orderId},
            success : function(data, textStatus, jqXHR) });

@RequestMapping(value = "/lastOrder", method=RequestMethod.GET)
public @ResponseBody OrderBean lastOrderDetail(@RequestParam(value="partyId") Long partyId,@RequestParam(value="orderId",required=false) Long orderId,Model m ) {}

3
답변에서 일부 텍스트를 편집하여 문제를 해결하는 데 도움이된다고 생각 하는지 설명 할 수 있습니다 (4 년 후).
Qirel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.