使用servlet中的sendRedirect方法时,jsp页面中无法使用请求属性(Request Attributes)

7

我是一个新手,对jsp和servlet不熟悉。我的情况如下:

我有一个包含两个字段的表单的jsp页面。jsp页面的代码片段如下:

MyFirstJSP.jsp文件

<body>
<h1> This is my first jsp and servlet project</h1>
<%
//System.out.println(request.getAttribute("fname"));

if(request.getAttribute("fname")!=null){
    System.out.println(request.getAttribute("fname"));
}else{
    System.out.println("No request ");
}
%>
<form action="MyFirstServlet" method="get">
First Name<input type="text" name="fname" value= ${fname}><br>
Last Name<input type="text" name="lname" value= ${lname}>
<input type="submit" value="Send">
</form>
</body>

当我提交这个表单时,将调用MyFirstServlet来检查用户输入的名字。 如果名字等于“abc”,则servlet将属性设置为请求对象并将其重定向到调用jsp页面,即上面的页面。 将从请求对象获取该值并将其填充到表单的相应字段中。 我也有用于相同效果的Java表达式语言。
以下是MyFirstServlet.java servlet文件的代码片段:
/**
 * Servlet implementation class MyFirstServlet
 */
public class MyFirstServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

/**
 * @see HttpServlet#HttpServlet()
 */
public MyFirstServlet() {
    super();
    // TODO Auto-generated constructor stub
}

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {       // TODO Auto-generated method stub
    String firstname=request.getParameter("fname");
    if(firstname.equalsIgnoreCase("abc")){
        System.out.println("Setting attributes");
        request.setAttribute("fname",firstname);
        request.setAttribute("lname",request.getParameter("lname"));
        response.sendRedirect("MyFirstJSP.jsp");
    }else{
        System.out.Println("No problem");
    }
}
/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    PrintWriter p=response.getWriter();
    p.println("Success!");
    doGet(request,response);
}
}

但是当我执行代码时,servlet会重定向到jsp页面,但不会使用相应值填充表单字段。 为了查找原因,我添加了if-else块以了解原因,并得知该请求对象属性在此处不可用。
如果在这种情况下使用请求分派程序,则可以使用值,表单将使用这些值填充,但地址栏中的url不会更改,并始终显示指向servlet的url。
所以我的问题是:
1)为什么使用sendRedirect时,请求对象对jsp页面不可用。
2)如果servlet sendredirects到调用jsp,则是否有其他方法在jsp页面上显示预填充的用户输入值,以便用户无需重新输入数据到表单中。
请在此问题中指导我吧。
谢谢!

阅读BalusC的回答:https://dev59.com/03I-5IYBdhLWcg3wBjnl - Hardik Mishra
2个回答

19

在服务器端需要使用转发(forward)到JSP页面,因为重定向(redirect)是客户端的一个动作(查看location头部1),请求属性会丢失。

替换(replace)

response.sendRedirect("MyFirstJSP.jsp");

使用

request.getRequestDispatcher("MyFirstJSP.jsp").forward(request, response);

编辑:抱歉,我跳过了这部分

如果在这种情况下使用请求调度程序,则值将可用,表单也会填充这些值,但地址栏中的URL不会更改,并始终显示到servlet的URL。

尽管如此,在重定向时无法将请求属性传递给您的JSP(正如我上面已经提到的,这是客户端操作)

我建议执行以下操作:

  • 仅实现 doGet 以渲染包含表单的页面
  • 实现 doPost 来处理提交的表单数据
  • 在 HTML-Form 中使用 POST 而不是 GET 提交表单

在 doGet 和 doPost 中都使用 forward 来呈现 *.jsp 页面。

GET /MyFirstServlet -> forward to MyFirstJSP.jsp

POST /MyFirstServlet -> forward to MyFirstJSP.jsp

这是最常用和清晰的方法。

编辑 2:简单示例

SimpleFormServlet.java

public class SimpleFormServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private static final String VIEW_NAME = "/WEB-INF/jsp/simpleForm.jsp";
private static final String MODEL_NAME = "form";

public SimpleFormServlet() {
    super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setAttribute(MODEL_NAME, new SimpleForm());
    request.getRequestDispatcher(VIEW_NAME).forward(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    final SimpleForm form = map(request);

    if(form.getfName().equalsIgnoreCase("abc")){
        request.setAttribute(MODEL_NAME, form);
        // put additional attributes on the request
        // e.g. validation errors,...
        request.getRequestDispatcher(VIEW_NAME).forward(request, response);
    }else{
        System.out.println("No problem");
        response.sendRedirect("/SuccessServlet");
    }
}

private SimpleForm map(final HttpServletRequest request) {
    SimpleForm form = new SimpleForm();
    form.setfName(request.getParameter("fName"));
    form.setlName(request.getParameter("lName"));
    return form;
}

public static class SimpleForm implements Serializable {
    private static final long serialVersionUID = -2756917543012439177L;

    private String fName;
    private String lName;

    public String getfName() {
        return fName;
    }
    public void setfName(String fName) {
        this.fName = fName;
    }
    public String getlName() {
        return lName;
    }
    public void setlName(String lName) {
        this.lName = lName;
    }

}

}

/WEB-INF/jsp/simpleForm.jsp

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
</head>
<body>

<form method="POST">
    First Name<input type="text" name="fName" value="${form.fName}"><br>
    Last Name<input type="text" name="lName" value="${form.lName}">
    <input type="submit" value="Send">
</form>

</body>
</html> 
  1. GET /SimpleFormServlet
  2. 使用doGet()方法准备表单模型(SimpleForm),并将其添加为名为'form'的请求属性
  3. 转发到simpleForm.jsp页面
  4. 访问模型值并预填表单:${form.fName}和${form.lName}
  5. 浏览器仍然显示/SimpleFormServlet(我们喜欢它;-))
  6. POST表单相对于/SimpleFormSerlvet(您不必显式设置表单元素的action属性)
  7. 使用doPost()方法将请求参数映射到SimpleForm
  8. 处理请求并执行所需操作(验证等)
  9. 然后可以将其转发到simpleForm.jsp(例如在验证失败时),或者重定向到另一个servlet(例如/SuccessServlet)

谢谢!朋友,感谢您的回复。但我的一个担忧是浏览器地址栏中的URL如果使用请求调度器就不会改变。我的需求是将该值可用于JSP页面以重新填写表单,同时浏览器地址栏中的URL应更改为JSP页面URL。 - Param-Ganak
@Param-Ganak:那么请使用Session作用域。 - Hardik Mishra
1
@Param-Ganak: 抱歉,我刚刚编辑了我的帖子(请不要将Session范围用于表单属性和参数等类似事情)。 - marco.eig
1
我正在为您准备一个简单的示例。请稍等一分钟;-) - marco.eig
@reagten 非常感谢!我正在等待您的示例! - Param-Ganak
显示剩余2条评论

6

我知道现在回答有点晚了,但这对某些人可能会有帮助。 重定向 是客户端的操作,因此我们无法获取 getAttribute 的值,但我们可以使用 URL 重写 概念来解决它。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {       // TODO Auto-generated method stub
String firstname=request.getParameter("fname");
if(firstname.equalsIgnoreCase("abc")){
    //System.out.println("Setting attributes");

    response.sendRedirect("MyFirstJSP.jsp?fname="+firstname+"&lname="+request.getParameter("lname")+"");
}
else{
    System.out.Println("No problem");
  }
}

然后在MyFirstJSP.jsp中使用request.getParameter()将值提取为字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接