web(Response、ServletContext)

Response

Response的概述与设置

概述

  • response对象表示web服务器给浏览器返回的响应信息

  • 作用:可以使用response对象的方法,设置要返回给浏览器的响应信息

    注意: tomcat在响应会有一些默认的设置, 在servlet中的设置会覆盖tomcat的设置
    在这里插入图片描述

	ServletResponse 接口 (理论上兼容大部分协议)
			|	
	HttpServletResponse 接口 (专门指的是http协议的响应)
			|	
	org.apache.catalina.connector.ResponseFacade 实现类(由tomcat提供的)

HTTP响应报文
在这里插入图片描述

设置Http响应行

* 格式
	 	协议/版本号 状态码(status code) 
* 例如
		HTTP/1.1 200	
* API
	1. 设置状态码 
			 void setStatus(int sc)  
    2. 常见响应状态码:
            200:请求和响应都OK
            302:重定向 
            304:浏览器从缓存中加载数据
            
            404:请求的路径错误或请求的资源不存在(开发的时候,路径有问题)
            405: 在HttpServlet的子类中, doGet或doPost方法没有重写
            500:服务器内部异常
	3. 注意事项:上述常见的响应状态码,通常是由tomcat服务器自动响应给浏览器。一般是不需要手动设置的;       

浏览器缓存

在这里插入图片描述

设置Http响应头

* 格式
		响应头名称:响应头的值
* 例如
		Content-Length : 5 (指的是响应体内容长度5个字符)
* API
	1. 设置指定头名称和对应的值
			void setHeader(String name, String value)  
	2. value值可以由多个参数组成,不同参数之间使用分号隔开: 		
			response.setHeader(key,"value1;value2");
	3. 常用响应头:
            refresh:定时刷新;
            content-type:设置响应数据的数据类型和编码格式;
            location:配合302响应状态码完成重定向;
            content-disposition:通知浏览器以附件的形式解析响应的数据;		

设置Http响应体

响应体中包含 响应数据的正文
响应是服务器给浏览器发送数据: 输出流
* API(输出流对象)
	1. 字符输出流 : 用于向浏览器输出字符数据(文本)
			PrintWriter getWriter()			
	2. 字节输出流 : 用于向浏览器输出二进制数据(比如文件下载)
			ServletOutputStream getOutputStream()

	注意:在同一个servlet中,二种类型的输出流不能同时存在,互斥
@WebServlet("/ResponseServlet01")
public class ResponseServlet01 extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //# 响应体
        //1. 打印字符流: 响应体出现网页上的(字符流的底层也是字节流)
//        PrintWriter writer = response.getWriter();
//        writer.print("hello world");

//        response.getWriter().print("hello world"); //链式编程

        //2. 字节输出流 (输出文件的数据)
        ServletOutputStream os = response.getOutputStream();
        String str = "hello world2";
        byte[] bytes = str.getBytes();
        os.write(bytes);
    }
}

响应头的功能

响应定时刷新(refresh)

@WebServlet("/RefreshServlet")
public class RefreshServlet extends HttpServlet {

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

    /*
        # 响应: 服务器发送给浏览器的数据!!!
    * API
        1. 设置指定头名称和对应的值
                void setHeader(String name, String value)
        2. value值可以由多个参数组成,不同参数之间使用分号隔开:
                response.setHeader(key,"value1;value2");
        3. 常用响应头:
                refresh:定时刷新;
           response.setHeader("refresh","time;url"); -> time秒之后跳转到url
    *
    * */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置响应头 refresh -> 定时刷新页面
        // 服务器通过这个响应头 告诉浏览器 : 你5秒之后,自己访问百度
        response.setHeader("refresh","5;http://www.baidu.com");

        response.setContentType("text/html;charset=utf-8");//防止中文乱码(待会)
        response.getWriter().print("支付成功,等待5秒跳转到订单页面"); // 响应体: 出现在网页上

    }

响应体中文乱码(content-type)

需求

向页面输出中文数据没有乱码

原因分析

1. 通过response获取字符输出流
		PrintWriter pw = response.getWriter();		
2. 通过字符输出输出中文字符
		pw.write("中文....");
3. 浏览器访问,网页出现中文乱码	

4. 原因: tomcat默认使用ISO-8859-1编码, 然后也让浏览器用ISO-8859-1解码
	而ISO-8859-1不支持中文,所以出现乱码
	
5. 解决 : 统一浏览器和服务器编码(utf-8)	
	response.setContentType("text/html;charset=utf-8");

解决中文乱码

统一浏览器和服务器编码
		response.setCharacterEncoding("utf-8"); // 简要写法	
		response.setHeader("content-type","text/html;charset=utf-8"); //完整写法
		
		response.setContentType("text/html;charset=utf-8"); //推荐!!!!
@WebServlet("/ContentTypeServlet")
public class ContentTypeServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
    /*
    *  1. 问题: 响应体中文乱码
    *  2. 原因: tomcat默认使用ISO-8859-1编码(欧码, 拉丁文, 不支持中文)
    *       服务端编码 : iso
    *       浏览器解码 : iso
    *
    *   3. 分析(响应头: 内容类型 )
    *       Content-Type: text/html;charset=ISO-8859-1
    *                   value1;value2
    *
    *       value2的意思是: 服务器跟浏览器约定 编解码使用字符集 ISO
    *            (chrome现在是无法查看网页使用的编码,淘汰了,  IE可以)
    *
    *   4. 解决
    *       1. response.setHeader("content-type","text/html;charset=utf-8");
    *         服务器跟浏览器约定 编解码使用字符集 utf-8 (支持中文)
    *
    *       2. response.setContentType("text/html;charset=utf-8"); 
    *
    *       3. response.setCharacterEncoding("utf-8");  
    *
    *   5. tips: value1解释(mime 类型)
    *         windows的文件类型(后缀名):     txt          html        json              jsp     exe    zip
    *         网络传输的文件类型(MIME):    text/plain    text/html   application/json
    *             MIME格式: 大类型/小类型
    *
    *       作用: 服务器告知浏览器, 响应体数据以何种类型的语法去解析
    * */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //响应体正文
//        response.getWriter().print("hello world");
        //如果这一行,不写, 是看不到这个响应头 , 是因为如果servlet中不设置这个头,tomcat默认设置是看不到的
        // Content-Type: text/html;charset=ISO-8859-1
        response.setHeader("content-type","text/html");
        //解决
//        response.setHeader("content-type","text/html;charset=utf-8");
        //简易 
        response.setContentType("text/plain;charset=utf-8");
        //修改content-type头中的charset的值, 这个不推荐
//        response.setCharacterEncoding("utf-8");
        response.getWriter().print("<h1>你好,世界</h1>");
    }

}

响应重定向(location+302)

步骤分析

* 方式一
	// 1.设置状态码
		response.setStatus(302);
	// 2.设置响应头 Location
		response.setHeader("Location","重定向网络地址");
			
* 方式二
	// 1.response这封装专门处理重定向的方法 
		response.sendRedirect("重定向网络地址");

重定向特点

1. 发起两次请求

2. 地址栏的url被修改了(指向最后访问的地址)

3. 重定向浏览器行为, 是可以访问服务器外部资源

4. 不能通过request域对象共享数据
@WebServlet("/AServlet")
public class AServlet extends HttpServlet {

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

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

        System.out.println("xxxxx");
        //重定向(302 + location)
        //表示重定向
//        response.setStatus(302);
        //重定向的地址
//        response.setHeader("location","/xxx/BServlet");
//        response.setHeader("location","http://www.baidu.com");

        //简化api (302+location)
        response.sendRedirect("/xxx/BServlet");
    }

}
@WebServlet("/BServlet")
public class BServlet extends HttpServlet {

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

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

        System.out.println("xxxxx.");
        //避免响应体中文乱码
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("xxx");
    }


转发与重定向的区别

1. 哪个对象
	转发(request对象的方法)		
		request.getRequestDispatcher("/bServlet").forward(request,response);
		
		地址栏: 没有改变  -> AServlet
		浏览器: 发了一次请求(可以通过request域对象共享数据)
		服务器: 只有一对请求和响应对象  (Aservlet  Bservlet的请求和响应和A传给他的)
		发生的位置: 服务器内部,无法访问服务器外部资源
	重定向(response对象的方法)		
		response.sendRedirect("/xxx/bServlet");
		
		地址栏: 发生了改变 -> BServlet
		浏览器: 发了两次请求(不可以通过request域对象共享数据)
		服务器: 有两对请求和响应对象
		发生的位置: 浏览器行为, 可以访问服务器外部资源
2. 几次请求
	转发 : 1次
	重定向: 起码2次
			
3. 总结
	写法 
		转发("/servlet资源路径") 服务器内部行为
		重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为
	使用场景
		如果需要传递数据(request域),使用请求转发
		如果不需要传递数据(request域),使用重定向

ServletContext

概述

  • web容器(tomcat)在启动时,它会为每个web项目承建一个对应的ServletContext对象(唯一)
  • 它代表:当前web项目

主要作用

  1. 域对象(共享数据)

    javaweb四大域对象:  有作用范围,并可在作用范围中共享数据的对象(有点像Map)
    
    1. 域对象方法api对一样 : 
           setAttribute(name,value) 
           value  = getAttribute(name)
           removeAttribute(name)
           
    2. 作用范围不一样
    		pageContext <  request < session < ServletContext
    3. 获取域对象规律:
    	小域对象可以获取大域对象
    
    
  2. 获取一些应用全局的数据

    1). 获取全局的配置参数

    2).获取项目中资源的真实路径

    3).获取资源的MIME类型

获取ServletContext对象

1. 通过request对象获得
		ServletContext sc = request.getServletContext();
		
2. 继承HttpServlet后,可以直接调用
		ServletContext sc = getServletContext();

域对象(共享数据)

在当前整个服务器应用范围内,共享数据

  • 生命周期

    1. 何时创建?
    		项目加载时,创建唯一的一个ServletContext对象(全局唯一)
    2. 何时销毁?
    		项目卸载时,销毁
    3. 作用范围?
    		与项目共存亡(多个servlet和多次请求都可以操作它)
    
  • API方法

    1. 存储数据
    		void setAttribute(String name,Object value)
    2. 获取数据
    		Object getAttribute(String name)
    3. 删除数据
    		void removeAttribute(String name)
    

在这里插入图片描述

@WebServlet("/ContextServlet01")
public class ContextServlet01 extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //不论哪个方法获取的ServletContext,都是同一对象
//        ServletContext context = this.getServletContext();//当前方法就在Servlet内部,this表示当前Servlet对象
        ServletContext context = getServletContext();// this是可以省略的
        ServletContext context2 = request.getServletContext();
        System.out.println("context:" + context);
        System.out.println("context2:" + context2);

        //域对象设置数据
        context.setAttribute("user","jack");
        
    }
}
@WebServlet("/ContextServlet02")
public class ContextServlet02 extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取ServletContext对象, 全局唯一
        ServletContext context3 = request.getServletContext();
        System.out.println("context3:" + context3);

        //域对象获取数据
        Object user = context3.getAttribute("user");
        System.out.println(user);
    }

}

域对象示例:统计网站的访问次数

需求

一般个人博客的首页,都会显示你是第几位访问此网站…

/*
* 示例: 记录本网站访问次数的
* */
// loadOnStartup 服务器启动时创建本Servlet并调用init方法
@WebServlet(value = "/ContextServlet03",loadOnStartup = 4)
public class ContextServlet03 extends HttpServlet {
    // 只执行一次
    @Override
    public void init() throws ServletException {
       //初始化工作
        ServletContext context = getServletContext();
        context.setAttribute("count",0);
    }
    //相当于service方法: 浏览器每访问一次,就执行一次
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 访问次数+1
        ServletContext context = getServletContext();

        Integer count = (Integer) context.getAttribute("count");
        count++; // Integer自动拆箱, 在计算时变成int
        context.setAttribute("count",count);

        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("<h1>欢迎来到首页</h1>");
        response.getWriter().print("<div>第"+count+"次访问</div>");
    }

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

获取全局的配置参数

  • 读取web.xml配置文件中标签信息,实现参数和代码的解耦(该项目中所有的servlet都可以获取)

获取web.xml中的初始化参数 getInitParameter(“encode”);

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!--
        web.xml配置全局参数(项目中任意Servlet都可以获取)
    -->
    <context-param>
        <param-name>encode</param-name>
        <param-value>gbk</param-value>
    </context-param>
</web-app>
/*
*   参数放在配置文件, 然后在代码中获取配置文件中的参数
*       (解耦)
* */
@WebServlet("/ContextServlet04")
public class ContextServlet04 extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取ServletContext对象
        ServletContext context = request.getServletContext();
        //获取web.xml中配置的全局参数
        String encode = context.getInitParameter("encode");
        System.out.println(encode);//gbk
    }

}

获取资源在服务器的真实地址

可以实现web项目的移植性…动态获取文件真实路径

* API
		String getRealPath(String path);
/*
*   E:\myword\xxx\xxx路径:
*       1. src:  java源码
*       2. web
*           1. html , css , js, img等静态资源
*           2. 特殊 web-inf : 浏览器不能直接访问
*               a. web.xml 工程配置文件
*               b. lib目录(jar: .class文件压缩包)
*               c. classes
*
*   当在idea中启动项目的时候, idea会自动编译项目
*       project/out 存放项目编译文件(主要 .class)
*       编译规则:
*           1. 静态资源无需编译
*           2. .java -> .class
*
*    out\artifacts\xxx路径下(真实运行路径)
*       1. resource
*       2. web-inf(浏览器不能直接访问,安全)
*           a. web.xml
*           b. classes (存放字节码)
*           c. lib(jar: 字节码)
*
* */
@WebServlet("/ContextServlet05")
public class ContextServlet05 extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //文件下载的功能
        // 不应该直接从源码路径获取(E:\mywork\xxx\xxx\web\            resource\1.zip)
        // 应该从真实路径去获取 (E:\mywork\xxx\out\artifacts\xxxxxx\1.zip)

        // 绝对路径: 在windows上从盘符开始(linux没有盘符) -> 开发中不用
        // 相对路径: 相对它而言 E:\mywork\xxx\out\artifacts\xxxx  (部署在不同的系统中,会动态变化)

        ServletContext context = getServletContext();
            //以相对路径的形式 去获取 真实路径 (复用性,项目部署在哪里都可以获取真实路径下的文件)
            // 相对 E:\mywork\xxx\out\artifacts\xxxx
        String realPath = context.getRealPath("resource/1.zip");
        System.out.println(realPath);

        // 获取资源的MIME类型
        String mimeType = context.getMimeType("resource/3.txt");
        System.out.println(mimeType); // txt -> text/plain  html->text/html
    }
}

获取资源的MIME类型

  • 在互联网通信过程中定义的一种文件数据类型
  • 格式:大类型/小类型 例如:text/html -> html text/plain-> txt

文件下载示例

需求

用户点击页面的链接,浏览器开始下载文件。
在这里插入图片描述

使用链接下载文件

将下载素材复制到web项目中

在这里插入图片描述

编写下载页面

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>donload.html</title>

</head>
<body>
<h3>文件下载</h3>
<h5>超链接下载</h5>
        <a href="resource/1.zip">1.zip</a> <br>
        <a href="resource/2.exe">2.exe</a> <br>
        <a href="resource/3.txt">3.txt</a> <br>
        <a href="resource/4.jpg">4.jpg</a> <br>
<h5>servlet下载</h5>
</body>
</html>

缺点

  1. 完全是浏览器的行为,浏览器对不可识别的文件进行下载,可识别的文件是直接打开而不是下载
  2. 资源直接对外暴露,无法对资源下载进行限制(比如需要会员才能下载)

使用Servlet下载文件【推荐…】

  • 二个响应头二个字节流
1. 被下载文件的字节输入流
		FileInputStream
2. response字节输出流
		ServletOutputStream	
3. 告知客户端下载文件的MIME类型(最新的浏览器此步骤可以省略....)
		Content-Type:MIME类型		
4. 告知浏览器以附件的方式保存
		Content-Disposition : attachment;filename=文件名
			attachment 附件
			filename=文件名

download.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <h3> 浏览器下载</h3>
        <!-- 让href直接指向静态资源位置 -->
        <a href="resource/1.zip">1.zip</a> <br>
        <a href="resource/2.exe">2.exe</a> <br>
        <a href="resource/3.txt">3.txt</a> <br>
        <a href="resource/4.jpg">4.jpg</a> <br>

        <h3> 代码下载</h3>
        <!-- 让href指向设置下载的Servlet
                1. 只要看不到请求方式,默认为get请求
                2. get请求的请求参数拼接url中
                    url?name=value&name=value
         -->
        <a href="/xxxx/DownLoadServlet?filename=1.zip">1.zip</a> <br>
        <a href="/xxxx/DownLoadServlet?filename=2.exe">2.exe</a> <br>
        <a href="/xxxx/DownLoadServlet?filename=3.txt">3.txt</a> <br>
        <a href="/xxxx/DownLoadServlet?filename=4.jpg">4.jpg</a> <br>
</body>
</html>

DownLoadServlet


@WebServlet("/DownLoadServlet")
public class DownLoadServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求参数: 知道浏览器要下载哪个文件
        String filename = request.getParameter("filename"); //1.zip
        System.out.println("要下载的文件是:" + filename);
        //两个头
            //1. 指定浏览器要下载文件,文件名为 x1.zip
                /*
                    文件名如果是中文,那么会乱码,
                        google浏览器默认要使用url编码,火狐是base64编码
                        1. 判断用户是何种浏览器 -> 请求头User-Agent
                        2. 修改编码
                  */
        String newName = DownLoadUtils.getName(request, filename);
        response.setHeader("content-disposition","attachment;filename=x" + newName);//x1.zip
            //2. 告诉浏览器文件的mime类型(现在浏览器可以自动识别,这行可以不写)
             //ServletContext可以根据文件后缀名 -> mime类型
        String mimeType = getServletContext().getMimeType(filename);
        response.setContentType(mimeType);

        //两个流: 先读本地文件,后写出到响应体
        String realPath = getServletContext().getRealPath("resource/" + filename);
        FileInputStream is = new FileInputStream(realPath);

        ServletOutputStream os = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while((length = is.read(buffer)) != -1){
            os.write(buffer,0,length);
        }
        is.close();
    }
}

中文乱码

* 如果该下载文件名是中文的话,会出现乱码...
	谷歌和绝大多数的浏览器是通过 url编码
		URLEncode() 编码
		URLDecode() 解码
	火狐浏览器   base64编码
	
* 就需要考虑浏览器兼容性问题....
	资料提供了判断浏览器不同编码的工具类直接使用即可....
public class DownLoadUtils {

	public static String getName(HttpServletRequest request, String filename) throws UnsupportedEncodingException {
		// 获得请求头中的User-Agent
		String agent = request.getHeader("User-Agent");
		// 根据不同的客户端进行不同的编码
		String filenameEncoder = "";
		 if (agent.contains("Firefox")) {
			// 火狐浏览器
			 System.out.println("火狐");
			BASE64Encoder base64Encoder = new BASE64Encoder();
			filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
		} else {
			// 其它浏览器
			 System.out.println("google");
			filenameEncoder = URLEncoder.encode(filename, "utf-8");
		}
		return filenameEncoder;
	}
}

点击切换验证码示例

需求

在页面展示登录验证码,点击此验证码可以更换新的验证码

作用:防止表单的恶意提交

本质上:就是一张随机图片

如何通过java代码制作一个验证码(不一定这种)
在这里插入图片描述

/*
	验证码的制作代码
 */
@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 = 40;
		BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		//  获得画笔
		Graphics g = bufferedImage.getGraphics();
		//  填充背景颜色
		g.setColor(Color.white);
		g.fillRect(0, 0, width, height);
		//  绘制边框
		g.setColor(Color.red);
		g.drawRect(0, 0, width - 1, height - 1);
		//  生成随机字符
		//  准备数据
		String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
		//  准备随机对象
		Random r = new Random();
		//  声明一个变量 保存验证码
		String code = "";
		//  书写4个随机字符
		for (int i = 0; i < 4; i++) {
			//  设置字体
			g.setFont(new Font("宋体", Font.BOLD, 28));
			//  设置随机颜色
			g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

			String str = data.charAt(r.nextInt(data.length())) + "";
			g.drawString(str, 10 + i * 28, 30);

			//  将新的字符 保存到验证码中
			code = code + str;
		}
		//  绘制干扰线
		for (int i = 0; i < 6; i++) {
			//  设置随机颜色
			g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

			g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
		}

		//  将验证码 打印到控制台
		System.out.println(code);

		//  将验证码放到session中
		request.getSession().setAttribute("code_session", code);

		//  将画布显示在浏览器中
		ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
	}

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

}
 <!--
            img的src属性 : 可以设置远程连接/本地连接
            CheckcodeServlet : 生成一张验证码图片,并响应这张图片字节流
                验证码的生成: java代码编写的(GUI技术: java中绘制界面的技术,被淘汰)
        -->
        验证码: <img src="/xxx/CheckcodeServlet" id="img">
        <script>
            /*
            *   点击切换验证码:
            *       1. 事件驱动: 图片点击事件
            *       2. 如果浏览器检测到网页中的标签或属性发生变化,会自动刷新
            *
            *       3. 解决方式是: 通过给url设置一个无意义的时间参数,让浏览器更新
            * */
            document.getElementById("img").onclick = function () {
                //this就是img标签
                let time = new Date().getTime()
                this.src = "/xxx/CheckcodeServlet?time=" + time
            }
        </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值