doGet e doPost em Servlets

105

Desenvolvi uma página HTML que envia informações para um Servlet. No Servlet, estou usando os métodos doGet()e 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");
}

No código da página html que chama o Servlet está:

<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> 

Quando eu uso method = "get"no Servlet, obtenho os valores de id e senha, porém quando uso method = "post", id e senha são configurados para null. Por que não obtenho os valores neste caso?

Outra coisa que gostaria de saber é como usar os dados gerados ou validados pelo Servlet. Por exemplo, se o Servlet mostrado acima autentica o usuário, gostaria de imprimir o ID do usuário na minha página HTML. Devo ser capaz de enviar a string 'id' como resposta e usar essa informação na minha página HTML. É possível?

dedalo
fonte
Como você está usando o método post em html?
Igor Artamonov
E também, para que você precisa de um loop tão estranho sobre nomes de parâmetro?
Igor Artamonov
1
Você já tentou remover `enctype = multipart / form-data`? Suspeito que seja o seu problema.
Jack Leow
Foi isso. Por que não postar trabalhos quando isso está presente? Obrigado pela ajuda!
dedalo

Respostas:

197

Introdução

Você deve usar doGet()quando quiser interceptar em solicitações HTTP GET . Você deve usar doPost()quando quiser interceptar em solicitações HTTP POST . Isso é tudo. Não transfira um para o outro ou vice-versa (como no processRequest()método infeliz de geração automática do Netbeans ). Isso não faz muito sentido.

OBTER

Normalmente, as solicitações HTTP GET são idempotentes . Ou seja, você obtém exatamente o mesmo resultado toda vez que executa a solicitação (deixando a autorização / autenticação e a natureza sensível ao tempo da página - resultados da pesquisa, últimas notícias, etc - sem consideração). Podemos falar sobre um pedido que pode ser marcado. Clicar em um link, clicar em um favorito, inserir o URL bruto na barra de endereço do navegador, etc., tudo disparará uma solicitação HTTP GET. Se um Servlet estiver escutando na URL em questão, seu doGet()método será chamado. Geralmente é usado para pré - processar uma solicitação. Ou seja, fazendo algumas coisas de negócios antes de apresentar a saída HTML de um JSP, como reunir dados para exibição em uma tabela.

@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>

Além disso, os links para visualizar / editar detalhes, conforme mostrado na última coluna acima, geralmente são idempotentes.

@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>

POSTAR

As solicitações HTTP POST não são idempotentes. Se o usuário final enviou um formulário POST em um URL anteriormente, o que não executou um redirecionamento, então o URL não é necessariamente favorito. Os dados do formulário enviado não são refletidos no URL. Copiar o URL em uma nova janela / guia do navegador pode não necessariamente produzir exatamente o mesmo resultado que após o envio do formulário. Assim, esse URL não pode ser marcado. Se um Servlet estiver ouvindo na URL em questão, ele doPost()será chamado. Geralmente é usado para pós - processar uma solicitação. Ou seja, coletar dados de um formulário HTML enviado e fazer algumas coisas de negócios com ele (conversão, validação, salvamento em banco de dados, etc.). Finalmente, geralmente o resultado é apresentado como HTML da página JSP encaminhada.

<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>

... que pode ser usado em combinação com este pedaço de Servlet:

@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);
        }
    }

}

Veja, se o Userfor encontrado no banco de dados (ou seja, nome de usuário e senha são válidos), então o Userserá colocado no escopo da sessão (ou seja, "conectado") e o servlet irá redirecionar para alguma página principal (este exemplo vai para http://example.com/contextname/home), caso contrário ele definirá uma mensagem de erro e encaminhará a solicitação de volta para a mesma página JSP para que a mensagem seja exibida ${error}.

Você também pode, se necessário, "ocultar" o login.jspin de /WEB-INF/login.jspmodo que os usuários só possam acessá-lo pelo servlet. Isso mantém o URL limpo http://example.com/contextname/login. Tudo que você precisa fazer é adicionar um doGet()ao servlet assim:

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

(e atualize a mesma linha de doPost()acordo)

Dito isso, não tenho certeza se é apenas brincar e atirar no escuro, mas o código que você postou não parece bom (como usar em compareTo()vez de equals()e cavar os nomes de parâmetros em vez de apenas usar getParameter()e o ide passwordparece ser declarados como variáveis ​​de instância de servlet - que NÃO é threadsafe ). Portanto, eu recomendo fortemente aprender um pouco mais sobre a API Java SE básica usando os tutoriais Oracle (consulte o capítulo "Trilhas que cobrem o básico") e como usar JSP / Servlets da maneira certa usando esses tutoriais .

Veja também:


Atualização : conforme a atualização da sua pergunta (o que é muito importante, você não deve remover partes da sua pergunta original, isso tornaria as respostas inúteis .. em vez disso, adicione as informações em um novo bloco), acontece que você configurar desnecessariamente o tipo de codificação do formulário para multipart/form-data. Isso enviará os parâmetros da solicitação em uma composição diferente do (padrão) application/x-www-form-urlencodedque envia os parâmetros da solicitação como uma string de consulta (por exemplo name1=value1&name2=value2&name3=value3). Você só precisa multipart/form-datasempre que tiver um<input type="file">elemento no formulário para fazer upload de arquivos que podem ser dados sem caracteres (dados binários). Este não é o seu caso, apenas remova-o e ele funcionará conforme o esperado. Se você alguma vez precisar fazer upload de arquivos, terá que definir o tipo de codificação dessa forma e analisar o corpo da solicitação você mesmo. Normalmente você usa o Apache Commons FileUpload lá para, mas se você já está usando a nova API Servlet 3.0, então você pode apenas usar os recursos integrados começando com HttpServletRequest#getPart(). Veja também esta resposta para um exemplo concreto: Como fazer upload de arquivos para o servidor usando JSP / Servlet?

BalusC
fonte
2

Tanto GET quanto POST são usados ​​pelo navegador para solicitar um único recurso do servidor. Cada recurso requer uma solicitação GET ou POST separada.

  1. O método GET é mais comumente (e é o método padrão) usado por navegadores para recuperar informações de servidores. Ao usar o método GET, a 3ª seção do pacote de solicitação, que é o corpo da solicitação, permanece vazia.

O método GET é usado de duas maneiras: Quando nenhum método é especificado, é quando você ou o navegador está solicitando um recurso simples, como uma página HTML, uma imagem, etc. Quando um formulário é enviado e você escolhe o método = GET na tag HTML. Se o método GET for usado com um formulário HTML, os dados coletados por meio do formulário serão enviados ao servidor anexando um "?" ao final do URL e, em seguida, adicionando todos os pares nome = valor (nome do campo de formulário html e valor inserido nesse campo) separados por um "&" Exemplo: GET /sultans/shop//form1.jsp?name= Sam% 20Sultan & iceCream = vanilla HTTP / 1.0 cabeçalho opcional cabeçalho opcional << linha vazia >>>

Os dados do formulário name = value serão armazenados em uma variável de ambiente chamada QUERY_STRING. Esta variável será enviada para um programa de processamento (como JSP, servlet Java, PHP etc.)

  1. O método POST é usado quando você cria um formulário HTML e solicita o método = POST como parte da tag. O método POST permite que o cliente envie dados do formulário ao servidor na seção do corpo da solicitação (conforme discutido anteriormente). Os dados são codificados e formatados de forma semelhante ao método GET, exceto que os dados são enviados ao programa por meio da entrada padrão.

Exemplo: POST /sultans/shop//form1.jsp HTTP / 1.0 cabeçalho opcional opcional << linha vazia >>> nome = Sam% 20Sultan & iceCream = vanilla

Ao usar o método post, a variável de ambiente QUERY_STRING ficará vazia. Vantagens / desvantagens de GET vs. POST

Vantagens do método GET: Um pouco mais rápido Os parâmetros podem ser inseridos por meio de um formulário ou anexando-os após a página URL ser marcada com seus parâmetros

Desvantagens do método GET: Só pode enviar 4 K de dados. (Você não deve usá-lo ao usar um campo textarea) Os parâmetros são visíveis no final do URL

Vantagens do método POST: Os parâmetros não são visíveis no final da URL. (Use para dados confidenciais) Pode enviar mais de 4 K de dados para o servidor

Desvantagens do método POST: não pode ser marcado com seus dados

S. Mayol
fonte
0

A implementação do contêiner de servlet do método HttpServlet.service () irá encaminhar automaticamente para doGet () ou doPost () conforme necessário, então você não deve precisar substituir o método de serviço.

Jay Jackson
fonte
0

Será que você está passando os dados por meio de get, não de post?

<form method="get" ..>
..
</form>
Tom
fonte
0

Se você fizer isso <form action="identification" >em seu formulário html, os dados serão passados ​​usando 'Get' por padrão e, portanto, você pode capturar isso usando a função doGet em seu código de servlet java. Dessa forma, os dados serão passados ​​sob o cabeçalho HTML e, portanto, estarão visíveis na URL quando enviados. Por outro lado, se você deseja passar dados no corpo HTML, use USE Post: <form action="identification" method="post">e pegue esses dados na função doPost. Ou seja, os dados serão passados ​​no corpo html e não no cabeçalho html, e você não verá os dados no URL após enviar o formulário.

Exemplos do meu html:

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

Exemplos do meu código de servlet 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");

.........
.........
Uzair Zaman Sheikh
fonte