目录

  • ServletContext:读取文件
  • ServletContext:读取全局参数(web.xml)
  • ServletContext:上下文域对象
  • http协议响应数据的组成
  • 1、响应行
  • 2、响应头
  • 3、响应体


ServletContext:读取文件

ServletContext称为上下文对象,每个 Web应用程序都对应了一个上下文对象。所以ServletContext的作用范围是整个应用程序,全局唯一的对象

自定义的上下文 java代码实现 java 上下文对象_响应头

//1.根据相对路径"/img/5.jpg"读取运行位置资源文件真实路径(ServletContext)
        String path = getServletContext().getRealPath("/img/5.jpg");
        System.out.println("img/5.jpg的真实绝对路径:"+path);

        //2.根据资源文件绝对真实路径获取字节输入流
        InputStream inputStream = new FileInputStream(path);

        //3.将输入流的数据输出到浏览器直接输出流中,最终在浏览器上展现图片
        byte[] bytes = new byte[1024];
        int length = -1;
        while ((length = inputStream.read(bytes))!=-1){
            //输出(response的输出字节流:response.getOutputStream())
            response.getOutputStream().write(bytes,0,length);
        }

        //关闭输入流
        inputStream.close();
        //注意:输出流不用关闭,因为tomcat服务器会关闭的

注意:

response.getOutputStream()不需要关闭,因为tomcat会自动关闭

自定义的上下文 java代码实现 java 上下文对象_自定义的上下文 java代码实现_02

//1.根据相对路径"/img/5.jpg"读取资源文件的输入流
        InputStream inputStream = getServletContext().getResourceAsStream("/img/5.jpg");

        //2.将输入流的数据输出到浏览器直接输出流中,最终在浏览器上展现图片
        byte[] bytes = new byte[1024];
        int length = -1;
        while ((length = inputStream.read(bytes))!=-1){
            //输出(response的输出字节流:response.getOutputStream())
            response.getOutputStream().write(bytes,0,length);
        }

        //关闭输入流
        inputStream.close();
        //注意:输出流不用关闭,因为tomcat服务器会关闭的

使用IOUtils工具类优化流读写操作

自定义的上下文 java代码实现 java 上下文对象_html_03


自定义的上下文 java代码实现 java 上下文对象_html_04

注意:

lib放在WEB-INF下面

//1.根据相对路径"/img/5.jpg"读取资源文件的输入流
        InputStream inputStream = getServletContext().getResourceAsStream("/img/5.jpg");

        //2.将输入流的数据输出到浏览器直接输出流中,最终在浏览器上展现图片
        IOUtils.copy(inputStream,response.getOutputStream());

ServletContext:读取全局参数(web.xml)

自定义的上下文 java代码实现 java 上下文对象_html_05


web.xml

<?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_4_0.xsd"
         version="4.0">

    <!--
    全局参数
    -->
    <context-param>
        <param-name>country</param-name>
        <param-value>China</param-value>
    </context-param>
    <context-param>
        <param-name>charset</param-name>
        <param-value>utf-8</param-value>
    </context-param>
</web-app>
//1.获取全局参数名称列表
        Enumeration<String> enumeration = getServletContext().getInitParameterNames();

        //2.遍历迭代名称列表, 获取每个参数名称, 根据参数名称获取对应的参数值
        while (enumeration.hasMoreElements()){
            String paramName = enumeration.nextElement();
            String paramValue = getServletContext().getInitParameter(paramName);
            System.out.println(paramName+"="+paramValue);
        }

ServletContext:上下文域对象

自定义的上下文 java代码实现 java 上下文对象_数据_06

上下文域对象的生命周期:从服务器开启到服务器关闭都是有效的,所有的用户所有的 Servlet 之间都可以实现数据共享。
作用域对象有三个:request请求域对象,会话域对象,上下文域对象(servletcontext)
request请求域内存最小

自定义的上下文 java代码实现 java 上下文对象_响应头_07

案例:显示第几个用户登录

自定义的上下文 java代码实现 java 上下文对象_自定义的上下文 java代码实现_08

LoginServlet

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    //定义原子类AtomicInteger存储登录人数
    private AtomicInteger count = null;
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);//这句代码不可以删除,必须保留,否则直接使用config会报错
        //初始化登录人数为:0
        count = new AtomicInteger(0);
        //将数据写入到上下文域中
        getServletContext().setAttribute("count",count);
    }

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

        //目标:处理登录请求,统计登录人数
        //处理乱码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //1.获取用户名与密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //2.校验登录数据,用户名必须为admin,密码必须为123
        if("admin".equals(username) && "123".equals(password)) {
            //3.校验通过
            // 3.1 登录人数+1,
            count.incrementAndGet();
            //注意:不用更新回上下文域中,因为具有共同的内存地址,修改这里的数据上下文域对象数据也会修改

            // 3.2 跳转到CountServlet去显示登录的人数
            response.sendRedirect(request.getContextPath()+"/CountServlet");
        }else {
            //4.输出用户名或密码错误,登录失败
            response.getWriter().print("<script>alert('用户名或密码错误');history.back();</script>");
        }
    }
}

CountServlet

@WebServlet("/CountServlet")
public class CountServlet extends HttpServlet {
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //目标:从上下文域对象获取统计的登录人数输出

        //1.获取登录人数
        AtomicInteger count = (AtomicInteger) getServletContext().getAttribute("count");

        //2.输出
        response.setContentType("text/html;charset=utf8");
        response.getWriter().print("您是第"+count.get()+"位登录成功的用户");

    }
}

注意:

1、并发量多的时候,使用加锁
2、并发量少的时候,使用原子类, 原子类在高并发情况下可能会出错

3、转发跳转共享同一个请求,不需要重新设置编码
4、重定向跳转不共享一个请求,需要重新设置编码,后一次请求会覆盖前一次请求


http协议响应数据的组成

自定义的上下文 java代码实现 java 上下文对象_html_09


http协议响应数据的组成:

响应行、响应头、空行、响应体

1、响应行

自定义的上下文 java代码实现 java 上下文对象_数据_10


常见http状态码

http协议状态码101~599个,都是系统的状态码,每个状态码都有不同的含义

自定义的上下文 java代码实现 java 上下文对象_响应头_11

设置状态码的方法

自定义的上下文 java代码实现 java 上下文对象_自定义的上下文 java代码实现_12

/*
         * 设置响应状态码的,response对象的方法api
         *   1、setStatus(int status)
         *      仅设置状态码,没有任何效果,常与响应头命令配合使用,不单独使用;
         *
         *   2、sendError(int sc)
         *      int sc, 设置的状态码
         *      设置状态码并且发送错误状态码页面给浏览器
         *
         *  3、sendError(int sc,String msg)
         *     设置状态码并且发送错误状态码页面给浏览器,并且可以自定义消息内容
         *     应用场景:自己开发平台定义逻辑可以给开发人员报错误消息页面
         * */

        response.sendError(408,"你吃了吗?");

2、响应头

自定义的上下文 java代码实现 java 上下文对象_数据_13

响应头1、location重定向跳转

response.sendRedirect(request.getContextPath()+"/Demo3Servlet")的底层原理。

/*
         * 响应头:location
         * 格式:location:重定向跳转的地址
         * 含义:通知浏览器,让浏览器重定向跳转到指定的地址
         * 让浏览重定向跳转必须的条件有2个:
         *      设置响应头location
         *      设置状态码为302
         * 设置响应头方法api:
         *      response.setHeader(Sting key,String value);
         * */

        //目标:重定向跳转到Demo3Servlet
        //1.设置重定向跳转状态码
        response.setStatus(302);
        //2.设置location响应头的重定向跳转地址
        response.setHeader("location",request.getContextPath()+"/Demo3Servlet");

        //以后重定向跳转使用如下代码,因为原理就是上面2句代码
        //response.sendRedirect(request.getContextPath()+"/Demo3Servlet");

响应头2、ContentType解决输出乱码

响应头ContentType含义

自定义的上下文 java代码实现 java 上下文对象_数据_14

1、设置服务器响应给浏览器数据的数据类型(MIME类型)(多用途响应类型)
2、设置浏览器接收服务器数据使用的码表

response.setContentType(“text/html;charset=utf-8”)的底层原理:

