小案例

2022年05月10日 阅读数:14
这篇文章主要向大家介绍小案例,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

案例:黑马旅游注册

目标

使用CSS样式排版出如图所示的效果javascript

效果

在这里插入图片描述

  1. 表格有四行,第一行和第四行跨2列,第一列占30%的宽度,第一行是标题th,第四行是放按钮。使用图片按钮
  2. table居中,宽300px,高180px; 边框solid 1px gray
  3. td的文字对齐居中,字体大小14px
  4. table添加背景,不平铺,图片背景的宽度和高度与table的宽和高同样。
  5. 用户名和密码文本框使用类样式,也可使用其它选择器。宽150px,高32px,边框用实线,圆角5px,1个宽度,黑色
  6. 使用伪类样式,当鼠标移动到文本框上的时候,变成虚线橙色边框。获得焦点,背景色变成浅黄色
  7. 文本框前面有头像,密码框前面有键盘,左内边距35

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>黑马旅游注册</title>
    <style>
        /*table居中,宽300px,高180px; 边框solid 1px gray*/
        table {
    
    
            width: 300px;
            height: 180px;
            margin: auto;
            border: solid 1px gray;
            border-radius: 10px;
            /*table添加背景,不平铺,图片背景的宽度和高度与table的宽和高同样。*/
            background-image: url("img/bg1.jpg");
            background-size: 300px 180px;
        }

        /*td的文字对齐居中,字体大小14px*/
        td {
    
    
            text-align: center;
            font-size: 14px;
        }


        /*用户名和密码文本框使用ID样式,也可使用其它选择器。宽150px,高32px,边框用实线,圆角5px,1个宽度,黑色*/
        #user,#password {
    
    
            width: 150px;
            height: 32px;
            border: solid 1px black;
            border-radius: 5px;
        }

        /*使用伪类样式,当鼠标移动到文本框上的时候,变成虚线橙色边框。获得焦点,背景色变成浅黄色*/
        #user:hover,#password:hover {
    
    
            border: dashed orange 1px;
        }

        #user:focus,#password:focus {
    
    
            background-color: lightyellow;
        }

        /*文本框前面有头像,密码框前面有键盘,左内边距35*/
        #user {
    
    
            background-image: url("img/head.png");
            background-repeat: no-repeat;
            /*左内边距为32*/
            padding-left: 32px;
        }

        #password {
    
    
            background-image: url("img/keyboard.png");
            background-repeat: no-repeat;
            /*左内边距为32*/
            padding-left: 32px;
        }
    </style>
</head>
<body>
<table>
    <tr>
        <!--跨2列-->
        <th colspan="2">黑马旅游注册</th>
    </tr>
    <tr>
        <td>用户名:</td>
        <td>
            <input type="text" id="user">
        </td>
    </tr>
    <tr>
        <td>密码:</td>
        <td>
            <input type="password" id="password">
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="image" src="img/regbtn.jpg">
        </td>
    </tr>
</table>
</body>
</html>

案例:轮播图

目标

  1. 函数的应用
  2. 定时函数的使用

方法说明

方法 描述
document.getElementById(“id”) 做用:经过id获取网页上惟一的元素(标签)
参数:ID的值
window.setInterval(“函数名()”,时间)
window.setInterval(函数名,时间)
做用:每隔一段时间调用一次指定的函数
参数1:要调用的函数名
参数2:隔多久调用,单位是毫秒

需求

每过3秒中切换一张图片的效果,一共5张图片,当显示到最后1张的时候,再次显示第1张。css

步骤

  1. 建立HTML页面,页面有一个img标签,id为pic,宽度600。
  2. body的背景色为黑色,内容居中。
  3. 五张图片的名字依次是0~4.jpg,放在项目的img文件夹下,图片一开始的src为第0张图片。
  4. 编写函数:changePicture(),使用setInterval()函数,每过3秒调用一次。
  5. 定义全局变量:num=1。
  6. 在changePicture()方法中,设置图片的src属性为img/num.jpg。
  7. 判断num是否等于5,若是等于5,则num=0;不然num++。

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>轮播图案例</title>
    <style>
        body {
    
    
            background-color: black;
            text-align: center;
        }
    </style>
</head>
<body>
    <img src="img/0.jpg" width="800" id="game">
</body>
<script type="text/javascript">
    //过2秒调用一次下面的图片
    window.setInterval("changePic()", 2000);

    let num = 1;

    /*
    建立一个函数:换图片
    技术点:修改img元素的src属性便可
     */
    function changePic() {
    
    
        //经过id获得一个元素,注:这个方法必须在网页已经加载完元素以后执行。要注意这个代码出现的位置
        let imgObj = document.getElementById("game");
        //alert(imgObj);
        //修改图片元素的src属性:对象名.属性名
        imgObj.src = "img/" + num + ".jpg";
        //文件名数字加1
        num++;
        //若是等于5,设置为0
        if (num == 5) {
    
    
            num = 0;
        }
    }

</script>

</html>

效果

在这里插入图片描述

案例:倒计时页面跳转

目标

window对象与location对象的综合案例应用html

window中计时器有关的方法

window中的方法 做用
setTimeout(函数名, 间隔毫秒数) 过一段时间后调用一次指定的函数,单位是毫秒,只调用一次。
返回值是一个整数类型,这就是计时器
clearTimeout(计时器) 清除上面的计时器,参数的计时器就是上面方法的返回值
setInterval(函数名, 间隔毫秒数) 每隔一段时间调用一次指定的函数,单位是毫秒,不停的调用。
返回值是一个整数类型,这就是计时器
clearInterval(计时器) 清除上面的计时器,参数的计时器就是上面方法的返回值

需求

页面上显示一个倒计时5秒的数字,到了5秒之后跳转到另外一个页面java

效果

在这里插入图片描述

分析

  1. 在页面上建立一个span用于放置变化的数字。
  2. 定义一个全局变量为5,每过1秒调用1次自定义refresh()函数
  3. 编写refresh()函数,修改span中的数字
  4. 判断变量是否为0,若是是0则跳转到新的页面
  5. 不然变量减1。并修改span中的数字

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>跳转</title>
</head>
<body>
<span id="counter">5</span>秒之后跳转
<script type="text/javascript">
    /*
    分析:
    1.用到倒计时:window.setInterval()
    2.页面跳转:location.href
    3.修改标签中文字使用属性:innerText
    */
    let count = 5;

    setInterval("countDown()", 1000);  //每过1秒调用一次

    //调用的函数
    function countDown() {
    
    
        //1.将数字减1
        count--;
        //2.更新span中数字
        document.getElementById("counter").innerText = count;
        //3.判断数字是否为0
        if (count == 0) {
    
    
            //4.若是为0就进行页面跳转
            location.href = "http://www.itcast.cn";
        }
    }

</script>
</body>
</html>

案例:会动的时钟

目标

​ 页面上有两个按钮,一个开始按钮,一个暂停按钮。点开始按钮时间开始走动,点暂停按钮,时间不动。再点开始按钮,时间继续走动。jquery

在这里插入图片描述

步骤

  1. 在页面上建立一个h1标签,用于显示时钟,设置颜色和大小。
  2. 一开始暂停按钮不可用,设置disabled属性,disabled=true表示不可用。
  3. 建立全局的变量,用于保存计时器
  4. 为了防止屡次点开始按钮出现bug,点开始按钮之后开始按钮不可用,暂停按钮可用。点暂停按钮之后,暂停按钮不可用,开始按钮可用。设置disabled=true。
  5. 点开始按钮,在方法内部每过1秒中调用匿名函数,在匿名函数内部获得如今的时间,并将获得的时间显示在h1标签内部。
  6. 暂停的按钮在方法内部清除clearInterval()的计时器。

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>会动的时钟</title>
</head>
<body>
<input type="button" value="开始" id="btnBegin">
<!--disabled就元素不可用-->
<input type="button" value="暂停" id="btnPause" disabled="disabled">
<hr/>

<h1 id="clock" style="color: darkgreen"></h1>

