重定向和请求转发
引言
重定向(Redirect)和请求转发(Forward)都是在Web开发中用来处理页面跳转的方式。
重定向
- 重定向(Redirect)是通过发送特定的HTTP响应来告诉浏览器将请求重定向到另一个URL。当服务器收到一个请求后,如果需要将用户从当前页面导航到另一个页面,可以发送一个重定向响应给浏览器,浏览器会遵循重定向并跳转到新的URL,并且原来的request请求失效,会产生一个新的request请求给客户端响应结果。重定向一般使用HTTP状态码,如302 Found或301 Moved Permanently。
- 重定向的过程:
从过程图可以看出,重定向会发出两次请求,产生两次响应。
- 为了实现请求重定向,在HttpServletResponse接口中定义了sendRedirect( ) 方法。该方法用于生成302响应码和Location响应头,从而通知客户端重新访问 Location响应头中指定的URL。
- 语法示例:
response.sendRedirect("/index.jsp");
重定向示例
在示例中,实现用户注册功能,注册成功则跳转到登录页面,注册失败则跳转到注册页面
- 登陆页面(index.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<jsp:include page="header.jsp"></jsp:include>
<table cellspacing="10" align="center" background="picture.jpg" width="600px" height="150px">
<form action="/LoginServlet" method="post">
<caption align="center" font-size="30px">用户登录</caption>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" value="${user.username}"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" value="${user.password}"></td>
</tr>
<tr>
<td align="center"><input type="submit" value="登录"></td>
<td align="center"><input type="button" value="注册" onclick="location.href='./register.jsp' "></td>
</tr>
</form>
</table>
</body>
</html>
- 注册页面(register.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<jsp:include page="header.jsp"></jsp:include>
<h2 align="center">用户注册</h2>
<table cellspacing="10" align="center" background="picture.jpg" width="600px" height="150px">
<form action="/RegisterServlet" method="post">
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td align="center"><input type="submit" value="注册"></td>
<td align="center"><input type="button" value="登录" onclick="location.href='/index.jsp' "></td>
</tr>
</form>
</table>
</body>
</html>
- 注册servlet(RegisterServlet)
package com.cn.servlet;
import com.cn.bean.User;
import com.cn.service.UserService;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "RegisterServlet", value = "/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取从浏览器中传递过来的参数
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = new User();
user.setUsername(username);
user.setPassword(password);
UserService userService = new UserService();
if(userService.registerUser(user)){
HttpSession session = request.getSession();
session.setAttribute("msg","注册成功,请登录");
response.sendRedirect("/index.jsp");
}else {
HttpSession session = request.getSession();
session.setAttribute("msg","用户名重复,请重新注册");
response.sendRedirect("/register.jsp");
}
}
}
- 若我们使用数据库中存在的用户进行注册
它会提示你用户名重复,并且重新跳转到注册界面。
- 若我们使用数据库中没有的用户注册
它会提示你注册成功,请登录,并且跳转到登录界面。我们可以发现,注册成功之后网址也发生了改变。
请求转发
- 请求转发是在服务器内部完成的,它是指将一个请求转发给同一个服务器内的另一个资源进行处理。当服务器收到一个请求后,如果需要将请求转发给另一个资源,它可以在服务器端通过调用另一个资源的方法来处理请求,并将处理结果返回给浏览器,而浏览器对此一无所知。请求转发一般是在服务器端完成的,对于浏览器而言,它只知道最初发送的请求,并不感知最终处理请求的资源。
- 请求转发的过程:
从过程图可以看出,请求转发会发出一次请求,产生一次响应。
- 请求转发使用RequestDispatcher接口中的forward()方法来实现,该方法可以把请求转发给另外一个servlet,并让该servlet对此请求进行响应。
- 语法示例:
request.getRequestDispatcher("/ShowStudentServlet").forward(request,response);
请求转发示例
在示例中,我们添加学生信息,添加成功之后还要把所有学生信息展示出来。
- 添加学生界面(addstudent.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>添加学生</title>
</head>
<body>
<table align="center" width="600" height="400">
<form action="/AddStudentServlet" method="post">
<tr>
<td>姓名:</td>
<td>
<input type="text" name="name">
</td>
</tr>
<tr>
<td>年龄:</td>
<td>
<input type="text" name="age">
</td>
</tr>
<tr>
<td>性别:</td>
<td>
<input type="radio" name="gender" value="男" />男
<input type="radio" name="gender" value="女" />女
</td>
</tr>
<tr>
<td>爱好:</td>
<td>
<input type="text" name="hobby">
</td>
</tr>
<tr>
<td>城市:</td>
<td>
<input type="text" name="city">
</td>
</tr>
<tr>
<td>
<input type="submit" value="提交">
</td>
<td>
<input type="button" value="重置" onclick="location.href='/addStudent.jsp' ">
</td>
</tr>
</form>
</table>
</body>
</html>
- 展示学生信息界面(welcome.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>success</title>
</head>
<body>
欢迎:${user.username}
<table align="center">
<form action="/SearchStudentServlet" method="post">
<tr>
<td>
<input type="text" name="content" placeholder="请输入学号或姓名" style="align-content: center">
</td>
<td>
<input type="submit" value="搜索">
</td>
</tr>
</form>
</table>
<table align="center">
<tr>
<td>
<input type="button" value="添加" onclick="location.href='addStudent.jsp' ">
</td>
<form action="/ShowStudentServlet" method="post">
<td>
<input type="submit" value="刷新">
</td>
</form>
<td>
<input type="button" value="退出" onclick="location.href='/LogoutServlet' " >
</td>
</tr>
</table>
<table border="1" width="500px" height="400px" align="center">
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>爱好</th>
<th>城市</th>
<th>操作</th>
<th>操作</th>
</tr>
<c:forEach var="student" items="${studentList}">
<tr>
<td align="center">
${student.id}
</td>
<td align="=center">
${student.name}
</td>
<td align="center">
${student.age}
</td>
<td align="center">
${student.gender}
</td>
<td align="center">
${student.hobby}
</td>
<td align="center">
${student.city}
</td>
<td align="center">
<button onclick="location.href='/QueryStudentServlet?id=${student.id}'">修改</button>
</td>
<td align="center">
<button onclick="location.href='/DeleteStudentServlet?id=${student.id}'">删除</button>
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
- 添加学生servlet(AddStudentServlet)
package com.cn.servlet;
import com.cn.bean.Student;
import com.cn.service.StudentService;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "AddStudentServlet", value = "/AddStudentServlet")
public class AddStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取从form表单传递过来的参数
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String gender = request.getParameter("gender");
String hobby = request.getParameter("hobby");
String city = request.getParameter("city");
Student student = new Student();
student.setName(name);
student.setAge(age);
student.setGender(gender);
student.setHobby(hobby);
student.setCity(city);
StudentService studentService = new StudentService();
studentService.insertStudent(student);
request.getRequestDispatcher("/ShowStudentServlet").forward(request,response);
}
}
- 展示学生信息servlet(ShowStudentServlet)
package com.cn.servlet;
import com.cn.bean.Student;
import com.cn.service.StudentService;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.ArrayList;
@WebServlet(name = "ShowStudentServlet", value = "/ShowStudentServlet")
public class ShowStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
StudentService studentService = new StudentService();
//获取session中传递过来的数据
HttpSession session = request.getSession();
session.getAttribute("user");
ArrayList<Student> studentList = studentService.findStudent();
request.setAttribute("studentList",studentList);
request.getRequestDispatcher("/welcome.jsp").forward(request,response);
}
}
我们添加一个学生,结果如下:
我们可以发现,添加成功后url地址不会发送变化。
总结
- 重定向是通过浏览器的重新请求来完成跳转,而请求转发是服务器内部直接将请求转发给另一个资源来处理。
- 重定向是先返回地址再重新访问,所以浏览器中的地址URL会发生变化,但是请求转发是只返回结果,浏览器中地址URL不会发生改变。
- 重定向是两次不同的请求,并产生响应两次;而请求转发只向服务端的发送了一次请求由服务端的内部实现请求的跳转,只响应一次。
- 重定向可以跳转到服务器的外部,而请求转发的只能是服务器的内部的跳转。
- 请求转发可利用request.setAttribute()将数据传递到下一个Servlet且下一个Servlet可用request.getAttribute()取出数据;但是重定向不可以,重定向之后会产生一个新的request域,不会保存原有request域存的数据。如果使用重定向跳转,可以使用session存数据。