Вопрос-ответ

doGet and doPost in Servlets

doGet и doPost в сервлетах

Я разработал HTML-страницу, которая отправляет информацию в сервлет. В сервлете я использую методы doGet() и doPost():

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {

String id = req.getParameter("realname");
String password = req.getParameter("mypassword");
}

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {

String id = req.getParameter("realname");
String password = req.getParameter("mypassword");
}

В коде html-страницы, вызывающей сервлет, есть:

<form action="identification" method="post" enctype="multipart/form-data">
User Name: <input type="text" name="realname">
Password: <input type="password" name="mypassword">
<input type="submit" value="Identification">
</form>

Когда я использую method = "get" в сервлете, я получаю значение id и пароль, однако при использовании method = "post" id и пароль устанавливаются равными null. Почему я не получаю значения в этом случае?

Еще одна вещь, которую я хотел бы знать, - это как использовать данные, сгенерированные или проверенные сервлетом. Например, если сервлет, показанный выше, аутентифицирует пользователя, я хотел бы напечатать идентификатор пользователя на моей HTML-странице. Я должен иметь возможность отправлять строку 'id' в качестве ответа и использовать эту информацию на своей HTML-странице. Возможно ли это?

Переведено автоматически
Ответ 1

Введение

Вам следует использовать doGet(), когда вы хотите перехватывать HTTP GET-запросы. Вам следует использовать doPost(), когда вы хотите перехватывать HTTP POST запросы. Вот и все. Не переносите одно на другое или наоборот (например, в неудачном автоматически сгенерированном методе Netbeans processRequest()). В этом нет абсолютного смысла.

ПОЛУЧИТЬ

Обычно HTTP GET-запросы идемпотентны. Т.е. вы получаете точно такой же результат каждый раз, когда выполняете запрос (оставляя авторизацию / аутентификацию и зависящий от времени характер страницы — результаты поиска, последние новости и т.д. — вне рассмотрения). Мы можем поговорить о запросе с возможностью добавления в закладки. Щелчок по ссылке, щелчок по закладке, ввод необработанного URL в адресной строке браузера и так далее - все это вызовет HTTP GET-запрос. Если сервлет прослушивает указанный URL, то будет вызван его doGet() метод. Обычно используется для предварительной обработки запроса. Т. е. Выполнения некоторых деловых действий перед представлением выходных данных HTML из JSP, таких как сбор данных для отображения в таблице.

@WebServlet("/products")
public class ProductsServlet extends HttpServlet {

@EJB
private ProductService productService;

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Product> products = productService.list();
request.setAttribute("products", products); // Will be available as ${products} in JSP
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
}

}

Обратите внимание, что файл JSP явно помещен в /WEB-INF папку, чтобы конечные пользователи не могли получить к нему прямой доступ без вызова сервлета предварительной обработки (и, таким образом, в конечном итоге запутаться, увидев пустую таблицу).

<table>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td><a href="product?id=${product.id}">detail</a></td>
</tr>
</c:forEach>
</table>

Также подробные ссылки для просмотра / редактирования, как показано в последнем столбце выше, обычно являются идемпотентными.

@WebServlet("/product")
public class ProductServlet extends HttpServlet {

@EJB
private ProductService productService;

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Product product = productService.find(request.getParameter("id"));
request.setAttribute("product", product); // Will be available as ${product} in JSP
request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response);
}

}
<dl>
<dt>ID</dt>
<dd>${product.id}</dd>
<dt>Name</dt>
<dd>${product.name}</dd>
<dt>Description</dt>
<dd>${product.description}</dd>
<dt>Price</dt>
<dd>${product.price}</dd>
<dt>Image</dt>
<dd><img src="productImage?id=${product.id}" /></dd>
</dl>

Публикация

HTTP POST-запросы не являются идемпотентными. Если конечный пользователь заранее отправил форму POST по URL-адресу, который не выполнял перенаправление, тогда URL-адрес не обязательно можно добавлять в закладки. Отправленные данные формы не отражены в URL. Копирование URL-адреса в новое окно / вкладку браузера не обязательно может привести к точно такому же результату, как после отправки формы. В таком случае такой URL-адрес нельзя будет добавить в закладки. Если сервлет прослушивает указанный URL-адрес, то будет вызван его doPost(). Обычно используется для последующей обработки запроса. Т. е. Сбора данных из отправленной HTML-формы и выполнения с ними некоторых бизнес-операций (преобразование, проверка, сохранение в БД и так далее). Наконец, обычно результат представляется в виде HTML с пересылаемой страницы JSP.

<form action="login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="login">
<span class="error">${error}</span>
</form>

...который можно использовать в сочетании с этой частью сервлета:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

@EJB
private UserService userService;

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);

if (user != null) {
request.getSession().setAttribute("user", user);
response.sendRedirect("home");
}
else {
request.setAttribute("error", "Unknown user, please try again");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}

}