<script type="text/javascript">

    let timer;  //计时器

    //开始按钮的点击事件
    document.getElementById("btnBegin").onclick = function() {
    
    
        timer = setInterval("showTime()", 1000);  //每过1秒调用1次
        //修改disabled的属性为true,表示不可用,false表示可用
        //让开始按钮不可用,让暂停按钮可用
        document.getElementById("btnBegin").disabled = true;
        document.getElementById("btnPause").disabled = false;
    }

    //暂停按钮的点击事件
    document.getElementById("btnPause").onclick=function () {
    
    
        document.getElementById("btnBegin").disabled = false;  //开始按钮可用
        document.getElementById("btnPause").disabled = true;   //暂停按钮不可用
        //让计时器失效
        clearInterval(timer);   //计时器是setInterval()的返回值
    }

    /**
     * 分析:
     * 每过1秒钟输出如今的时间
     * 不能使用document.write方法
     * 应该放在一个标签内部,修改标签内部的内容,使用innerText或innerHTML
     */
    function showTime() {
    
    
        //获得如今的时间
        let now = new Date().toLocaleString();
        //在有些浏览器上,会覆盖整个网页,致使这些脚本都没有了
        //document.write(now);
        //在h1中显示时间
        document.getElementById("clock").innerText = now;
    }
</script>
</body>
</html>

案例:省市级联

案例需求

​ 页面上有两个下拉列表框,页面加载的时候访问数据库,获得全部的省份显示在第1个列表框中。当选择不一样的省份的时候,加载这个省份下全部的城市显示在第二个下拉列表中。web

案例效果

在这里插入图片描述

实现步骤

  1. 建立两个下拉列表,一个显示省份,一个显示城市
  2. 注册网页加载事件:在网页加载完毕只会显示省份信息
  3. 给省份下拉列表注册值改变事件:在省份发生变化时更新城市下拉列表信息

示例代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>省市联动</title>
</head>
<body>
<select id="province">
    <option>--请选择省份--</option>
</select>
<select id="city">
    <option>--请选择城市--</option>
</select>
</body>

<script>
    // 省份数据
    var provinces= ["广东省","湖南省","广西省"];
    // 城市数据,数据是一个二维数组,一维中每一个元素是一个数组
    var cities = [["深圳","广州","东莞"],["长沙市","郴州市","湘潭市"],["南宁市","桂林市","柳州市"]];

    /*
    在页面加载完毕之后读取全部的省份,而且填充到#province中
    分析:动态建立option对象,而且设置 <option value="0">广东省</option> 这个value就是它对应的城市数组索引
     */
    window.onload = function () {
    
    
        //1.获得省份这个select对象
        let selectProvince = document.getElementById("province");
        //遍历省份这个数组
        for (let i = 0; i < provinces.length; i++) {
    
    
            let province = provinces[i];  //i=0  province=广东省
            //2.建立option对象
            let optionElement = document.createElement("option");
            //3.设置value和文本
            optionElement.value = i;
            optionElement.innerText = province;
            //4.添加到select的最后一个子元素: 父元素.appendChild(子元素)
            selectProvince.appendChild(optionElement);
        }
    }

    /**
     * 省份下拉列表的改变事件
     */
    document.getElementById("province").onchange = function () {
    
    
        //alert(this.value);  //value就是它的索引
        var arr = cities[this.value];  //获得相应城市的数组
        //获得城市下拉select对象
        let city = document.getElementById("city");  //city下拉列表对象
        //修改city中innerHTML
        city.innerHTML = "<option>--请选择城市--</option>";  //覆盖原来的HTML子元素
        //向城市下拉列表添加option
        //1. 遍历城市数组
        for (let i = 0; i < arr.length; i++) {
    
    
            let arrElement = arr[i];  //每一个城市字符串
            //2. 建立option对象 <option>广州市</option>
            let optionElement = document.createElement("option");
            //3. 设置文本
            optionElement.innerText = arrElement;
            //4. 添加到select的最后一个子元素: 父元素.appendChild(子元素)
            city.appendChild(optionElement);
        }
    }
</script>
</html>

案例:校验注册表单

目标

在这里插入图片描述

onsubmit事件说明

 onsubmit事件,若是return false就能够阻止表单提交

案例需求

用户注册,须要进行以下验证,请在JS中使用正则表达式进行验证。ajax

  1. 用户名:只能由英文字母和数字组成,长度为4~16个字符,而且以英文字母开头
  2. 密码: 大小写字母和数字6-20个字符
  3. 确认密码:两次密码要相同
  4. 电子邮箱: 符合邮箱地址的格式 /^\w+@\w+(.[a-zA-Z]{2,3}){1,2}$/
  5. 手机号:/^1[3456789]\d{9}$/
  6. 生日:生日的年份在1900~2009之间,生日格式为1980-5-12或1988-05-04的形式,/^((19\d{2})|(200\d))-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\d|3[0-1])$/

案例分析

  1. 建立正则表达式
  2. 获得文本框中输入的值
  3. 若是不匹配,在后面的span中显示错误信息,返回false
  4. 若是匹配,在后面的span中显示一个打勾图片,返回true
  5. 写一个验证表单中全部的项的方法,全部的方法都返回true,这个方法才返回true.

代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>验证注册页面</title>
    <style type="text/css">
        body {
    
    
            margin: 0;
            padding: 0;
            font-size: 12px;
            line-height: 20px;
        }

        .main {
    
    
            width: 525px;
            margin-left: auto;
            margin-right: auto;
        }

        .hr_1 {
    
    
            font-size: 14px;
            font-weight: bold;
            color: #3275c3;
            height: 35px;
            border-bottom-width: 2px;
            border-bottom-style: solid;
            border-bottom-color: #3275c3;
            vertical-align: bottom;
            padding-left: 12px;
        }

        .left {
    
    
            text-align: right;
            width: 80px;
            height: 25px;
            padding-right: 5px;
        }

        .center {
    
    
            width: 280px;
        }

        .in {
    
    
            width: 130px;
            height: 16px;
            border: solid 1px #79abea;
        }

        .red {
    
    
            color: #cc0000;
            font-weight: bold;
        }

        div {
    
    
            color: #F00;
        }

        span {
    
    
            color: red;
        }
    </style>
    <script type="text/javascript">
        /**
         * 校验全部的表单项
         */
        function checkAll() {
    
    
            return checkUser() && checkMobile();
        }

        /**
         * 检查用户名是否正确
         * 由英文字母和数字组成,长度为4~16个字符,而且以英文字母开头
         */
        function checkUser() {
    
    
            //1.获得文本框的值
            let value = document.getElementById("user").value;
            //2.建立正则表达式
            let reg = /^[a-zA-Z][a-zA-Z0-9]{3,15}$/;
            //3.比较正则表达式与文本框的值是否匹配
            if (reg.test(value)) {
    
    
                //4.若是匹配就经过,在后面显示打勾的图片,返回true
                document.getElementById("userInfo").innerHTML = "<img src='img/gou.png' width='15'/>";
                return true;
            } else {
    
    
                //5.若是不匹配,在后面显示错误信息,返回false
                document.getElementById("userInfo").innerHTML = "用户名格式有误";
                return false;
            }
        }

        /**
         * 判断手机号
         */
        function checkMobile() {
    
    
            //1.获得文本框的值
            let value = document.getElementById("mobile").value;
            //2.建立正则表达式
            let reg = /^1[3456789]\d{9}$/;
            //3.比较正则表达式与文本框的值是否匹配
            if (reg.test(value)) {
    
    
                //4.若是匹配就经过,在后面显示打勾的图片,返回true
                document.getElementById("mobileInfo").innerHTML = "<img src='img/gou.png' width='15'/>";
                return true;
            } else {
    
    
                //5.若是不匹配,在后面显示错误信息,返回false
                document.getElementById("mobileInfo").innerHTML = "手机格式有误";
                return false;
            }
        }
    </script>
</head>

<body>
<!--  onsubmit事件,若是return false就能够阻止表单提交-->
<form action="server" method="post" id="myform" onsubmit="return checkAll()">
    <table class="main" border="0" cellspacing="0" cellpadding="0">
        <tr>
            <td><img src="img/logo.jpg" alt="logo"/><img src="img/banner.jpg" alt="banner"/></td>
        </tr>
        <tr>
            <td class="hr_1">新用户注册</td>
        </tr>
        <tr>
            <td style="height:10px;"></td>
        </tr>
        <tr>
            <td>
                <table width="100%" border="0" cellspacing="0" cellpadding="0">
                    <tr>
                        <!-- 不能为空, 输入长度必须介于 5 和 10 之间 -->
                        <td class="left">用户名:</td>
                        <td class="center">
                            <!--文本框失去焦点进行验证-->
                            <input id="user" name="user" type="text" class="in" onblur="checkUser()"/>
                            <span id="userInfo"></span>
                        </td>
                    </tr>
                    <tr>
                        <!-- 不能为空, 输入长度大于6个字符 -->
                        <td class="left">密码:</td>
                        <td class="center">
                            <input id="pwd" name="pwd" type="password" class="in"/>
                        </td>
                    </tr>
                    <tr>
                        <!-- 不能为空, 与密码相同 -->
                        <td class="left">确认密码:</td>
                        <td class="center">
                            <input id="repwd" name="repwd" type="password" class="in"/>
                        </td>
                    </tr>
                    <tr>
                        <!-- 不能为空, 邮箱格式要正确 -->
                        <td class="left">电子邮箱:</td>
                        <td class="center">
                            <input id="email" name="email" type="text" class="in"/>
                        </td>
                    </tr>
                    <tr>
                        <!-- 不能为空, 使用正则表达式自定义校验规则,1开头,11位全是数字 -->
                        <td class="left">手机号码:</td>
                        <td class="center">
                            <input id="mobile" name="mobile" type="text" class="in" onblur="checkMobile()"/>
                            <span id="mobileInfo"></span>
                        </td>
                    </tr>
                    <tr>
                        <!-- 不能为空, 要正确的日期格式 -->
                        <td class="left">生日:</td>
                        <td class="center">
                            <input id="birth" name="birth" type="text" class="in"/>
                        </td>
                    </tr>
                    <tr>
                        <td class="left">&nbsp;</td>
                        <td class="center">
                            <input name="" type="image" src="img/register.jpg"/>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

案例:表格隔行换色与全选全不选

目标

  1. 实现隔行变色的效果
  2. 实现全选全不选的效果

效果

在这里插入图片描述

步骤

隔行变色

  1. 页面加载完毕,获得全部的tr。
  2. 使用基本过滤选择器,除了第0行,设置偶数行背景色为lightgreen
  3. 使用基本过滤选择器,除了第0行,设置奇数行背景色为lightyellow

全选全不选

  1. 给最上面的id=all的复选框添加点击事件
  2. 使用属性选择器选中全部item=name的复选框,设置它的checked属性与id=all的复选框的checked属性相同。

代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>隔行换色/全选全不选</title>
    <style type="text/css">
        table {
    
    
            border-collapse: collapse;
        }

        tr {
    
    
            height: 35px;
            text-align: center;
        }

        a:link {
    
    
            text-decoration: none;
        }
    </style>
    <script type="text/javascript" src="js/jquery-3.3.1.js"></script>
    <script type="text/javascript">
        $(function () {
    
    
            //隔行变色,除了第1行以外,even表示偶数行,剩下的行中偶数行
            $("tr:gt(0):even").css("background-color", "lightgreen");
            $("tr:gt(0):odd").css("background-color", "lightyellow");

            //全选,全不选
            $("#all").click(function () {
    
      //最上面的复选框点击事件
                //获得all的值是true或是false
                //选中全部下面的checkbox
                $("input[name=item]").prop("checked", $("#all").prop("checked"));    //设置boolean类型的属性
            });
        })
    </script>
</head>
<body>
<table id="tab1" border="1" width="700" align="center">
    <tr style="background-color: #999999;">
        <td><input type="checkbox" id="all"></td>
        <td>分类ID</td>
        <td>分类名称</td>
        <td>分类描述</td>
        <td>操做</td>
    </tr>
    <tr>
        <td><input type="checkbox" name="item"></td>
        <td>1</td>
        <td>手机数码</td>
        <td>手机数码类商品</td>
        <td><a href="">修改</a>|<a href="">删除</a></td>
    </tr>
    <tr>
        <td><input type="checkbox" name="item"></td>
        <td>2</td>
        <td>电脑办公</td>
        <td>电脑办公类商品</td>
        <td><a href="">修改</a>|<a href="">删除</a></td>
    </tr>
    <tr>
        <td><input type="checkbox" name="item"></td>
        <td>3</td>
        <td>鞋靴箱包</td>
        <td>鞋靴箱包类商品</td>
        <td><a href="">修改</a>|<a href="">删除</a></td>
    </tr>
    <tr>
        <td><input type="checkbox" name="item"></td>
        <td>4</td>
        <td>家居饰品</td>
        <td>家居饰品类商品</td>
        <td><a href="">修改</a>|<a href="">删除</a></td>
    </tr>
</table>
</body>
</html>

小结

  1. 选中大于0的tr的偶数行的选择器怎么写?正则表达式

    tr:gt(0):even
    
  2. 设置某个复选框选中的方法是什么?数据库

    jq对象.prop("checked",true)
    

案例:实现购物车

目标

使用今天学习的内容制做一个购物车案例apache

需求

  1. 实现添加商品,若是商品名为空,提示:商品名不能为空。若是不为空,则添加成功一行,清空文本框的内容,图片使用固定一张。
  2. 实现删除一行商品的功能,删除前弹出确认对话框。

效果

在这里插入图片描述

代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>购物车的实现</title>
    <style type="text/css">
        table {
    
    
            width: 400px;
            border-collapse: collapse;
            margin: auto;
        }

        td,th {
    
    
            text-align: center;
            height: 30px;
        }

        .container {
    
    
            width: 400px;
            margin: auto;
            text-align: right;
        }

        img {
    
    
            width: 100px;
            height: 100px;
        }

        th {
    
    
            background-color: lightgray;
        }

        tr:hover {
    
    
            background-color: lightyellow;
        }
    </style>
    <script type="text/javascript" src="js/jquery-3.3.1.js" ></script>
    <script type="text/javascript">
        //添加到购物车的点击事件
        function addRow() {
    
    
            //1.获取文本框中内容
            let val = $("#pname").val().trim();   //去掉先后的空格
            if (val == "") {
    
      //注:不一样于Java
                alert("商品名字不能为空");
                //让文本框得到焦点
                $("#pname").focus();
                return;
            }
            //2.建立tr
            let tr = "<tr>" +
                "<td><img src=\"img/girl.jpg\" /></td>" +
                "<td>" + val + "</td>" +
                "<td><input type=\"button\" value=\"删除\" οnclick=\"deleteRow(this)\"></td>" +
                "</tr>";
            //3.建立好的tr的放到父元素tbody中
            $("#cart").append(tr);
            //4.清空文本框内容
            $("#pname").val("");
        }

        //删除一行
        function deleteRow(obj) {
    
       //obj其实就是一个按钮对象,这是JS对象,转成JQ对象
            if (confirm("真的要从购物车中移除这件商品吗?")) {
    
    
                //按钮的父元素->td  的父元素 -> tr  删除tr便可
                $(obj).parent().parent().remove();   //本身删除本身
            }
        }
    </script>
</head>

<body>
<div class="container">
    <table border="1">
        <tbody id="cart">
        <tr>
            <th>
                图片
            </th>
            <th>
                商品名
            </th>
            <th>
                操做
            </th>
        </tr>
        <tr>
            <td><img src="img/sx.jpg" /></td>
            <td>
                三星Note7
            </td>
            <td>
                <!--this表示当前按钮-->
                <input type="button" value="删除" onclick="deleteRow(this)">
            </td>
        </tr>
        </tbody>
    </table>
    <br />
    商品名:
    <input type="text" id="pname" value="" />&nbsp;
    <input type="button" value="添加到购物车" onclick="addRow()" />
