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

105

Я разработал 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"в сервлете, я получаю значение идентификатора и пароля, однако при использовании method = "post"идентификаторы и пароль устанавливаются на null. Почему я не получаю значения в этом случае?

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

дедало
источник
Как вы используете метод публикации в html?
Игорь Артамонов
А еще зачем вам такой странный цикл по именам параметров?
Игорь Артамонов
1
Вы пробовали удалить enctype = multipart / form-data? Я подозреваю, что это твоя проблема.
Джек Леу,
Вот и все. Почему не публикует работу, когда она есть? Спасибо за вашу помощь!
dedalo

Ответы:

197

Введение

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

ПОЛУЧИТЬ

Обычно запросы 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);
    }

}
<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в /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()и копаясь в parameternames вместо использования getParameter()и idи , passwordкажется, быть объявленными как переменные экземпляра сервлета - что НЕ является потокобезопасным ). Поэтому я настоятельно рекомендую узнать немного больше о базовом API Java SE, используя учебные пособия Oracle (см. Главу «Следы, охватывающие основы») и о том, как правильно использовать JSP / сервлеты с помощью этих руководств .

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


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

BalusC
источник
2

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

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

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

Данные формы имя = значение будут храниться в переменной среды с именем QUERY_STRING. Эта переменная будет отправлена ​​в программу обработки (например, JSP, сервлет Java, 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: может отправлять данные только размером 4K. (Вы не должны использовать его при использовании поля textarea) Параметры отображаются в конце URL-адреса

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

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

С. Майоль
источник
0

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

<form method="get" ..>
..
</form>
Том
источник
0

Если вы это сделаете <form action="identification" >для своей html-формы, данные по умолчанию будут передаваться с использованием Get, и, следовательно, вы можете поймать это с помощью функции doGet в своем коде Java-сервлета. Таким образом, данные будут передаваться под заголовком HTML и, следовательно, будут отображаться в URL-адресе при отправке. С другой стороны, если вы хотите передавать данные в теле HTML, используйте команду USE Post:<form action="identification" method="post"> и перехватите эти данные в функции doPost. Это было то, что данные будут передаваться под телом html, а не под заголовком html, и вы не увидите данные в URL-адресе после отправки формы.

Примеры из моего html:

<body>  
<form action="StartProcessUrl" method="post">
.....
.....

Примеры из моего кода сервлета Java:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        PrintWriter out = response.getWriter();
         String surname = request.getParameter("txtSurname");
         String firstname = request.getParameter("txtForename");
         String rqNo = request.getParameter("txtRQ6");
         String nhsNo = request.getParameter("txtNHSNo");

         String attachment1 = request.getParameter("base64textarea1");
         String attachment2 = request.getParameter("base64textarea2");

.........
.........
Узаир Заман Шейх
источник
0

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

Джей Джексон
источник