Резюме использования позиции Spring RequestBody
Существует несколько различных способов обработки параметров запроса в SpringMVC, например, следующие:
- в соответствии с
HttpServletRequest
приобретение объекта - в соответствии с
@PathVariable
Аннотация для получения параметров URL - в соответствии с
@RequestParam
Аннотация для получения параметров запроса - Получить параметры запроса в соответствии с методом bean
- в соответствии с
@ModelAttribute
Аннотация для получения параметров запроса
Если вы заинтересованы в вышеуказанных методах, вы можете прочитать этот пост в блоге:Как получить параметры запроса SpringMVC
Помимо вышеперечисленных методов, существует также@RequestBody
Эта статья в основном знакомит с положением использования и соответствующими мерами предосторожности при передаче этого параметра.
I. Использование позы
1. Сервисный интерфейс
С помощью фреймворка Spring используйте@RequestBody
Сложности нет, очень просто написать вариант использования, вот так
@Slf4j
@RestController
public class ReqBodyController {
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Req {
private String key;
private Integer size;
}
@RequestMapping(value = "/body", method = {RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS})
public BaseRsp body(@RequestBody Req req) {
log.info("req: {}", req);
return new BaseRsp<>(req);
}
}
Глядя на приведенную выше реализацию, она ничем не отличается от нашего обычного способа написания, это не что иное, как предыдущая@RequsetParam
заменить аннотацию на@RequsetBody
аннотации, а внутри этой аннотации только одно поле, болееRequsetParam
меньше
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
// 默认参数必须存在,否则会抛一个异常
boolean required() default true;
}
Глядя на приведенную выше реализацию, предполагается, что вы можете догадаться, что эта аннотация не является проблемой для написания бэкенда, ключ в том, как ее использовать (в частности, как использовать ее для внешнего интерфейса).
2. Вызов интерфейса
После того, как написано выше, следующий ключевой момент — как им пользоваться.RequestBody
Оригинальный и прикладной сценарии этой аннотации (проще говоря, чем она отличается от RequestParam, зачем нужно делать отдельную)
RequestBody
Аннотация @requestBody часто используется для обработки содержимого, тип содержимого которого не является кодировкой application/x-www-form-urlcoded по умолчанию, например application/json или application/xml. Как правило, он используется для обработки типов application/json.
а. определение типа контента
Прежде чем перейти к следующему шагу, необходимо сказатьContent-Type
Используется этот заголовок HTTP-запроса. Следующий абзац взят из других сообщений блога. См. исходную ссылку в конце.
MediaType, то есть Internet Media Type, тип Интернет-медиа; также называемый типом MIME, в заголовке сообщения протокола Http Content-Type используется для представления информации о типе мультимедиа в конкретном запросе.
Распространенные медиаформаты следующие:
- текст/html : формат HTML
- text/plain : обычный текстовый формат
- текст/xml : формат XML
- image/gif : формат изображения gif
- изображение/jpeg: формат изображения jpg
- изображение/png: формат изображения png
Типы медиаформатов, начинающиеся с application:
- application/xhtml+xml : формат XHTML
- application/xml : формат данных XML
- application/atom+xml : формат агрегации Atom XML
- application/json : формат данных JSON
- приложение/pdf : формат pdf
- application/msword : формат документа Word
- application/octet-stream : данные двоичного потока (например, загрузка обычных файлов)
- application/x-www-form-urlencoded : encType по умолчанию в , данные формы кодируются в формате ключ/значение и отправляются на сервер (формат данных отправки формы по умолчанию)
б) описание экземпляра типа контента
Выше приведены основные определения и значения. Ниже приведены некоторые типичные способы объяснения с примерами.
- application/x-www-form-urlencoded: данные закодированы как пары имя/значение. Это стандартный формат кодирования.
- multipart/form-data: данные кодируются как сообщение, и каждый элемент управления на странице соответствует части сообщения.
- text/plain: данные закодированы в виде простого текста (text/json/xml/html) без каких-либо элементов управления или символов форматирования.
Для внешнего интерфейса атрибут enctype формы формы является методом кодирования, и есть два часто используемых метода:application/x-www-form-urlencoded
иmultipart/form-data
, По умолчаниюapplication/x-www-form-urlencoded
.
Получить запрос
При инициировании запроса Get браузер используетapplication/x-www-form-urlencoded
образом, преобразовать данные формы в строку (ключ1=значение1&ключ2=значение2...) и соединить их с URL-адресом, это наш общий URL-адрес с параметрами запроса
Почтовая форма
При инициировании почтового запроса, если файл не загружен, браузер также инкапсулирует данные формы формы как k=v и выдает результат в тело http.В качестве примера возьмем форму, отправленную китайским блогом с открытым исходным кодом, типичная форма сообщения, загруженная Данные собраны в данные формы, которая представляет собой структуру kv
Если есть сценарий передачи файлов, тип Content-Type будет обновлен доmultipart/form-data
, этот кусок не буду подробно развёртывать, о нём я расскажу позже
Опубликовать строку json
Помимо предыдущего метода, есть еще один, общий для нас, который заключается в том, чтобы поместить все данные формы в большую json-строку, а затем кинуть ее на бэкенд.Также здесь есть пример онлайн, e- выпуск продукта торговой платформы, скриншоты следующие
Обратите внимание на приведенную выше полезную нагрузку запроса, которая представляет собой большую строку json, которая явно отличается от предыдущей.
в. Запрос RequestBody
Согласно определению RequestBody, для доступа к определенному ранее интерфейсу невозможно использовать традиционный метод передачи формы.Команда curl тестируется следующим образом
curl -X POST -d 'key=haha&size=123' http://127.0.0.1:19533/body
Соответствующий вывод бэкенда выглядит следующим образом (выдается исключение, указывающее, что аннотация @RequestBody модифицирует оставшийся интерфейс, который не поддерживаетсяContent type 'application/x-www-form-urlencoded;charset=UTF-8'
Следовательно, использование позы требует отображения добавления заголовка запроса, а также изменения параметров.
curl -l -H "Content-type: application/json" -X GET -d '{"key": "!23", "size": 10}' http://127.0.0.1:19533/body
Результат возврата следующий
3. Меры предосторожности
а. Спецификация отображения типа контента
По предыдущему описанию известно, что@RequestBody
Использование этой аннотации делает тип содержимого, полученный интерфейсом REST, больше неapplication/x-www-form-urlencoded
, вместо этого его необходимо явно указать какapplication/json
б. Метод запроса
Поддерживает ли RequestBody метод GET? Спереди используются параметры отправки сообщения, что если изменить на GET?
метод теста на скручивание
curl -l -H "Content-type: application/json" -X GET -d '{"key": "!23", "size": 10}' http://127.0.0.1:19533/body\?key\=app
Соответствующие скриншоты внутренней отладки выглядят следующим образом: Обнаружено, что с использованием метода GET проблем нет, и параметры все еще можно получить.
Сменить на знаменитого ПОЧТАЛЬНИКА для теста
При использовании метода post для запроса скриншот выглядит следующим образом, главное изменить content-type заголовка, а затем добавить запрос в формате строки json в тело
Однако после изменения на get тело сразу становится серым, то есть оно не поддерживает отправку данных тела во время запроса на получение.
метод запроса URL
Затем напрямую измените метод запроса URL, чтобы увидеть, поддерживает ли он напрямую запросы на получение.
http://127.0.0.1:19533/body?{"key": "!23", "size": 10}
При вводе в браузере сервер 400, заменённый curl-запросом, выкидывает исключение об отсутствии RequestBody, то есть вклеивание json-строки в url вроде как не работает (может быть и так, что моя поза неправильно...)
резюме
- Подводя итог, при использовании RequestBody для получения параметров более целесообразно честно выбирать метод POST.Что касается причины, то лучше следовать за публикой, следовать мейнстриму и следовать привычкам каждого.
c. Получение параметров
В основном это проблема получения параметра RequestBody, когда бэкенд пишет интерфейс.HttpServletRequest
В параметрах отсутствуют представленные параметры RequestBody.Демонстрация выглядит следующим образом
URL-адрес запроса
curl -l -H "Content-type: application/json" -X POST -d '{"key": "!23", "size": 10}' http://127.0.0.1:19533/body\?url\=ddd
Соответствующий скриншот отладки выглядит следующим образом, параметр url можно получить, параметр RequestBody нет.
Прежде всего, я заявляю, что следующий анализ не читает исходный код.Это чисто личный вывод.Если возникнут какие-либо проблемы, я хотел бы извиниться перед друзьями, которые были введены в заблуждение.Я также надеюсь, что друзья, которые это понимают будет критиковать и поправлять меня
从传文件的思路出发,前端传文件给后端时,后端是基于流的方式,将上传的二进制流,写入到`MultipartFile`;而二进制流读完之后,没法再重复的读
RequestBody可能也是这么个逻辑,首先是从HttpServletRequest的Reader流中读取body参数并封装到上面的req对象,而不会像url参数一样,写回到`javax.servlet.ServletRequest#getParameterMap`
Сделайте небольшую проверку приведенного выше предположения и измените его, чтобы получить параметр тела запроса непосредственно из потока Reader HttpServletRequest.
@RequestMapping(value = "/body", method = {RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS})
public BaseRsp body(HttpServletRequest request) throws IOException {
BufferedReader reader = request.getReader();
StringBuilder builder = new StringBuilder();
String line = reader.readLine();
while (line != null) {
builder.append(line);
line = reader.readLine();
}
reader.close();
String reqBody = builder.toString();
Req req = JSON.parseObject(reqBody, Req.class);
log.info("req: {}, request: {}", req, request.getParameterMap());
return new BaseRsp<>(req);
}
Проверьте следующим образом
На самом деле, здесь есть интересное место, которое вызвало у меня любопытство, а именно, как работает HttpServletRequest в контейнере Spring, об этом я расскажу позже, здесь я не буду его распространять...
4. Резюме
- ReuqestBody в основном имеет дело с параметрами запроса в формате строки json, требуя от пользователя указания заголовка.
content-type:application/json
- RequestBody обычно требует, чтобы вызывающая сторона использовала почтовый запрос.
- Параметр RequsetBody не будет помещен в карту HttpServletRequest, поэтому он не может пройти
javax.servlet.ServletRequest#getParameter
Получать
II. Другое
0. Ссылка
1. Серый блог: https://juneb.GitHub.IO/hex блог
Серый персональный блог, запись всех сообщений в блоге в кабинете и работе, приветствуют всех посетить
2. Заявление
Это не так хорошо, как письмо веры.Контент уже был размещен, и это чисто из семьи.Из-за ограниченных личных возможностей неизбежно будут упущения и ошибки.Если вы найдете ошибки или лучше предложения, вы можете критиковать и исправлять их.
- Адрес вейбо:Блог Маленького Серого
- QQ: серо-серый / 3302797840
3. Сканируйте внимание
Блог Little Grey и общедоступный номер
планета знаний