Servlet 重定向(带案例代码)

目录

重定向的工作流程

转发和重定向的区别

response.sendRedirect()

示例


重定向属于客户端行为。服务器在收到客户端请求后,会通知客户端浏览器重新向另外一个 URL 发送请求,这称为请求重定向。它本质上是两次 HTTP 请求,对应两个 request 对象和两个 response 对象。

重定向的工作流程

重定向的工作流程如下:

  1. 用户在浏览器中输入 URL,请求访问服务器端的 Web 资源。
  2. 服务器端的 Web 资源返回一个状态码为 302 的响应信息,该响应的含义为:通知浏览器再次发送请求,访问另一个 Web 资源(在响应信息中提供了另一个资源的 URL)。
  3. 当浏览器接收到响应后,立即自动访问另一个指定的 Web 资源。
  4. 另一 Web 资源将请求处理完成后,由容器把响应信息返回给浏览器进行展示。

转发和重定向的区别

转发和重定向都能实现页面的跳转,但是两者也存在以下区别。

区别转发重定向
浏览器地址栏 URL 是否发生改变
是否支持跨域跳转
请求与响应的次数一次请求和一次响应两次请求和两次响应
是否共享 request 对象和 response 对象
是否能通过 request 域对象传递数据
速度相对要快相对要慢
行为类型服务器行为客户端行为

response.sendRedirect()

HttpServletResponse 接口中的 sendRedirect() 方法用于实现重定向。

返回值类型方法描述
voidsendRedirect(String location)向浏览器返回状态码为 302 的响应结果,让浏览器访问新的 URL。若指定的 URL 是相对路径,Servlet 容器会将相对路径转换为绝对路径。参数 location 表示重定向的URL。

示例

下面我们通过一个案例加深对 response 对象和重定向的理解。

在 webapp 中,创建登录页面 login.html,代码如下。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>
<form action="/web/DoServlet" method="GET">
    <table border="1" width="50%">
        <tr>
            <td colspan="2" align="center">
                welcome to servlet !!!
            </td>
        </tr>
        <tr>
            <td>账号</td>
            <td>
                <input type="text" name="username"/>
            </td>
        </tr>
        <tr>
            <td>密码</td>
            <td>
                <input type="password" name="password"/>
            </td>
        </tr>
        <tr>
            <td>验证码</td>
            <td><input type="text" name="code"/>
                <img id="imgId" src="/web/CheckCodeServlet">
                <a href="#" onclick="run()">看不清,换一张</a>
            </td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <input type="submit" value="提交"/>
            </td>
        </tr>
    </table>
</form>
</body>
<script type="text/javascript">
    // 看不清,换一张,时间戳
    function run() {
        // 获取图片
        var image = document.getElementById("imgId");
        image.src = "/web/CheckCodeServlet?" + new Date().getTime();
    }
</script>
</html>

创建名称为 CheckCodeServlet 的 Servlet 类,代码如下。

package swadian.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@WebServlet("/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int width = 120;
        int height = 30;
        // 在内存中生成图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 先获取画笔对象
        Graphics2D g = (Graphics2D) image.getGraphics();
        // 设置灰色
        g.setColor(Color.GRAY);
        // 画填充的矩形
        g.fillRect(0, 0, width, height);
        // 设置颜色
        g.setColor(Color.BLUE);
        // 画边框
        g.drawRect(0, 0, width - 1, height - 1);
        // 准备数据,随机获取4个字符
        String words = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
        // 设置颜色
        g.setColor(Color.YELLOW);
        // 设置字体
        g.setFont(new Font("隶书", Font.BOLD, 20));
        String code = "";
        //构造存储字符的数组
        char[] a = {};
        //构造存储字符串的集合
        List<String> list = new ArrayList<String>();
        Random random = new Random();
        int x = 20;
        int y = 20;
        for (int i = 0; i < 4; i++) {
            // void rotate(double theta, double x, double y)
            // theta 弧度
            // hudu = jiaodu * Math.PI / 180;
            // 获取正负30之间的角度
            int jiaodu = random.nextInt(60) - 30;
            double hudu = jiaodu * Math.PI / 180;
            g.rotate(hudu, x, y);
            // 获取下标
            int index = random.nextInt(words.length());
            // 返回指定下标位置的字符,随机获取下标
            char ch = words.charAt(index);
            //将字符存入字符数组中
            char[] chc = {ch};
            //使用字符数组构造字符串
            String string = new String(chc);
            //将构造好的字符串添加进list集合中
            list.add(string);
            // 写字符串
            g.drawString("" + ch, x, y);
            g.rotate(-hudu, x, y);
            x += 20;
        }
        for (int i = 0; i < list.size(); i++) {
            code += list.get(i);
        }
        //将验证码存入上下文中->合适的方式是放在会话域session中
        getServletContext().setAttribute("code", code);
        // 设置颜色
        g.setColor(Color.GREEN);
        int x1, x2, y1, y2;
        // 画干扰线
        for (int i = 0; i < 4; i++) {
            x1 = random.nextInt(width);
            y1 = random.nextInt(height);
            x2 = random.nextInt(width);
            y2 = random.nextInt(height);
            g.drawLine(x1, y1, x2, y2);
        }
        // 输出到客户端
        ImageIO.write(image, "jpg", response.getOutputStream());
    }

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

