【JavaWeb】Response对象详解,验证码案例

HTTP之Response:接上一篇博文HTTP协议详细.


一.设置Response对象

响应消息数据格式:

  1. 响应行
  2. 响应头
  3. 响应空行
  4. 响应体

Response对象功能:设置响应消息


1.设置响应行

响应行格式:

协议/版本信息 响应状态码 状态码描述

HTTP/1.1 200 ok

我们可以进行响应状态码的设置,告诉浏览器本次请求和响应的一个状态。像请求重定向中,响应状态码为304,告诉浏览器这是一次重定向操作。响应状态码设置的方法:

  • void setStatus(int var1); 设置了状态码,参数是设置状态码的整数值。

响应行中的状态描述信息直接与状态码相关,而HTTP版本由服务器确定。正常情况下,Web服务器会默认产生一个状态码为200的状态行。


2.设置响应头

设置响应头的方法:

  • void setHeader(String name, String value); 参数是设置的响应头名称,和对应的值。

3.设置响应体

使用输出流,将数据输出到客户端浏览器。使用步骤:

1.获取输出流

  • PrintWriter getWriter(); 字符输出流
  • ServletOutputStream getOutputStream(); 就是一个字节输出流

2.调用输出流中的方法,写入数据


二.Response重定向

重定向,也叫请求重定向,也是一种资源跳转的方式。如下图:

当客户端访问Servlet1时 ,由于在Servlet1中设置了请求重定向到Servlet2,因此,浏览器在收到Servlet1的响应消息后,立刻向Servlet2发送请求。Servlet2对请求处理完毕后,再将响应消息回送给客户端。
在这里插入图片描述

forward(转发)和 redirect(重定向)的区别:常见面试题

redirect重定向的特点:

  • 1.地址栏发生变化
  • 2.重定向可以访问其他站点(服务器)的资源
  • 3.重定向是两次请求。不能使用request对象来共享数据

forward转发的特点:

  • 1.转发地址栏路径不变
  • 2.转发只能访问当前服务器下的资源
  • 3.转发是一次请求,可以使用request对象来共享数据

重定向代码实现

需求:访问/ResponseDemo1,会自动跳转到/ResponseDemo2资源

//设置重定向方式1
//1.设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/Response/ResponseDemo2");

//设置重定向方式2:推荐的简单方式
response.sendRedirect(contextPath+"/ResponseDemo2");

ResponseDemo1.java

/**
 * 请求重定向
 * 需求:访问/ResponseDemo1,会自动跳转到/ResponseDemo2资源
 */
@WebServlet(name = "ResponseDemo1", urlPatterns = "/ResponseDemo1")
public class ResponseDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("Demo1请求重定向...");

        //设置重定向方式1
        //1.设置状态码为302
        response.setStatus(302);
        //2.设置响应头location
        response.setHeader("location","/Response/ResponseDemo2");

        //共享一个请求域数据:验证重定向是否可以共享请求域的数据
        request.setAttribute("msg","hello");

        //动态获取虚拟目录
        String contextPath = request.getContextPath();

        //设置重定向方式2:推荐的简单方式
        response.sendRedirect(contextPath+"/ResponseDemo2");

        //重定向可以指向外部的资源
        //response.sendRedirect("https://www.baidu.com");
    }
}

ResponseDemo2.java

@WebServlet(name = "ResponseDemo2", urlPatterns = "/ResponseDemo2")
public class ResponseDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("Demo2......");

        //获取共享数据
        Object msg = request.getAttribute("msg");
        System.out.println(msg);
    }
}

浏览器访问ResponseDemo1结果:

在这里插入图片描述

自动跳转到ResponseDemo2

在这里插入图片描述

控制台打印:

在这里插入图片描述

获取共享数据的结果为null,可以证明重定向是两次请求,不能使用request对象来共享数据。



三.相对路径和绝对路径

资源路径分类:相对路径绝对路径

1.相对路径:通过相对路径不可以确定唯一资源,因为不知道相对谁确定的。

如:./index.html,一般不 / 开头,以.开头路径都是相对路径。

确定相对路径的规则:要找到当前资源和目标资源之间的相对位置关系。

目录表示:
./:当前目录
…/:后退一级目录
…/…/:以此类推,后退多级目录。

例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>相对路径</h1>
    <h1>找到当前资源和目标资源之间的相对位置关系</h1>
    <P>
        当前资源:location.html
        访问路径:http://localhost/dong/location.html
    </P>
    <P>
        目标资源:ResponseDemo2
        访问路径:http://localhost/dong/ResponseDemo2
    </P>
	<!-- ResponseDemo2与location.html处在同一目录下,
		目标资源相对于location.html路径就是: ./responseDemo2
		相对路径可以省略./
	-->
    <a href="./responseDemo2">responseDemo2</a>
    <a href="responseDemo2">responseDemo2</a>
</body>
</html>

2.绝对路径:通过绝对路径可以确定唯一资源

如:http://localhost/dong/ResponseDemo2和/dong/responseDemo2,都是绝对路径。

一般以 / 开头路径都是绝对路径。

确定相对路径的规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出。

2.1 给客户端浏览器使用:需要加虚拟目录(项目的访问路径),如/dong/ResponseDemo2

  • 建议虚拟目录动态获取:request.getContextPath()
  • 常用场景,<a> , <form>标签, 重定向路径使用

2.2 给服务器使用:不需要加虚拟目录,如/ResponseDemo2

  • 常用场景,请求转发路径

例子

<h1>绝对路径</h1>
<a href="/dong/ResponseDemo2">responseDemo2</a>



四.Response输出数据

就是设置响应体的内容。使用输出流,将数据输出到客户端浏览器。