/*
         * 目标:响应头Content-Type
         * 格式:content-type:text/html;charset=utf-8;
         * 含义:设置2部分内容
         *       第一部分:text/html,设置服务响应数据的类型,
         *               也叫mime类型,常用mime类:
         *                      text/html  ,响应数据为符合html代码规范的文本字符串数据
         *                      text/plain ,响应数据为普通文本字符串数据
         *                      application/json, 响应数据为符合json格式标准的文本字符串数据(以后会讲解)
         *       第二部分:charset=utf-8, 设置浏览器使用的字符码表
         *
         * 作用:设置输出数据格式类型与浏览器使用的字符码表
         * 应用场景:用于解决输出中文乱码底层原理就是使用这个响应头
         * */

        //解决输出中文乱码【推荐方式】
        //response.setContentType("text/html;charset=utf-8"); 底层原理就是上面的响应头content-type和服务器响应码表设置


        //乱码产生的原理:经历2个过程
        //第一个过程:服务器response默认输出中文字符采用的码表是iso8859-1
        //第二个过程:浏览器默认码表,中国大陆浏览器默认码表为GBK

        //解决乱码需要操作2个过程【原理方式,只需要了解】
        //设置服务器response输出码表为utf-8
        response.setCharacterEncoding("utf-8");
        //设置浏览器码表为utf-8
        response.setHeader("content-type","text/html;charset=utf-8");

        response.getWriter().print("传智");

自定义的上下文 java代码实现 java 上下文对象_自定义的上下文 java代码实现_15


自定义的上下文 java代码实现 java 上下文对象_html_16

响应头3、refresh定时跳转

自定义的上下文 java代码实现 java 上下文对象_响应头_17

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
	//定义倒计时数字
	var count = 3;
	//当页面加载完成时调用
	window.onload=function(){
		//倒计时
		tick();
	}
	//启动倒计时
	function tick(){
		//判断倒计时数字大于0继续进行倒计时操作
		if(count>0){
			//获得页面中显示倒计时的标签对象
			var p = document.getElementById("one");
			//页面显示倒计时数字,显示后数字减1
			p.innerHTML=count--;

			// if(count==0){
			//     location.href = "Demo3Servlet";
            // }
			//设置定时在一秒后继续调用当前方法
			window.setTimeout(tick, 1000);
		}
	}
</script>
</head>
<body>
页面在<p id="one">3</p>秒后跳转...
</body>
</html>
@WebServlet("/RefreshServlet")
public class RefreshServlet extends HttpServlet {
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        /*
         * 响应头: refresh
         * 格式:refresh:秒数;url=/项目路径/资源路径
         * 含义:通过响应头倒计时秒数后重定向跳转到指定资源地址【跳转本质:使用重定向】
         *
         * 注意:
         *     倒计时跳转页面,不会使用后端实现,以后推荐完全由前端实现就可以了
         * */

        //目标:倒计时3秒跳转到指定的资源Demo3Servlet

        response.setHeader("refresh","3;url="+request.getContextPath()+"/Demo3Servlet");

        //跳转到refresh.html展现倒计时数据
        //response.sendRedirect(request.getContextPath()+"/refresh.html");
        //这里不可以使用重定向:因为重定向是2次请求,会覆盖掉上面响应头refresh的设置,导致倒计时跳转失效

        //使用转发跳转到refresh.html, 这样response对象不会被覆盖
        request.getRequestDispatcher("/refresh.html").forward(request,response);

    }
}

响应头4、ContentDisposition附件下载

自定义的上下文 java代码实现 java 上下文对象_html_18


案例:下载不同类型的文件

解决请求体(post)或者请求行(get)非法数据(中文)乱码的问题

在这里插入代码片<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>

        function isIE(){
            //获取当前浏览器相关信息
            var explorer = window.navigator.userAgent.toLowerCase() ;
            //判断是否是ie浏览器
            if (explorer.indexOf("msie") >= 0 || explorer.indexOf("rv:11.0) like gecko") >= 0) {
                return true;
            }else {
                return false;
            }
        }
        window.onload = function () {
            if(isIE()){
                //在是IE浏览器的情况下,对中文请求参数编码
                var str = document.getElementById("ww").href;
                var str = encodeURI(str);
                document.getElementById("ww").href = str;
            }
        };
    </script>
</head>
<body>
<a href="Download2Servlet?fileName=ff.jpg">ff.jpg</a>
<a href="Download2Servlet?fileName=file.jpg">file.jpg</a>
<a href="Download2Servlet?fileName=file.txt">file.txt</a>
<!--IE浏览器get方式传递中文不会进行url编码,需要手动使用浏览器的url编码 -->
<a id="ww" href="Download2Servlet?fileName=美女.jpg">美女.jpg</a>
<a href="Download2Servlet?fileName=file.zip">file.zip</a>

