Với Spring, tôi có thể tạo một biến đường dẫn tùy chọn không?


185

Với Spring 3.0, tôi có thể có một biến đường dẫn tùy chọn không?

Ví dụ

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

Ở đây tôi muốn /json/abchoặc /jsongọi phương thức tương tự.
Một cách giải quyết rõ ràng typelà một tham số yêu cầu:

@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();
}

và sau đó /json?type=abc&track=aahoặc /json?track=rrsẽ làm việc

Câu trả lời:


193

Bạn không thể có các biến đường dẫn tùy chọn, nhưng bạn có thể có hai phương thức điều khiển gọi cùng một mã dịch vụ:

@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: Đây là một lý do thuyết phục để không sử dụng các biến đường dẫn, theo ý kiến ​​của tôi. Sự tăng sinh kết hợp có thể nhanh chóng ra khỏi tầm tay.
skaffman

9
Thực tế không phải vì đường dẫn không thể phức tạp trong khi được lấp đầy với các thành phần tùy chọn. Nếu bạn có nhiều hơn một hoặc tối đa hai yếu tố đường dẫn tùy chọn, bạn nên nghiêm túc xem xét chuyển đổi một vài trong số chúng để yêu cầu tham số.
Patrick Cornelissen

1
Và đối với một số người, có phương thức bộ điều khiển thứ hai gọi phương thức bộ điều khiển thứ nhất cũng có thể hoạt động, nếu chẳng hạn, tham số khác nhau có thể được cung cấp bằng một số phương tiện khác
chrismarx

2
Vui lòng xem xét cập nhật câu trả lời của bạn, thay vì tạo hai phương pháp điều khiển trong phiên bản mới hơn của mùa xuân, chúng tôi chỉ có thể sử dụng @RequestMappingvới hai giá trị như trong: stackoverflow.com/questions/17821731/...
csharpfolk

Làm thế nào để bạn mong đợi để duy trì các điểm cuối? Và nếu thay vì chỉ có một biến đường dẫn chúng ta có 5, hãy làm toán cho tôi, bạn sẽ làm bao nhiêu điểm cuối? Xin hãy giúp tôi và thay thế @PathVariablecho@RequestParam
Guilherme Alencar

113

Nếu bạn đang sử dụng Spring 4.1 và Java 8 bạn có thể sử dụng java.util.Optionalđược hỗ trợ ở @RequestParam, @PathVariable, @RequestHeader@MatrixVariabletrong Spring 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"
    }       
}

Bạn có chắc chắn điều này sẽ làm việc? Câu trả lời của riêng bạn ở đây cho thấy rằng bộ điều khiển sẽ không bị tấn công nếu {type} không có trong đường dẫn. Tôi nghĩ PathVariable Map sẽ là cách tiếp cận tốt hơn hoặc sử dụng các bộ điều khiển riêng biệt.
Anshul Tiwari

4
Có nếu bạn chỉ có "/json/{type}"và loại không có mặt thì nó sẽ không bị ảnh hưởng (như câu trả lời được liên kết của tôi cho thấy) nhưng ở đây bạn có value = {"/json/{type}", "/json" }. Vì vậy, nếu bất kỳ một phù hợp với phương pháp điều khiển sẽ được nhấn.
Aniket Thakur

Có thể là cùng một giá trị, v.v., loại sẽ là RequestParam và RequestParam không?
zygimantus

Nó hoạt động, nhưng dù sao thì chức năng của bộ điều khiển sẽ không được gọi vì nó mong đợi một tham số ở đó
EliuX 30/03/2017

15
Điều này hoạt động và kể từ Mùa xuân 4.3.3, bạn cũng có thể đi cùng @PathVariable(required = false)và nhận null nếu không có biến.
Nicolai Ehemann

76

Bạn cũng không biết rằng bạn cũng có thể chèn Bản đồ các biến đường dẫn bằng cách sử dụng chú thích @PathVariable. Tôi không chắc liệu tính năng này có khả dụng trong Spring 3.0 hay nếu nó được thêm vào sau, nhưng đây là một cách khác để giải quyết ví dụ:

@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
Tôi sử dụng nó mọi lúc. Điều này rất hữu ích khi tôi muốn một phương thức duy nhất để xử lý các loại uri khác nhau ex: {"/ json / {type}", "/ json / {type} / {xyz}", "/ json / {type} / {abc} "," / json / {type} / {abc} / {
Something

25

Bạn có thể sử dụng một:

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

cho các thông số tùy chọn thay vì một đường dẫn


1
Đây là phiên bản cụ thể, có vẻ như. Không đi vào mùa xuân 3.
Stu Thompson

5
Hiện đang sử dụng phương pháp này cho dự án spring 3.1 và các tài liệu nói rằng nó hoạt động cho 2.5+, vì vậy nó chắc chắn hoạt động cho Spring 3. EDIT: source .
Evan B.

22
Đúng, nhưng đây không phải là những gì câu hỏi về. Sử dụng các tham số yêu cầu thực sự được đề cập trong câu hỏi là "Một cách giải quyết rõ ràng" , nhưng bản thân câu hỏi là về các tham số đường dẫn . Đây không phải là một giải pháp cho các tham số đường dẫn tùy chọn.
Arjan

9
PathVariable và RequestParam là khác nhau.
Vượt thời gian

9

Spring 5 / Spring Boot 2 ví dụ:

chặn

@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));
}

phản ứng

@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));
}

5

Ví dụ đơn giản về nhận xét của Nicolai Ehmann và câu trả lời của wildloop (hoạt động với Spring 4.3.3+), về cơ bản bạn có thể sử dụng required = falsengay bây giờ:

  @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
Bạn có thể muốn chỉnh sửa một số văn bản trong câu trả lời của mình, giải thích lý do tại sao bạn nghĩ rằng điều này góp phần giải quyết vấn đề trong tay (4 năm sau).
Qirel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.