1.服务器输出字符数据到浏览器

实现步骤:

  • 1.获取字符输出流
  • 2.调用流中的方法,写入数据

注意乱码问题:

  • PrintWriter pw = response.getWriter(); 获取的流的默认编码是ISO-8859-1
  • 设置该流的默认编码为UTF-8(GBK也可以,要与浏览器请求编码格式一致)。
  • 设置响应头content-type:告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
//简单的形式,设置响应体编码,必须在获取流之前设置
response.setContentType("text/html;charset=utf-8");

在这里插入图片描述

代码实现

/**
 * Response输出数据
 */
@WebServlet(name = "ResponseDemo4", urlPatterns = "/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //解决输出中文乱码
        //设置response编码方式1
        //1.获取流对象之前,设置流的默认编码:ISO-8859-1 设置为:UTF-8(GBK也可以,要与浏览器请求编码格式一致)
        response.setCharacterEncoding("UTF-8");
        //2.设置响应头:告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
        response.setHeader("content-type","text/html;charset=UTF-8");

        //设置response编码方式2:推荐简单形式设置编码,里面封装上面2步
        response.setContentType("text/html;charset=UTF-8");

        //输出数据
        //1.获取字符输出流
        PrintWriter pw = response.getWriter();
        //2.调用方法,写入数据
        pw.write("<h1>你好呀,response...</h1>");
    }
}

浏览器访问ResponseDemo4

在这里插入图片描述


2.服务器输出字节数据到浏览器

实现步骤:

  • 1.获取字符输出流
  • 2.调用流中的方法,写入数据

也需要统一编码格式,避免中文数据乱码

response.setContentType("text/html;charset=UTF-8");

代码实现

/**
 * Response输出数据
 */
@WebServlet(name = "ResponseDemo5", urlPatterns = "/ResponseDemo5")
public class ResponseDemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //解决Response输出中文乱码
        response.setContentType("text/html;charset=UTF-8");

        //1.获取字节输出流
        ServletOutputStream os = response.getOutputStream();
        //2.调用方法,写入数据
        os.write("你好,我是董小帅..".getBytes("utf-8"));
    }
}

浏览器访问ResponseDemo5

在这里插入图片描述


五.Response验证码案例

验证码的本质是一张图片,目的是为了防止恶意表单注册。

恶意表单注册:像注册账号,这些数据都会存储在数据库中,如果恶意无限循环注册,用不了多久数据库就会崩溃。
随机不重复的验证码有效限制了这样的恶意行为,并且现在验证码越来越高级了。

制作验证码一般有两种方式:

  • 静态图片验证码:需要有大量图片,不推荐,始终是有限的,并且可能重复出现。
  • 动态生成验证码:在程序中动态随机生成,推荐。

现在使用java动态生成如下一张简单的验证码图片。

在这里插入图片描述

需求:在网页上显示一张验证码图片,点击超链接或者图片,需要换一张验证码图片。

实际开发中,一般是修改现存的美观好看的验证码代码,逻辑是一致的。

实现步骤

服务器端编写Servlet资源

  • 1.创建一对象,在内存中图片(验证码图片对象)
  • 2.美化图片
  • 3.将图片输出到页面展示

代码实现

@WebServlet(name = "CheckCodeServlet", urlPatterns = "/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //图片宽高,单位像素
        int width = 100;
        int height = 50;
        //1.创建一对象,在内存中图片(验证码图片对象)
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        //2.美化图片
        //2.1 填充背景颜色
        Graphics g = image.getGraphics();//获取画笔对象
        g.setColor(Color.PINK);//设置画笔颜色
        g.fillRect(0,0,width,height);//填充一个矩形
        //2.2 画边框
        g.setColor(Color.BLUE);
        g.drawRect(0,0,width-1,height-1);//边框会占空间

        //验证码取值范围
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        for (int i = 1; i <= 4; i++) {
            //生成随机角标
            int index = random.nextInt(str.length());
            //获取字符
            char ch = str.charAt(index);
            //2.3 写出验证码
            g.drawString(ch+"",width/5*i,height/2);
        }
        //2.4 画干扰线
        g.setColor(Color.GREEN);
        //随机生成坐标点
        for (int i = 0; i < 10; i++) {//画10条干扰线
            int x1 = random.nextInt(width);
            int x2 = random.nextInt(width);

            int y1 = random.nextInt(height);
            int y2 = random.nextInt(height);
            //画线
            g.drawLine(x1,y1,x2,y2);
        }
        //3.将图片输出到页面展示,使用字节输出流
        ImageIO.write(image,"jpg",response.getOutputStream());
    }
}

前端页面代码

验证码功能分析:点击超链接或者图片,需要换一张

  1. 给超链接和图片绑定单击事件
  2. 重新设置图片的src属性值

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>验证码案例</title>
</head>
<body>

<img id="checkCode" src="CheckCodeServlet" alt="换一张"/>
<a id="change" href="#">看不清,换一张?</a>

<script type="text/javascript">
    //1.获取图片和超链接对象
    var img = document.getElementById("checkCode");
    var change = document.getElementById("change");

    //2.绑定单击事件
    img.onclick = function () {
        //加时间戳
        var time = new Date().getTime();
        //设置img资源路径src
        img.src = "CheckCodeServlet?"+time;
    };
    change.onclick = function () {
        //加时间戳
        var time = new Date().getTime();
        //设置img资源路径src
        img.src = "CheckCodeServlet?"+time;
    };
</script>
</body>
</html>

案例效果:
在这里插入图片描述


简单验证码例子,到这HTTP之Response对象细节结束,学无止境,每天都要全力以赴!

推荐阅读

欢迎点赞评论,指出不足,笔者由衷感谢哦!~

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值