</body>
</html>

解决响应头非法数据(中文)乱码的问题

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

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

        //目标:处理各种文件下载


        //1.获取客户端传递过来要下载的文件名,例如“file.zip”
        String fileName = request.getParameter("fileName");

        //2.获取指定文件名对应服务器磁盘文件的输入流
        InputStream inputStream = getServletContext().getResourceAsStream("/download/" + fileName);

        //3.对用户下载后的文件名进行url编码操作
        String ua = request.getHeader("User-Agent");
        boolean IE_LT11 = ua.contains("MSIE"); // IE11以下版本
        boolean IE11 = ua.contains("rv:11.0) like Gecko"); // IE11
        boolean Edge = ua.contains("Edge"); // win10自带的Edge浏览器
        // 如果是微软的浏览器,直接进行UTF-8编码
        if (IE_LT11 || IE11 || Edge) {
            fileName = URLEncoder.encode(fileName, "UTF-8");
            //由于编码数据给到浏览器,浏览器会自动url解码,所以jav编码的数据必须浏览器可以识别
            // java的编码方式和浏览器有略微的不同:对于空格,java编码后的结果是加号,
            // 而浏览器的编码结果是%20,因此将+替换成%20, 这样浏览器才能正确解析空格
            fileName = fileName.replace("+", "%20");
        }
        // 标准浏览器使用Base64编码
        else {
            Base64.Encoder encoder = Base64.getEncoder();
            fileName = encoder.encodeToString(fileName.getBytes("utf-8"));
            // =?utf-8?B?文件名?= 是告诉浏览器以Base64进行解码
            fileName = "=?utf-8?B?" + fileName + "?=";
        }


        //4.设置浏览器对数据进行附件下载
        response.setHeader("content-disposition","attachment;filename="+fileName);

        //5.将文件的输入流输出给response的的字节输出流
        IOUtils.copy(inputStream,response.getOutputStream());
    }
}

响应头5、content-encoding解压数据

gzip压缩介绍

Gzip压缩是在一个文本文件中找出类似的字符串, 并临时替换他们,使整个文件变小。这种形式的压缩对Web来说非常适合,因为HTML和CSS文件通常包含大量的重复的字符串,例如空格,标签。

自定义的上下文 java代码实现 java 上下文对象_自定义的上下文 java代码实现_19

自定义的上下文 java代码实现 java 上下文对象_自定义的上下文 java代码实现_20

/*
         * 响应头: content-encoding
         * 格式:content-encoding:gzip
         * 含义:通知浏览器对http协议传输的gzip压缩文件进行解压显示数据
         *       gzip是http协议压缩文件规范格式
         * 应用场景:当服务器输出大量文本信息会采用压缩方式压缩数据,压缩提高网络传输数据速度,这样浏览器会接收到一个压缩文件
         *           浏览器默认接收压缩文件会进行附件下载,可以通过这个响应头设置浏览器会对其解压显示数据
         * 文本数据压缩的原理:
         *           因为文本字符存在大量的重复数据,压缩的原理去掉重复数据,记录重复的次数,
         *           从而减轻传输的数据大小
         * 对数据进行压缩语法:
         *      创建压缩流对象
         *      GZIPOutputStream gzipOutputStream = new GZIPOutputStream(response.getOutputStream());
         *      对数据进行压缩到缓存中
         *      gzipOutputStream.write(sb.toString().getBytes());
         *      将缓存中的数据输出到输出流
         *      gzipOutputStream.finish();
         * */

        //1.压缩前传输大量文本数据:长度4000个字符
        StringBuilder stringBuilder =new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            stringBuilder.append("abcd");
        }
        //response.getWriter().print(stringBuilder.toString());

        //2.压缩后传输大量文本数据:44个字符(压缩将近100倍)
        //设置响应头解压gzip文件显示数据
        response.setHeader("content-encoding","gzip");

        //2.1 创建压缩输出流
        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(response.getOutputStream());
        //2.2 压缩数据存储在缓存中
        gzipOutputStream.write(stringBuilder.toString().getBytes());
        //2.3 将压缩数据给到response字节输出流输出到浏览器
        gzipOutputStream.finish();

        //注意:如果没有设置响应头content-encoding,浏览器默认会接收到一个压缩包并且会附件下载

3、响应体

响应体的介绍

就是输出网页的数据,给用户看的

1.输出字节流数据,动态资源图片的输出、视频、音频

2.输出字符流

案例1-响应体验证码-实现原理

自定义的上下文 java代码实现 java 上下文对象_html_21

自定义的上下文 java代码实现 java 上下文对象_自定义的上下文 java代码实现_22

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

    //定义一个随机类(共享多个地方使用)
    private Random random = new Random();

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

        //目标:输出一个内存图片验证码

        //1.创建一个内存图片BufferdImage对象
        //构造函数语法:BufferedImage(int width,int height,int imageType)
        // width,设置图片的宽度
        // height,设置图片的高度
        // imageType,设置图片的类型,RGB类型等
        BufferedImage image = new BufferedImage(150, 50, BufferedImage.TYPE_INT_RGB);

        //2.获取一个画笔(Graphics,具有画图功能)
        Graphics g = image.getGraphics();

        //3.填充一个矩形区域确定验证码的范围
        //设置画笔颜色白色
        g.setColor(Color.white);
        //填充一个矩形
        //语法: g.fillRect(int x, int y, int width, int height)
        //  参数:x,y 设置矩形起始点的坐标,从坐标(0,0)原点开始
        //  参数:width,height 设置矩形宽度与高度
        g.fillRect(0,0,150,50);

        //4.给矩形画一个边框
        //设置画笔颜色为黑色
        g.setColor(Color.black);
        //画边框语法: g.drawRect(int x, int y, int width, int height)
        //   参数:x,y 设置矩形起始点的坐标
        //   参数:width,height 设置矩形宽度与高度
        g.drawRect(1,1,147,47);

        //5.画4条干扰线(防止扫描软件识别)
        for (int i = 0; i < 4; i++) {

            //确定一个随机颜色
            g.setColor(getRandomColor());

            //画干扰线语法: g.drawLine(int x1, int y1, int x2, int y2)
            //确定随机的点的位置
            int x1 = random.nextInt(146)+1;  //1~146
            int y1 = random.nextInt(46)+1;   //1~46
            int x2 = random.nextInt(146)+1;  //1~146
            int y2 = random.nextInt(46)+1;   //1~46
            //画线
            g.drawLine(x1,y1,x2,y2);
        }

        //6.画4个随机生成的验证码字符串到图片上
        //6.0 定义验证码生成的范围
        String str = "zxcvbnmasdfghjkqwertyuipZXCVBNMASDFGHJKLQWERTYUP23456789传智教育";
        //定义一个变量接收最后生成的4个随机字符,以后用于验证
        StringBuilder checkCodeBuilder = new StringBuilder();
        //6.1 随机生成4个验证码字符串
        for (int i = 0; i < 4; i++) {
            //随机生成一个位置
            int index = random.nextInt(str.length());
            //根据位置获取对应的字符
            char c = str.charAt(index);
            //将生成的字符拼接存储到checkCodeBuilder
            checkCodeBuilder.append(c);

            //设置画笔的字体大小
            //g.setFont(Font font)
            //Font构造函数语法:Font(String name, int style, int size)
            //  name是字体类型,比如微软雅黑
            //  style,设置加粗,Font.BOLD
            //  size,设置字体大小
            g.setFont(new Font("微软雅黑",Font.BOLD,20));

            //6.2 画到图片上
            //画字符串语法:g.drawString(String str, int x, int y)
            g.drawString(c+"",30+i*30,30);
        }


        //7.画完后,将内存图片给到输出流输出到浏览器上显示
        // 语法:ImageIO.write(RenderedImage image,String format, OutputStream outputSteam)
        // RenderedImage 是一个接口,实现类BufferedImage
        ImageIO.write(image,"png",response.getOutputStream());
    }

    //定义获取一个随机颜色的方法
    private Color getRandomColor(){

        //创建颜色对象构造语法:new Color(int r, int g, int b)
        //每个颜色值范围:0~255
        int r = random.nextInt(256);
        int g = random.nextInt(256);
        int b = random.nextInt(256);
        return new Color(r,g,b);
    }
}

案例2、响应体-验证码切换以及滑动验证

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>登录页面</title>
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <script src="js/jquery-3.2.1.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
	  <style>
		  /* 滑块使用定位,背景没有设置宽度*/
		  .box {
			  width: 250px;
			  height: 50px;
			  background-color: #ccc;
			  position: relative;
			  margin: 0 auto;
		  }
		  .btn2 {
			  box-sizing: border-box;
			  width: 50px;
			  height: 50px;
			  border: 1px solid #ccc;
			  color: #ccc;
			  background-color: #fff;
			  position: absolute;
			  left: 0;
			  top: 0;
			  cursor: pointer;
			  z-index: 4;
		  }
		  .text {
			  position: absolute;
			  height: 50px;
			  left: 50%;
			  transform: translateX(-50%);
			  z-index: 2;
			  user-select: none;
			  padding-top: 15px;
		  }
		  .bg {
			  width: 0;
			  height: 50px;
			  background-color: #25c20f;
			  z-index: 3;
			  position: absolute;
			  top: 0;
			  left: 0;
		  }
	  </style>
  </head>
  <body>
    <div class="container" style="max-width:400px">
	    <h3 style="text-align: center">用户登录</h3>
	    <form action="login" method="post" >
	    	<div class="form-group">
	    		<label for="name">用户名:</label>
	    		<input type="text" name="name" class="form-control" id="name" placeholder="请输入用户名">
	    	</div>
	    	<div class="form-group">
	    		<label for="password">密码:</label>
	    		<input type="password" name="password" class="form-control" id="password" placeholder="请输入密码"/>
	    	</div>
			<div class="form-inline">
	    		<label for="vcode">验证码:</label>
	    		<input type="text" name="vcode" class="form-control" id="vcode" placeholder="验证码" style="width: 70px" maxlength="4"/> 
				<!--设置图片的src执行验证码图片输出的Servlet: CheckCodeServlet-->
				<img src="CheckCodeServlet" style="width: 90px; height: 30px; cursor: pointer;" title="看不清,点击刷新" onclick="changeCheckCode(this)">
				<script>
					//验证码图片点击事件
					function changeCheckCode(img){

						//图标标签让浏览器重新加载src的资源的原理:就是src的值必须要变化,注意请求的资源CheckCodeServlet不能变
						img.src = "CheckCodeServlet?time="+new Date().getTime();
					}
				</script>
	    	</div>
			<!--验证-->
			<div class="box">
				<!--滑块-->
				<div class="btn2"></div>
				<!--文字-->
				<p class="text">请滑动滑块</p>
				<!--背景-->
				<div class="bg"></div>
			</div>
	    	<div style="text-align: center; padding-top: 20px;">
		    	<input type="submit" value=" 登 录 " class="btn btn-primary" disabled="disabled"/>
	    	</div>
	    </form>
	    </div>


	<script>
		function selector(name) {
			return document.querySelector(name);
		}
		var box = selector('.box'),
				btn2 = selector('.btn2'),
				text = selector('.text'),
				bg = selector('.bg'),
				flag = false;
		// 鼠标按下,移动,松开
		// 按下的距离和移动的距离差就是滑块移动的距离
		btn2.onmousedown = function (e) {//按钮按下的
			var downX = e.clientX
			btn2.onmousemove = function(e){//e 事件的状态
				var moveX = e.clientX - downX;
				if(moveX > 0) {
					this.style.left = moveX + 'px';
					bg.style.width = moveX + 'px'
					// 滑块拉到头了,表示验证成功
					if (moveX >= box.offsetWidth - this.offsetWidth) {
						bg.style.zIndex = 1;// 设置bg的z-index的值是为了处理党滑块经过原始值的时候,bg将文字覆盖了。验证成功后,有让文字显示出来
						text.innerText = '验证成功';
						text.style.color = '#fff';
						flag = true;
						// 此时鼠标移动或者按下,滑块不在跟着移动了
						btn2.onmousemove = null;//
						btn2.onmousedown = null;//清除事件

						/*
                        * 这里处理验证成功的操作
                        * */
						document.querySelector(".btn").disabled = false;

					}
				}
			}
		}
		btn2.onmouseup = function () {
			btn2.onmousemove = null;
			// 如果验证成功了,那就不会回到原点
			if(flag){
				return ;
			}
			this.style.left = 0;
			bg.style.width = 0;
		}
	</script>
  </body>
</html>