Видите ли, если User найдено в базе данных (т. Е. Имя пользователя и пароль действительны), то User будет помещен в область сеанса (т. Е. "вошел в систему"), и сервлет перенаправит на какую-либо главную страницу (этот пример относится к http://example.com/contextname/home), в противном случае он выдаст сообщение об ошибке и перешлет запрос обратно на ту же страницу JSP, чтобы сообщение отобразилось ${error}.

При необходимости вы также можете "скрыть" login.jsp in /WEB-INF/login.jsp, чтобы пользователи могли получить к нему доступ только с помощью сервлета. Это сохраняет URL чистым http://example.com/contextname/login. Все, что вам нужно сделать, это добавить doGet() в сервлет следующим образом:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}

(и соответствующим образом обновите ту же строку в doPost())

Тем не менее, я не уверен, что это просто игра и стрельба в темноте, но опубликованный вами код выглядит не очень хорошо (например, использование compareTo() вместо equals() и копание в именах параметров вместо простого использования getParameter() и id и password, похоже, объявлены как переменные экземпляра сервлета, что НЕ потокобезопасно). Итак, я бы настоятельно рекомендовал узнать немного больше о базовом Java SE API с помощью руководств Oracle (см. главу "Маршруты, охватывающие основы") и о том, как правильно использовать JSP / сервлеты, используя эти руководства.

Смотреть также:


Обновление: согласно обновлению вашего вопроса (что довольно важно, вам не следует удалять части вашего исходного вопроса, это сделало бы ответы бесполезными .. скорее добавьте информацию в новый блок) , оказывается, что вы без необходимости устанавливаете тип кодировки формы на multipart/form-data. Это приведет к отправке параметров запроса в составе, отличном от (по умолчанию), application/x-www-form-urlencoded который отправляет параметры запроса в виде строки запроса (например, name1=value1&name2=value2&name3=value3). Вам нужно только multipart/form-data всякий раз, когда у вас есть <input type="file"> элемент в форме, загружать файлы, которые могут быть безсимвольными данными (двоичными данными). В вашем случае это не так, поэтому просто удалите это, и все будет работать так, как ожидалось. Если вам когда-нибудь понадобится загрузить файлы, вам придется установить тип кодировки so и проанализировать тело запроса самостоятельно. Обычно вы используете для этого Apache Commons FileUpload, но если вы уже используете новый Servlet 3.0 API, то вы можете просто использовать встроенные средства, начинающиеся с HttpServletRequest#getPart(). Смотрите также этот ответ для конкретного примера: Как загрузить файлы на сервер с помощью JSP / Servlet?

Ответ 2

Как GET, так и POST используются браузером для запроса одного ресурса с сервера. Для каждого ресурса требуется отдельный запрос GET или POST.


  1. Метод GET чаще всего (и является методом по умолчанию) используется браузерами для получения информации с серверов. При использовании метода GET третий раздел пакета запроса, который является телом запроса, остается пустым.

Метод GET используется одним из двух способов: когда метод не указан, то есть когда вы или браузер запрашиваете простой ресурс, такой как HTML-страница, изображение и т.д. Когда форма отправлена, и вы выбираете method=GET в теге HTML. Если метод GET используется с HTML-формой, то данные, собранные через форму, отправляются на сервер путем добавления "?" в конец URL-адреса, а затем добавления всех пар имя = значение (имя поля html-формы и введенное в это поле значение), разделенных символом "&" Пример: GET /sultans/shop//form1.jsp?name=Sam%20Sultan&iceCream=vanilla HTTP/1.0 необязательный заголовок<< пустая строка >>>

Данные формы name=value будут сохранены в переменной окружения с именем QUERY_STRING. Эта переменная будет отправлена программе обработки (такой как JSP, Java servlet, PHP и т.д.)


  1. Метод POST используется при создании HTML-формы, а метод запроса=POST - как часть тега. Метод POST позволяет клиенту отправлять данные формы на сервер в разделе тела запроса запроса (как обсуждалось ранее). Данные кодируются и форматируются аналогично методу GET, за исключением того, что данные отправляются в программу через стандартный ввод.

Пример: POST /sultans/shop//form1.jsp HTTP/1.0 необязательный заголовок<< пустая строка>>> name=Sam%20Sultan&iceCream=vanilla

При использовании метода post переменная среды QUERY_STRING будет пустой. Преимущества / недостатки GET по сравнению с POST

Преимущества метода GET: немного более быстрые параметры могут быть введены через форму или путем добавления их после того, как URL-страница может быть помечена своими параметрами

Недостатки метода GET: может отправлять данные объемом не более 4 тыс. (Не следует использовать его при использовании текстового поля) Параметры видны в конце URL-адреса

Преимущества метода POST: параметры не видны в конце URL-адреса. (Используется для конфиденциальных данных) Позволяет отправлять на сервер данные объемом более 4 тыс.

Недостатки метода POST: Can не может быть добавлен в закладки с его данными

Ответ 3

Реализация HttpServlet.service() метода в контейнере сервлета автоматически пересылается в doGet() или doPost() по мере необходимости, поэтому вам не нужно переопределять метод service.

Ответ 4

Может быть, вы передаете данные через get, а не post?

<form method="get" ..>
..
</form>
java servlets