Каков предпочтительный способ указания HTTP & ldquo; Location & rdquo; Заголовок ответа в Spring MVC 3?

Я нашел, что все выше всего найдено ['a', 'b', 'd'] как подсловитель ['a', 'b', 'c', 'e', ​​'d'], который может быть неверным, несмотря на то, что все элементы подсписчика присутствуют в списке. Поэтому, чтобы поддерживать порядок, и я придумал:

def sublist4(sublist,lst):
    #Define an temp array to populate 
    sub_list=[]
    comparable_sublist=[]
    #Define two constants to iterate in the while loop
    i=0
    k=0
    #Loop the length of lst
    while i < len(lst):
        #If the element is in the sublist append to temp array, 
        if k < len(sublist) and lst[i] == sublist[k]:
            sub_list.append(lst[i])
            #set a comparable array to the value of temp array
            comparable_sublist = sub_list
            k += 1
            #If the comparable array is the same as the sublist, break
            if len(comparable_sublist) == len(sublist):
                break

        #If the element is not in the sublist, reset temp array
        else:
            sub_list = []


        i += 1

    return comparable_sublist == sublist

Хотя это не очень эффективно для памяти, я нахожу, что он отлично работает с небольшими списками.

29
задан Brian Kent 23 July 2010 в 14:09
поделиться

5 ответов

Начиная с весны 3.1, лучший способ для создания Location - использовать параметр UriComponentBuilder и установить его в возвращаемое значение ResponseEntity. UriComponentBuilder знает о контексте и манипулирует относительными путями:

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> createCustomer(UriComponentsBuilder b) {

    UriComponents uriComponents = 
        b.path("/customers/{id}").buildAndExpand(id);

    HttpHeaders headers = new HttpHeaders();
    headers.setLocation(uriComponents.toUri());
    return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}

Начиная с версии 4.1 вы можете сделать его еще короче

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> createCustomer(UriComponentsBuilder b) {

    UriComponents uriComponents = 
        b.path("/customers/{id}").buildAndExpand(id);

    return ResponseEntity.created(uriComponents.toUri()).build();
}

Благодаря Дитеру Хубау за указание на это.

74
ответ дан Roman Konoval 23 July 2010 в 14:09
поделиться

Согласно: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30

Следует использовать абсолютный URI:

Location       = "Location" ":" absoluteURI  

И URI следует правильно экранировать:

http://www.ietf.org/rfc/rfc2396.txt

1
ответ дан tszming 23 July 2010 в 14:09
поделиться

Это старый вопрос, но вот что вы можете сделать, если хотите, чтобы Spring действительно создала для вас URI.

@RestController
@RequestMapping("/api/v1")
class JobsController {

  @PostMapping("/jobs")
  fun createJob(@RequestParam("use-gpu") useGPU: Boolean?): ResponseEntity<Unit> {

    val headers = HttpHeaders()

    val jobId = "TBD id"

    headers.location =
            MvcUriComponentsBuilder
                    .fromMethodName(JobsController::class.java, "getJob", jobId)
                    .buildAndExpand(jobId)
                    .toUri()

    return ResponseEntity(headers, HttpStatus.CREATED)
  }

  @GetMapping("/job/{jobId}")
  fun getJob(@PathVariable jobId: String) = ... // fetch job
}

В этом примере (который написан на Kotlin, но похож на Java), базовый URI равен /api/v1 (определен в верхней части класса). Использование вызова MvcUriComponentsBuilder.fromMethodName позволяет Spring определить правильный полный URI. (MvcUriComponentsBuilder был добавлен в 4.0).

2
ответ дан yan 23 July 2010 в 14:09
поделиться

Следующий пример взят из весеннего учебного пособия:

@RequestMapping(method = RequestMethod.POST)
ResponseEntity<?> add(@PathVariable String userId, @RequestBody Bookmark input) {
    this.validateUser(userId);

    return this.accountRepository
            .findByUsername(userId)
            .map(account -> {
                Bookmark result = bookmarkRepository.save(new Bookmark(account,
                        input.uri, input.description));

                URI location = ServletUriComponentsBuilder
                    .fromCurrentRequest().path("/{id}")
                    .buildAndExpand(result.getId()).toUri();

                return ResponseEntity.created(location).build();
            })
            .orElse(ResponseEntity.noContent().build());

}

Обратите внимание, что следующее вычислит путь контекста (URI), чтобы вы избежали дублирования кода и сделали ваше приложение более переносимым:

ServletUriComponentsBuilder
                    .fromCurrentRequest().path("/{id}")
16
ответ дан Agustí Sánchez 23 July 2010 в 14:09
поделиться

Ваш подход кажется нормальным, но чтобы сохранить его в чистоте, вы можете поместить код в пользовательский HandlerInterceptor, который срабатывает только при наличии HTTP 201, например.

См. здесь для получения дополнительной информации.

0
ответ дан earldouglas 23 July 2010 в 14:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: