无法在另一个 .jsp 文件中捕获通过表单输入的值。为什么?

Can't catch the value entered via form in another .jsp file. Why?

我在 index.jsp 文件中有一个表单,它允许登录我的应用程序。我需要捕获插入的登录名,以便使用 Java 代码在另一个名为 mainPage.jsp 的文件中使用它。当我这样做时:

String login = request.getParameter("login");

这个字符串有空值。我怎样才能捕捉到插入的值?

这是来自 index.jsp 的代码,其中包含用于登录我的应用程序的表单:

<body>
<form id="log" method="post" onsubmit="return check()" action="mainPage.jsp">
        <div align="center">
            
            Login: <input type="text" id="login" name="login"/>
            <br/></br>
            
            Password: <input type="password" id="password"/>   
            <br/></br>
            
            <button name="login" type="submit">Log in!</button>
        </div> 
    </form> 

        <script type="text/javascript">
        function check() {
            var login = document.getElementById("login").value;
            var password = document.getElementById("password").value;
            var flag = false;
            
            var _users = JSON.parse(users);
            
            for (var i = 0; i < _users.length; i++) {
                if (_users[i].login == login && _users[i].password == password) {
                    flag = true;
                }
            }
            
            if (flag == false) {   
                document.getElementById('info').innerHTML = "Wrong login or password!";
            }
            
            return flag;
        }        
    </script>
</body>

第一个问题是使用错误的方法: HttpRequest.getParameter。此方法在 URL 中查找参数。例如在这个 url

https://google.com/search?q=java

request.getParameter("q") returns java.

在您的示例中,您使用了 POST 查询。这意味着参数将以 www-form-url 编码格式出现在您的请求正文中。请求看起来像

login=login&password=password

第二个问题是使用 ID 而不是名称。要在标签中传输参数,您需要使用名称,而不是 ID。带有名称参数的按钮也将发送空输入。按下按钮后,您将在服务器上看到下一个结果

login=login&login=

这是我们没有预料到的。在下面的示例中,我使用名称来正确发送参数。如果您需要 css 样式 - 使用 类 或 id 参数而不是 html 标签名称


要在没有外部库的情况下解析它,我们必须

  1. 解析请求正文
  2. 提取参数
  3. 向客户端发送响应

这个简单的例子:

login.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>Login page</title>
    <style>
        /* TODO: use classes of method to make styles */
        label, input {
            display: block;
        }
    </style>
</head>
<body>
    <form method="post">
        <label>Login: 
            <input type="text" name="login" />
        </label>
        <label>Password:
            <input label="password" type="password" name="password"/>
        </label>

        <button type="submit">Log in!</button>
    </form>
</body>
</html>

Servlet

@WebServlet(name = "login", value = "/login")
public class LoginServlet extends HttpServlet {

    public static final String IS_AUTHENTICATED_PARAM = "isAuthenticated";

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        this.getServletContext().getRequestDispatcher("/login.jsp").include(request, response);
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //Parse body
        String requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        //System.out.println(requestBody); - uncomment to view what is in body
        String login = getParamFromBodyUrlEncoded(requestBody, "login");
        String password = getParamFromBodyUrlEncoded(requestBody, "password");
        //In future you can setup secret cookie and check it in other pages
        if(login == null || password == null) {
            request.setAttribute(IS_AUTHENTICATED_PARAM, false);
        } else {
            request.setAttribute("isAuthenticated", isCredentialsCorrect(login, password));
        }
        this.getServletContext().getRequestDispatcher("/loginResult.jsp").include(request, response);
    }

    private String getParamFromBodyUrlEncoded(String requestBody, String paramName) {
        String paramUrlEncoded = paramName + "=";//param format is like login=. We expect paramname like login
        //Search for param
        int paramWithNameStart = requestBody.indexOf(paramUrlEncoded);
        if(paramWithNameStart == -1) {
            return null;
        }
        //Set pointer after param name
        int paramStart = paramWithNameStart + paramUrlEncoded.length();
        //Param should end with & or end of string
        int paramEnd = requestBody.indexOf("&", paramStart);
        if(paramEnd == -1) {
            paramEnd = requestBody.length();
        }

        return requestBody.substring(paramStart, paramEnd);
    }

    private boolean isCredentialsCorrect(String login, String password) {
        if("admin".equals(login) && "password".equals(password)) {
            return true;
        } else {
            return false;
        }
    }
}

loginResult.jsp

<%@ page import="com.example.demo_jsp.LoginServlet" %>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>Login result</title>
</head>
<body>

<h1><%=(boolean)request.getAttribute(LoginServlet.IS_AUTHENTICATED_PARAM) ? 
        "Success authentication" : "Wrong login or password"%></h1>
</body>
</html>

所以,我终于设法以一种非常简单的方式做到了这一点。 当我登录时,我将登录名存储在会话中,然后在我的程序中提取它。

我通过在登录到我的应用程序后调用这部分代码来执行此操作:

   if (request.getParameter("login") != null) {    
        session.setAttribute("_login", request.getParameter("login"));
   }

然后,我通过以下方式获取登录人的姓名:

   String login = session.getAttribute("_login").toString();

效果很好! :-D