创建名称为 DoServlet 的 Servlet 类,代码如下

package swadian.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/DoServlet")
public class DoServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置向页面输出内容格式
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        String username = request.getParameter("username");
        // 获取密码
        String password = request.getParameter("password");
        //获取验证码
        String code = request.getParameter("code");
        //设置是否成功标识
        Boolean IsSuccess = true;
        //从上下文获取存储的验证码
        String code1 = (String) getServletContext().getAttribute("code");
        //账号密码为admin.且验证码(忽略大小写)输入正确,则跳转到登陆成功页面
        if (!"".equals(code) && code != null && code.equalsIgnoreCase(code1) && "admin".equals(username) && "admin".equals(password)) {
            response.sendRedirect("/web/Success");
            //账号密码不为admin,设置错误信息
        } else if (!"admin".equals(username) || !"admin".equals(password)) {
            getServletContext().setAttribute("msg", "账号或密码不正确");
            IsSuccess = false;
            //验证码错误,设置错误信息
        } else if ("".equals(code) || code == null || !code.equalsIgnoreCase(code1)) {
            getServletContext().setAttribute("msg", "验证码输入错误");
            IsSuccess = false;
        }
        if (!IsSuccess) {
            //设置自动跳转的时间,存储在上下文中
            getServletContext().setAttribute("time", 5);
            //向request对象中设置属性requestAttr,在重定向之后取值->实际上取不到
            request.setAttribute("requestAttr", "重定向中使用request域对象传递的数据");
            response.sendRedirect("/web/RefreshServlet");
        }
    }

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

创建名称为 RefreshServlet 的 Servlet 类,代码如下。

package swadian.servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

@WebServlet("/RefreshServlet")
public class RefreshServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        Object requestAttr = request.getAttribute("requestAttr");
        //获取存在上下文中的跳转时间
        Integer times = (Integer) getServletContext().getAttribute("time");
        //获取存在上下文中的错误信息
        String msg = (String) getServletContext().getAttribute("msg");
        /**
         *
         * 设置三个头信息,禁用浏览器缓存
         * Cache-Control : no-cache
         * Expires: -1 值是日期类型(setDateHeader())
         *     Pragma : no-cache
         */
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", -1);
        //
        response.setContentType("text/html;charset=UTF-8");
        //设置提示
        String title = msg + ",即将在" +
                times + "秒钟后跳转到登录页";
        //使用默认时区和语言环境获得一个日历
        Calendar cale = Calendar.getInstance();
        //将Calendar类型转换成Date类型
        Date tasktime = cale.getTime();
        //设置日期输出的格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //格式化输出
        String nowTime = df.format(tasktime);
        //只要倒计时时间没有到0,就直至输出下面内容
        if (times != 0) {
            response.getWriter().write("<html>\n" +
                    "<head><title >" + title + "</title></head>\n" +
                    "<body bgcolor=\"#f0f0f0\">\n" +
                    "<h1 align=\"center\">RefreshServlet  提醒您:</h1>" +
                    "<h1 align=\"center\" style=\"font-family:arial;color:red;\">" + title + "</h1>\n" +
                    "<h1 align=\"center\">当前时间 是:" + nowTime + "</h1>\n" +
                    "<h1 align=\"center\">重定向通过request传递的数据为:" + requestAttr + "</h1>\n");
            //倒计时
            times--;
            //将倒计时的时间重新存入上下文中覆盖原来的值
            getServletContext().setAttribute("time", times);
            // 通过refresh头完成页面刷新——>达到循环的效果
            response.setHeader("refresh", "1;url=/web/RefreshServlet");
        } else {
            //倒计时归零,则跳转到登陆页面
            response.sendRedirect("/web/login.html");
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        doGet(request, response);
    }
}

创建名称为 SuccessServlet 的 Servlet 类,代码如下。

package swadian.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/Success")
public class SuccessServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置响应输出的格式
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write("<h1>登录成功</h1>");
    }

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

启动 Tomcat,在地址栏输入“http://localhost:8080/web/login.html”,访问登录页,如下图所示。

在登录页面输入账号、密码、验证码等信息(该实例中没有使用数据库,所以当账号和密码都为 admin 时验证成功,否则验证失败),这里我们输入错误的验证码点击提交按钮,结果如下图。倒计时完成后,自动跳转到登录页面。

输入正确信息,点击提交,结果如下图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

swadian2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值