HttpServletRequest - Отримати параметри рядка запиту, без даних форми


76

У HttpServletRequest , getParameterMapповертає карту всіх параметрів рядка запиту і пост параметрів даних.

Чи є спосіб отримати карту ТІЛЬКИ параметрів рядка запиту? Я намагаюся уникати використання getQueryString та аналізу значень.


15
Ви можете мати обидва ... Ви можете мати параметри рядка запиту на запит POST. І в цьому випадку їх усіх повертає "getParameterMap"
JasonStoltz

О, добре. Навіщо потрібні обидва, просто цікаві?
Jacob

2
Оскільки на результуючій сторінці я хочу, щоб рядок запиту відображався у url / бути в рядку запиту. У нас є система відстеження, яка шукає конкретні параметри в рядку запиту.
JasonStoltz

req.getParameterMap (). containsKey ("ім'я користувача");
Параг Ядхав

Відповіді:


22

На відміну від сказаного cularis, у карті параметрів може бути як те, так і інше.

Найкращий спосіб, який я бачу, - це встановити проксі-параметр і для кожного пошуку параметрів перевірити, чи містить queryString "&? <parameterName> =".

Зауважте, що для того, щоб здійснити цю перевірку, як слід зазначити Qerub, параметрName потрібно закодувати URL-адресою.

Це заощаджує аналіз і надає лише параметри URL-адреси.


2
Зверніть увагу, що parameterNameперед виконанням цієї перевірки потрібно закодувати URL-адресу.
qerub

12
Рядок запиту ніколи не містить ?. Це символ розділювача між URI та рядком запиту.
BalusC

Привіт @DoubleMalt, у мене така сама вимога, але я не можу отримати рішення, яке ви надали. Чи можете ви навести приклад коду?
Vishal Zanzrukia

@VishalZanzrukia: Який ваш код не працює?
DoubleMalt

1
Мені ця ідея подобається, але не завжди в рядку запиту є символ "=". Якщо значення параметра порожнє, у рядку запиту є лише <parameterName>. Я особисто вважаю, що розділення на "&" та "=" було б кращим рішенням.
Брен

95

Ви можете використовувати request.getQueryString(), якщо рядок запиту подібний

username=james&password=pwd

Щоб отримати ім’я, ви можете це зробити

request.getParameter("username"); 

Це для використання на сторінках Java Server.
Jorgesys

2
другий зіпсує потік запитів, я припускаю, що питання полягає в тому, як отримати ім’я користувача та зберегти вхідний потік для подальшої обробки
Павел Нієдоба

23

API сервлета не має цієї функції, оскільки він був створений у той час, коли багато хто вважав, що рядок запиту та тіло повідомлення - це лише два різні способи надсилання параметрів, не розуміючи, що цілі параметрів принципово різні.

Параметри рядка запиту? Foo = bar є частиною URL-адреси, оскільки вони беруть участь у ідентифікації ресурсу (який може бути сукупністю багатьох ресурсів), наприклад "усі особи у віці 42 років":

GET / осіб? Вік = 42

Параметри тіла повідомлення в POST або PUT існують для вираження модифікації цільових ресурсів. Fx встановлює значення атрибуту "волосся":

Покласти / осіб? Вік = 42

волосся = сиве

Отож, безумовно, НАДІЙНО використовувати одночасно параметри запиту та параметри тіла, розділені таким чином, що ви можете використовувати їх для різних цілей. Ця функція точно відсутня в API сервлету Java.


12

Оскільки інші відповіді стверджують, немає можливості отримати параметри рядка запиту за допомогою API сервлету.

Отже, я думаю, що найкращим способом отримати параметри запиту є синтаксичний аналіз рядка запиту. (Це більш складна ітерація параметрів і перевірка, чи рядок запиту містить параметр)

Я написав нижче код, щоб отримати параметри рядка запиту. Використання apache StringUtils та ArrayUtils, які також підтримують значення параметрів запиту, розділених CSV.

Приклад: username=james&username=smith&password=pwd1,pwd2повернеться

password : [pwd1, pwd2] (довжина = 2)

username : [james, smith] (довжина = 2)

public static Map<String, String[]> getQueryParameters(HttpServletRequest request) throws UnsupportedEncodingException {
    Map<String, String[]> queryParameters = new HashMap<>();
    String queryString = request.getQueryString();
    if (StringUtils.isNotEmpty(queryString)) {
        queryString = URLDecoder.decode(queryString, StandardCharsets.UTF_8.toString());
        String[] parameters = queryString.split("&");
        for (String parameter : parameters) {
            String[] keyValuePair = parameter.split("=");
            String[] values = queryParameters.get(keyValuePair[0]);
            //length is one if no value is available.
            values = keyValuePair.length == 1 ? ArrayUtils.add(values, "") :
                    ArrayUtils.addAll(values, keyValuePair[1].split(",")); //handles CSV separated query param values.
            queryParameters.put(keyValuePair[0], values);
        }
    }
    return queryParameters;
}

Я вважаю це набагато кращою за прийняту відповідь, не знаю, чому уникати розбору рядка запиту, оскільки створення проксі-сервера не є кращим рішенням
Павел Нієдоба

1
Мені просто цікаво, якщо якийсь із параметрів запиту містить &символ у своєму значенні, чи дасть він вам правильний результат
amdg

1
@amdg - цей символ буде закодований за URL-адресою, так що код хороший. Якби він не був закодований, рядок був би нерозбірним.
марафон

Подумайте також про використання URLDecoder.decode(keyValuePair[0])(або [1]): docs.oracle.com/javase/6/docs/api/java/net/URLDecoder.html
Плутон

1
параметри запиту зі значеннями, розділеними csv, тут не розглядаються. для напр .: username=james&username=smith&password=pwd1,pwd2матиме карту з 2 значеннями для імені користувача (що є правильним), але лише 1 значенням для пароля (що є неправильним)
Niv,

4

Java 8

return Collections.list(httpServletRequest.getParameterNames())
                  .stream()
                  .collect(Collectors.toMap(parameterName -> parameterName, httpServletRequest::getParameterValues));

2

Я боюся, що немає можливості отримати параметри рядка запиту, проаналізовані окремо від параметрів повідомлення. До речі, той факт, що такий API відсутній, може означати, що, мабуть, вам слід перевірити свій дизайн. Чому ви використовуєте рядок запиту під час надсилання POST? Якщо ви дійсно хочете надіслати більше даних у URL-адресу, використовуйте REST-подібну конвенцію, наприклад, замість надсилання

http://mycompany.com/myapp/myservlet?first=11&second=22

казати:

http://mycompany.com/myapp/myservlet/11/22


Я використовую параметр рядка запиту в POST, оскільки я хочу підтримувати будь-які та всі рядки запитів, передані у вихідну форму через POST. Це в першу чергу для цілей відстеження ... я не впевнений, що в цьому випадку буде схоже на REST-правило, оскільки я впевнений, що бібліотека відстеження шукає конкретні параметри в рядку запиту.
JasonStoltz

Будь-яка причина, зокрема, що ви рекомендували б використовувати REST-подібну конвенцію для параметра рядка запиту? Не впевнений, що розумію, в чому перевага?
JasonStoltz

8
"До речі, той факт, що такий API відсутній, може означати, що, мабуть, вам слід перевірити свій дизайн." У цьому випадку це означає, що Oracle повинен перевірити їх дизайн :)
Stijn de Witt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.