</div>
</body>
</html>

小结

1. 建立tr
2. 添加到tbody中
3. 删除元素remove()
4. 获取父元素:parent()

案例:原生的AJAX判断用户名是否存在

目标

​ 了解原生的ajax如何去实现这个案例

需求

​ 用户注册时输入一个用户名,失去焦点之后,经过ajax后台判断用户名是否存在。服务器先不访问数据库,直接判断用户名,若是用户名为newboy,则表示用户已经存在,不然用户名能够注册使用。

效果

在这里插入图片描述

服务器端

准备数据文件 users.json

[
"Newboy",
"Jack",
"Rose",
"Tom",
"Lina"
]

客户端

步骤

  1. 文本框失去焦点,获得文本框中的姓名
  2. 建立 XMLHttpRequest 请求对象
  3. 设置请求的 URL
  4. 调用 open 方法,设置提交给服务器的请求方式和访问地址
  5. 调用 send 方法发送请求
  6. 设置请求对象的 onreadystatechange 事件,即"准备状态改变"事件。
    a) 当 readyState 等于 4,而且服务器 status 响应码为 200 则表示响应成功
    b) 经过 responseText 获得响应的字符串,服务器返回的是一个字符串数组。
    c) 转成 JSON 数组,再与文本框中输出的值进行比较,若是存在就设置为 true,不然设置为 false。
    d) 若是是 true,则表示用户存在,在后面的 span 显示"用户名已经存在"
    e) 不然表示不存在,在后面的 span 中显示"恭喜你,能够注册"。

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户是否存在</title>
</head>
<body>
用户名:<input type="text" id="user"> <span id="info"></span>
<script type="text/javascript">
    /*用户注册时输入一个用户名,失去焦点之后,经过ajax后台判断用户名是否存在。
    服务器先不访问数据库,直接判断用户名,若是用户名为newboy,则表示用户已经存在,不然用户名能够注册使用。 */

    //用户名的改变事件
    document.getElementById("user").onchange = function () {
    
    
        //建立XMLHttpRequest对象
        let request = new XMLHttpRequest();
        //打开服务器的链接,参数:GET或POST,服务器地址,true
        request.open("GET", "json/users.json", true);
        //发送请求给服务器
        request.send();
        //设置回调函数,准备状态发生改变时激活这个函数
        request.onreadystatechange = function () {
    
    
            //准备状态等于4,服务器状态码等于200
            if (request.readyState == 4 && request.status == 200) {
    
    
                //接收服务器返回的数据
                let text = request.responseText;  //字符串
                //将字符串转成JSON
                let users = JSON.parse(text);  //全部用户的数组
                //获得用户在文本框中输入的数据
                let user = document.getElementById("user").value;
                //设置标记
                let exists = false;
                //遍历服务器返回的数组
                for (let u of users) {
    
    
                    if (u == user) {
    
      //当前元素等于输入的用户名
                        exists = true;  //修改标记
                        break;
                    }
                }
                //判断标记
                if (exists) {
    
      //用户名已经存在
                    document.getElementById("info").innerText = "用户名已经存在";
                }
                else {
    
      //不存在
                    document.getElementById("info").innerText = "恭喜,能够注册";
                }
            }
        }
    }
</script>
</body>
</html>

小结

浏览器端的访问流程

在这里插入图片描述

案例:输入自动补全

需求

在输入框输入关键字,下拉框中异步显示与该关键字相关的用户名称

效果

在这里插入图片描述

服务器端代码

search.json

[
  "张三",
  "李四",
  "王五",
  "赵六",
  "田七",
  "孙八",
  "张三丰",
  "张无忌",
  "李寻欢",
  "王维",
  "李白",
  "杜甫",
  "李贺",
  "李逵",
  "宋江",
  "王英",
  "鲁智深",
  "武松",
  "张薇",
  "刘小轩",
  "刘浩宇",
  "刘六"
]

流程分析

在这里插入图片描述

分析页面组成

在这里插入图片描述

步骤

  1. 编写文本框的keyup事件
  2. 获得word文本框的值
  3. 去掉值先后的空格,判断值是否为空,若是为空,则返回再也不继续。
  4. 不然使用$.post方法发送请求给服务器
  5. 在success回调函数中获得服务器返回数据:JSON格式全部用户的集合
  6. 建立正则表达式,匹配以^word开头的用户
  7. 建立一个数组用来保存符合条件的字符串
  8. 若是上面的数组不为空,则进行字符串拼接,每一个用户是一个div。
  9. 拼接完成之后使用html()方法填充到#show的div中
  10. 若是集合为空,则隐藏#show的div

拓展

  1. 给#show中div添加点击事件
  2. 将 div 的文本内容显示在#word的值中
  3. 隐藏#show这个div

代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>自动完成</title>
    <style type="text/css">
        .content {
    
    
            width: 400px;
            margin: 30px auto;
            text-align: center;
        }

        input[type='text'] {
    
    
            box-sizing: border-box;
            width: 280px;
            height: 30px;
            font-size: 14px;
            border: 1px solid #38f;
        }

        input[type='button'] {
    
    
            width: 100px;
            height: 30px;
            background: #38f;
            border: 0;
            color: #fff;
            font-size: 15px;
        }

        #show {
    
    
            box-sizing: border-box;
            position: relative;
            left: 7px;
            font-size: 14px;
            width: 280px;
            border: 1px solid dodgerblue;
            text-align: left;
            border-top: 0;
            /*一开始是隐藏不可见*/
            display: none;
        }

        #show div {
    
    
            padding: 4px;
            background-color: white;
        }

        #show div:hover {
    
    
            /*鼠标移上去背景变色*/
            background-color: #3388ff;
            color: white;
        }
    </style>
    <script type="text/javascript" src="js/jquery-3.3.1.js"></script>
</head>
<body>
<div class="content">
    <img alt="传智播客" src="img/logo.png"><br/><br/>
    <input type="text" name="word" id="word">
    <input type="button" value="搜索一下">
    <div id="show"></div>
</div>

<script type="text/javascript">
    /*
    alert(event.keyCode);  //keyCode键盘码表,每一个按键都会对应一个号码
     */
    //不能使用change事件,由于change要失去焦点才激活,只要松开任何一个键就激活
    $("#word").keyup(function () {
    
    
        //判断文本框中是否有数据,若是不为空,才继续,去掉先后空格
        let word = $("#word").val().trim();
        if (word == "") {
    
    
            //若是文本框中没有内容,也要隐藏div
            $("#show").hide();
            return;  //再也不继续
        }
        //表示有数据的,开始访问服务器
        $.get({
    
    
            url: "json/search.json",  //服务器的访问地址
            success: function (users) {
    
      //返回服务器上全部的数据
                //使用正则表达式,只保留指定字符串开头的用户名
                let reg = new RegExp("^" + word);
                //建立一个数组,用来保存全部以word开头的用户
                let arr = new Array();
                //遍历整个数组
                for (let user of users) {
    
    
                    //判断每一个字符串是否匹配正则表达式
                    if (reg.test(user)) {
    
    
                        arr.push(user);  //添加到数组中
                    }
                }

                //把arr数组显示在div中
                //先判断数组中是否有元素,有元素才显示
                if (arr.length > 0) {
    
    
                    //拼接字符串
                    let html="";
                    for (let name of arr) {
    
    
                        html+="<div>" + name + "</div>";
                    }
                    //放在#show的div中
                    $("#show").html(html);  //括号中是一个变量名html
                    //显示div
                    $("#show").show();

                    //若是点击每一个小的div,就把div中文本赋值给文本框的value
                    $("#show div").click(function () {
    
    
                        //this至关于你点击的那个div
                        $("#word").val($(this).text());
                        //隐藏大的div
                        $("#show").slideUp("normal");  //加个动画 
                    });
                }
                else {
    
      //没有元素隐藏div
                    $("#show").hide();
                }
            }
        });
    });
</script>
</body>
</html>

