Поведение службы REST с использованием HTTPServletRequest и использование @PathVariable

63
5

Ниже приведены два сценария, которыми я сталкивался при кодировании услуг для проекта в школе.

Сценарий 1
@RequestMapping("/customer/firstName/")
public CustomerRepresentation getCustomersByFirstName(HttpServletRequest request) {
String name = request.getParameter("fname");
List<Customer> customer = customerActivity.findByCustFirstName(name);
// etc
}
Сценарий 2
@RequestMapping(value="/customer/firstName/{fname}",method = RequestMethod.GET, produces = {"text/html","application/json", "application/xml"})
public @ResponseBody List<CustomerRepresentation> getCustomersByFirstName(@PathVariable("fname") String name) {
List<Customer> customer = customerActivity.findByCustFirstName(name);
// etc
}

Поведение:

Если я использую первый подход, я могу получить доступ к результатам, используя ссылку из любого браузера и даже из Postman.

Если я использую второй подход, я могу получить доступ к результатам, используя Postman, только когда я укажу Accept Headers. Если я использую браузер, он дает мне ошибку 406, тип не поддерживается.

Использование клиента оба отлично работают с незначительными изменениями в URL.

Что вызывает это? Я предполагаю настройки по умолчанию в HttpServletRequest? Если мы используем второй подход, как будут работать веб-сайты, или я делаю что-то неправильно?

спросил(а) 2021-01-25T20:04:39+03:00 5 месяцев назад
1
Решение
64

Эти два URI принципиально различаются и не должны считаться одинаковыми.

Во-первых, существует огромная разница между переменной пути и параметром запроса - переменные пути должны быть частью пути или путь не будет доступен. Это разница в этих двух URI:

/customer/firstName?fname=Bob
/customer/firstName/Bob

Вы не можете получить доступ ко второму URI без Боба, в отличие от первого URI; вы можете просить что-то другое, кроме fname.

Во- вторых, по этой причине вы должны иметь ваши Accept набор заголовков связано с образом ваш produces массив настроен: у вас есть text/html, application/json и application/xml; ваш клиент не сможет принять ничего, что не является одним из этих трех типов.

В-третьих, чтобы напрямую ответить на последний вопрос, я бы явно отказался от вашего второго подхода из-за того, что путь переменных пути должен быть разделен. Путь описывает некоторую информацию, которая требуется для продолжения запроса; здесь вы только запрашиваете информацию о клиенте, которая должна содержаться в запросе.

В этом ключе ваш запрос URI должен действительно быть customer с запросом firstName.

/customer?firstName=Bob

ответил(а) 2021-01-25T20:04:39+03:00 5 месяцев назад
63

если вы укажете

produces = {"text/html","application/json", "application/xml"}

вам нужно отправить заголовок Accept с одним из этих типов. Некоторые клиенты используют заголовок Accept по умолчанию и могут отличаться от ожидаемого.

ответил(а) 2021-01-25T20:04:39+03:00 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема