自学之javaWeb

  • Post author:
  • Post category:java




JAVA Web



js



三个查询方法:

  • getElementsById()
  • getElementsByTagName()
  • getElementsByName()

注:document对象的三个查询方法,如果有id属性,优先使用getElementsById()方法来查询,如果没有id属性,则优先使用getElementsByName()方法来进行查询,如果id属性和name属性都没有最后再按标签名查getElementsByTagName()

以上三个方法,一定要在页面加载完成之后执行,才能查询到标签对象




属性

childNodes属性,获取当前节点的所有子节点。

firstChild属性,获取当前节点的第一个子节点。

lastChild属性,获取当前节点的最后一个子节点。

parentNode属性,获取当前节点的父节点。

nextSibling属性,获取当前节点的下一个节点。

previousSibling属性,获取当前节点的上一个节点。

className属性,用于获取或设置标签的class属性值。

innerHTML属性,表示获取/设置起始标签和结束标签中的内容。

innerText属性,表示获取/设置起始标签和结束标签中的文本。



jQuery



选择器



1.基础选择器

  • #id 选择器:根据id查找标签对象
  • .class 选择器:根据class查找标签对象
  • element 选择器:根据标签名查找标签对象
  • ‘*’ 选择器:表示任意的,所有元素
  • selector1,selector2 组合选择器:合并选择器1,选择器2的结果并返回
p.myClass

表示标签名必须是p标签,而且class类型还要是myClass

//选择id为one的元素"background-color","red"
$(function(){
   $("#btn1").click(function(){
       $("one").css("background-color","red");
   }) ;
                                   
});



2.层级选择器

  • ancerstora descendant 后代选择器:在给定祖先元素下匹配所有的后代元素
  • parent>child 子元素选择器:在给定父元素下匹配所有的子元素
  • prev+next 相邻元素选择器:匹配所有紧接在prev元素后的next元素
  • prev~siblings 之后的兄弟元素选择器:匹配prev元素之后的所有siblings元素



3.基本过滤选择器

  • :first 获取第一个元素
  • :last 获取最后一个元素
  • :not(selector) 去除所有给定选择器匹配的元素
  • :even 匹配所有索引值为偶数的元素,从0开始计数
  • :odd 匹配所有索引值为奇数的元素,从0开始计数
  • :eq(index) 匹配一个给定索引值的元素
  • :gt(index) 匹配所有大于给定索引值的元素
  • :It(index) 匹配所有小于于给定索引值的元素
  • :header 匹配如h1,h2,h3之类的标题元素
  • :animated 匹配所有正在执行动画效果的元素



4.内容过滤器

  • :contains(text) 匹配包含给定为本的元素
  • :empty 匹配所有不包含子元素或者文本的空元素
  • :parent 匹配含有子元素或者文本的元素
  • :has(selector) 匹配含有选择器所匹配的元素的元素



5.属性过滤器

  • [attribute] 匹配包含给定属性的元素
  • [attribute=value] 匹配给定的属性是某个特定值的元素
  • [attribute!=value] 匹配所有不含有指定的属性,或者属性不等于特定值的元素
  • [attribute^=value] 匹配给定的属性是以某些值开始的元素
  • [attribute$=value] 匹配给定的属性是以某些值结束的元素
  • [attribute*=value] 匹配给定的属性是以包含某些值的元素
  • [attrSel1] [attrSel2] [attrSelN] 复合属性选择器,需要同时满足多个条件时使用



6.表单过滤选择器

  • :input 匹配所有的input,textarea,select,button元素
  • :text 匹配所有的单行文本框
  • :password
  • :readio
  • :checkbox
  • :submit
  • :image
  • :reset
  • :button
  • :file 匹配所有文件域
  • :hidden 匹配所有不可见元素,或者type为hidden的元素


表单对象属性

  • :enabled 匹配所有可用元素
  • :disabled 匹配所有不可用元素
  • :checked 匹配所有选中的被选中元素(复选框,单选框等,不包括select中的option)
  • :selected 匹配所有的option元素



元素的筛选

  • eq() 获取给定索引的元素

  • first() 获取第一个元素

  • last() 获取最后一个元素

  • filter() 留下匹配的元素

  • is() 判断是否匹配给定的选择器,只要有一个匹配就返回true

  • has(exp) 返回包含有匹配选择器的元素的元素

  • not(exp) 删除匹配选择器的元素

  • children(exp) 返回匹配给定选择器的子元素

  • find(exp) 返回匹配给定选择器的后代元素

  • next() 返回当前元素的下一个兄弟元素

  • nextAll() 返回当前元素后面所有的兄弟元素

  • nextUntil() 返回当前元素到指定匹配的元素为止的后面元素

  • parent() 返回父元素

  • prev(exp) 返回当前元素的上一个兄弟元素

  • prevAll() 返回当前元素前面所有的兄弟元素

  • prevUntil(exp) 返回当前元素到指定匹配的元素为止的前面元素

  • siblings(exp) 返回所有兄弟元素



jQuery属性操作

  • html() 可以设置和获取起始标签和结束标签中的内容。跟dom属性innerHTML一样。
  • text() 可以设置和获取起始标签和结束标签中的文本。 跟dom属性innerText一样。
  • val() 可以设置和获取表单项的value属性值。 跟dom属性value一样。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="../script/jquery-3.5.1.min.js"></script>
    <script>
        $(function () {
            //不传参是获取,传参是设置

            // alert($("div").html());//获取
            // $("div").html("<h1>我是div中的标题1</h1>");//设置

            // alert($("div").text());
            // $("div").text("<h1>我是div中的标题1</h1>");//设置

            $("button").click(function () {
                alert($("#username").val());//获取
                $("#username").val("超级程序员");//设置
            });


        })

    </script>
</head>
<body>
<div>我是div标签 <span>我是div中的span</span></div>
<input type="text" name="username" id="username">
<button>操作输入框</button>
</body>
</html>


val()方法同时设置多个表单项的选中状态

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="../script/jquery-3.5.1.min.js"></script>
    <script>
        $(function () {
           /* //批量操作单选
            $(":radio").val(["radio1"])
            //批量操作复选框的选中状态
            $(":checkbox").val(["checkbox1","checkbox2"]);
            //批量操作多选的下拉框选中状态
            $("#multiple").val(["mul2","mul3"]);
            //批量操作单选的下拉框选中状态
            $("#single").val(["sin1"]);*/

            $(":radio,:checkbox,#multiple").val(["radio2","checkbox1","checkbox2","mul1","mul4"]);
        })

    </script>
</head>
<body>
单选:
<input name="radio" type="radio" value="radio1"/>radio1
<input name="radio" type="radio" value="radio2"/>radio2
<br/>
多选:
<input name="checkbox" type="checkbox" value="checkbox1"/>checkbox1
<input name="checkbox" type="checkbox" value="checkbox2"/>checkbox2
<input name="checkbox" type="checkbox" value="checkbox3"/>checkbox3
<br/>
下拉多选:
<select id="multiple" multiple="multiple" size="4">
    <option value="mul1">mul1</option>
    <option value="mul2">mul2</option>
    <option value="mul3">mul3</option>
    <option value="mul4">mul4</option>
</select>
<br/>
下拉单选:
<select id="single">
    <option value="sin1">sin1</option>
    <option value="sin2">sin2</option>
    <option value="sin3">sin3</option>
</select>

</body>
</html>
  • attr() 可以设置和获取属性的值,不推荐操作checked,readOnly,selected,disabled等等。

    ​ attr方法还可以操作非标准的属性。比如自定义属性:abc,bbj

  • prop() 可以设置和获取属性的值,只推荐操作checked,readOnly,selected,disabled等等。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script type="text/javascript" src="../script/jquery-3.5.1.min.js"></script>
  <script>
    $(function () {
     //attr
     //  alert($(":checkbox:first").attr("name"));//获取
     //  $(":checkbox:first").attr("name","abc");//设置
     // alert($(":checkbox").attr("checked"));//官方觉得返回undefined是一个错误
      alert($(":checkbox").prop("checked"));
      //设置都选中
      $(":checkbox").prop("checked",true);
      
      $(":checkbox:first").attr("abc","abcValue");
      alert($(":checkbox:first")).attr("abc");
    })

  </script>
</head>
<body>

<br/>
多选:
<input name="checkbox" type="checkbox" checked="checked" value="checkbox1"/>checkbox1
<input name="checkbox" type="checkbox" value="checkbox2"/>checkbox2
<input name="checkbox" type="checkbox" value="checkbox3"/>checkbox3


</body>
</html>


案例:全选/全不选

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>全选全不选</title>
  <script type="text/javascript" src="../script/jquery-3.5.1.min.js"></script>
  <script>
    $(function () {

      //给全选绑定单击事件
      $("#checkedAllBtn").click(function () {
        $(":checkbox").prop("checked",true);
      });

      //给全不选绑定单击事件
      $("#checkedNoBtn").click(function () {
        $(":checkbox").prop("checked",false);
      });

      //反选单击事件
      $("#checkedRevBtn").click(function () {
        //查询全部的球类的复选框
        $(":checkbox[name='items']").each(function () {
          //在each中遍历的function函数中,有一个this对象,这个this对象是当前正在遍历到的dom对象
          this.checked = !this.checked;
        });
        //要检查 是否满选
        //获取全部的球类个数
        var allCount = $(":checkbox[name='items']").length;
        //在获取选中的球类个数
        var checkedCount = $(":checkbox[name='items']:checked").length;

        // if(allCount == checkedCount){
        //   $("#checkedAllBox").prop("checked",true);
        // }else {
        //   $("#checkedAllBox").prop("checked",false);
        // }
        $("#checkedAllBox").prop("checked",allCount == checkedCount);
      });



      //提交 按钮单击事件
      $("#sendBtn").click(function () {
        $(":checkbox[name='items']:checked").each(function () {
          alert(this.value);
        });
      });

      //给全选/全不选 绑定单击事件
      $("#checkedAllBox").click(function () {
        //在时间的function函数中,有一个this对象,这个this对象是当前正在响应事件的dom对象

        $(":checkbox[name='items']").prop("checked",this.checked);
      });

      //给全部球类绑定单击事件
      $(":checkbox[name='items']").click(function () {
        //要检查 是否满选
        //获取全部的球类个数
        var allCount = $(":checkbox[name='items']").length;
        //在获取选中的球类个数
        var checkedCount = $(":checkbox[name='items']:checked").length;

        $("#checkedAllBox").prop("checked",allCount == checkedCount);
      })


    });

  </script>
</head>
<body>

<br/>
<form method="post" action="">
  你爱好的运动是?<input type="checkbox" id="checkedAllBox" />全选/全不选
  <br/>
  <input type="checkbox" name="items" value="足球" />足球
  <input type="checkbox" name="items" value="篮球" />篮球
  <input type="checkbox" name="items" value="羽毛球" />羽毛球
  <input type="checkbox" name="items" value="乒乓球" />乒乓球
  <br/>
  <input type="button" id="checkedAllBtn" value="全 选" />
  <input type="button" id="checkedNoBtn" value="全不选" />
  <input type="button" id="checkedRevBtn" value="反 选" />
  <input type="button" id="sendBtn" value="提 交" />
</form>


</body>
</html>



DOM的增删改


内部插入:

  • appendTo() a.appendTo(b) 把a插入到b子元素末尾,成为最后一个子元素。

  • prependTo() a.prependTo(b) 把a插到b所有子元素前面,成为第一个子元素


外部插入:

  • insertAfter() a.insertAfter(b) 得到ba

  • insertBefore() a.insertBefore(b) 得到ab


替换:

  • replaceWith() a.replaceWith(b) 用b替换掉a

  • replaceAll() a.replaceAll(b) 用a替换掉所有的b


删除:

  • remove() a.remove 删除a标签

  • empty() a.empty() 清空a标签里的内容



CSS样式的操作

  • addClass() 添加样式
  • removeClass() 删除样式
  • toggleClass() 有就删除,没有就添加样式
  • offset() 获取和设置元素的坐标



jQuery动画


基本动画:

  • show() 将隐藏的元素显示
  • hide() 将可见的元素隐藏
  • toggle() 可见就隐藏,不可见就显示

以上动画方法都可以添加参数:

​ 1.第一个参数是动画执行的时长,以毫秒为单位

​ 2.第二个参数是动画的回调函数(动画完成后自动调用的函数)


淡入淡出动画:

fadeln() 淡入(慢慢可见)

fadeOut() 淡出(慢慢消失)

fadeTo() 在指定时长内慢慢的将透明度修改到指定的值。0不可见,1完全可见,0.5半透明

fadeToggle() 切换淡入/淡出



jQuery事件操作


$(function(){});和window.οnlοad=function(){}的区别:

它们分别实在什么时候触发?

1.jQuery的页面加载完成之后是浏览器的内核解析完页面的标签创建好Dom对象之后就会马上执行。

2.原生的js页面加载完成之后,除了要等浏览器内核解析完标签创建好Dom对象,还要等标签显示时需要的内容加载完成。=

它们触发的顺序?

1.jQuery页面加载完成之后先执行

2.原生js的页面加载完成之后

它们执行的次数?

1.原生的js的页面加载完成之后,只会执行最后一次的赋值函数。

2.jQuery的页面加载完成之后是全部把注册的function函数,依次全部执行。



jQuery中其他事件的处理方法

  • click() 它可以绑定单击事件,以及触发单击事件
  • mouseover() 鼠标移入事件
  • mouseout() 鼠标移出事件
  • bind() 可以给元素一次性绑定一个或多个事件
  • one() 使用上跟bind一样。但是one方法绑定的事件只会响应一次。
  • unbind() 跟bind方法相反的操作,解除事件的绑定
  • live() 也是用来绑定事件。它可以用来绑定选择器匹配的所有元素的事件。哪怕这个元素是后面动态创建出来的也有效。



事件的冒泡

什么是事件的响应?

事件的冒泡是指,父子元素同时监听同一个事件。当触发子元素事件的时候,同一个事件也被传递到了父元素的事件里去响应。

如何阻止事件的冒泡?

在子元素事件函数体内,return false;可以阻止事件的冒泡传递



javaScript事件对象

事件对象,是封装有触发的时间信息的一个javaScript对象。

如何获取javascript事件对象呢?

在给元素绑定事件的时候,在事件的function(event)参数列表中添加一个参数,这个参数名,我们习惯取名为event。

这个event就是javascript传参事件处理函数的事件对象。

//1.原生javascript获取事件对象
window.onload = function () {
      document.getElementById("areaDiv").onclick = function (event){
        console.log(event);
      }
    }
//jQuery获取事件对象
$(function () {
      $("#areaDiv").click(function (event) {
        console.log(event);
      });
    });



XML

xml是可扩展的标记性语言


xml的主要作用:

1、用来保存数据,而且这些数据具有自我描述性

2、它可以作为项目或者模块的配置文件

3、还可以作为网络传输数据的格式(现在以JSON为主)。



语法



1.文档声明
<?xml version="1.0" encoding="UTF-8" ?>
<!--
<?xml version="1.0" encoding="UTF-8" ?>
以上内容就是xml文件的声明
version="1.0"  version表示xml的版本
encoding="UTF-8"   encoding表示xml文件本身的编码
-->

<books>  <!--books 表示多个图书信息-->
    <book sn="SN12341213412"><!--book 表示一个图书信息 sn属性表示图书序列号-->
        <name>时间简史</name><!--name 标签表示书名-->
        <author>霍金</author><!--author 表示作者-->
        <price>75</price><!--price 表示图书价格-->
    </book>
    <book sn="SN12341213411"><!--book 表示一个图书信息 sn属性表示图书序列号-->
        <name>java从入门到放弃</name><!--name 标签表示书名-->
        <author>沙老师</author><!--author 表示作者-->
        <price>9.9</price><!--price 表示图书价格-->
    </book>
</books>


2.xml注释
<!---->


3.元素(标签)

(1)什么是 XML 元素?


XML 元素

指的是从(且包括)开始标签直到(且包括)结束标签的部分。

元素可包含其他元素、文本或者两者的混合物。元素也可以拥有属性。

<bookstore>
<book category="CHILDREN">
  <title>Harry Potter</title> 
  <author>J K. Rowling</author> 
  <year>2005</year> 
  <price>29.99</price> 
</book>
<book category="WEB">
  <title>Learning XML</title> 
  <author>Erik T. Ray</author> 
  <year>2003</year> 
  <price>39.95</price> 
</book>
</bookstore> 

在上例中, 和 都拥有

元素内容

,因为它们包含了其他元素。 只有

文本内容

,因为它仅包含文本。

在上例中,只有 元素拥有

属性

(category=“CHILDREN”)。

(2)XML 元素必须遵循以下

命名规则:

  • 名称可以含字母、数字以及其他的字符
  • 名称不能以数字或者标点符号开始
  • 名称不能以字符 “xml”(或者 XML、Xml)开始
  • 名称不能包含空格

(3)xml中元素(标签)也分成单标签和双标签

单标签: 格式 <标签名 属性=“值”… />

双标签: 格式 <标签名 属性=“值” 属性=“值”… />文本数据或子标签</标签名>



4.属性

xml的标签属性和html的标签属性是非常类似的,属性可以提供元素的额外信息。

在标签上可以书写属性:一个标签上可以书写多个属性。每个属性的值必须用引号引起来。

其他语法规则:

  • 所有的xml元素都需要有关闭标签(也就是闭合)
  • xml对大小写敏感
  • xml必须正确的嵌套
  • xml必须有根元素 根元素就是顶级元素,没有父标签的元素叫顶级元素,而且必须是唯一一个才行
  • xml属性值必须加引号


5.文本区域

CDATA语法可以告诉xml解析器,我CDATA里的文本内容,只是纯文本,不需要xml语法解析。

CDATA格式:

<![CDATA[这里可以把你输入的字符原样显示,不会解析xml]]>



xml解析技术

xml可扩展的标记性语言。

不管是html文件还是xml文件他们都是标记型文档,都可以使用w3c组织制定的dom技术来解析。



dom4j解析技术

编程步骤:

1、先加载xml文件创建Document对象

2、通过Document对象拿到根元素对象

3、通过根元素.elements(标签名);可以返回一个集合,这个集合里放着所有你指定标签名的元素对象

4、找到你想要修改、删除的子元素,进行响应的操作

5、保存到硬盘上

package com.atguigu.pojo;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.util.List;

public class Dom4jTest {
    @Test
    public void test1() throws Exception {
     //创建一个SaxReader输入流,去读取xml配置文件,生成Document对象
        SAXReader saxReader = new SAXReader();

        Document document=saxReader.read("src/books.xml");

    }

    /**
     * 读取books.xml文件生成Book类
     */
    @Test
    public void test2() throws Exception {
        //1.读取books.xml文件
        SAXReader reader = new SAXReader();
        //在Junit测试中,相对路径是从模块名开始算
        Document document = reader.read("src/books.xml");
        //2.通过Document对象获取根元素
        Element rootElement = document.getRootElement();

        //3.通过根元素获取book标签对象
        //element()和elements()都是通过标签名查找子元素
        List<Element> books = rootElement.elements("book");


        //4.遍历,处理每个book标签转换为Book类
        for (Element book : books){
            //asXML()把标签对象转化为标签字符串
            Element nameElement = book.element("name");
            //getText()方法可以获取标签文本中的内容
            String nameText = nameElement.getText();

            //直接获取指定标签名中的内容
            String priceText = book.elementText("price");
            String authorText = book.elementText("author");
            //获取属性
            String snValue = book.attributeValue("sn");

            System.out.println(new Book(snValue,nameText,Double.parseDouble(priceText),authorText));
        }

    }
}



Tomcat



1.JaveWeb概念

a)什么是javaweb?

javaweb指,所有通过java语言编写可以通过浏览器访问的程序的总称。

b)什么是请求?

请求是指客户端给服务器发送数据,叫请求request。

c)什么是响应?

响应是指服务器给客户端回传数据,叫响应response。

d)请求和相应的关系

请求和响应是成对出现的,有请求就有响应。



2.Web资源分类

Web资源按实现的技术和呈现的效果的不同,又分为静态资源和动态资源两种。

静态资源:hml、css、js、txt、mp4视频,jpg图片

动态资源:jsp页面、Servlet程序



3.常用的Web服务器

Tomcat,Jboss,GlassFish,Resin,WebLogic



4.Tomcat服务器和Servlet版本的对应关系

Servlet程序从2.5版本是现在市面使用最多的版本(xml配置)到了Servlet3.0之后。就是注解版本的Servlet使用。



5.Tomcat的使用


a)安装


b)目录介绍

bin:专门来存放tomcat服务器可执行程序

conf:专门用来存放tomcat服务器的配置文件

lib:专门用来存放tomcat服务器的jar包

logs:专门用来存放tomcat服务器运行时输出的日记信息

temp:专门中来tomcat运行时产生的临时数据

webapps:专门用来存放部署的Web工程

work’:是Tomcat工作时的目录,用来存放Tomcat运行时jsp翻译为Servlet的源码,和Session钝化的目录。


c)如何启动Tomcat服务器

找到Tomcat目录下的bin目录下的startup.bat文件,双击,就可以启动Tomcat服务器。

如何测试是否启动成功?

打开浏览器,在浏览器中输入:http://localhost:8080

另一种启动Tomcat的方式:

1.打开命令行 2.cd到你的Tomcat的bin目录下 3.敲入启动命令:catalina run


d)Tomcat的停止

1.点击tomcat服务器窗口的x关闭按钮

2.把tomcat服务器窗口置为当前窗口,然后按快捷键Ctrl+C

3.找到tomcat的bin目录下的shutdown.bat双击,就可以停止tomcat服务器


e)如何修改tomcat的端口号

Mysql默认的端口号是:3306

Tomcat默认的端口号是:8080

找到Tomcat目录下的conf目录,找到server.xml配置文件。找到Connector标签,修改port属性为你需要的端口号。端口号的范围是1~65535。修改完端口号一定要重启Tomcat服务器才能生效


f)如何部署web工程到Tomcat中

第一种方法:只需要把web工程的目录拷贝到Tomcat的webapps目录下即可。

如何访问Tomcat下的wenb工程?

只需要在浏览器中输入访问地址格式如下:http://ip:port/工程名/目录下/文件名

第二种部署方法:

找到Tomcat下的conf目录\Catalina\localhost\下,创建如下的配置文件:

<!--
Context表示一个工程上下文
path表示工程访问路径:/abc
docBase表示你的工程目录在哪里
-->
<Context path= "/abc" docBase="C:\book">


g)手托html页面到浏览器和在浏览器中输入http://ip:端口号/工程名/访问的区别

手托html页面到浏览器:

使用的是file://协议

file协议表示告诉浏览器直接读取file:协议后面的路径,解析在浏览器上即可。

如果是在浏览器地址栏中输入访问地址格式如下:http://ip:port工程名/资源名

所使用的是http协议,背后的原因完全不同

1.请求发给服务器 2.服务器收到请求后,读取你要访问的资源文件,然后回传给客户端要的页面的内容 3.得到index.html页面内容,解析展示在浏览器上


h)ROOT的工程的访问,以及默认index.html页面的访问

当我们在浏览器地址栏中输入访问地址如下:

http://ip:port 没有工程名的时候,默认访问的是ROOT工程。

当我们在浏览器地址栏中输入访问地址如下:

http://ip:port /工程名/ 没有资源名,默认访问index.html页面



6.IDEA整合Tomcat



7.IDEA中动态web工程的操作

a)IDEA中如何创建动态web工程

b)web工程目录的介绍

src:用来存放自己编写的java源代码

web:专门用来存放web工程的资源文件。比如:html页面 css文件 js文件等等

WEB-INF:是一个受服务器保护的目录,浏览器无法直接访问到此目录的内容

web.xml:是整个动态web工程的配置部署描述文件,可以在这里配置很多web工程的组件,比如:Servlet程序,Filter过滤器,Listerer监听器,Session超时…等等

lib:用来存放第三方的jar包(IDEA还需要自己配置导入)

c)给Tomcat添加第三方jar包

d)如何在IDEA中部署工程到Tomcat上运行

1.建议修改web工程对应的Tomcat运行实例名称:

2.确认你的Tomcat实例中有你要部署运行的Web工程模块

3.还可以修改tomcat实例启动后默认的访问地址:



Servlet技术

a)什么是servlet

1.servlet是javaEE规范之一。规范就是接口

2.servlet就是JavaWeb三大组件之一。三大组件分别是:servlet程序、Filter过滤器、Listener监听器。

3.servlet是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。

b)手动实现Servlet程序

1.编写一个类去实现servlet接口

2.实现service方法,处理请求,并响应数据

3.到web.xml中去配置servlet程序的访问地址

c)url地址到Servlet程序的访问

d)Servlet生命周期

1.执行Servlet构造器方法

2.执行init初始化方法

第一、二步,是在第一次访问,的时候创建Servlet程序会调用。

3.执行service方法

第三步每次访问都会调用。

4.执行destroy销毁方法

第四步,在web工程停止的时候调用。

e)GET和POST请求的分发处理

f)通过继承HttpServlet实现Servlet程序

一般在实际项目开发中,都是使用继承HttpServlet类的方式去实现Servlet程序。

1.编写一个类去继承HttpServlet类

2.根据业务需要重写doGet或doPost方法

3.到web.xml中的配置Servlet程序的访问地址

package com.atguigu.servlet;

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

public class HelloServlet2 extends HttpServlet {

    /**
     * doGet() 在get请求的时候调用
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2 的doGet方法");
    }

    /**
     * doPost()在post请求的时候调用
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2 的doPost方法");
    }
}

xml中的配置:

        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>HelloServlet2</servlet-name>
        <servlet-class>com.atguigu.servlet.HelloServlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet2</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>

g)使用IDEA创建Servlet程序

h)Servlet类的继承体系

Interface Servlet:Servlet接口,只是负责定义Servlet程序的访问规范。

Class GenericServlet:GenericServlet类实现了Servlet接口,做了很多空实现。并持有一个ServletConfig类的引用。并对ServletConfig的使用做一些方法。

Class HttpServlet:HttpServlet抽取类实现了service()方法,并实现了请求的分发处理

自定义的Servlet程序:我们只需要根据自己的业务需要去重写doGet或doPost方法即可。



ServletConfig类

ServletConfig类从类名上来看,就知道是Servlet程序的配置信息类。

Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。

Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象。

a)ServletConfig类的三大作用:

1.可以获取Servlet程序的别名servlet-name的值

2.可以获取初始化参数init-param

3.获取ServletContext对象



ServletContext类

a)什么是ServletContext?

1.ServletContext是一个接口,表示Servlet上下文对象

2.一个web工程,只有一个ServletContext对象实例

3.ServletContext对象是一个域对象

4.ServletContext是在Web工程部署启动的时候创建。在web工程停止的时候销毁。

域对象:是可以像Map一样存取数据的对象。这里的域指的是存取数据的操作范围,整个web工程。

​ 存数据 取数据 删除数据

Map put() get() remove()

域对象 setAttribute() getAttribute() removeAttribute()

b)ServletContext类的四个作用

1、web.xml中配置的上下文参数 context-param

2、获取当前的工程路径,格式:/工程路径

3、获取工程部署后在服务器硬盘上的绝对路径

4、像Map一样存取数据



Http协议

a)什么是http协议

什么是协议?

协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。

所谓http协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫HTTP协议。HTTP协议中的数据叫报文。

b)请求的HTTP协议格式

客户端给服务器发送数据叫请求。

服务器给客户端回传数据叫响应。

请求又分为GET请求和POST请求两种

i.GET请求

1.请求行

1)请求的方式 GET

2)请求的资源路径{+?+请求参数}

3)请求的协议的版本号 HTTP/1.1

Accept:告诉服务器,客户端可以接收的数据类型

Accept-Language:告诉服务器客户端可以接收的语言类型

​ zh_CN 中文中国

​ en_US 英文美国

User-Agent:就是浏览器的信息

Accept-Encoding:告诉服务器,客户端可以接收的数据编码(压缩)格式

Host:表示请求的服务器ip和端口号

Connection:告诉服务器请求连接如何处理

​ Keep-Alive 告诉服务器回传数据不要马上关闭,保持一小段时间的连接。

​ Closed 马上关闭

2.请求头

​ key:value 组成 不同的键值对表示不同的含义。

ii.POST请求

1、请求行

1)请求的方式 POST

2)请求的资源路径{+?+请求参数}

3)请求的协议的版本号 HTTP/1.1

2、请求头

1)key:value 不同的请求头,有不同的含义

​ 空行

3、请求体——>就是发送给服务器的数据

Accept:告诉服务器,客户端可以接收的数据类型

Accept-Language:告诉服务器客户端可以接收的语言类型

Referer:表示请求发起时,浏览器地址中的地址(从哪来)

User-Agent:表示浏览器的信息

Content-Type:表示发送的数据的类型

​ application/x-www-form-urlencoded

​ 表示提交的数据格式是:name=value&name=value,然后对其进行url编码

​ url编码是把非英文内容转换为:%xx%xx

​ multipart/form-data

​ 表示以多段的形式提交数据给服务器(以流的形式提交,用于上传)

Content-Length:表示发送的数据的长度

Cache-Control:表示如何控制缓存 no-cache不缓存

iii)常用请求头的说明

Accept:告诉服务器,客户端可以接收的数据类型

Accept-Language:告诉服务器客户端可以接收的语言类型

User-Agent:表示客户端浏览器的信息

Host:表示请求时的服务器ip和端口号

iv)哪些是GET请求,哪些是POST请求

GET请求有哪些:

​ 1、form标签 method=get

​ 2、a标签

​ 3、link标签引入css

​ 4、Script标签引入js文件

​ 5.img标签引入图片

​ 6、iframe引入html页面

​ 7、在浏览器地址栏中输入地址后敲回车

POST请求有哪些:

​ 8、form标签 method=post

c)响应的HTTP协议格式

1、响应行

​ 1)key:value 不同的响应头,有其不同含义

​ 空行

2、响应头

3、响应体‘

响应行:

​ 1、响应的协议 HTTP/1.1

​ 2、响应的状态码 200

​ 3、响应状态描述符 OK

响应头:

​ Server:表示服务器的信息

​ Content-Type:表示响应体的数据类型

​ Content-Length:响应体的长度

​ Date:请求响应的时间(这是格林时间)

d)常见的响应码说明

200:表示请求成功

302:表示请求重定向

404:表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)

500:表示服务器已经收到请求,但是服务器内部错误(代码错误)

e)MIME类型说明

MIME是HTTP协议中数据类型。MIME类型的格式是”大类型/小类型”,并与某一种文件的扩展名相对应。

常见的MIME类型:

超文本标记语言文本 .html,.html text/html

普通文本 .txt text/plain

RTF文本 .rtf application/rtf

GIF图形 .gif image/gif

JPEG图形 .jpeg,.jpg image/jpeg

au声音文件 .au audio/basic

MIDI音乐文件 mid,.midi audio/midi,audio/x-midi

RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio

MPEG文件 .mpg,.mpeg video/mpeg

AVI文件 .avi video/x-msvideo

GZIP文件 .gz application/x-gzip

TAR文件 .tar application/x-tar



HttpServletRequest类

a)HttpServletRequest类有什么作用

每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的Http协议信息解析好封装到Request对象中。然后传递到

service方法(doGet和doPost)中给我们使用。我们可以通过HttpServletRequset对象,获取到所有请求的信息。

b)HttpServletRequest类的常用方法

getRequestURI() 获取请求的资源路径

getRequestURL() 获取请求的统一资源定位符(绝对路径)

getRemoteHost() 获取客户端的ip地址

getHeader() 获取请求头

getParameter() 获取请求的参数

getParameterValues() 获取请求的参数(多个值的时候使用)

getMethod() 获取请求的方式GET或POST

setAttribute(key,value) 设置域对象

getAttribute(key) 获取域对象

getRequestDispatcher() 获取请求转发对象

c)如何获取请求参数

package com.atguigu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

public class ParameterServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String [] hobby = req.getParameterValues("hobby");

        System.out.println("用户名:"+username);
        System.out.println("密码:"+password);
        System.out.println("兴趣爱好:"+ Arrays.asList(hobby));


    }
}

d)解决post乱码问题

//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
req.setCharacterEncoding("UTF-8");

e)请求的转发

什么是请求的转发?

请求的转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求的转发。

请求转发的特点:

1、浏览器地址没有变化

2、他们是一次请求

3、他们共享Request域中的数据

4、可以转发到WEB-INF目录下

5、不可以访问工程以外的资源

f)base 标签

base标签设置页面相对路径工作时参照的地址 herf 属性就是参数的地址值

g)Web中的相对路径和绝对路径

相对路径是:

. 表示当前目录

… 表示上一级目录

资源名 表示当前目录/资源名

绝对路径:

​ http://ip:port/工程路径/资源路径

h)web中 / 斜杠的不同意义

/ 斜杠 如果被浏览器解析,得到的地址是:http://ip:port/

斜杠

/斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径

1./servlet1

2.serveltContext.getRealPath(“/”);

3.request.getRequestDispatcher(“/”);

特殊情况:reponse.sendRediect(“/”); 把斜杠发送给浏览器解析。得到http://ip:port/

2.HttpServletResponse类

a)HttpServletResponse类的作用



HttpServletResponse类

a)HttpServletResponse类的作用

HttpServletResponse类和HttpServletRequest类一样。每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息。

​ 我们如果需要设置返回客户端的信息,都可以通过HttpServletResponse对象来进行设置。

b)两个输出流的说明。

字节流 getOutputStream(); 常用于下载(传递二进制数据)

字符流 getWriter(); 常用于回传字符串(常用)

两个流同时只能使用一个。

使用了字节流,就不能再使用字符流,反之亦然。

c)如何往客户端回传数据

要求:往客户端回传字符串数据

package com.atguigu.servlet;

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

public class ResponseIOServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //要求:往客户端回传 字符串 数据。
        PrintWriter writer = resp.getWriter();
        writer.write("response's content!!!");
    }
}

d)响应的乱码解决

package com.atguigu.servlet;

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

public class ResponseIOServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //要求:往客户端回传 字符串 数据。
        //设置服务器字符集为UTF-8
        resp.setCharacterEncoding("UTF-8");
        //通过响应头,设置浏览器也使用UTF-8字符集
        //resp.setHeader("Content-Type","text/html;charset=UTF-8");

        //它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头
        resp.setContentType("text/html;char-set=UTF-8");
        System.out.println(resp.getCharacterEncoding());

        PrintWriter writer = resp.getWriter();
        writer.write("我们一起去吃饭");
    }

e)请求重定向

请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向。(因为之前的地址可能已经被废弃)。

请求重定向的特点:

1、浏览器地址栏会发生变化

2、两次请求

3、不共享Request域中的数据

4、不能访问WEB-INF下的资源

5、可以访问工程外的资源

请求重定向第一种方案:

//设置响应状态码302,表示重定向,(已搬迁)
resp.setStatus(302);
//设置响应头,说明新的地址在哪里
resp.setHeader("Location","http://localhost:8080/07_servlet/response2");

请求重定向第二种方案(推荐):

resp.sendRedirect("http://localhost:8080");



jsp



jsp定义

jsp的全称是java server pages。java的服务器页面。

jsp的主要作用是代替Servlet程序回传html页面的数据

因为Servlet程序回传html页面的数据是一件非常繁琐的事情。开发成本和维护成本都极高

jsp访问

jsp页面和html页面一样,都是存放在web目录下。访问也跟访问html页面一样。

比如:

在web目录下有如下的文件:

web目录:

a.html页面 访问地址是:=====>http://ip:port/工程路径/a.html

b.jsp页面 访问地址是:=====>http://ip:port/工程路径/b.jsp



jsp的本质

jsp页面本质上是一个Servlet程序。

当我们第一次访问jsp页面的时候。Tomcat服务器会帮我们把jsp页面翻译成为一个java源文件。并且对它进行编译成为.class字节码程序。我们打开java源文件不难发现里面的内容是:

跟踪代码发现,HttpJspBase类。它直接地继承了HttpServlet类。也就是说,jsp翻译出来的java类,它间接继承了HttpServlet类。也就是说,翻译出来的是一个Servlet程序。

总结:通过翻译的java源代码我们就可以得到结果:jsp就是Servlet程序。

也可以去观察翻译出来的Servlet程序的源代码,不难发现。其底层实现,也是通过输出流。把html页面数据回传给客户端。



jsp的三种语法



a)jsp头部的page指令

jsp的page指令可以修改jsp页面中一些重要的属性,或者行为。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

i. language属性 表示jsp翻译后是什么语言文件,暂时只支持java。

ii.contentType属性 表示jsp返回的数据类型是什么。也是源码中response.setContentType()参数值

iii.pageEncoding属性 表示jsp页面文件本身的字符集。

iv.import属性 跟java源代码一样。用于导包导类。














两个属性是给out输出流使用













=========

v.autoFlush属性 设置当out输出流缓冲区满了之后,是否自动刷新缓冲区。默认值是true

vi.buffer属性 设置out输出流缓冲区的大小。默认是8kb。














两个属性是给out输出流使用













=========

vii.errorPage属性 设置当jsp页面运行时出错,自动跳转去的错误页面路径。

viii.isErrorPage属性 设置访问当前jsp页面,是否会创建HttpSession对象。默认是true。

x.extends属性 设置jsp翻译出来的java类默认继承谁。



b)jsp中的常用脚本

i)声明脚本(极少使用)

声明的脚本格式是:<%! 声明java代码 %>

作用:可以给jsp翻译出来的java类定义属性和方法甚至是静态代码块。内部类等。

<%--声明类属性--%>
<%!
    private Integer id;
    private String name;
    private static Map<String,String> map;
%>

ii)表达式脚本(常用)

表达式脚本格式是:<%=表达式%>

表达式脚本的作用是:在jsp页面上输出数据

<%=12%> <br>
<%=12.12%> <br>
<%="我是字符串"%>

表达式脚本的特点:

1.所有的表达式脚本都会被翻译到_jspService()方法中

2.表达式脚本都会被翻译成为out.print()输出到页面上

3.由于表达式脚本翻译的内容都在 _jspService()方法中,所以 _jspService()方法中的对象都可以直接使用

4.表达式脚本中的表达式不能以分号结束

iii)代码脚本

代码脚本的给是是:

<%

java语句

%>

代码脚本的作用是:可以在jsp页面中,编写我们自己需要的功能(写的是java语句)。

代码脚本的特点是:

1、代码脚本翻译之后都在_jspService()方法中

2、代码脚本由于翻译到_jspService()方法中,所以在_ _jspService()方法中的现有对象都可以直接使用。

3、还可以由多个代码脚本块组合完成一个完整的java语句

4、代码脚本还可以和表达式脚本一起组合使用,在jsp页面上输出数据

<%--练习:--%>
<%--if语句--%>
<%
    int i = 12;
    if (i==12){
        System.out.println("我们一起吃饭");
    }else {
        System.out.println("我们一起学习");
    }
%>
<%--for循环语句--%>
<%
    for (int j = 0; j < 10; j++) {
        System.out.println(j);
    }
%>
<%--翻译后java文件中_jspService()方法内的代码都可以写--%>
<%
    String username = request.getParameter("username");
    System.out.println("用户名请求的参数值是:"+username);
%>

<%--组合使用--%>
<table border="1" cellspacing="0">
    <%
        for (int j = 0; j < 10; j++) {
      %>
    <tr>
        <td>第<%=j+1%>行</td>
    </tr>
    <%
        }
    %>



c)jsp中的三种注释

i.html注释

html注释会被翻译到java源代码中。在_jspService()方法里,以out.writer输出到客户端。

ii.java注释

//单行java注释

/* 多行java注释 * /

java注释会被翻译到java源代码中。

iii.jsp注释

<%–这里jsp注释–%>

jsp注释可以注掉,jsp页面中所有代码。



jsp中九大内置对象

jsp中的内置对象,是指Tomcat在翻译jsp页面成为Servlet源代码后,内部提供的九大对象,叫内置对象。

request 请求对象

response 响应对象

pageContext jsp的上下文对象

session 会话对象

application ServletContext对象

config ServletConfig对象

out jsp输出流对象

page 指向当前jsp的对象

exception 异常对象



jsp四大域对象

四个域对象:

pageContext (PageContextimpl类) 当前jsp页面范围内有效

request (HttpServletRequest类) 一次请求内有效

session (HttpSession类) 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器)

application (ServletContext类) 整个web工程范围内都有效(只要web工程不停止,数据都在)

域对象是可以像Map一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存取范围。

虽然四个域对象都可以存储数据。在使用上它们是有优先顺序的。

四个域对象在使用的使用,优先顺序分别是,它们从小到大的范围的顺序。

pageContext==>request==>session==>application



jsp中out输出和response.getWriter输出的区别

response中表示响应,我们经常用于设置返回给客户端的内容(输出)

out也是给用户做输出使用的

当jsp页面中所有代码完成后会做以下两个操作:

1、执行out.flush()操作,会把out缓冲区中的数据追加写入到response缓冲区末尾

2、会执行response的刷新操作,把全部数据写给客户端。

由于jsp翻译之后,底层源代码都是使用out来进行输出,所以一般情况下。我们在jsp页面中同意使用out来进行输出。避免打乱页面输出内容的顺序。

out.write() 输出字符串没有问题

out.print() 输出任意数据都没有问题(都转换成为字符串后调用的write输出)

深入源码,浅出结论:在jsp页面中,可以统一使用out.print()来进行输出。



jsp的常用标签

a)jsp静态包含

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
   头部信息 <br>
   主题内容 <br>
<%--
<%@include file=""%>就是静态包含
flie属性指定你要包含的jsp页面的路径

地址中第一个斜杠  /  表示为http://ip:port/工程路径/   映射到代码的web目录

静态包含的特点:
     1、静态包含不会翻译被包含的jsp页面
     2、静态包含其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出

--%>
   <%@include file="/footer.jsp"%>


</body>
</html>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
     脚页信息 <br>
</body>
</html>

b)jsp动态包含

<%--
<jsp:include page=""></jsp:include>
这是动态包含
page属性是指定你要包含的jsp页面的路径
动态包含也可以像静态包含一样,把被包含的内容执行输出到包含位置

动态包含的特点:
1、动态包含会把包含的jsp页面也翻译成为java代码
2、动态包含底层代码使用如下代码去调用被包含的jsp页面执行输出 JsRuntimeLibrary.inclue(request,response,"/include/footer.jsp",out,false);
3、动态包含,还可以传递参数
--%>

<jsp:include page="/footer.jsp">
    <jsp:param name="uesername" value="bbj"/>
    <jsp:param name="password" value="root"/>
</jsp:include>

**静态包含的本质:**它的本质是文件的导入(不会对导入的文件进行编译),它不管是什么文件,.jsp,.txt,.json,.html,还是各种各样的文件后缀都行。只要是文本文件就行,因为它的本质是文件的导入。

查看tomcat 中jsp用了静态包含的jsp servlet,jsp最终都会被编译成servlet class文件。反编译查看,被包含的界面原封不动的导入到被包含的jsp中。所以静态包含就是普通的文件导入。

**动态包含的本质:**它的本质是先编译包含的文件,然后再进行导入,而且文件只能是.jsp后缀,因为是jsp标签的动态包含,tomcat只识别jsp后缀的文件,其实再往底层分析,一个jsp就是一个servlet,动态包含,其实包含的是一个servlet,而可以传参是,传参给包含的servlet,所以动态包含相当于http请求调用了一次servlet,而这个包含的servlet就会接受参数,并且解析自己的页面数据,最后response.write发送回被包含的jsp里面,jsp会整合包含的servlet发送回的数据,然后再统一返回给前端。

c)jsp标签-转发

<%--
<jsp:forward page=""></jsp:forward>是请求转发标签,它的功能就是请求转发
              page  属性设置请求转发的路径
--%>
<jsp:forward page="/scope2.jsp"></jsp:forward>



Listener监听器

1、Listener监听器它是JavaWeb的三大组件之一。JavaWeb的三大组件分别是:Servlet程序、Filter过滤器、Listener监听器

2、Listener它是JavaEE的规范,就是接口

3、监听器的作用是,监听某种事务的变化。然后通过回调函数,反馈给客户(程序)去做一些响应的处理



ServletContextListener监听器

ServletContextListener它可以监听ServletContext对象的创建和销毁

ServletContext对象在web工程启动的时候创建,在web工程停止的时候销毁。

两个方法分别是:

//在ServletContext对象创建之后马上调用,做初始化
public void contextInitialized(ServletContextEventsce)
//在ServletContext对象销毁之后调用   
public void contextDestroyed(ServletContextEventsce)


如何使用ServletContextListener监听器监听ServletContext对象。

public class MyServletContextListenerImpl implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象被创建了");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象被销毁了");
    }
}
<!--配置监听器-->
    <listener>
        <listener-class>com.atguigu.listener.MyServletContextListenerImpl</listener-class>
    </listener>

使用步骤如下:

1、编写一个类去实现ServletContextListener

2、实现其两个回调方法

3、到web.xml中去配置监听器



EL表达式



a)什么是EL表达式?

EL表达式的全称是:Expression Language

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("key","值");
%>
表达式脚本输出key的值是:<%=request.getAttribute("key")%> <br/>
EL表达式key的值是:${key}
</body>
</html>

EL表达式的格式是:${表达式}

EL表达式在输出null值的时候,输出的是空串。jsp表达式脚本输出null值的时候,输出的是null字符串。



b)EL表达式搜索域数据的顺序

EL表达式主要在jsp页面中输出数据。

主要是输出域对象中的数据。

当四个域中都有相同的key的数据的时候,EL表达式会按照四个域从小到大的顺序去进行搜索,找到就输出。



c)EL表达式输出Bean的普通属性,数组属性。List集合属性,map集合属性。

<%@ page import="com.atguigu.pojo.Person" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.ArrayList" %><%--
  Created by IntelliJ IDEA.
  User: 1
  Date: 2021/10/16
  Time: 21:21
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    Person person = new Person();
    person.setName("国哥好帅!");
    person.setPhones(new String[]{"18610541354","18688886666","18699998888"});

    List<String> cities = new ArrayList<String>();
    cities.add("北京");
    cities.add("上海");
    cities.add("深圳");
    person.setCities(cities);

    Map<String,Object>map = new HashMap<>();
    map.put("key1","value1");
    map.put("key2","value2");
    map.put("key3","value3");
    person.setMap(map);

    pageContext.setAttribute("p", person);
%>

输出Person:${ p }<br/>
输出Person的name属性:${p.name} <br>
输出Person的pnones数组属性值:${p.phones[2]} <br>
输出Person的cities集合中的元素值:${p.cities} <br>
输出Person的List集合中个别元素值:${p.cities[2]} <br>
输出Person的Map集合: ${p.map} <br>
输出Person的Map集合中某个key的值: ${p.map.key3} <br>



</body>
</html>



d)EL表达式——运算

1)关系运算

2)逻辑运算

3)算数运算

    ${ 12 == 12 } 或 ${ 12 eq 12 } <br>
    ${ 12 != 12 } 或 ${ 12 ne 12 } <br>
    ${ 12 < 12 } 或 ${ 12 lt 12 } <br>
    ${ 12 > 12 } 或 ${ 12 gt 12 } <br>
    ${ 12 <= 12 } 或 ${ 12 le 12 } <br>
    ${ 12 >= 12 } 或 ${ 12 ge 12 } <br>
    <hr>
    ${ 12 == 12 && 12 > 11 } 或 ${ 12 == 12 and 12 > 11 } <br>
    ${ 12 == 12 || 12 > 11 } 或 ${ 12 == 12 or 12 > 11 } <br>
    ${ ! true } 或 ${ not true } <br>
    <hr>
    ${ 12 + 12 } <br>
    ${ 12 - 12 } <br>
    ${ 12 * 12 } <br>
    ${ 18 / 12 } 或 ${ 18 div 12 }<br>
    ${ 18 % 12 } 或 ${ 18 mod 12 } <br>

i.empty运算

empty运算可以判断一个数据是否为空,如果为空,则输出true,不为空输出false。

以下几种情况为空:

1、值为null值的时候

2、值为空串的时候

3、值是Object类型数组

4、list集合,元素个数为零

5、map集合,元素个数为零

<body>
<%
//    1、值为null值的时候
  request.setAttribute("emptyNull",null);
//    2、值为空串的时候
   request.setAttribute("emptyStr","");
//    3、值是Object类型数组
   request.setAttribute("emptyArr",new Object[]{});
//    4、list集合,元素个数为零
    List<String> list = new ArrayList<>();
    request.setAttribute("emptyList",list);
//    5、map集合,元素个数为零
    Map<String,Object> map = new HashMap<String,Object>();
    map.put("key1","value1");
    request.setAttribute("emptyMap",map);
%>
${empty emptyNull} <br/>
${empty emptyStr} <br/>
${empty emptyArr} <br/>
${empty emptyList} <br/>
${empty emptyMap} <br/>
</body>

ii.三元运算

表达式 1?表达式 2:表达式 3

如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。

${ 12==12 ? "去吃饭":"不吃饭"}

iii. “.”点运算和[]中括号运算符

.点运算,可以输出 Bean 对象中某个属性的值。

[]中括号运算,可以输出有序集合中某个元素的值。

并且[]中括号运算,还可以输出 map 集合中 key 里含有特殊字符的 key 的值。

<body>
<%
    Map<String,Object> map = new HashMap<String,Object>();
    map.put("a.a.a","aaaValue");
    map.put("b+b+b","bbbValue");
    map.put("c-c-c","cccValue");

    request.setAttribute("map",map);
%>

${ map['a.a.a'] } <br>
${ map["b+b+b"] } <br>
${ map['c-c-c'] } <br>
${ map["c-c-c"] } <br>
</body>



e)EL表达式的11个隐含对象

i.EL获取四个特定域中的属性

pageScope ===== pageContext域

requestScope ===== Request域

sessionScope ===== Session域

applicationScope ===== ServletContext域

ii. pageContext 对象的使用

<body>
    <%--
    request.getScheme() 它可以获取请求的协议
    request.getServerName() 获取请求的服务器ip或域名
    request.getServerPort() 获取请求的服务器端口号
    getContextPath() 获取当前工程路径
    request.getMethod() 获取请求的方式(GET或POST)
    request.getRemoteHost()  获取客户端的ip 地址
    session.getId() 获取会话的唯一标识
    --%>
    <%
        pageContext.setAttribute("req", request);
    %>
    <%=request.getScheme() %> <br>
    1.协议: ${ req.scheme }<br>
    2.服务器ip:${ pageContext.request.serverName }<br>
    3.服务器端口:${ pageContext.request.serverPort }<br>
    4.获取工程路径:${ pageContext.request.contextPath }<br>
    5.获取请求方法:${ pageContext.request.method }<br>
    6.获取客户端ip地址:${ pageContext.request.remoteHost }<br>
    7.获取会话的id编号:${ pageContext.session.id }<br>

</body>

iii)EL表达式其他隐含对象的使用

param Map<String,String> 它可以获取请求参数的值

paramValues Map<String,String[]> 它也可以获取请求参数的值,获取多个值的时候使用。

输出请求参数username的值:${ param.username } <br>
输出请求参数password的值:${ param.password } <br>
输出请求参数username的值:${ paramValues.username[0] } <br>
输出请求参数hobby的值:${ paramValues.hobby[0] } <br>
输出请求参数hobby的值:${ paramValues.hobby[1] } <br>

请求地址:

http://localhost:8080/09_EL_JSTL/other_el_obj.jsp?username=wzg168&password=666666&hobby=java&hobby=cpp

header Map<String,String> 它可以获取请求头的信息

headerValues Map<String,String[]> 它可以获取请求头的信息,它可以获取多个值的情况

    输出请求头【User-Agent】的值:${ header['User-Agent'] } <br>
    输出请求头【Connection】的值:${ header.Connection } <br>
    输出请求头【User-Agent】的值:${ headerValues['User-Agent'][0] } <br>

cookie Map<String,Cookie> 它可以获取当前请求的 Cookie 信息

    获取Cookie的名称:${ cookie.JSESSIONID.name } <br>
    获取Cookie的值:${ cookie.JSESSIONID.value } <br>

initParam Map<String,String> 它可以获取在 web.xml 中配置的上下文参数

    输出&lt;Context-param&gt;username的值:${ initParam.username } <br>
    输出&lt;Context-param&gt;url的值:${ initParam.url } <br>



JSTL标签库

JSTL 标签库 全称是指 JSP Standard Tag Library JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标

签库。

EL 表达式主要是为了替换 jsp 中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个 jsp 页面

变得更佳简洁。

JSTL由五个不同功能的标签库组成

在jsp标签库中使用taglib指令引入标签库

CORE 标签库 <%@ taglib prefix=

“c”

uri=

“http://java.sun.com/jsp/jstl/core”

%>

XML 标签库 <%@ taglib prefix=

“x”

uri=

“http://java.sun.com/jsp/jstl/xml”

%>

FMT 标签库 <%@ taglib prefix=

“fmt”

uri=

“http://java.sun.com/jsp/jstl/fmt”

%>

SQL 标签库 <%@ taglib prefix=

“sql”

uri=

“http://java.sun.com/jsp/jstl/sql”

%>

FUNCTIONS 标签库 <%@ taglib prefix=

“fn”

uri=

“http://java.sun.com/jsp/jstl/functions”

%>

SQL 标签库



f)JSTL标签库的使用步骤

1、先导入 jstl 标签库的 jar 包。

taglibs-standard-impl-1.2.1.jar

taglibs-standard-spec-1.2.1.jar

2、第二步,使用 taglib 指令引入标签库。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>



g)core核心库的使用

<body>
    <%--
    i.<c:set />
        作用:set标签可以往域中保存数据

        域对象.setAttribute(key,value);
        scope 属性设置保存到哪个域
            page表示PageContext域(默认值)
            request表示Request域
            session表示Session域
            application表示ServletContext域
        var属性设置key是多少
        value属性设置值
    --%>
    保存之前:${ sessionScope.abc } <br>
    <c:set scope="session" var="abc" value="abcValue"/>
    保存之后:${ sessionScope.abc } <br>
    <hr>

    <%--
       ii.<c:if />
         if标签用来做if判断。
         test属性表示判断的条件(使用EL表达式输出)
    --%>
    <c:if test="${ 12 == 12 }">
        <h1>12等于12</h1>
    </c:if>
    <c:if test="${ 12 != 12 }">
        <h1>12不等于12</h1>
    </c:if>
    <hr>

    <%--
    iii.<c:choose> <c:when> <c:otherwise>标签
    作用:多路判断。跟switch ... case .... default非常接近

    choose标签开始选择判断
    when标签表示每一种判断情况
        test属性表示当前这种判断情况的值
    otherwise标签表示剩下的情况

    <c:choose> <c:when> <c:otherwise>标签使用时需要注意的点:
        1、标签里不能使用html注释,要使用jsp注释
        2、when标签的父标签一定要是choose标签
    --%>
    <%
        request.setAttribute("height", 180);
    %>
    <c:choose>
        <%-- 这是html注释 --%>
        <c:when test="${ requestScope.height > 190 }">
            <h2>小巨人</h2>
        </c:when>
         <c:when test="${ requestScope.height > 180 }">
            <h2>很高</h2>
        </c:when>
        <c:when test="${ requestScope.height > 170 }">
            <h2>还可以</h2>
        </c:when>
        <c:otherwise>
            <c:choose>
                <c:when test="${requestScope.height > 160}">
                    <h3>大于160</h3>
                </c:when>
                <c:when test="${requestScope.height > 150}">
                    <h3>大于150</h3>
                </c:when>
                <c:when test="${requestScope.height > 140}">
                    <h3>大于140</h3>
                </c:when>
                <c:otherwise>
                    其他小于140
                </c:otherwise>
            </c:choose>
        </c:otherwise>
    </c:choose>


</body>

forEach遍历1到10

<body>
<%--
1.遍历1到10,输出
        begin属性设置开始的索引
        end 属性设置结束的索引
        var 属性表示循环的变量(也是当前正在遍历到的数据)
--%>
<table>
<c:forEach begin="1" end="10" var="i">
    <tr>
        <td>第${i}行</td>
    </tr>
</c:forEach>
</table>
</body>

遍历Map集合

<%-- 2.遍历Object数组
        for (Object item: arr)
        items 表示遍历的数据源(遍历的集合)
        var 表示当前遍历到的数据
--%>
<%
    request.setAttribute("arr",new String[]{"11111111","22222222","33333333"});
%>
<c:forEach items="${requestScope.arr}" var="item">
    ${item} <br>
</c:forEach>
<hr>
<%
    Map<String,Object> map = new HashMap<>();
    map.put("key1","value1");
    map.put("key2","value2");
    map.put("key3","value3");
    request.setAttribute("map",map);
%>
<c:forEach items="${ requestScope.map }" var="entry">
    <h1>${entry.key}=${entry.value}</h1>
</c:forEach>

遍历List集合

 <%--4.遍历List集合---list中存放 Student类,有属性:编号,用户名,密码,年龄,电话信息--%>
    <%
        List<Student> studentList = new ArrayList<Student>();
        for (int i = 1; i <= 10; i++) {
            studentList.add(new Student(i,"username"+i ,"pass"+i,18+i,"phone"+i));
        }
        request.setAttribute("stus", studentList);
    %>
    <form action="" enctype=""></form>
    <table>
        <tr>
            <th>编号</th>
            <th>用户名</th>
            <th>密码</th>
            <th>年龄</th>
            <th>电话</th>
            <th>操作</th>
        </tr>
        <%--
            items 表示遍历的集合
            var 表示遍历到的数据
            begin表示遍历的开始索引值
            end 表示结束的索引值
            step 属性表示遍历的步长值
            varStatus 属性表示当前遍历到的数据的状态
            for(int i = 1; i < 10; i+=2)
        --%>
    <c:forEach begin="2" end="7" step="2" varStatus="status" items="${requestScope.stus}" var="stu">
        <tr>
            <td>${stu.id}</td>
            <td>${stu.username}</td>
            <td>${stu.password}</td>
            <td>${stu.age}</td>
            <td>${stu.phone}</td>
            <td>${status.step}</td>
        </tr>
    </c:forEach>
    </table>



文件的上传和下载

文件的上传和下载,是非常常见的功能。很多的系统中,或者软件中都经常使用文件的上传和下载。

比如:QQ 头像,就使用了上传。

邮箱中也有附件的上传和下载功能。

OA 系统中审批有附件材料的上传。



1、文件的上传介绍(重点)

1、要有一个 form 标签,method=post 请求

2、form 标签的 encType 属性值必须为 multipart/form-data 值

3、在 form 标签中使用 input type=file 添加上传的文件

4、编写服务器代码(Servlet 程序)接收,处理上传的数据。

encType=multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼

接,然后以二进制流的形式发送给服务器.



2、commons-fileupload.jar常用API介绍说明


commons-fileupload.jar


需要依赖


commons-io.jar


这个包,所以两个包我们都要引入。


第一步,就是需要导入两个


jar


包:

commons-fileupload-1.2.1.jar

commons-io-1.4.jar


commons-fileupload.jar





commons-io.jar


包中,我们常用的类有哪些?

ServletFileUpload 类,用于解析上传的数据。

FileItem 类,表示每一个表单项。

boolean ServletFileUpload.

isMultipartContent

(HttpServletRequest request); 判断当前上传的数据格式是否是多段的格式。

public List parseRequest(HttpServletRequest request) 解析上传的数据

boolean FileItem.isFormField() 判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。 true 表示普通类型的表单项 false 表示上传的文件类型

String FileItem.getFieldName() 获取表单项的 name 属性值

String FileItem.getString() 获取当前表单项的值。

String FileItem.getName(); 获取上传的文件名

void FileItem.write( file ); 将上传的文件写到 参数 file 所指向抽硬盘位置 。



3、文件下载

public class Download extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //1.获取要下载的文件名
        String downloadFileName = "a.jpg";
    //2.读取要下载的内容
        ServletContext servletContext = getServletContext();
        //获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        System.out.println("下载的文件类型"+mimeType);
     //4.再回传前,通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);
     //5.还要告诉客户端收到的数据是用于下载使用 (还是使用响应头)
        //Content-Disposition响应头,表示收到的数据怎么处理
        //attament表示附件,表示下载使用
        //filename表示指定下载的文件名
        resp.setHeader("Content-Disposition","attament;filename"+downloadFileName);

        /**
         * /斜杠被服务器解析表示地址为http://ip:port/工程名/ 映射 到代码的web目录
         */
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
       //获取响应的输出流
        OutputStream outputStream = resp.getOutputStream();
      //3.把下载的文件内容回传给客户端
        //读取输入流中全部由的数据,复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream,outputStream);



    }
}

解决谷歌和IE浏览器乱码问题

如果客户端浏览器是 IE 浏览器 或者 是谷歌浏览器。我们需要使用 URLEncoder 类先对中文名进行 UTF-8 的编码

操作。因为 IE 浏览器和谷歌浏览器收到含有编码后的字符串后会以 UTF-8 字符集进行解码显示。

resp.setHeader("Content-Disposition","attament;filename"+ URLEncoder.encode("中国.jpg","UTF-8"));

火狐浏览器 Base64编解码操作

public class Base64Test {
    public static void main(String[] args) throws Exception {
        String content = "这是需要Base64编码的内容";
        //创建一个Base64编码器
        BASE64Encoder base64Encoder = new BASE64Encoder();
        //执行Base64编码操作
        String encodedString = base64Encoder.encode(content.getBytes("UTF-8"));
        System.out.println(encodedString);

        //创建Base64解码器
        BASE64Decoder base64Decoder = new BASE64Decoder();
        //解码操作
        byte [] bytes = base64Decoder.decodeBuffer(encodedString);
        String str = new String(bytes,"UTF-8");

        System.out.println(str);
    }
}

如果客户端浏览器是火狐浏览器。 那么我们需要对中文名进行 BASE64 的编码操作。

这时候需要把请求头 Content-Disposition: attachment; filename=中文名

编码成为:Content-Disposition: attachment; filename==?charset?B?xxxxx?=

=?charset?B?xxxxx?= 现在我们对这段内容进行一下说明。

=? 表示编码内容的开始

charset 表示字符集

B 表示BASE64编码

xxxx 表示文件名BASE64编码后的内容

?= 表示编码内容的结束

resp.setHeader("Content-Disposition","attament;filename==?UTF-8?B?"+new BASE64Encoder("中国.jpg".getBytes("UTF-8")) +"?=");
String ua = request.getHeader("User-Agent");
// 判断是否是火狐浏览器 
if (ua.contains("Firefox")) { 
 // 使用下面的格式进行 BASE64 编码后
 String str = "attachment; 
 fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?=";
 // 设置到响应头中
     response.setHeader("Content-Disposition", str); } 
else { 
    // 把中文名进行 UTF-8 编码操作。 
    String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8"); 
    // 然后把编码后的字符串设置到响应头中
    response.setHeader("Content-Disposition", str);
}



Cookie



a)什么是Cookie?

1、Cookie 是服务器通知客户端保存键值对的一种技术。

2、客户端有了 Cookie 后,每次请求都发送给服务器。

3、每个 Cookie 的大小不能超过 4kb

b)如何创建Cookie

public class CookieServlet extends BaseServlet{

    protected void creatCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     //1、创建Cookie对象
        Cookie cookie = new Cookie("key1","value1");
     //2、通知客户端保存Cookie
     resp.addCookie(cookie);

     resp.getWriter().write("Cookie创建成功");
    }
}



c)服务器如何获得Cookie

服务器获取客户端的 Cookie 只需要一行代码:req.getCookies():Cookie[]



d)Cookie值的修改

方案一:

1、先创建一个要修改的同名(指的就是 key)的 Cookie 对象

2、在构造器,同时赋于新的 Cookie 值。

3、调用 response.addCookie( Cookie );

方案二:

1、先查找到需要修改的 Cookie 对象

2、调用 setValue()方法赋于新的 Cookie 值。

3、调用 response.addCookie()通知客户端保存修改



e)浏览器查看Cookie



f)Cookie生命控制

Cookie 的生命控制指的是如何管理 Cookie 什么时候被销毁(删除)

setMaxAge()

正数,表示在指定的秒数后过期

负数,表示浏览器一关,Cookie 就会被删除(默认值是-1)

零,表示马上删除 Cookie

    protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("defaultLife","defaultLife");
        cookie.setMaxAge(-1);//设置存活时间
        resp.addCookie(cookie);
    }
    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //先找到要删除的Cookie对象
        Cookie cookie = CookieUtils.findCookie("key4",req.getCookies());
        if(cookie!=null){
            //调用setMaxAge(0)
            cookie.setMaxAge(0);//表示马上删除,都不需要等待浏览器关闭
            //调用response.addCookie(cookie)
            resp.addCookie(cookie);
            resp.getWriter().write("key4的Cookie已经被删除");
        }

    }


    protected void life3600(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("life3600","life3600");
        cookie.setMaxAge(60*60);//设置Cookie一小时后被删除,无效
        resp.addCookie(cookie);
        resp.getWriter().write("已经创建了一个存活一小时的Cookie");
        }



g)Cookie有效路径Path的设置

Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。

path 属性是通过请求的地址来进行有效的过滤。

CookieA path=/工程路径

CookieB path=/工程路径/abc

请求地址如下:

http://ip:port/工程路径/a.html

CookieA 发送

CookieB 不发送

http://ip:port/工程路径/abc/a.html

CookieA 发送

CookieB 发送

    protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("path1","path1");
        //getContextPath()  得到工程路径
        cookie.setPath(req.getContextPath()+"/abc"); // ==>/工程路径/abc
        resp.addCookie(cookie);
        resp.getWriter().write("创建了一个带有Path路径的Cookie");

    }



h)Cookie练习–免用户名登录

package com.atguigu.servlet;

import com.atguigu.util.CookieUtils;

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

public class CookieServlet extends BaseServlet{


    protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("path1","path1");
        //getContextPath()  得到工程路径
        cookie.setPath(req.getContextPath()+"/abc"); // ==>/工程路径/abc
        resp.addCookie(cookie);
        resp.getWriter().write("创建了一个带有Path路径的Cookie");

    }

    protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies){
            //getName方法返回Cookie的key(名)
            //getValue返回Cookie的value值
            resp.getWriter().write("Cookie["+ cookie.getName()+ "=" + cookie.getValue() +"] <br/>");
        }
        Cookie iWantCookie = CookieUtils.findCookie("key1",cookies);
        //如果不等于null,说明赋过值,也就是找到了需要改的Cookie
        if (iWantCookie!=null){
            resp.getWriter().write("找到了需要的Cookie");
        }

    }

    protected void creatCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     //1、创建Cookie对象
        Cookie cookie = new Cookie("key1","value1");
        Cookie cookie2 = new Cookie("key2","value2");
        Cookie cookie3 = new Cookie("key3","value3");
        Cookie cookie4 = new Cookie("key4","value4");
        Cookie cookie5 = new Cookie("key5","value5");
     //2、通知客户端保存Cookie
        resp.addCookie(cookie);
        resp.addCookie(cookie2);
        resp.addCookie(cookie3);
        resp.addCookie(cookie4);
        resp.addCookie(cookie5);

     resp.getWriter().write("Cookie创建成功");
    }

    protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //方案一:
        //1、先创建一个要修改的同名(指的就是 key)的 Cookie 对象
        //2、在构造器,同时赋于新的 Cookie 值。
        //Cookie cookie = new Cookie("key1","newValue");
        //3、调用 response.addCookie( Cookie );
        //resp.addCookie(cookie);

//        方案二:
//        1、先查找到需要修改的 Cookie 对象
        Cookie cookie = CookieUtils.findCookie("key1",req.getCookies());
        if (cookie!=null){
//        2、调用 setValue()方法赋于新的 Cookie 值。
            cookie.setValue("newValue2");
//        3、调用 response.addCookie()通知客户端保存修改
            resp.addCookie(cookie);
        }


        resp.getWriter().write("key1的Cookie已经修改好");
    }

    protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("defaultLife","defaultLife");
        cookie.setMaxAge(-1);//设置存活时间
        resp.addCookie(cookie);
    }
    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //先找到要删除的Cookie对象
        Cookie cookie = CookieUtils.findCookie("key4",req.getCookies());
        if(cookie!=null){
            //调用setMaxAge(0)
            cookie.setMaxAge(0);//表示马上删除,都不需要等待浏览器关闭
            //调用response.addCookie(cookie)
            resp.addCookie(cookie);
            resp.getWriter().write("key4的Cookie已经被删除");
        }

    }


    protected void life3600(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("life3600","life3600");
        cookie.setMaxAge(60*60);//设置Cookie一小时后被删除,无效
        resp.addCookie(cookie);
        resp.getWriter().write("已经创建了一个存活一小时的Cookie");
        }

    }



Session会话



i)什么是Session会话?

1、Session 就一个接口(HttpSession)。

2、Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术。

3、每个客户端都有自己的一个 Session 会话。

4、Session 会话中,我们经常用来保存用户登录之后的信息。



j)如何创建Session和获取(id号,是否为新)

如何创建和获取 Session。它们的 API 是一样的。

request.getSession()

第一次调用是:创建 Session 会话

之后调用都是:获取前面创建好的 Session 会话对象。

isNew(); 判断到底是不是刚创建出来的(新的)

true 表示刚创建

false 表示获取之前创建

每个会话都有一个身份证号。也就是 ID 值。而且这个 ID 是唯一的。

getId() 得到 Session 的会话 id 值。

public class SessionServlet extends BaseServlet{

    protected void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建和获取Session对象
        HttpSession session = req.getSession();
        //判断当前session会话是否是新创建出来的
        boolean isNew = session.isNew();
        //获取session会话的唯一标识id
        String id = session.getId();
        resp.getWriter().write("得到的session,它的id是:"+id+"<br/>");
        resp.getWriter().write("这个Session是否是新创建的"+isNew+"<br/>");
    }



k)Session域数据的存取

/**
     * 往Session域中保存数据
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getSession().setAttribute("key1","value1");
        resp.getWriter().write("已经往Session中保存了数据");
    }

    /**
     * 获取session域中的数据
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object attribute = req.getSession().getAttribute("key1");
        resp.getWriter().write("从Session中获取出key1的数据是:"+attribute);
    }



l)Session生命周期控制

public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位),超过指定的时长,Session

就会被销毁。

值为正数的时候,设定 Session 的超时时长。

负数表示永不超时(极少使用)

public int getMaxInactiveInterval()获取 Session 的超时时间

public void invalidate() 让当前 Session 会话马上超时无效。

Session 默认的超时时长是多少?

Session 默认的超时时间长为 30 分钟。

因为在 Tomcat 服务器的配置文件 web.xml中默认有以下的配置,它就表示配置了当前 Tomcat 服务器下所有的 Session

超时配置默认时长为:30 分钟。

30

如果说。你希望你的 web 工程,默认的 Session 的超时时长为其他时长。你可以在你自己的 web.xml 配置文件中做

以上相同的配置。就可以修改你的 web 工程所有 Seession 的默认超时时长。

<!--表示当前 web 工程。创建出来 的所有 Session 默认是 20 分钟 超时时长-->
<session-config> 
    <session-timeout>20</session-timeout> 
</session-config>

如果你想只修改个别 Session 的超时时长。就可以使用上面的 API。setMaxInactiveInterval(int interval)来进行单独的设

置。

session.setMaxInactiveInterval(int interval)单独设置超时时长。

    protected void life3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取Session对象
        HttpSession session = req.getSession();
        //设置当前Session 3秒后超时
        session.setMaxInactiveInterval(3);
        resp.getWriter().write("当前Session已设置为3秒后超时");
    }

session的超时指的是,客户端两次请求的最大间隔时长。

Session 马上被超时示例:



m)浏览器和Session之间关联的技术内幕

Session 技术,底层其实是基于 Cookie 技术来实现的。

1.服务器每次创建Session会话的时候,都会创建一个Cookie对象。这个Cookie对象的key永远是:JSESSIONID,值是新创建出来的Session的id值。

2.通过响应把新创建出来的Session的id值返回给客户端。

3.浏览器解析收到数据,就马上创建一个Cookie对象。

4.后面有了Cookie之后,每次请求,都会把Session的id以Cookie的形式发送给服务器。

5.通过Cookie中的id值找到自己之前创建好的Session对象并返回



Filter过滤器



1.什么是Filter过滤器

1、Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器

2、Filter 过滤器它是 JavaEE 的规范。也就是接口

3、Filter 过滤器它的作用是:拦截请求,过滤响应。

拦截请求常见的应用场景有:

1、权限检查

2、日记操作

3、事务管理

……等等



2.Filter初体验

要求:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必

须是用户登录之后才允许访问。

思考:根据之前我们学过内容。我们知道,用户登录之后都会把用户登录的信息保存到 Session 域中。所以要检查用户是否

登录,可以判断 Session 中否包含有用户登录的信息即可!!!

<body>
    <%
        Object user = session.getAttribute("user");
        //如果等于null,说明还没有登录
        if (user==null){
            request.getRequestDispatcher("/login.jsp").forward(request,response);
            return;
        }
    %>
     我是a.jsp文件
</body>

filter过滤器:来检查用户是否有登录,也就是检查权限,有权限,让程序默认执行,无权限,让它跳转到登录页面或不允许其访问。

@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        HttpSession session = httpServletRequest.getSession();
        Object user = session.getAttribute("user");
        //如果等于null,说明还没有登录
        if (user==null){
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return;
        }else {
            //让程序继续向下访问用户的目标资源
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
<!--filter标签用于配置一个Filter过滤器-->
    <filter>
        <!--给filter起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置filter的全类名-->
        <filter-class>com.atguigu.filter.AdminFilter</filter-class>
    </filter>
<!-- filter-mapping配置filter过滤器的拦截路径-->
    <filter-mapping>
<!--filter-name表示当前的拦截路径给哪个filter使用-->
     <filter-name>AdminFilter</filter-name>
<!--url-pattern配置拦截路径
      /  表示请求地址为:http://ip:port/工程路径/   映射到IDEA 的web 目录
      /admin/* 表示请求地址为http://ip:port/工程路径/admin/*
-->
    <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

Filter 过滤器的使用步骤:

1、编写一个类去实现 Filter 接口

2、实现过滤方法 doFilter()

3、到 web.xml 中去配置 Filter 的拦截路径



完整的登录和权限检查

login.jsp 页面 == 登录表单

<body>
这是登录页面。login.jsp页面 <br>
<form action="http://localhost:8080/15_filter_war_exploded/loginServlet" method="get">
    用户名:<input type="text" name="username"/> <br>
    密码:<input type="password" name="password"/> <br>
    <input type="submit"/>
</form>
</body>

LoginServlet 程序

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if ("wzg168".equals(username)&&"123456".equals(password)){
            req.getSession().setAttribute("user",username);
            resp.getWriter().write("登陆成功!!!");
        }else {
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }
    }
}



3.Filter的生命周期

Filter 的生命周期包含几个方法

1、构造器方法

2、init 初始化方法

第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)

3、doFilter 过滤方法

第 3 步,每次拦截到请求,就会执行

4、destroy 销毁

第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)

public class AdminFilter implements Filter {

    public AdminFilter(){
        System.out.println("1.Filter构造器方法AdminFilter()");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2.Filter的init(FilterConfig filterConfig)的初始化");
    }

    /**
     * doFilter方法,专门用于拦截请求。可以做权限检查
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("3.Filter的doFilter()过滤方法");
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        HttpSession session = httpServletRequest.getSession();
        Object user = session.getAttribute("user");
        //如果等于null,说明还没有登录
        if (user==null){
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return;
        }else {
            //让程序继续向下访问用户的目标资源
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {

        System.out.println("4、Filter的destory()销毁方法");
    }
}



4.FilterConfig类

FilterConfig类见名知义,它是Filter过滤器的配置文件类。

Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。

FilterConfig 类的作用是获取 filter 过滤器的配置内容

1、获取 Filter 的名称 filter-name 的内容

2、获取在 Filter 中配置的 init-param 初始化参数

3、获取 ServletContext 对象

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2.Filter的init(FilterConfig filterConfig)的初始化");
//        1、获取 Filter 的名称 filter-name 的内容
        System.out.println("filter-name的值是:"+filterConfig.getFilterName());
//        2、获取在 web.xml 中配置的 init-param 初始化参数
        System.out.println("初始化参数username的值是:"+filterConfig.getInitParameter("username"));
        System.out.println("初始化参数url的值是:"+filterConfig.getInitParameter("url"));
//        3、获取 ServletContext 对象
        System.out.println(filterConfig.getServletContext());
    }



5.FilterChain过滤器链

Filter 过滤器

Chain 链,链条

FilterChain 就是过滤器链(多个过滤器如何一起工作)

FilterChain.doFilter()方法的作用:

​ 1、执行下一个Filter过滤器(如果有Filter)

​ 2、执行目标资源(没有Filter)

在多个Filter过滤器执行的时候,它们执行的优先顺序是由它们在web.xml中从上到下的顺序决定。

多个Filter过滤器执行的特点:

1、所有的filter和目标资源默认都执行在同一个线程中。

2、多个filter共同执行的时候,它们都使用同一个Request对象。



6、Filter的拦截路径



–精确匹配

<

url-pattern

>/target.jsp</

url-pattern

>

以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp



–目录匹配

<

url-pattern

>/admin/*</

url-pattern

>

以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/*



–后缀名匹配

<

url-pattern

>*.html</

url-pattern

>

以上配置的路径,表示请求地址必须以.html 结尾才会拦截到

<

url-pattern

>*.do</

url-pattern

>

以上配置的路径,表示请求地址必须以.do 结尾才会拦截到

<

url-pattern

>*.action</

url-pattern

>

以上配置的路径,表示请求地址必须以.action 结尾才会拦截到

Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在!!!



JSON



在JavaScript中的使用

json是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式,而且很多语言都提供了对json的支持。这样就使得json成为理想的数据交换格式。

json是一种轻量级的数据交换格式。轻量级指的是和xml作比较。

数据交换指的是客户端和服务器之间业务数据的传递格式。



1.定义

json是由键值对组成,并且有花括号(大括号)包围。每个键由引号引起来,键和值之间使用冒号进行分隔,多组键值对之间进行逗号进行分割。

//json定义
    var jsonObj = {
        "key1":12,
        "key2":"abc",
        "key3":true,
        "key4":[11,"arr",false],
        "key5":{
            "key5_1":551,
            "key5_2":"key_2_value"
        },
        "key6":[{
            "key6_1_1":6611,
            "key6_1_2":"key6_1_2value"
        },{
            "key6_2_1":6621,
            "key6_2_2":"key6_2_2value"
        }]
    }



2.访问

json本身是一个对象。

json中的key我们可以理解为是对象中的一个属性。

json中的key访问就跟访问对象的属性一样:json对象.key

//访问
    alert(jsonObj.key4);
    //json中数组值的遍历
    for (var i = 0; i < jsonObj.key4.length; i++) {
        alert(jsonObj.key4[i]);
    }
    alert(jsonObj.key5.key5_1);//551
    alert(jsonObj.key6);//得到json数组
    
    var jsonItem = jsonObj.key6[0];
    alert(jsonItem.key6_1_1);



3.json的两个常用方法

json的存在有两种形式。

一种是:对象的形式存在,我们叫它json对象。

一种是:字符串的形式存在,我们叫它json字符串。

一般我们要操作json中的数据的时候,需要json对象的格式

一般我们要在客户端和服务器之间进行数据交换的时候,使用json字符串

JSON.stringify() 把json对象转换成为json字符串

JSON.parse() 把json字符串转换为json对象

    //把json对象转换成json字符串
    var jsonObjString = JSON.stringify(jsonObj);//特别想java中对象的toString
    alert(jsonObjString);
    //把json字符串转换成json对象
    var jsonObj2 = JSON.parse(jsonObjString);
    alert(jsonObj2);



在java中的使用

public class JsonTest {
    //javaBean和json的互转
    @Test
    public void test1(){
        Person person = new Person(1,"我们去吃饭");
        //创建Gson对象实例
        Gson gson = new Gson();
        //toJson方法可以把java对象转换成为json字符串
        String personJsonString = gson.toJson(person);
        System.out.println(personJsonString);
        //fromJson把json字符串转换回java对象
        //第一个参数是json字符串
        //第二个参数是转换回去的java对象类型
        Person person1 = gson.fromJson(personJsonString, Person.class);
        System.out.println(person1);
    }
    //List和json的互换
    @Test
    public void test2(){
        List<Person> personList = new ArrayList<>();

        personList.add(new Person(1,"国哥"));
        personList.add(new Person(2,"康师傅"));

        Gson gson = new Gson();
        //把List转换为json字符串
        String personListJsonString = gson.toJson(personList);
        System.out.println(personListJsonString);

        List<Person> list  = gson.fromJson(personListJsonString, new PersonListType().getType());
        System.out.println(list);
        Person person = list.get(0);
        System.out.println(person);
    }
    //json和Map的互换
    @Test
    public void test3(){
        Map<Integer,Person> personMap = new HashMap<>();
        personMap.put(1,new Person(1,"国哥好帅"));
        personMap.put(2,new Person(2,"康师傅也很帅"));

        Gson gson = new Gson();
        //把map集合转换成json字符串
        String personMapJSonString = gson.toJson(personMap);
        System.out.println(personMapJSonString);

        Map<Integer,Person> personMap2 = gson.fromJson(personMapJSonString,new PersonMapType().getType());
        System.out.println(personMap2);
        Person p = personMap2.get(1);
        System.out.println(p);
        
    }
}



Ajax请求

AJAX是指一种创建交互式网页应用的网页开发技术。

ajax是一种浏览器通过js异步发起请求。局部更新页面的技术。

Ajax请求的局部更新,浏览器地址栏不会发生变化

局部更新不会舍弃原来页面的内容



jQuery中的AJAX请求

$.ajax方法
url    	表示请求的地址
type   	表示请求的类型GETPOST请求
data   	表示发送给服务器的数据
     格式有两种:
            一、name=value&name=value
            二、{key:value}
success  请求响应,响应回调函数
dataType 响应的数据类型
                 常用的数据类型有:
                 text  表示纯文本
                 xml   表示xml数据
                 json  表示json对象
                 
 $.get方法和$.post方法
url   请求的url地址
data  发送的数据
callback  成功的回调函数
type  返回的数据类型

$.getJSON方法
url      请求的url地址
data     发送给服务器的数据
callback 成功的回调函数

表单序列化serialize()
serialize()可以把表单中所有表单项的内容都获取到,并以name=value&name=value的形式进行拼接



i18n国际化



1、什么是i18n国际化

 国际化(Internationalization)指的是同一个网站可以支持多种不同的语言,以方便不同国家,不同语种的用户访问。

 关于国际化我们想到的最简单的方案就是为不同的国家创建不同的网站,比如苹果公司,他的英文官网是:

http://www.apple.com 而中国官网是 http://www.apple.com/cn

 苹果公司这种方案并不适合全部公司,而我们希望相同的一个网站,而不同人访问的时候可以根据用户所在的区域显示

不同的语言文字,而网站的布局样式等不发生改变。

 于是就有了我们说的国际化,国际化总的来说就是同一个网站不同国家的人来访问可以显示出不同的语言。但实际上这

种需求并不强烈,一般真的有国际化需求的公司,主流采用的依然是苹果公司的那种方案,为不同的国家创建不同的页

面。所以国际化的内容我们了解一下即可。

 国际化的英文 Internationalization,但是由于拼写过长,老外想了一个简单的写法叫做 I18N,代表的是 Internationalization

这个单词,以 I 开头,以 N 结尾,而中间是 18 个字母,所以简写为 I18N。以后我们说 I18N 和国际化是一个意思。



2、国际化相关要素介绍



版权声明:本文为m0_56747819原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。