小结

  1. 使用文本框的键盘松开事件 keyup
  2. $.post() 提交数据给服务器,返回JSON集合
  3. 遍历集合,拼接成div的字符串
  4. 使用html()方法将拼接好的字符串覆盖div中原有的内容
  5. 显示show这个div

案例:使用连接下载文件不足

目标

连接下载文件存在的问题

页面效果

在这里插入图片描述

下载页面

<!DOCTYPE html>
<html>
  <head>
    <title>资源下载列表</title>
    <meta charset="utf-8">
  </head>
  
  <body>
   <h2>文件下载页面列表</h2>
   <h3>超连接的下载</h3>
   <a href="download/file.txt">文本文件</a><br/>
   <a href="download/file.jpg">图片文件</a><br/>
   <a href="download/file.zip">压缩文件</a><br/>
   <hr/>
   <h3>手动编码的下载方式</h3>
   <!-- 注:down这里是下载的Servlet的访问地址 -->
   <a href="down?filename=file.txt">文本文件</a><br/>
   <a href="down?filename=file.jpg">图片文件</a><br/>
   <a href="down?filename=file.zip">压缩文件</a><br/>
   <a href="down?filename=美女.jpg">美女</a><br/>
  </body>
</html>

小结:使用超连接下载的不足

  1. 有些资源是直接打开的,不知足下载的要求
  2. 暴露资源的真实地址,有可能被盗链。
  3. 不利于业务逻辑的控制,要有积分才能够下载。

案例:使用Servlet下载文件

目标

  1. 实现使用Servlet的方式下载文件
  2. 文件名有汉字的处理

下载设置的响应头

技术点,须要设置如下响应头才能够实现下载

设置响应头 参数说明
Content-Disposition:
attachment; filename=文件名
Content-Disposition: 浏览器打开资源的方式
attachment: 表示以附件的方式下载,而不是打开
filename: 下载到浏览器端使用的文件名

步骤

  1. 从连接上获得文件名
  2. 设置content-disposition头
  3. 获得文件的输入流
  4. 获得response的输出流
  5. 写出到浏览器端

汉字乱码原理

在这里插入图片描述

注:IE、Chrome下载中文采用的是URL编码,注:FireFox不能采用这种方式。

下载的Servlet代码

package com.itheima.servlet;

import org.apache.commons.io.IOUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

/**
 * 处理下载的Servlet
 * 在其实开发过程当中,不建议在服务器上使用汉字
 * 在Chrome和IE等浏览器中,文件名使用的URL编码
 */
@WebServlet("/down")
public class Demo5DownloadServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        //0.获得下载的文件,filename与地址栏提交的名字相同
        String filename = request.getParameter("filename");  //GET汉字没有乱码
        System.out.println("下载的文件名是:" + filename);
        //必须设置响应头,考虑汉字的问题,对文件名使用URL编码
        response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(filename,"utf-8"));
        //1.获得上下文对象
        ServletContext application = getServletContext();
        //2.获得web目录下资源的输入流对象
        InputStream inputStream = application.getResourceAsStream("/download/" + filename);
        //3.获得响应对象的字节输出流
        OutputStream outputStream = response.getOutputStream();
        //4.使用IOUtils复制流
        IOUtils.copy(inputStream, outputStream);
        //5.关闭流
        outputStream.close();
        inputStream.close();
    }

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

小结

  1. 下载须要设置哪一个响应头?

    Content-disposition: attachment;filename=文件名
    
  2. 若是下载文件名中有汉字使用哪一个方法编码?

    URLEncoder.encode("文件名","utf-8")
    

案例:获得用户上次访问的时间

目标

  1. 若是用户是第一次访问,则输出:您好,您是第1次访问,欢迎您的加入!当前的时间是xxx

  2. 若是以前已经访问过,则从Cookie中获得上次访问的时间,显示:您好,欢迎您再次访问。

    上次访问的时间是:xxxx,当前的时间是xxxxx。

  3. 不管是不是第一次访问,都要把此次访问服务器的时间写到Cookie中

流程分析

在这里插入图片描述

代码

package com.itheima.servlet;

import com.itheima.utils.CookieUtils;

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

/**
 * 1. 若是用户是第一次访问,则输出:您好,您是第1次访问,欢迎您的加入!当前的时间是xxx
 * 2. 若是以前已经访问过,则从Cookie中获得上次访问的时间,显示:您好,欢迎您再次访问。
 * 上次访问的时间是:xxxx,当前的时间是xxxxx。
 * 3. 不管是不是第一次访问,都要把此次访问服务器的时间写到Cookie中
 */
@WebServlet("/demo6")
public class Demo6VisitedServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //0.建立如今的时间,不建议使用空格
        String now = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒").format(new Date());
        //1.获取浏览器端发送来的Cookie的值,假设这个键是visitedTime,使用工具类
        String visitedTime = CookieUtils.getCookieValue(request, "visitedTime");
        //2.判断是否为空,若是为空表示第1次访问
        if (visitedTime == null) {
   
   
            out.print("<h1>您是第1次访问,如今的时间是:" + now + "</h1>");
        } else {
   
   
            //不为空,表示从cookie中获取到指定的值,这就是上次访问的时间
            out.print("<h1>欢迎您再次访问,上次访问的时间是:" + visitedTime + "</h1>");
            out.print("<h2 style='color:green'>如今的时间是:" + now + "</h2>");
        }

        //3.还要将如今的时间写回到浏览器,键与读取的要相同
        Cookie cookie = new Cookie("visitedTime", now);
        //设置过时时间
        cookie.setMaxAge(60 * 60 * 24 * 30);  //保存1个月
        //写到浏览器端
        response.addCookie(cookie);
    }

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

小结

  1. 从Cookie中取一个叫visitedTime的信息,若是为null,则表示第一次访问
  2. 不然读取Cookie的信息字符串,显示上次访问的时间
  3. 不管上次访问时间是否为空,都把此次访问的时间写入Cookie中

案例:利用cookie实现自动登陆

案例part1:Cookie实现自动登陆Servlet

目标

可以使用Cookie保存用户名和密码

结构

在这里插入图片描述

分析

在这里插入图片描述

Servlet步骤

  1. 获得表单提交的数据:用户名和密码
  2. 判断用户名和密码实现登陆
  3. 若是登陆成功,则判断是否勾选了记住我。
  4. 若是勾选了,则将用户名和密码写入Cookie中,保存一周的时间,并跳转到成功页面。
  5. 不然跳转到登陆失败页面

代码

LoginServlet

package com.itheima.servlet;

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

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        //1. 获得用户名和密码,判断是否正确
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //2. 若是登陆成功
        if ("admin".equals(username) && "123".equals(password)) {
   
   
            //再判断是否勾选自动登陆
            String remember = request.getParameter("remember");
            if (remember != null) {
   
     //不为空表示勾选了
                //3. 把用户名和密码建立成Cookie
                Cookie cookieUsername = new Cookie("username", username);
                //4. 设置访问路径和过时的时间,发送给浏览器
                cookieUsername.setPath(request.getContextPath() + "/login.html");
                cookieUsername.setMaxAge(60 * 60 * 24 * 7);  //保存1周
                response.addCookie(cookieUsername);

                Cookie cookiePassword = new Cookie("password", password);
                //4. 设置访问路径和过时的时间,发送给浏览器
                cookiePassword.setPath(request.getContextPath() + "/login.html");
                cookiePassword.setMaxAge(60 * 60 * 24 * 7);  //保存1周
                response.addCookie(cookiePassword);
            }
            //表示登陆成功,跳转到登陆成功的页面
            response.sendRedirect("success.html");
        }
        else {
   
   
            response.sendRedirect("failure.html");  //登陆失败
        }
    }

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

案例part2:Cookie实现自动登陆浏览器端

目标

浏览器端代码的实现

JS代码步骤

  1. 编写工具方法,读取指定键的值
  2. 页面加载完成,读取cookie的信息
  3. 若是有username不为null,而且password也不为null
  4. 则将用户名和密码赋值给文件框,而且提交表单

代码

login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>用户登陆</title>
    <!--导入js文件-->
    <script src="js/commons.js"></script>
</head>
<body>
<h2>用户登陆</h2>
<form action="login" method="post" id="loginForm">
    <table>
        <tr>
            <td width="60">用户名</td>
            <td><input type="text" name="username" id="username"/></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="password" id="password"/></td>
        </tr>
        <tr>
            <td>记住我</td>
            <!--没有value属性的前提下,点中它的值是on,若是没有勾上为null -->
            <td><input type="checkbox" name="remember"/></td>
        </tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" value="登陆"/></td>
        </tr>
    </table>
</form>
</body>
</html>

commons.js

/**
 页面加载完毕之后执行
 */
window.onload = function () {
   
   
    //从cookie中获得用户名和密码
    let username = getCookieValue("username");
    let password = getCookieValue("password");
    //若是字符串不为空,才将数据提交给服务器
    if (username!="" && password!="") {
   
   
        //设置文本框的值
        document.getElementById("username").value = username;
        document.getElementById("password").value = password;

        //提交表单
        document.getElementById("loginForm").submit();
    }
}

/**
 经过键获得Cookie中的值
 @param name表示要找的名字
 */
function getCookieValue(name) {
   
   
    //能够获得当前路径下全部的cookie信息
    let cookie = document.cookie;   //username=admin; password=123
    if (cookie!="") {
   
   
        //按分号进行拆分红数组,数组中有2个元素
        let split = cookie.split("; ");
        for (let i = 0; i < split.length; i++) {
   
      //split[0] = "username=admin"   split[1] = "password=123"
            let splitElement = split[i];   //每一个元素
            //再按等于号来拆分
            let arr = splitElement.split("=");
            let key = arr[0];  //[0]号元素是username,[1]号元素admin
            let value = arr[1];
            //若是name与key相等,就返回value
            if (key == name) {
   
   
                return value;
            }
        }
    }
    return "";  //没有找到
}

案例:商品购物车

目标

有一个商品页面,能够点击超连接将商品添加到购物车,并能够查看购物车中商品信息

流程分析

购物车要保存在哪一个做用域?

在这里插入图片描述

步骤

添加到购物车的Servlet

  1. 获得会话
  2. 从会话中取出购物车
  3. 若是购物车为空,则建立一个购物车
  4. 获得商品名字
  5. 经过名字为键取出有多少件商品
  6. 若是为空,表示第 1 次添加,设置为 值为1,不然将原来的值加 1,再放进去Map中
  7. 更新会话
  8. 输出操做结果和信息

查看购物车的Servlet

  1. 从会话中获得购物车
  2. 若是为空则输出购物车为空
  3. 不然遍历购物车输出每一行
  4. 输出继续购物的连接

代码

显示商品列表页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>商品列表页面</title>
    <style>
        table {
    
    
            border-collapse: collapse;
        }

        td,th {
    
    
            text-align: center;
            padding: 3px;
        }
    </style>
</head>
<body>
<table border="1" width="300">
    <tr>
        <th>商品名称</th>
        <th>操做</th>
    </tr>

    <tr>
        <td>洗衣机</td>
        <td>
            <!--访问servlet中,add是servlet的访问地址-->
            <a href="add?name=洗衣机">添加到购物车</a>
        </td>
    </tr>

    <tr>
        <td>电视机</td>
        <td>
            <!--访问servlet中,add是servlet的访问地址-->
            <a href="add?name=电视机">添加到购物车</a>
        </td>
    </tr>

    <tr>
        <td>缝纫机</td>
        <td>
            <!--访问servlet中,add是servlet的访问地址-->
            <a href="add?name=缝纫机">添加到购物车</a>
        </td>
    </tr>

    <tr>
        <td>打火机</td>
        <td>
            <!--访问servlet中,add是servlet的访问地址-->
            <a href="add?name=打火机">添加到购物车</a>
        </td>
    </tr>
</table>
</body>
</html>

添加到购物车的Servlet

package com.itheima.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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

/**
 * 访问地址与html的连接地址相同
 */
@WebServlet("/add")
public class AddProductToServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        //1.得到会话对象
        HttpSession session = request.getSession();
        //2.从会话域中取出购物车对象(Map对象),购物车键是商品名,值是商品数量
        HashMap<String, Integer> cart = (HashMap<String, Integer>) session.getAttribute("cart");
        //3.判断购物车是否为空,若是为空建立一个购物车,表示第一次访问
        if (cart == null) {
   
   
            cart = new HashMap<>();
        }
        // 购物车对象是存在
        //4.获得商品的名字
        String name = request.getParameter("name");  //键:商品名
        //5.若是商品不存在,向购物车中添加1件商品,若是存在,从购物车中取出商品的数量,加1再放进去
        Integer num = cart.get(name);  //值:数量
        if (num == null) {
   
      //商品在购物车中不存在
            cart.put(name, 1);  //添加数量1到购物车中
        }
        else {
   
     //商品在购物车中存在
            cart.put(name, num + 1);  //加1放进去
        }
        //6. 更新会话域中购物车这个键
        session.setAttribute("cart", cart);
        //7.输出操做结果和连接
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("添加1件" + name + "商品成功<hr/>");
        out.print("<a href='productlist.html'>继续购物</a>");
        out.print("<a href='cart'>查看购物车</a>");
    }

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

查看购物车的Servlet

package com.itheima.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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

/**
 * 显示购物车
 * 与连接地址要相同
 */
@WebServlet("/cart")
public class CartServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //1.从会话中获取购物车
        HttpSession session = request.getSession();
        HashMap<String, Integer> cart = (HashMap<String, Integer>) session.getAttribute("cart");

        //2.若是购物车为空输出空
        if (cart == null) {
   
   
            out.print("购物车居然是空的");
        }
        //3.若是不为空,遍历Map集合输出购物车中每一项
        else {
   
   
            out.print("<table border=\"1\" width=\"300\">");
            out.print("<tr><th>商品名称</th><th>数量</th></tr>");
            //每一行是一个tr,就是购物车中一项
            cart.forEach((k,v) -> {
   
   
                out.print("<tr><td>"+ k +"</td><td>" +v + "</td></tr>");
            });
            out.print("</table>");
        }
        out.print("<a href='productlist.html'>继续购物</a>");
    }

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

小结

方法 说明
Map<String,Integer> cart = new HashMap<>(); 建立一个购物车,结构是Map结构
键是商品名,值商品数量
request.getSession() 获取会话对象,若是没有就是建立,若是有就获取
session.setAttribute() 向会话域中添加对象

案例:过滤全局汉字乱码

目标

编写过滤器,过滤全部Servlet中使用POST方法提交的汉字的编码。

分析

在这里插入图片描述

开发步骤

  1. 有2个Servlet,一个是LoginServlet登陆,一个是RegisterServlet注册
  2. 有2个JSP页面,1个是login.jsp,有表单,登陆名。1个register.jsp,有表单,有注册的名字。都使用POST提交用户名使用汉字提交。
  3. 使用过滤器,对全部的Servlet的POST方法进行过滤。
  4. 在没有使用过滤器以前,每一个Servlet必须加上汉字编码:request.setCharacterEncoding(字符集); 字符集与网页的编码要一致

代码

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆</title>
</head>
<body>
<form action="login" method="post">
    登陆名:<input type="text" name="user"><br>
    <input type="submit" value="登陆">
</form>
</body>
</html>

register.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
</head>
<body>
<h2>用户注册</h2>
<form action="register" method="post">
    注册名:<input type="text" name="name"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>

LoginServlet.java

package com.itheima.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("/login")
public class LoginServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取请求的数据
        String username = request.getParameter("user");
        //打印输出
        out.print("登陆成功:" + username);
    }

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

RegisterServlet.java

package com.itheima.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("/register")
public class RegisterServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获得请求提交的数据
        String name = request.getParameter("name");
        out.print("注册成功:" + name);
    }

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

CharacterEncodingFilter.java

package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/*
过滤全部的资源
 */
@WebFilter(filterName = "CharacterEncodingFilter", urlPatterns = "/*")
public class CharacterEncodingFilter implements Filter {
   
   
    public void destroy() {
   
   
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
   
   
        //0.将转成子接口才有这个方法
        HttpServletRequest request = (HttpServletRequest) req;
        //1.判断是不是POST方法,注:这里是大写
        if (request.getMethod().equals("POST")) {
   
   
            //2.若是是才进行编码
            request.setCharacterEncoding("utf-8");
        }
        //3.不管是不是POST方法都要放行
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
   
   

    }

}

小结

编写一个过滤器就能够对全部的Servlet进行汉字编码

  1. 汉字编码使用哪一个方法:setCharacterEncoding()
  2. 过滤的地址: /* 全部地址
  3. 放行使用哪一个方法:chain.doFilter(request, response)

案例:过滤敏感词汇

需求

当用户发帖的时候,若是发出敏感词汇就进行过滤,并提示发贴失败,不然显示正常的发贴内容。

案例效果

  1. 在表单中输入含有非法字符的言论,点击提交按钮

在这里插入图片描述

  1. 在浏览器上显示发贴失败

在这里插入图片描述

  1. 正常发贴的状况

在这里插入图片描述

案例分析

  1. 建立一个表单用于发表言论。
  2. 建立一个PostWordServlet,正常接收用户的输入信息,而且打印到浏览器
  3. 建立一个words.txt文件,其中存入非法字符。
  4. 建立一个Filter,只过滤PostWordServlet。
    1. 在init方法中将txt文件中的非法字符读取到List集合中。注:指定字符的编码为utf-8
    2. 在doFilter方法中,使用获取请求中的参数,判断请求的文字中是否包含非法字符。
    3. 若是言论中含有非法字符,就拦截,而且提示用户非法言论,退出过滤器
    4. 继续执行表示没有非法字符,就放行。

分析

在这里插入图片描述

实现步骤

  1. 建立一个表单,用于发表言论
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>发贴</title>
</head>
<body>
<form method="post" action="PostWordServlet">
    发贴:<input type="text" name="message"> <input type="submit" value="提交">
</form>
</body>
</html>
  1. 建立一个txt文件,存入非法字符。要注意,文件存储使用的字符集,不然可能出现乱码。
穷逼
笨蛋
白痴
王八
贱人
傻逼

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xLHsXleM-1592189481791)(C:\Users\Administrator\Desktop\study\zimg\1592189067781.png)]

  1. 建立一个servlet用于接受表单提交的内容
package com.itheima.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;

/**
 * 发贴显示的Servlet
 */
@WebServlet("/PostWordServlet")
public class PostWordServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取到帖子的内容
        String message = request.getParameter("message");
        //显示在页面上
        out.print("您的发贴内容以下:<hr/>" + message);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        this.doPost(request, response);
    }
}
  1. 建立一个过滤器,用来拦截请求,过滤请求中发表的言论的非法字符
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 只过滤发贴的Servlet
 */
@WebFilter(filterName = "IllegalWordFilter", urlPatterns = "/PostWordServlet")
public class IllegalWordFilter implements Filter {
   
   
    //建立一个集合,保存全部的词汇
    private List<String> illegalWords = new ArrayList<>();

    //在初始化的方法中读取全部的词汇,这个方法只会执行1次
    public void init(FilterConfig config) throws ServletException {
   
   
        //获得当前的类对象 -> 获得类加载器 -> 获取src目录下资源
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("words.txt");
        //将字节流使用utf-8转成字符流来使用,指定字符的编码
        try(BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"))) {
   
   
            String line = null;
            while((line = br.readLine())!=null) {
   
     //不为空就继续,每次读取一行
                illegalWords.add(line);  //将读取到的这一行添加到集合中
            }
        } catch (IOException e) {
   
   
            e.printStackTrace();
        }
        //在控制器上输出是否读取成功
        System.out.println(illegalWords);
    }

    public void destroy() {
   
   
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
   
   
        //设置汉字编码,否则会有乱码
        req.setCharacterEncoding("utf-8");
        //获取发贴的信息
        String message = req.getParameter("message");

        HttpServletResponse response = (HttpServletResponse) resp;

        //遍历全部词汇,发贴的内容中是否包含了这些词汇
        for (String illegalWord : illegalWords) {
   
   
            //包含了这些词汇就拦截
            if (message.contains(illegalWord)) {
   
   
                response.setContentType("text/html;charset=utf-8");
                PrintWriter out = response.getWriter();
                out.print("您的帖子中包含了非法的词汇,发贴失败");
                return;  //再也不继续
            }
        }
        //执行这句话才会放行
        chain.doFilter(req, resp);
    }

}

小结

过滤敏感词汇过滤器的开发步骤:

  1. 在init中从文件中加载全部的敏感词汇,复习缓存字符流
  2. 判断用户发贴是否包含这些词汇之一
  3. 若是有就拦截,没有就放行

案例:统计网站当前在线人数

执行效果

页面

在这里插入图片描述

服务器控制台信息

在这里插入图片描述

分析

每当一个用户访问项目的时候,都会建立一个session会话。因此当前session会话被建立,当前在线用户+1,每当session会话被销毁,当前在线用户-1。

HttpSessionListener能够用来监听session对象的建立和销毁的。因此能够在HttpSessionListener中的监听session对象建立和销毁的方法中控制在线人数的加减。

步骤

  1. 建立一个监听器 SessionCountListener

    a) 监听会话建立的方法

​ i. 在会话建立的监听方法中,从上下文域中取出当前计数值

​ ii. 若是为空,表示是第1个用户,设置值为1

​ iii. 不为空则加1,而且更新上下文域

​ b) 监听会话销毁的方法

​ i. 从上下文域中获得当前在线的人数

​ ii. 减1后更新

  1. 建立一个注销的LogoutServlet

    a) 让会话失效

    b) 打印输出:您已经安全退出网站

  2. 编写JSP

    a) 在JSP上取出上下文域中用户数显示

    b) 显示安全退出的连接

代码

监听器

package com.itheima.listener;

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 统计会话的监听器
 * 当前session会话被建立,当前在线用户+1,每当session会话被销毁,当前在线用户-1
 * 人数最后是要放在上下文域中才能给全部的用户使用
 * HttpSessionListener 接口用来监听会话的建立和销毁
 */
@WebListener
public class SessionCounterListener implements HttpSessionListener {
   
   
    //监听会话的建立
    @Override
    public void sessionCreated(HttpSessionEvent event) {
   
   
        //获取当前会话对象
        HttpSession session = event.getSession();
        //在服务器上输出信息
        System.out.println("建立会话:" + session.getId());
        //获得上下文域,能够经过会话对象获取上下文对象
        ServletContext application = session.getServletContext();
        //从上下文对象中取number的值
        Integer number = (Integer) application.getAttribute("number");
        //由于第1个用户是没有值的
        if (number == null) {
   
   
            //第1个用户向上下文域中添加1的值
            application.setAttribute("number", 1);
        } else {
   
   
            //有值就加1,再放回去。这里要写成++number,不能写成number++
            application.setAttribute("number", ++number);
        }
    }

    //监听会话的销毁
    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
   
   
        //向服务器输出信息
        HttpSession session = event.getSession();
        System.out.println("会话销毁:" + session.getId());
        //获得上下文域
        ServletContext application = session.getServletContext();
        //获得number的值
        Integer number = (Integer) application.getAttribute("number");
        //减1再放进去,要先减
        application.setAttribute("number", --number);
    }
}

考虑线程安全问题

package com.itheima.listener;

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 统计会话的监听器
 * 当前session会话被建立,当前在线用户+1,每当session会话被销毁,当前在线用户-1
 * 人数最后是要放在上下文域中才能给全部的用户使用
 * HttpSessionListener 接口用来监听会话的建立和销毁
 *
 * 使用原子类,必须是同一个对象,不管是加或减都是操做同一个对象才正确
 * 若是做用域中属性值是引用类型,咱们直接修改引用类型的值,不须要从新更新做用域
 */
@WebListener
public class SessionCounterListener implements HttpSessionListener {
   
   

    private AtomicInteger number = null;  //声明

    //监听会话的建立
    @Override
    public void sessionCreated(HttpSessionEvent event) {
   
   
        //获取当前会话对象
        HttpSession session = event.getSession();
        //在服务器上输出信息
        System.out.println("建立会话:" + session.getId());
        //获得上下文域,能够经过会话对象获取上下文对象
        ServletContext application = session.getServletContext();
        //从上下文对象中取number的值
        number = (AtomicInteger) application.getAttribute("number");
        //由于第1个用户是没有值的
        if (number == null) {
   
   
            number = new AtomicInteger(1);  //第1次赋值
            //第1个用户向上下文域中添加1的值
            application.setAttribute("number", number);
        } else {
   
   
            //把值取出来
            number = (AtomicInteger) application.getAttribute("number");
            //本身加1
            number.incrementAndGet();
            //更新这个值
            //application.setAttribute("number",number);
        }
    }

    //监听会话的销毁
    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
   
   
        //向服务器输出信息
        HttpSession session = event.getSession();
        System.out.println("会话销毁:" + session.getId());
        //获得上下文域
        ServletContext application = session.getServletContext();
        //获得number的值
        number = (AtomicInteger) application.getAttribute("number");
        //减1
        number.decrementAndGet();
        //减1再放进去,要先减
        //application.setAttribute("number", number);
    }
}

退出的Servlet

package com.itheima.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("/logout")
public class LogoutServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("您已经安全退出");
        //让会话过时
        request.getSession().invalidate();
    }

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

显示人数的JSP

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>显示在线人数</title>
  </head>
  <body>
  <%--人数放在上下文域中,给全部的用户能访问--%>
  <h2>当前网站在线人数是:${applicationScope.number}</h2>
  <hr/>
  <a href="logout">安全退出</a>
  </body>
</html>

案例:上传图片

目标

经过案例学习文件上传组件file-upload的使用

效果

  1. 上传页面

在这里插入图片描述

  1. 上传结果

流程

  1. 复制jar包

    在这里插入图片描述

  2. 按如下流程编写上传的代码便可

在这里插入图片描述

步骤

  1. 建立文件上传的页面
  2. 复制文件上传的jar包到WEB-INF/lib目录下
  3. 编写文件上传的Servlet
    1. 建立磁盘操做工具类工厂 DiskFileItemFactory
    2. 建立核心解析类 ServletFileUpload,传入上面的工厂对象作为参数
    3. 解析Request请求,返回List结合,即分割线的每一个部份内容
    4. 遍历List集合,若是是普通项,获得它的参数名和参数值。获取参数值要指定字符集,不然会有乱码。
    5. 若是是文件项则获得文件名和输入流
    6. 获取当前项目的绝对地址,经过绝对地址和获得的文件名,计算文件上传的真实地址。注:idea的bug,若是是空文件夹,服务器不会自动建立。
    7. 建立文件输出流
    8. 使用IOUtils工具类将输入流写到输出流中
    9. 关闭输入输出流
    10. 选作:使用img显示上传的图片

代码

页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>文件上传</title>
  </head>
  <body>
  <h2>文件上传</h2>
 <%--
 文件上传表单的三要素:
  1. 必须使用post方法(文件要在请求体中发送)
  2. 必须指定属性:enctype="multipart/form-data",若是没有指定这个属性,默认是application/x-www-form-urlencoded
  application/x-www-form-urlencoded:表单中全部的参数是键=值的方式发送
  multipart/form-data:将表单分红多个部分,每一个部分使用一串数字进行分隔,不能经过servlet的getParameter()等方法去获取参数值
  3. 要使用文件域 type="file",必须指定name属性

  action是要提交的servlet地址
  --%>
  <form enctype="multipart/form-data" action="upload" method="post">
      用户名:
      <input type="text" name="user"> <br/>
      文件:<br/>
      <input type="file" name="file1"> <br/>
      <input type="file" name="file2"> <hr/>
      <input type="submit" value="上传文件">
  </form>
  </body>
</html>

上传的Servlet

package com.itheima.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;

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.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;

@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {
   
   
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
   
        /*
        不能获得值
        String user = request.getParameter("user");
        System.out.println("用户名:" + user);
         */

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //1.建立硬盘文件的工厂类
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //2.建立一个文件上传的类,这是上传文件的核心类,须要上面的对象作为参数
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        //3.经过上面这个类的方法解析请求的数据,生成一个List集合,集合中每一个元素就是上传的一部分
        try {
   
   
            List<FileItem> fileItems = fileUpload.parseRequest(request);
            //4. FileItem表示上传的每一个部分
            for (FileItem fileItem : fileItems) {
   
   
                //5. 判断是不是普通的文本值,是就返回true,不是表示这个是上传的文件
                if (fileItem.isFormField()) {
   
     //普通文本框
                    //获得表单项的名字和值
                    String fieldName = fileItem.getFieldName();
                    String value = fileItem.getString("utf-8");
                    out.print("表单项名字:" + fieldName + ",表单项值:" + value + "<hr/>");
                }
                else {
   
     //表示上传的文件
                    String name = fileItem.getName();   //获得文件名
                    InputStream inputStream = fileItem.getInputStream();  //获得文件输入流
                    //写到服务器上,获得文件的输出流,文件上传到out目录下/upload
                    //获取upload真实地址,注:若是upload是一个空目录,idea不会在out目录下自动建立
                    String realPath = getServletContext().getRealPath("/upload");
                    //建立文件输出流:  c:/xxx/upload/file1.txt
                    FileOutputStream outputStream = new FileOutputStream(realPath + "/" + name);
                    //使用工具类复制
                    IOUtils.copy(inputStream, outputStream);
                    //关闭流
                    outputStream.close();
                    inputStream.close();
                    //打印上传成功
                    out.print("上传文件:" + name + "成功<hr/>");
                }
            }
        } catch (FileUploadException e) {
   
   
            e.printStackTrace();
        }
    }

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

tResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;

@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
不能获得值
String user = request.getParameter(“user”);
System.out.println(“用户名:” + user);
*/

    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();

    //1.建立硬盘文件的工厂类
    DiskFileItemFactory factory = new DiskFileItemFactory();
    //2.建立一个文件上传的类,这是上传文件的核心类,须要上面的对象作为参数
    ServletFileUpload fileUpload = new ServletFileUpload(factory);
    //3.经过上面这个类的方法解析请求的数据,生成一个List集合,集合中每一个元素就是上传的一部分
    try {
        List<FileItem> fileItems = fileUpload.parseRequest(request);
        //4. FileItem表示上传的每一个部分
        for (FileItem fileItem : fileItems) {
            //5. 判断是不是普通的文本值,是就返回true,不是表示这个是上传的文件
            if (fileItem.isFormField()) {  //普通文本框
                //获得表单项的名字和值
                String fieldName = fileItem.getFieldName();
                String value = fileItem.getString("utf-8");
                out.print("表单项名字:" + fieldName + ",表单项值:" + value + "<hr/>");
            }
            else {  //表示上传的文件
                String name = fileItem.getName();   //获得文件名
                InputStream inputStream = fileItem.getInputStream();  //获得文件输入流
                //写到服务器上,获得文件的输出流,文件上传到out目录下/upload
                //获取upload真实地址,注:若是upload是一个空目录,idea不会在out目录下自动建立
                String realPath = getServletContext().getRealPath("/upload");
                //建立文件输出流:  c:/xxx/upload/file1.txt
                FileOutputStream outputStream = new FileOutputStream(realPath + "/" + name);
                //使用工具类复制
                IOUtils.copy(inputStream, outputStream);
                //关闭流
                outputStream.close();
                inputStream.close();
                //打印上传成功
                out.print("上传文件:" + name + "成功<hr/>");
            }
        }
    } catch (FileUploadException e) {
        e.printStackTrace();
    }
}

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

}


下一篇: jQuery基础