JavaWeb

1.0 XML 简介

1.1 什么是 xml?
  • xml 是可扩展的标记性语言。
2.2 xml 的作用?
  • xml 的主要作用有:
    1、用来保存数据,而且这些数据具有自我描述性
    2、它还可以做为项目或者模块的配置文件
    3、还可以做为网络传输数据的格式(现在 JSON 为主)。
    在这里插入图片描述

【books.xml】

<?xml version="1.0" encoding="UTF-8"?>
<!-- xml 声明 version 是版本的意思 encoding 是编码 -->
<books> <!-- books表示多个图书信息 -->
    <book id="SN123123413241"> <!-- book 标签描述一本图书id属性描述的是图书的编号 -->
        <name>java 编程思想</name><!-- name 标签描述 的是图书的信息 -->
        <author>华仔</author><!-- author 单词是作者的意思,描述图书作者 -->
        <price>9.9</price><!--  price 单词是价格,描述的是图书 的价格 -->
    </book>
    <book id="SN12341235123"> <!-- book 标签描述一本图书id属性描述的是图书的编号 -->
        <name>葵花宝典</name><!-- name 标签描述的是图书的信息-->
        <author>班长</author><!-- author 单词是作者的意思,描述图书作者 -->
        <price>5.5</price><!-- price 单词是价格,描述的是图书的价格 -->
    </book>
</books>

1.3 xml 注释
  • html 和 XML 注释 一样 : < !-- html 注释 -->

1.4 元素(标签)

html 标签:

  • 格式:<标签名>封装的数据</标签名>
  • 单标签: <标签名 /> < br /> 换行 < hr />水平线
  • 双标签 <标签名>封装的数据</标签名>
  • 标签名大小写不敏感
  • 标签有属性,有基本属性和事件属性
  • 标签要闭合(不闭合 ,html 中不报错。但我们要养成良好的书写习惯。闭合)

1.5 什么是 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”)。

1.6 XML 命名规则

XML 元素必须遵循以下命名规则:

  • 名称可以含字母、数字以及其他的字符
  • 名称不能以数字或者标点符号开始
  • 名称不能以字符 “xml”(或者 XML、Xml)开始
  • 名称不能包含空格
  • 可使用任何名称,没有保留的字词

如名称不能以数字或者标点符号开始
在这里插入图片描述


1.7 xml 中的元素(标签)也分成单标签和双标签:
  • 单标签格式: <标签名 属性=”值” 属性=”值” … />
  • 双标签格式:< 标签名 属性=”值” 属性=”值” …>文本数据或子标签</标签名>
    在这里插入图片描述

1.8 xml 属性
  • 从 HTML,你会回忆起这个:< img src=“computer.gif”>。“src” 属性提供有关 元素的额外信息。

  • 在 HTML 中(以及在 XML 中),属性提供有关元素的额外信息。

  • 属性值必须被引号包围,不过单引号和双引号均可使用。比如一个人的性别,person 标签可以这样写:

<person sex="female">  or  <person sex='female'>

在这里插入图片描述


XML 标签对大小写敏感
在这里插入图片描述


XML 中的特殊字符
在这里插入图片描述


文本区域(CDATA 区)

  • CDATA 语法可以告诉 xml 解析器,我 CDATA 里的文本内容,只是纯文本,不需要 xml 语法解析
  • CDATA 格式:
  • <![CDATA[ 这里可以把你输入的字符原样显示,不会解析 xml ]]>

在这里插入图片描述

1.9 xml 解析技术介绍
  • xml 可扩展的标记语言。 不管是 html 文件还是 xml 文件它们都是标记型文档,都可以使用 w3c 组织制定的 dom 技术来解析。
    在这里插入图片描述
  • document 对象表示的是整个文档(可以是 html 文档,也可以是 xml 文档)
  • 早期 JDK 为我们提供了两种 xml 解析技术 DOM 和 Sax 简介(已经过时,但我们需要知道这两种技术)
  • dom 解析技术是 W3C 组织制定的,而所有的编程语言都对这个解析技术使用了自己语言的特点进行实现。 Java 对 dom 技术解析标记也做了实现。
  • sun 公司在 JDK5 版本对 dom 解析技术进行升级:SAX( Simple API for XML ) SAX 解析,它跟 W3C 制定的解析不太一样。它是以类似事件机制通过回调告诉用户当前正在解析的内容。 它是一行一行的读取 xml 文件进行解析的。不会创建大量的 dom 对象。 所以它在解析 xml 的时候,在内存的使用上。和性能上。都优于 Dom 解析。
  • 第三方的解析: jdom 在 dom 基础上进行了封装 、 dom4j 又对 jdom 进行了封装。 pull 主要用在 Android 手机开发,是在跟 sax 非常类似都是事件机制解析 xml 文件。这个 Dom4j 它是第三方的解析技术。我们需要使用第三方给我们提供好的类库才可以解析 xml 文件
1.10 dom4j 解析技术(xml)

导入jar包
在这里插入图片描述

1.10.1 dom4j 编程步骤:
  • 第一步: 先加载 xml 文件创建 Document 对象
  • 第二步:通过 Document 对象拿到根元素对象
  • 第三步:通过根元素.elelemts(标签名); 可以返回一个集合,这个集合里放着。所有你指定的标签名的元素对象
  • 第四步:找到你想要修改、删除的子元素,进行相应在的操作 第五步,保存到硬盘上

需要解析的 books.xml 文件内容

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book sn="SN12341232">
        <name>辟邪剑谱</name>
        <price>9.9</price>
        <author>班主任</author>
    </book>
    <book sn="SN12341231">
        <name>葵花宝典</name>
        <price>99.99</price>
        <author>班长</author>
    </book>
</books>

    /*
     * dom4j 获取 Documet 对象
     */
    @Test
    public void test1() throws Exception {
        // 创建一个SaxReader输入流,去读取 xml配置文件,生成Document对象
        // 要创建一个 Document 对象,需要我们先创建一个 SAXReader 对象
        SAXReader saxReader = new SAXReader();
        // 这个对象用于读取 xml 文件,然后返回一个 Document。
        Document document = saxReader.read("05_xml/src/books.xml");
        // 打印到控制台,看看是否创建成功
        System.out.println(document);
    }

运行结果:
org.dom4j.tree.DefaultDocument@39ed3c8d [Document: name 05_xml/src/books.xml]


遍历标签获取所有标签中的内容

需要分四步操作:

  • 第一步,通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
  • 第二步,通过 Document 对象。拿到 XML 的根元素对象
  • 第三步,通过根元素对象。获取所有的 book 标签对象
  • 第四小,遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,再通过 getText() 方法拿到起始标签和结 束标签之间的文本内容
     /*
     * 读取 xml 文件中的内容
     */
    @Test
    public void readXML() throws DocumentException {
        //需要分四步操作:
        //第一步,通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
        //第二步,通过 Document 对象。拿到 XML 的根元素对象
        //第三步,通过根元素对象。获取所有的 book 标签对象
        //第四小,遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,再通过 getText() 方法拿到起始标签和结束标签之间的文本内容
        //第一步,通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read("05_xml/src/books.xml");
        // 第二步,通过 Document 对象。拿到 XML 的根元素对象
        Element root = document.getRootElement();
        //打印测试
        //Element.asXML() 它将当前元素转换成为 String 对象
        System.out.println(root.asXML());
        //第三步,通过根元素对象。获取所有的 book标签对象
        // Element.elements(标签名)它可以拿到当前元素下的指定的子元素的集合
        List<Element> books = root.elements("book");
        //第四小,遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,
        for (Element book : books) {
            //测试
            //System.out.println(book.asXML());
            //拿到 book 下面的 name 元素对象
            Element nameElement = book.element("name");
            // 拿到 book 下面的 price 元素对象
            Element priceElement = book.element("price");
            // 拿到 book 下面的 author 元素对象
            Element authorElement = book.element("author");
            // 再通过 getText() 方法拿到起始标签和结束标签之间的文本内容
            System.out.println("书名" + nameElement.getText() + " , 价格:"
                    + priceElement.getText() + ", 作者:" + authorElement.getText());
        }
    }

运行结果:

<books>
    <book sn="SN12341232">
        <name>辟邪剑谱</name>
        <price>9.9</price>
        <author>班主任</author>
    </book>
    <book sn="SN12341231">
        <name>葵花宝典</name>
        <price>99.99</price>
        <author>班长</author>
    </book>
</books>
书名辟邪剑谱 , 价格:9.9, 作者:班主任
书名葵花宝典 , 价格:99.99, 作者:班长

2.0 Tomcat简介

JavaWeb 的概念

2.1 什么是 JavaWeb
  • JavaWeb 是指,所有通过 Java 语言编写可以通过浏览器访问的程序的总称,叫 JavaWeb。
  • JavaWeb 是基于请求和响应来开发的。
2.2 什么是请求
  • 请求是指客户端给服务器发送数据,叫请求 Request
2.3 什么是响应
  • 响应是指服务器给客户端回传数据,叫响应 Response。
2.4 请求和响应的关系
  • 请求和响应是成对出现的,有请求就有响应
    在这里插入图片描述

2.5 Web 资源的分类

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

  • 静态资源: html、css、js、txt、mp4 视频 , jpg 图片
  • 动态资源: jsp 页面、Servlet 程序

2.6 常用的 Web 服务器
  • Tomcat:由 Apache 组织提供的一种 Web 服务器,提供对 jsp 和 Servlet 的支持。它是一种轻量级的 javaWeb 容器(服务 器),也是当前应用最广的 JavaWeb 服务器(免费)。
  • -Jboss:是一个遵从 JavaEE 规范的、开放源代码的、纯 Java 的 EJB 服务器,它支持所有的 JavaEE 规范(免费)。
  • GlassFish: 由 Oracle 公司开发的一款 JavaWeb 服务器,是一款强健的商业服务器,达到产品级质量(应用很少)。
  • Resin:是 CAUCHO 公司的产品,是一个非常流行的服务器,对 servlet 和 JSP 提供了良好的支持, 性能也比较优良,resin 自身采用 JAVA 语言开发(收费,应用比较多)。
  • WebLogic:是 Oracle 公司的产品,是目前应用最广泛的 Web 服务器,支持 JavaEE 规范, 而且不断的完善以适应新的开发要求,适合大型项目(收费,用的不多,适合大公司)。

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

当前企业常用的版本 7*、8.*
在这里插入图片描述

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

2.8 Tomcat 的使用
2.8.1 安装
  • 找到你需要用的 Tomcat 版本对应的 zip 压缩包,解压到需要安装的目录即可。

2.8.2 目录介绍
  • bin :专门用来存放 Tomcat 服务器的可执行程序
  • conf :专门用来存放 Tocmat 服务器的配置文件
  • lib :专门用来存放 Tomcat 服务器的 jar 包
  • logs :专门用来存放 Tomcat 服务器运行时输出的日记信息
  • temp :专门用来存放 Tomcdat 运行时产生的临时数据
  • webapps :专门用来存放部署的 Web 工程。
  • work :是 Tomcat 工作时的目录,用来存放 Tomcat 运行时 jsp 翻译为 Servlet 的源码,和 Session 钝化的目录。

2.8.3 如何启动 Tomcat 服务器
  • 找到 Tomcat 目录下的 bin 目录下的 startup.bat 文件,双击,就可以启动 Tomcat 服务器。
  • 如何测试 Tomcat 服务器启动成功???
    打开浏览器,在浏览器地址栏中输入以下地址测试:
    1、http://localhost:8080
    2、http://127.0.0.1:8080
    3、http://真实 ip:8080
  • 当出现如下界面,说明 Tomcat 服务器启动成功!!!
    在这里插入图片描述
  • 常见的启动失败的情况有,双击 startup.bat 文件,就会出现一个小黑窗口一闪而来。 这个时候,失败的原因基本上都是因为没有配置好 JAVA_HOME 环境变量。

2.8.4 另一种启动 tomcat 服务器的方式
  • 1、打开命令行
  • 2、cd 到 你的 Tomcat 的 bin 目录下
    在这里插入图片描述
  • 3、敲入启动命令: catalina run

2.8.5 Tomcat 的停止
  • 1、点击 tomcat 服务器窗口的 x 关闭按钮
  • 2、把 Tomcat 服务器窗口置为当前窗口,然后按快捷键 Ctrl+C
  • 3、找到 Tomcat 的 bin 目录下的 shutdown.bat 双击,就可以停止 Tomcat 服务器

2.8.6 如何修改 Tomcat 的端口号
  • Mysql 默认的端口号是:3306
  • Tomcat 默认的端口号是:8080 找到 Tomcat 目录下的 conf 目录,找到 server.xml 配置文件。
    在这里插入图片描述
  • 平时上百度:http://www.baidu.com:80 ,HTTP 协议默认的端口号是:80

2.8.7 如何部暑 web 工程到 Tomcat 中
  • 第一种部署方法:只需要把 web 工程的目录拷贝到 Tomcat 的 webapps 目录下 即可。

1、在 webapps 目录下创建一个 book 工程:
在这里插入图片描述

2、把上午做的书城第一阶段的内容拷贝到里面:
在这里插入图片描述

3、如何访问 Tomcat 下的 web 工程。

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

2.8.8 第二种部署方法:

找到 Tomcat 下的 conf 目录\Catalina\localhost\ 下,创建如下的配置文件:
在这里插入图片描述
abc.xml 配置文件内容如下:

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

访问这个工程的路径如下:http://ip:port/abc/ 就表示访问 E:\book 目录


2.9 手托 html 页面到浏览器和在浏览器中输入 http://ip:端 口号/工程名/访问的区别
  1. 手托 html 页面的原理:
    在这里插入图片描述
  2. 输入访问地址访问的原因:
    在这里插入图片描述

2.10 ROOT 的工程的访问,以及 默认 index.html 页面的访问
  1. 当我们在浏览器地址栏中输入访问地址如下:

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

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

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


2. 11 IDEA 整合 Tomcat 服务器
  1. 操作的菜单如下:File | Settings | Build, Execution, Deployment | Application Servers
    在这里插入图片描述
  2. 配置你的 Tomcat 安装目录:
    在这里插入图片描述
  3. 就可以通过创建一个 Model 查看是不是配置成功!!!
    在这里插入图片描述

2.12 IDEA 中动态 web 工程的操作
  1. 创建一个新模块:
    在这里插入图片描述
  2. 选择你要创建什么类型的模块:
    在这里插入图片描述
  3. 输入你的模块名,点击【Finish】完成创建。
  4. 创建成功如下图:
    在这里插入图片描述
    注意事项:copy进来的web子模块并没有加入项目模块中,可以new一个重名的web模块使生效。

2.13 Web 工程的目录介绍

在这里插入图片描述


2.14 如何给动态 web 工程添加额外 jar 包
  1. 可以打开项目结构菜单操作界面,添加一个自己的类库:
    在这里插入图片描述
  2. 添加你你类库需要的 jar 包文件。
    在这里插入图片描述
  3. 选择你添加的类库,给哪个模块使用:
    在这里插入图片描述
  4. 选择 Artifacts 选项,将类库,添加到打包部署中:
    在这里插入图片描述

2.15 如何在 IDEA 中部署工程到 Tomcat 上运行
  1. 建议修改 web 工程对应的 Tomcat 运行实例名称:
    在这里插入图片描述
  2. 确认你的 Tomcat 实例中有你要部署运行的 web 工程模块:
    在这里插入图片描述
  3. 你还可以修改你的 Tomcat 实例启动后默认的访问地址:
    在这里插入图片描述
  4. 配置资源热部署
    在这里插入图片描述

3.Servlet

3.1 Servlet 技术
3.1.1 什么是 Servlet
  • 1、Servlet 是 JavaEE 规范之一。规范就是接口
  • 2、Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
  • 3、Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
3.2 手动实现 Servlet 程序
  • 1、编写一个类去实现 Servlet 接口
  • 2、实现 service 方法,处理请求,并响应数据
  • 3、到 web.xml 中去配置 servlet 程序的访问地址

Servlet源码

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

【HelloServlet.java】

public class HelloServlet implements Servlet {

    public HelloServlet() {

    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * service方法是专门用来处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 被访问了");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
    }
}

web.xml 中的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- servlet标签给Tomcat配置Servlet程序 -->
    <servlet>
        <!--servlet-name标签 Servlet程序起一个别名(一般是类名) -->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class是Servlet程序的全类名-->
        <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--servlet-mapping标签给servlet程序配置访问地址-->
    <servlet-mapping>
        <!--servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个Servlet程序使用-->
        <servlet-name>HelloServlet</servlet-name>
        <!--
            url-pattern标签配置访问地址                                     <br/>
               / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径          <br/>
               /hello 表示地址为:http://ip:port/工程路径/hello              <br/>
        -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
</web-app>

浏览器输入:http://localhost:8080/06_servlet_war_exploded /hello
运行结果:
Hello Servlet 被访问了


3.3 常见错误
  1. 常见的错误 1:url-pattern 中配置的路径没有以斜杠打头。
<url-pattern>hello</url-pattern>

在这里插入图片描述

  1. 常见错误 2:servlet-name 配置的值不存在:
<servlet-mapping>
     <!--servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个Servlet程序使用-->
     <servlet-name>HelloServlet1</servlet-name>
     <url-pattern>/hello</url-pattern>
</servlet-mapping>

在这里插入图片描述

  1. 常见错误 3:servlet-class 标签的全类名配置错误。

3.4 url地址到Servlet 程序的访问

在这里插入图片描述

3.5 Servlet 的生命周期
  • 1、执行 Servlet 构造器方法
  • 2、执行 init 初始化方法 第一、二步,是在第一次访问,的时候创建 Servlet 程序会调用。
  • 3、执行 service 方法 第三步,每次访问都会调用。
  • 4、执行 destroy 销毁方法 第四步,在 web 工程停止的时候调用。

3.6 GET 和 POST 请求的分发处理
  public class HelloServlet implements Servlet {
    /**
     * service方法是专门用来处理请求和响应的
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 被访问了");
        // 类型转换(因为它有getMethod()方法)
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        // 获取请求的方式
        String method = httpServletRequest.getMethod();

        if ("GET".equals(method)) {
            doGet();
        } else if ("POST".equals(method)) {
            doPost();
        }
    }
    /**
     * 做get请求的操作
     */
    public void doGet(){
        System.out.println("get请求");
        System.out.println("get请求");
    }
    /**
     * 做post请求的操作
     */
    public void doPost(){
        System.out.println("post请求");
        System.out.println("post请求");
    }
 }

【a.html】

<body>
    <form action="http://localhost:8080/06_servlet_war_exploded/hello" method="post">
        <input type="submit">
    </form>
</body>

输入http://localhost:8080/06_servlet_war_exploded/a.html
运行结果:
Hello Servlet 被访问了
post请求
post请求


3.7 通过继承 HttpServlet 实现 Servlet 程序

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

  • 1、编写一个类去继承 HttpServlet 类
  • 2、根据业务需要重写 doGet 或 doPost 方法
  • 3、到 web.xml 中的配置 Servlet 程序的访问地址
public class HelloServlet2 extends HttpServlet {
    /**
     * doGet()在 get 请求的时候调用
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet2 的 doGet 方法");
    }

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

【web.xml】

 <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>

【a.html】

<body>
    <form action="http://localhost:8080/06_servlet_war_exploded/hello2" method="post">
        <input type="submit">
    </form>
</body>

http://localhost:8080/06_servlet_war_exploded/a.html
运行结果:
HelloServlet2 的 doPost 方法


3.8 使用 IDEA 创建 Servlet 程序
  1. 菜单:new ->Servlet 程序
    在这里插入图片描述
  2. 配置 Servlet 的信息:
    在这里插入图片描述

3.9 Servlet 类的继承体系

在这里插入图片描述


3.10 ServletConfig 类的三大作用
  1. 可以获取 Servlet 程序的别名 servlet-name 的值
  2. 获取初始化参数 init-param
  3. 获取 ServletContext 对象

【web.xml】

  <servlet>
        <!--servlet-name标签 Servlet程序起一个别名(一般是类名) -->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class是Servlet程序的全类名-->
        <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
        <!--init-param是初始化参数-->
        <init-param>
            <!--是参数名-->
            <param-name>username</param-name>
            <!--是参数值-->
            <param-value>root</param-value>
        </init-param>
        <!--init-param是初始化参数-->
        <init-param>
            <!--是参数名-->
            <param-name>url</param-name>
            <!--是参数值-->
            <param-value>jdbc:mysql://localhost:3306/test</param-value>
        </init-param>
  </servlet>

【HelloServlet.java】

 @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("2 init初始化方法");

//        1、可以获取Servlet程序的别名servlet-name的值
        System.out.println("HelloServlet程序的别名是:" + servletConfig.getServletName());
//        2、获取初始化参数init-param
        System.out.println("初始化参数username的值是;" + servletConfig.getInitParameter("username"));
        System.out.println("初始化参数url的值是;" + servletConfig.getInitParameter("url"));
//        3、获取ServletContext对象
        System.out.println(servletConfig.getServletContext());
    }

运行结果:
2 init初始化方法
HelloServlet程序的别名是:HelloServlet
初始化参数username的值是;root
初始化参数url的值是;jdbc:mysql://localhost:3306/test
org.apache.catalina.core.ApplicationContextFacade@3c3d6b1a


3.11 ServletContext 类
  1. ServletContext 是一个接口,它表示 Servlet 上下文对象
  2. 一个 web 工程,只有一个 ServletContext 对象实例。
  3. ServletContext 对象是一个域对象。
  4. ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。

3.11.1 什么是域对象?
域对象,是可以像 Map 一样存取数据的对象,叫域对象。这里的域指的是存取数据的操作范围,整个 web 工程。
在这里插入图片描述

3.11.1 ServletContext 演示代码:

【ContextServlet.java】

public class ContextServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、获取web.xml中配置的上下文参数context-param
        ServletContext context = getServletConfig().getServletContext();

        String username = context.getInitParameter("username");
        System.out.println("context-param参数username的值是:" + username);
        System.out.println("context-param参数password的值是:" + context.getInitParameter("password"));
        //2、获取当前的工程路径,格式: /工程路径
        System.out.println( "当前工程路径:" + context.getContextPath() );
        //3、获取工程部署后在服务器硬盘上的绝对路径
        /**
         *  / 斜杠被服务器解析地址为:http://ip:port/工程名/  映射到IDEA代码的web目录<br/>
         */
        System.out.println("工程部署的路径是:" + context.getRealPath("/"));
        System.out.println("工程下css目录的绝对路径是:" + context.getRealPath("/css"));
        System.out.println("工程下imgs目录1.jpg的绝对路径是:" + context.getRealPath("/imgs/1.jpg"));
    }
}

web.xml 中的配置:

<!--context-param是上下文参数(它属于整个web工程)-->
    <context-param>
        <param-name>username</param-name>
        <param-value>context</param-value>
    </context-param>
    <!--context-param是上下文参数(它属于整个web工程)-->
    <context-param>
        <param-name>password</param-name>
        <param-value>root</param-value>
    </context-param>
    <servlet>
        <servlet-name>ContextServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.ContextServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ContextServlet</servlet-name>
        <url-pattern>/contextServlet</url-pattern>
    </servlet-mapping>

运行结果:
context-param参数username的值是:context
context-param参数password的值是:root
当前工程路径:/06_servlet_war_exploded
工程部署的路径是:D:\IdeaProjects\JavaWeb\out\artifacts\06_servlet_war_exploded
工程下css目录的绝对路径是:D:\IdeaProjects\JavaWeb\out\artifacts\06_servlet_war_exploded\css
工程下imgs目录1.jpg的绝对路径是:D:\IdeaProjects\JavaWeb\out\artifacts\06_servlet_war_exploded\imgs\1.jpg


3.12 HTTP 协议
3.12.1什么是 HTTP 协议

**什么是协议? **

  • 协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。 所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。 HTTP 协议中的数据又叫报文。

3.12.2 请求的 HTTP 协议格式
  • 客户端给服务器发送数据叫请求。
  • 服务器给客户端回传数据叫响应。
  • 请求又分为 GET 请求,和 POST 请求两种

1.GET 请求
在这里插入图片描述
在这里插入图片描述


  1. POST 请求
    在这里插入图片描述
    在这里插入图片描述
3.13 常用请求头的说明
  • Accept: 表示客户端可以接收的数据类型
  • Accpet-Languege: 表示客户端可以接收的语言类型
  • User-Agent: 表示客户端浏览器的信息
  • Host: 表示请求时的服务器 ip 和端口号
3.14 哪些是 GET 请求,哪些是 POST 请求

GET 请求有哪些:

  1. form 标签 method=get
  2. a 标签
  3. link 标签引入 css
  4. Script 标签引入 js 文件
  5. img 标签引入图片
  6. iframe 引入 html 页面
  7. 在浏览器地址栏中输入地址后敲回车

POST 请求有哪些

  1. form 标签 method=post

3.15 响应的 HTTP 协议格式

在这里插入图片描述
在这里插入图片描述


3.16 常用的响应码说明
  • 200 表示请求成功
  • 302 表示请求重定向
  • 404 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)
  • 500 表示服务器已经收到请求,但是服务器内部错误(代码错误)

3.17 MIME 类型说明
  • MIME 是 HTTP 协议中数据类型。
  • MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小 类型”,并与某一种文件的扩展名相对应。

常见的 MIME 类型:

文件MIME 类型
超文本标记语言文本.html , .htm ——text/html
普通文本.txt ——text/plain
RTF 文本.rtf ——application/rtf
GIF 图形.gif ——image/gifl
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

谷歌浏览器如何查看 HTTP 协议:
在这里插入图片描述


3.18 Servlet2
3.18.1 HttpServletRequest 类
3.18.2HttpServletRequest 类有什么作用。
  • 每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。

3.19 HttpServletRequest 类的常用方法
方法作用
getRequestURI()获取请求的资源路径
getRequestURL()获取请求的统一资源定位符(绝对路径)
getRemoteHost()获取客户端的 ip 地址
getHeader()获取请求头
getParameter()获取请求的参数
getParameterValues()获取请求的参数(多个值的时候使用)
getMethod()获取请求的方式 GET 或 POST
setAttribute(key, value)设置域数据
getAttribute(key)getAttribute(key)
getRequestDispatcher()获取请求转发对象

3.20 常用 API 示例代码:

【RequestAPIServlet.java】

public class RequestAPIServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        i.getRequestURI()					获取请求的资源路径
        System.out.println("URI => " + req.getRequestURI());
//        ii.getRequestURL()					获取请求的统一资源定位符(绝对路径)
        System.out.println("URL => " + req.getRequestURL());
//        iii.getRemoteHost()				获取客户端的ip地址
        /**
         * 在IDEA中,使用localhost访问时,得到的客户端 ip 地址是 ===>>> 127.0.0.1<br/>
         * 在IDEA中,使用127.0.0.1访问时,得到的客户端 ip 地址是 ===>>> 127.0.0.1<br/>
         * 在IDEA中,使用 真实ip 访问时,得到的客户端 ip 地址是 ===>>> 真实的客户端 ip 地址<br/>
         */
        System.out.println("客户端 ip地址 => " + req.getRemoteHost());
//        iv.getHeader()						获取请求头
        System.out.println("请求头User-Agent ==>> " + req.getHeader("User-Agent"));
//        vii.getMethod()					获取请求的方式GET或POST
        System.out.println( "请求的方式 ==>> " + req.getMethod() );
    }
}

【web.xml】

    <servlet>
        <servlet-name>RequestAPIServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.RequestAPIServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestAPIServlet</servlet-name>
        <url-pattern>/requestAPIServlet</url-pattern>
    </servlet-mapping>

运行结果:
URI => /07_servlet_war_exploded/requestAPIServlet
URL => http://localhost:8080/07_servlet_war_exploded/requestAPIServlet
客户端 ip地址 => 0:0:0:0:0:0:0:1
请求头User-Agent ==>> Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
请求的方式 ==>> GET


3.21 如何获取请求参数

【RequestAPIServlet.java】

public class RequestAPIServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //        i.getRequestURI()					获取请求的资源路径
        System.out.println("URI => " + req.getRequestURI());
//        ii.getRequestURL()					获取请求的统一资源定位符(绝对路径)
        System.out.println("URL => " + req.getRequestURL());
//        iii.getRemoteHost()				获取客户端的ip地址
        /**
         * 在IDEA中,使用localhost访问时,得到的客户端 ip 地址是 ===>>> 127.0.0.1<br/>
         * 在IDEA中,使用127.0.0.1访问时,得到的客户端 ip 地址是 ===>>> 127.0.0.1<br/>
         * 在IDEA中,使用 真实ip 访问时,得到的客户端 ip 地址是 ===>>> 真实的客户端 ip 地址<br/>
         */
        System.out.println("客户端 ip地址 => " + req.getRemoteHost());
//        iv.getHeader()						获取请求头
        System.out.println("请求头User-Agent ==>> " + req.getHeader("User-Agent"));
//        vii.getMethod()					获取请求的方式GET或POST
        System.out.println("请求的方式 ==>> " + req.getMethod());
    }
}

【form.html】

<body>
    <form action="http://localhost:8080/07_servlet_war_exploded/parameterServlet" method="post">
        用户名:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
        兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
        <input type="checkbox" name="hobby" value="java">Java
        <input type="checkbox" name="hobby" value="js">JavaScript<br/>
        <input type="submit">
    </form>
</body>

运行结果:
-------------doPost------------
用户名:爱你一万年
密码:123456
兴趣爱好:[cpp, java]


3.22 请求的转发

什么是请求的转发?

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

在这里插入图片描述


【Servlet1.java】

public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 获取请求的参数(办事的材料)查看
        String username = req.getParameter("username");
        System.out.println ("在Servlet1(柜台1)中查看参数(材料):" + username);

        // 给材料 盖一个章,并传递到Servlet2(柜台 2)去查看
        req.setAttribute("key1","柜台1的章");

        // 问路:Servlet2(柜台 2)怎么走
        /**
         * 请求转发必须要以斜杠打头,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到IDEA代码的web目录<br/>
         *
         */
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
//        RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.baidu.com");

        // 走向Sevlet2(柜台 2)
        requestDispatcher.forward(req,resp);

    }
}

【Servlet2.java】

public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求的参数(办事的材料)查看
        String username = req.getParameter("username");
        System.out.println("在Servlet2(柜台2)中查看参数(材料):" + username);

        // 查看 柜台1 是否有盖章
        Object key1 = req.getAttribute("key1");
        System.out.println("柜台1是否有章:" + key1);

        // 处理自己的业务
        System.out.println("Servlet2 处理自己的业务 ");
    }
}

配制好web.xml
输入http://localhost:8080/07_servlet_war_exploded/servlet1?username=爱你一万年
运行结果:
在Servlet1(柜台1)中查看参数(材料):爱你一万年
在Servlet2(柜台2)中查看参数(材料):爱你一万年
柜台1是否有章:柜台1的章
Servlet2 处理自己的业务


3.23 base 标签的作用

在这里插入图片描述
【index.html】

<body>
    这是Web下的index.html <br/>
    <a href="a/b/c.html">a/b/c.html</a><br/>
    <a href="http://localhost:8080/07_servlet_war_exploded/forwardC">请求转发:a/b/c.html</a><br/>
    <a href="/">斜杠</a>
</body>

【ForwardC.java】

public class ForwardC extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("经过了ForwardC程序");
        req.getRequestDispatcher("/a/b/c.html").forward(req, resp);
    }
}

【c.html】

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--base标签设置页面相对路径工作时参照的地址
            href 属性就是参数的地址值
    -->
    <base href="http://localhost:8080/07_servlet_war_exploded/a/b/c.html">
</head>
<body>
    这是a下的b下的c.html页面<br/>
    <a href="../../index.html">跳回首页</a><br/>
</body>

实现页面返回跳转
运行结果:
在这里插入图片描述
在这里插入图片描述
总结
在这里插入图片描述


3.24 Web 中的相对路径和绝对路径

在这里插入图片描述


3.25 Web 中的相对路径和绝对路径

在这里插入图片描述


3.26 HttpServletResponse 类
3.26.1 HttpServletResponse 类的作用
  • HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息。
  • 我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置
3.26.2 两个输出流的说明。

在这里插入图片描述
在这里插入图片描述


【ResponseIOServlet.java】

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//        System.out.println( resp.getCharacterEncoding() );//默认ISO-8859-1

//        // 设置服务器字符集为UTF-8
//        resp.setCharacterEncoding("UTF-8");
//        // 通过响应头,设置浏览器也使用UTF-8字符集
//        resp.setHeader("Content-Type", "text/html; charset=UTF-8");

        // 它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头
        // 此方法一定要在获取流对象之前调用才有效
        resp.setContentType("text/html; charset=UTF-8");

//        System.out.println( resp.getCharacterEncoding() );

//        要求 : 往客户端回传 字符串 数据。
        PrintWriter writer = resp.getWriter();
        writer.write("国哥很帅!");
    }
}

运行结果:
在这里插入图片描述


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

在这里插入图片描述
在这里插入图片描述
【Response1,java】

public class Response1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("曾到此一游 Response1 ");

        req.setAttribute("key1", "value1");

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

        resp.sendRedirect("http://localhost:8080/07_servlet_war_exploded/response2");
    }
}

【Response2,java】

public class Response2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(req.getAttribute("key1"));
        resp.getWriter().write("response2's result!");
    }
}

运行结果:
在这里插入图片描述
曾到此一游 Response1
null


4.0 jsp

4.1 什么是 jsp,它有什么用?
  1. jsp 的全换是 java server pages。Java 的服务器页面。
  2. jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据。
  3. 因为 Servlet 程序回传 html 页面数据是一件非常繁锁的事情。开发成本和维护成本都极高。

4.2 Servlet 回传 html 页面数据的代码

【PringHtml.java】

public class PringHtml extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//        JspWriter
        // 通过响应的回传流回传html页面数据
        resp.setContentType("text/html; charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write("<!DOCTYPE html>\r\n");
        writer.write("  <html lang=\"en\">\r\n");
        writer.write("  <head>\r\n");
        writer.write("      <meta charset=\"UTF-8\">\r\n");
        writer.write("      <title>Title</title>\r\n");
        writer.write("  </head>\r\n");
        writer.write(" <body>\r\n");
        writer.write("    这是html页面数据 \r\n");
        writer.write("  </body>\r\n");
        writer.write("</html>\r\n");
        writer.write("\r\n");
    }
}
    <servlet>
        <servlet-name>PringHtml</servlet-name>
        <servlet-class>com.atguigu.servlet.PringHtml</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>PringHtml</servlet-name>
        <url-pattern>/pringHtml</url-pattern>
    </servlet-mapping>

运行结果:
在这里插入图片描述


jsp 回传一个简单 html 页面的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    这是html页面数据
</body>
</html>

运行结果:
这是html页面数据

在这里插入图片描述


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

控制台内容地址
在这里插入图片描述
在这里插入图片描述

  • 我们跟踪原代码发现,HttpJspBase 类。它直接地继承了 HttpServlet 类。也就是说。jsp 翻译出来的 java 类,它间接了继 承了 HttpServlet 类。也就是说,翻译出来的是一个 Servlet 程序
  • 总结:通过翻译的 java 源代码我们就可以得到结果:jsp 就是 Servlet 程序。
  • 大家也可以去观察翻译出来的 Servlet 程序的源代码,不难发现。其底层实现,也是通过输出流。把 html 页面数据回传给客户端
public void _jspService(final javax.servlet.http.HttpServletRequest request, final
    javax.servlet.http.HttpServletResponse response)
            throws java.io.IOException, javax.servlet.ServletException {
        final java.lang.String _jspx_method = request.getMethod();
        if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)
                && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
            response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
            return;
        }
        final javax.servlet.jsp.PageContext pageContext;
        javax.servlet.http.HttpSession session = null;
        final javax.servlet.ServletContext application;
        final javax.servlet.ServletConfig
                config;
        javax.servlet.jsp.JspWriter
                out =
                null;
        final java.lang.Object page
                = this;
        javax.servlet.jsp.JspWriter
                _jspx_out = null;
        javax.servlet.jsp.PageContext _jspx_page_context = null;
        try {
            response.setContentType("text/html;charset=UTF-8");
            pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
            _jspx_page_context = pageContext;
            application = pageContext.getServletContext();
            config = pageContext.getServletConfig();
            session = pageContext.getSession();
            out = pageContext.getOut();
            _jspx_out = out;
            out.write("\r\n");
            out.write("\r\n");
            out.write("<html>\r\n");
            out.write("<head>\r\n");
            out.write(" < title > Title < / title >\r\n ");
            out.write("</head>\r\n");
            out.write("<body>\r\n");
            out.write(" a.jsp 页面\r\n");
            out.write("</body>\r\n");
            out.write("</html>\r\n");
        } catch (java.lang.Throwable t) {
            if (!(t
                    instanceof javax.servlet.jsp.SkipPageException)) {
                out
                        = _jspx_out;
                if
                (out
                        != null && out.getBufferSize() != 0)
                    try {
                        if (response.isCommitted()) {
                            out.flush();
                        } else {
                            out.clearBuffer();
                        }
                    } catch (java.io.IOException e) {
                    }
                if
                (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
                else throw new ServletException(t);
            }
        } finally {
            _jspxFactory.releasePageContext(_jspx_page_context);
        }
    }
4.4 jsp 的三种语法
4.4.1 jsp 头部的 page 指令

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


4.5 jsp 中的常用脚本

声明脚本(极少使用)

  • 声明脚本的格式是: <%! 声明 java 代码 %> 作用:可以给 jsp 翻译出来的 java 类定义属性和方法甚至是静态代码块。内部类等。

练习:

  1. 声明类属性
  2. 声明 static 静态代码块
  3. 声明类方法
  4. 声明内部类
<body>
<%--练习:
--%>

<%--1、声明类属性--%>
    <%!
        private Integer id;
        private String name;
        private static Map<String,Object> map;
    %>
<%--2、声明static静态代码块--%>
    <%!
        static {
            map = new HashMap<String,Object>();
            map.put("key1", "value1");
            map.put("key2", "value2");
            map.put("key3", "value3");
        }
    %>
<%--3、声明类方法--%>
    <%!
        public int abc(){
            return 12;
        }
    %>
<%--4、声明内部类--%>
    <%!
        public static class A {
            private Integer id = 12;
            private String abc = "abc";
        }
    %>

<%--练习:
1.输出整型
2.输出浮点型
3.输出字符串
4.输出对象    --%>
    <%=12 %> <br>

    <%=12.12 %> <br>

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

    <%=map%> <br>

    <%=request.getParameter("username")%>


<%--练习:--%>
<%--1.代码脚本----if 语句--%>
    <%
        int i = 13 ;
        if (i == 12) {
    %>
            <h1>国哥好帅</h1>
    <%
        } else {
    %>
        <h1>国哥又骗人了!</h1>
    <%
        }
    %>
<br>
<%--2.代码脚本----for 循环语句--%>
    <table border="1" cellspacing="0">
    <%
        for (int j = 0; j < 10; j++) {
    %>
        <tr>
            <td>第 <%=j + 1%>行</td>
        </tr>
    <%
        }
    %>
    </table>
<%--3.翻译后java文件中_jspService方法内的代码都可以写--%>
    <%
        String username = request.getParameter("username");
        System.out.println("用户名的请求参数值是:" + username);
    %>
</body>

声明脚本代码翻译对照
在这里插入图片描述


4.6 表达式脚本(常用)
  • 表达式脚本的格式是:<%=表达式%>
  • 表达式脚本的作用是:的 jsp 页面上输出数据。

表达式脚本的特点:

  1. 所有的表达式脚本都会被翻译到_jspService() 方法中
  2. 表达式脚本都会被翻译成为 out.print()输出到页面上
  3. 由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象都可以直接使用。
  4. 表达式脚本中的表达式不能以分号结束

练习:

  1. 输出整型
  2. 输出浮点型
  3. 输出字符串
  4. 输出对象
    在这里插入图片描述

4.7 代码脚本

代码脚本的格式是:

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

代码脚本的特点是:

  1. 代码脚本翻译之后都在_jspService 方法中
  2. 代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用。
  3. 还可以由多个代码脚本块组合完成一个完整的 java 语句。
  4. 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据
<%--练习:--%>
<%--1.代码脚本----if 语句--%>
    <%
        int i = 13 ;
        if (i == 12) {
    %>
            <h1>国哥好帅</h1>
    <%
        } else {
    %>
        <h1>国哥又骗人了!</h1>
    <%
        }
    %>
<br>
<%--2.代码脚本----for 循环语句--%>
    <table border="1" cellspacing="0">
    <%
        for (int j = 0; j < 10; j++) {
    %>
        <tr>
            <td>第 <%=j + 1%>行</td>
        </tr>
    <%
        }
    %>
    </table>
<%--3.翻译后java文件中_jspService方法内的代码都可以写--%>
    <%
        String username = request.getParameter("username");
        System.out.println("用户名的请求参数值是:" + username);
    %>

翻译之后的对比:

在这里插入图片描述


4.8 jsp 中的三种注释
<%@ page import="java.util.Map" %>
<%@ page contentType="text/html;charset=utf-8" isErrorPage="true" language="java" %>
<!--
errorPage表示错误后自动跳转去的路径 <br/>
这个路径一般都是以斜杠打头,它表示请求地址为http://ip:port/工程路径/
映射到代码的Web目录
-->
<html>
<head>
    <title>Title</title>
</head>
<body>
    b.jsp页面
    <!-- 这是html注释  -->
    <%
        // 单行java注释
        /*  多行java注释  */
    %>
    <%-- 这是jsp注释  --%>
</body>
</html>

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

在这里插入图片描述


4.10 sp 四大域对象

在这里插入图片描述


scope.jsp 页面

<body>
    <h1>scope.jsp页面</h1>
    <%
        // 往四个域中都分别保存了数据
        pageContext.setAttribute("key", "pageContext");
        request.setAttribute("key", "request");
        session.setAttribute("key", "session");
        application.setAttribute("key", "application");
    %>
    pageContext域是否有值:<%=pageContext.getAttribute("key")%> <br>
    request域是否有值:<%=request.getAttribute("key")%> <br>
    session域是否有值:<%=session.getAttribute("key")%> <br>
    application域是否有值:<%=application.getAttribute("key")%> <br>
    <%
//        request.getRequestDispatcher("/scope2.jsp").forward(request,response);
    %>
    <%--
        <jsp:forward page=""></jsp:forward> 是请求转发标签,它的功能就是请求转发
            page 属性设置请求转发的路径
    --%>
    <jsp:forward page="/scope2.jsp"></jsp:forward>
</body>

scope2.jsp 页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>scope2.jsp页面</h1>
    pageContext域是否有值:<%=pageContext.getAttribute("key")%> <br>
    request域是否有值:<%=request.getAttribute("key")%> <br>
    session域是否有值:<%=session.getAttribute("key")%> <br>
    application域是否有值:<%=application.getAttribute("key")%> <br>
</body>

4.11 jsp 中的 out 输出和 response.getWriter 输出的区别
  • response 中表示响应,我们经常用于设置返回给客户端的内容(输出) out 也是给用户做输出使用的。
    在这里插入图片描述
  • 由于 jsp 翻译之后,底层源代码都是使用 out 来进行输出,所以一般情况下。我们在 jsp 页面中统一使用 out 来进行输出。避 免打乱页面输出内容的顺序。
  • out.write() 输出字符串没有问题
  • out.print() 输出任意数据都没有问题(都转换成为字符串后调用的 write 输出)
  • 深入源码,浅出结论:在 jsp 页面中,可以统一使用 out.print()来进行输出

4.12 jsp 的常用标签
4.12.1 jsp 静态包含

示例说明:

    <%--
        <%@ include file=""%> 就是静态包含
            file 属性指定你要包含的jsp页面的路径
            地址中第一个斜杠 / 表示为http://ip:port/工程路径/  映射到代码的web目录

         静态包含的特点:
            1、静态包含不会翻译被包含的jsp页面。
            2、静态包含其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出。
    <%@ include file="/include/footer.jsp"%>--%>


4.12.2 jsp 动态包含

示例说明:

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

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

动态包含的底层原理
在这里插入图片描述


4.13 jsp 标签-转发

示例说明:

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

4.14 jsp 的练习题
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <style type="text/css">

        table{
            width: 650px;
        }

    </style>
</head>
<body>
    <%-- 练习一:在jsp页面中输出九九乘法口诀表 --%>
    <h1 align="center">九九乘法口诀表</h1>
    <table align="center">
    <% for (int i = 1; i <= 9; i++) { %>
        <tr>
        <% for (int j = 1; j <= i ; j++) { %>
            <td><%=j + "x" + i + "=" + (i*j)%></td>
        <% } %>
        </tr>
    <% } %>
    </table>
</body>
</html>

运行结果:
在这里插入图片描述


4.15 什么是 Listener 监听器?
  • ServletContextListener 它可以监听 ServletContext 对象的创建和销毁。
  • ServletContext 对象在 web 工程启动的时候创建,在 web 工程停止的时候销毁。
  • 监听到创建和销毁之后都会分别调用ServletContextListener 监听器的方法反馈。

两个方法分别是:

public interface ServletContextListener extends EventListener {
    /**
     * 在 ServletContext 对象创建之后马上调用,做初始化 
     */
    public void contextInitialized(ServletContextEvent sce);
    /**
     * 在 ServletContext 对象销毁之后调用 
     */
    public void contextDestroyed(ServletContextEvent sce);
}

如何使用 ServletContextListener 监听器监听 ServletContext 对象。
使用步骤如下:

  1. 编写一个类去实现 ServletContextListener
  2. 实现其两个回调方法
  3. 到 web.xml 中去配置监听器

监听器实现类:

public class MyServletContextListenerImpl implements ServletContextListener {

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

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext对象被销毁了");
    }
}

web.xml 中的配置:

   <!--配置监听器-->
    <listener>
        <listener-class>com.atguigu.listener.MyServletContextListenerImpl</listener-class>
    </listener>

4.16 EL 表达式
4.17 什么是 EL 表达式,EL 表达式的作用?
  • EL 表达式的全称是:Expression Language。是表达式语言。
  • EL 表达式的什么作用:EL 表达式主要是代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。
  • 因为 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁很多。
<body>
    <%
        request.setAttribute("key","值");
    %>
    表达式脚本输出key的值是:<%=request.getAttribute("key1")%><br/>
    EL表达式输出key的值是:${key1}
</body>

运行结果:
表达式脚本输出key的值是:null
EL表达式输出key的值是:

总结

  • EL 表达式的格式是:${表达式} EL 表达式在输出 null 值的时候,输出的是空串。jsp 表达式脚本输出 null 值的时候,输出的是 null 字符串。

4.18 EL表达式搜索域数据的顺序
  • EL 表达式主要是在 jsp 页面中输出数据。
  • 主要是输出域对象中的数据。
  • 当四个域中都有相同的 key 的数据的时候,EL 表达式会按照四个域的从小到大的顺序去进行搜索,找到就输出。
<body>
    <%
        //往四个域中都保存了相同的key的数据。
        request.setAttribute("key", "request");
        session.setAttribute("key", "session");
        application.setAttribute("key", "application");
        pageContext.setAttribute("key", "pageContext");
    %>
    ${ key }
</body>

运行结果:
pageContext
(优先度最大)


4.19 EL表达式输出Bean的普通属性,数组属性。List 集 合属性,map集合属性
  • 需求——输出 Person 类中普通属性,数组属性。list 集合属性和 map 集合属性。

Person 类

public class Person {
//    i.需求——输出Person类中普通属性,数组属性。list集合属性和map集合属性。
    private String name;
    private String[] phones;
    private List<String> cities;
    private Map<String,Object> map;

    public int getAge() {
        return 18;
    }
    .....

输出的代码

<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>
    输出Person的age属性:${p.age} <br>
</body>

运行结果:
在这里插入图片描述


4.20 EL 表达式——运算

语法:${ 运算表达式 } , EL 表达式支持如下运算符

在这里插入图片描述


算数运算
在这里插入图片描述


4.21 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<>();
//        list.add("abc");
        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/>

    <hr>
    ${ 12 != 12 ? "国哥帅呆":"国哥又骗人啦" }
</body>

运行结果:
//判断是否为空 true
true
true
true
true
国哥又骗人啦


4.22 三元运算
  • 表达式 1?表达式 2:表达式 3
  • 如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。

示例:
${ 12 != 12 ? “国哥帅呆”:“国哥又骗人啦” }


4.23 “.”点运算 和 [] 中括号运算符
  • .点运算,可以输出 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>
</body>

运行结果:
aaaValue
bbbValue
cccValue


4.24 EL表达式的 11 个隐含对象
  • EL 个达式中 11 个隐含对象,是 EL 表达式中自己定义的,可以直接使用。
    在这里插入图片描述
    在这里插入图片描述

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

在这里插入图片描述

<body>
    <%
        pageContext.setAttribute("key1", "pageContext1");
        pageContext.setAttribute("key2", "pageContext2");
        request.setAttribute("key2", "request");
        session.setAttribute("key2", "session");
        application.setAttribute("key2", "application");
    %>
    ${ applicationScope.key2 }
</body>

运行结果:
application


3.26 pageContext 对象的使用
  1. 协议:
  2. 服务器 ip:
  3. 服务器端口:
  4. 获取工程路径:
  5. 获取请求方法:
  6. 获取客户端 ip 地址:
  7. 获取会话的 id 编号:
<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>
3.27 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" %>
4.28 JSTL 标签库的使用步骤

在这里插入图片描述


4.29 core 核心库使用
  • <c:set />(使用很少)
  • 作用:set 标签可以往域中保存数据
<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>

运行结果:
保存之前:
保存之后:abcValue
12等于12
还可以


4.30 forEach遍历
public class Student {
    //4.编号,用户名,密码,年龄,电话信息
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String phone;
    ......
<body>
    <%--1.遍历1到10,输出
        begin属性设置开始的索引
        end 属性设置结束的索引
        var 属性表示循环的变量(也是当前正在遍历到的数据)
        for (int i = 1; i < 10; i++)

    <table border="1">
        <c:forEach begin="1" end="10" var="i">
            <tr>
                <td>第${i}行</td>
            </tr>
        </c:forEach>
    </table>--%>
    <hr>
   <%-- 2.遍历Object数组
        for (Object item: arr)
        items 表示遍历的数据源(遍历的集合)
        var 表示当前遍历到的数据

    <%
        request.setAttribute("arr", new String[]{"18610541354","18688886666","18699998888"});
    %>
    <c:forEach items="${ requestScope.arr }" var="item">
        ${ item } <br>
    </c:forEach> --%>
    <hr>
    <%
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
//        for ( Map.Entry<String,Object> entry : map.entrySet()) {
//        }
        request.setAttribute("map", map);
    %>
    <c:forEach items="${ requestScope.map }" var="entry">
        <h1>${entry.key} = ${entry.value}</h1>
    </c:forEach>
    <hr>
    <%--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>
</body>

运行结果:
在这里插入图片描述


5.0 文件的上传和下载

5.1 文件的上传介绍(*****重点)
  1. 要有一个 form 标签,method=post 请求
  2. form 标签的 encType 属性值必须为multipart/form-data 值
  3. 在 form 标签中使用 input type=file 添加上传的文件
  4. 编写服务器代码(Servlet 程序)接收,处理上传的数据。

encType=multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼 接,然后以二进制流的形式发送给服务器


5.2 文件上传,HTTP 协议的说明。

在这里插入图片描述


5.3 commons-fileupload.jar 常用 API 介绍说明
  • commons-fileupload.jar 需要依赖 commons-io.jar 这个包,所以两个包我们都要引入。
  • 第一步,就是需要导入两个 jar 包: commons-fileupload-1.2.1.jar commons-io-1.4.jar
5.3.1 commons-fileupload.jar 和 commons-io.jar 包中,我们常用的类有哪些?

在这里插入图片描述
在这里插入图片描述


5.4 fileupload 类库的使用

上传文件的表单

<body>
    <form action="http://localhost:8080/09_EL_JSTL/uploadServlet" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username" /> <br>
        头像:<input type="file" name="photo" > <br>
        <input type="submit" value="上传">
    </form>
</body>

解析上传的数据的代码

public class UploadServlet extends HttpServlet {
    /**
     * 用来处理上传的数据
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1 先判断上传的数据是否多段数据(只有是多段的数据,才是文件上传的)
        if (ServletFileUpload.isMultipartContent(req)) {
//           创建FileItemFactory工厂实现类
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            // 创建用于解析上传数据的工具类ServletFileUpload类
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            try {
                // 解析上传的数据,得到每一个表单项FileItem
                List<FileItem> list = servletFileUpload.parseRequest(req);
                // 循环判断,每一个表单项,是普通类型,还是上传的文件
                for (FileItem fileItem : list) {

                    if (fileItem.isFormField()) {
                        // 普通表单项
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        // 参数UTF-8.解决乱码问题
                        System.out.println("表单项的value属性值:" + fileItem.getString("UTF-8"));
                    } else {
                        // 上传的文件
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        System.out.println("上传的文件名:" + fileItem.getName());

                        fileItem.write(new File("d:\\" + fileItem.getName()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

web.xml

    <servlet>
        <servlet-name>UploadServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.UploadServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>UploadServlet</servlet-name>
        <url-pattern>/uploadServlet</url-pattern>
    </servlet-mapping>

运行结果:
表单项的name属性值:username
表单项的value属性值:admin
表单项的name属性值:photo
上传的文件名:2003219.jpg
(成功传入d盘中)
在这里插入图片描述


5.5 文件下载

在这里插入图片描述

下载的常用 API 说明:

  1. response.getOutputStream();
  2. servletContext.getResourceAsStream();
  3. servletContext.getMimeType();
  4. response.setContentType();
  • response.setHeader(“Content-Disposition”, “attachment; fileName=1.jpg”);
  • 这个响应头告诉浏览器。这是需要下载的。而 attachment 表示附件,也就是下载的一个文件。fileName=后面, 表示下载的文件名。
  • 完成上面的两个步骤,下载文件是没问题了。但是如果我们要下载的文件是中文名的话。你会发现,下载无法正确
    显示出正确的中文名。 原因是在响应头中,不能包含有中文字符,只能包含 ASCII 码。

5.6 附件中文名乱码问题解决方案

方案一:URLEncoder 解决 IE 和谷歌浏览器的 附件中 文名问题。

  • 如果客户端浏览器是 IE 浏览器 或者 是谷歌浏览器。我们需要使用 URLEncoder 类先对中文名进行 UTF-8 的编码 操作。因为 IE 浏览器和谷歌浏览器收到含有编码后的字符串后会以 UTF-8 字符集进行解码显示。
// 把中文名进行 UTF-8 编码操作。 
String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8"); 
// 然后把编码后的字符串设置到响应头中 
response.setHeader("Content-Disposition", str);

方案二:BASE64 编解码 解决 火狐浏览器的附件中文名问题
在这里插入图片描述


【Download.java】

public class Download extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、获取要下载的文件名
        String downloadFileName = "2.jpg";
//        2、读取要下载的文件内容 (通过ServletContext对象可以读取)
        ServletContext servletContext = getServletContext();
        // 获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        System.out.println("下载的文件类型:" + mimeType);
//        4、在回传前,通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);
//        5、还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
        // Content-Disposition响应头,表示收到的数据怎么处理
        // attachment表示附件,表示下载使用
        // filename= 表示指定下载的文件名
        // url编码是把汉字转换成为%xx%xx的格式
        if (req.getHeader("User-Agent").contains("Firefox")) {
            // 如果是火狐浏览器使用Base64编码
            resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + new BASE64Encoder().encode("中国.jpg".getBytes("UTF-8")) + "?=");
        } else {
            // 如果不是火狐,是IE或谷歌,使用URL编码操作
            resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("中国.jpg", "UTF-8"));
        }
        /**
         * /斜杠被服务器解析表示地址为http://ip:prot/工程名/  映射 到代码的Web目录
         */
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
        // 获取响应的输出流
        OutputStream outputStream = resp.getOutputStream();
        //        3、把下载的文件内容回传给客户端
        // 读取输入流中全部的数据,复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream, outputStream);
    }
}

配制好web.xml
在这里插入图片描述
运行结果:
在这里插入图片描述
在这里插入图片描述


6.0 Cookie 和 Session

6.1 什么是 Cookie?
  1. Cookie 翻译过来是饼干的意思。
  2. Cookie 是服务器通知客户端保存键值对的一种技术。
  3. 客户端有了 Cookie后,每次请求都发送给服务器。
  4. 每个 Cookie 的大小不能超过 4kb

6.2 如何创建 Cookie

在这里插入图片描述


Servlet 程序中的代码:
【CookieServlet.java】

public class CookieServlet extends BaseServlet {
    protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1 创建Cookie对象
        Cookie cookie = new Cookie("key4", "value4");
        //2 通知客户端保存Cookie
        resp.addCookie(cookie);
        //1 创建Cookie对象
        Cookie cookie1 = new Cookie("key5", "value5");
        //2 通知客户端保存Cookie
        resp.addCookie(cookie1);

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

public abstract class BaseServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决post请求中文乱码问题
        // 一定要在获取请求参数之前调用才有效
        req.setCharacterEncoding("UTF-8");
        // 解决响应中文乱码问题
        resp.setContentType("text/html; charset=UTF-8");

        String action = req.getParameter("action");
        try {
            // 获取action业务鉴别字符串,获取相应的业务 方法反射对象
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//            System.out.println(method);
            // 调用目标业务 方法
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

【web.xml】

    <servlet>
        <servlet-name>CookieServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.CookieServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieServlet</servlet-name>
        <url-pattern>/cookieServlet</url-pattern>
    </servlet-mapping>

【cookie.htnl】

<body>
	<iframe name="target" width="500" height="500" style="float: left;"></iframe>
	<div style="float: left;">
		<ul>
			<li><a href="cookieServlet?action=createCookie" target="target">Cookie的创建</a></li>
			<li><a href="cookieServlet?action=getCookie" target="target">Cookie的获取</a></li>
			<li><a href="cookieServlet?action=updateCookie" target="target">Cookie值的修改</a></li>
			<li>Cookie的存活周期</li>
			<li>
				<ul>
					<li><a href="cookieServlet?action=defaultLife" target="target">Cookie的默认存活时间(会话)</a></li>
					<li><a href="cookieServlet?action=deleteNow" target="target">Cookie立即删除</a></li>
					<li><a href="cookieServlet?action=life3600" target="target">Cookie存活3600秒(1小时)</a></li>
				</ul>
			</li>
			<li><a href="cookieServlet?action=testPath" target="target">Cookie的路径设置</a></li>
			<li><a href="" target="target">Cookie的用户免登录练习</a></li>
		</ul>
	</div>
</body>

运行结果:
在这里插入图片描述


6.3 服务器如何获取Cookie

服务器获取客户端的 Cookie 只需要一行代码:req.getCookies():Cookie[]
在这里插入图片描述


Cookie 的工具类:
【CookieUtils】

public class CookieUtils {
    /**
     * 查找指定名称的Cookie对象
     * @param name
     * @param cookies
     * @return
     */
    public static Cookie findCookie(String name , Cookie[] cookies){
        if (name == null || cookies == null || cookies.length == 0) {
            return null;
        }

        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                return cookie;
            }
        }
        return null;
    }
}

Servlet 程序中的代码:

    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);

//        for (Cookie cookie : cookies) {
//            if ("key2".equals(cookie.getName())) {
//                iWantCookie = cookie;
//                break;
//            }
//        }
        // 如果不等于null,说明赋过值,也就是找到了需要的Cookie
        if (iWantCookie != null) {
            resp.getWriter().write("找到了需要的Cookie");
        }
    }

运行结果:
在这里插入图片描述


6.4 Cookie 值的修改

方案一:

  1. 先创建一个要修改的同名(指的就是 key)的 Cookie 对象
  2. 在构造器,同时赋于新的 Cookie 值。
  3. 调用 response.addCookie( Cookie );
// 
方案一: 
// 
1、先创建一个要修改的同名的 Cookie 对象 
// 
2、在构造器,同时赋于新的 Cookie 值。Cookie cookie = new Cookie("key1","newValue1"); 
// 
3、调用 response.addCookie( Cookie ); 通知 客户端 保存修改 
resp.addCookie(cookie);

方案二:

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

6.5 谷歌浏览器如何查看 Cookie:

在这里插入图片描述


6.6 Cookie 生命控制

在这里插入图片描述

    /**
     * 设置存活1个小时的Cooie
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    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");

    }

    /**
     * 马上删除一个Cookie
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    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已经被删除");
        }

    }

6.7 Cookie 有效路径 Path 的设置

在这里插入图片描述

   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");
    }


6.8 Cookie 练习—免输入用户名登录

在这里插入图片描述


login.jsp 页面

<form action="http://localhost:8080/13_cookie_session/loginServlet" method="get">
    用户名:<input type="text" name="username" value="${cookie.username.value}"> <br>
    密码:<input type="password" name="password"> <br>
    <input type="submit" value="登录">
</form>

LoginServlet 程序:

public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if ("wzg168".equals(username) && "123456".equals(password)) {
            //登录 成功
            Cookie cookie = new Cookie("username", username);
            cookie.setMaxAge(60 * 60 * 24 * 7);//当前Cookie一周内有效
            resp.addCookie(cookie);
            System.out.println("登录 成功");
        } else {
//            登录 失败
            System.out.println("登录 失败");
        }
    }
}

运行结果:
第二次访问时username会存在
在这里插入图片描述


6.9 什么是 Session 会话?
  1. Session 就一个接口(HttpSession)。
  2. Session就是会话。它是用来维护一个客户端和服务器之间关联的一种技术。
  3. 每个客户端都有自己的一个 Session 会话。
  4. Session会话中,我们经常用来保存用户登录之后的信息。

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

在这里插入图片描述


6.11 Session 域数据的存取
public class SessionServlet extends BaseServlet {
    /**
     * 往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);
    }
   }

<body>
	<iframe name="target" width="500" height="500" style="float: left;"></iframe>
	<div style="float: left;">
		<ul>
			<li><a href="sessionServlet?action=createOrGetSession" target="target">Session的创建和获取(id号、是否为新创建)</a></li>
			<li><a href="sessionServlet?action=setAttribute" target="target">Session域数据的存储</a></li>
			<li><a href="sessionServlet?action=getAttribute" target="target">Session域数据的获取</a></li>
			<li>Session的存活</li>
			<li>
				<ul>
					<li><a href="sessionServlet?action=defaultLife" target="target">Session的默认超时及配置</a></li>
					<li><a href="sessionServlet?action=life3" target="target">Session3秒超时销毁</a></li>
					<li><a href="sessionServlet?action=deleteNow" target="target">Session马上销毁</a></li>
				</ul>
			</li>
			<li><a href="" target="target">浏览器和Session绑定的原理</a></li>
		</ul>
	</div>
</body>

运行结果:
在这里插入图片描述


6.12 Session 生命周期控制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


6.13 Session 超时的概念介绍:

在这里插入图片描述

示例代码:

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

        resp.getWriter().write("当前Session已经设置为3秒后超时");
    }

Session 马上被超时示例:

    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 先获取Session对象
        HttpSession session = req.getSession();
        // 让Session会话马上超时
        session.invalidate();

        resp.getWriter().write("Session已经设置为超时(无效)");
    }

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

Session 技术,底层其实是基于 Cookie 技术来实现的。
在这里插入图片描述


7.0 Filter 过滤器

7.1 Filter 什么是过滤器

在这里插入图片描述


7.2 Filter 的初体验
  • 要求:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必 须是用户登录之后才允许访问。
  • 思考:根据之前我们学过内容。我们知道,用户登录之后都会把用户登录的信息保存到 Session 域中。所以要检查用户是否
  • 登录,可以判断 Session 中否包含有用户登录的信息即可!!!

【a.jsp】

<%
    System.out.println("a.jsp页面执行了");
    Object user = session.getAttribute("user");
    //如果等于 null,说明还没有登录
    if (user == null) {
        request.getRequestDispatcher("login.jsp").forward(request, response);
        return;
    }
%>

在这里插入图片描述


Filter 的代码:

public class AdminFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤方法");
        HttpServletRequest httpServletRequest= (HttpServletRequest) servletRequest;
        HttpSession session=httpServletRequest.getSession();
        Object user = session.getAttribute("user");
        //如果等于 null,说明还没有登录
        if (user == null) {
            servletRequest.getRequestDispatcher("/admin/login.jsp").forward(servletRequest,servletResponse);
            return;
        }else {
            //让程序继续往下访问用户的目标资源
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
  }

web.xml 中的配置:

    <!--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 的拦截路径

7.3 完整的用户登录

login.jsp 页面 == 登录表单

<body>
这是登录页面。login.jsp 页面 <br>
<form action="http://localhost:8080/15_filter/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("/admin/login.jsp").forward(req, resp);
        }
    }
}

在这里插入图片描述
在这里插入图片描述

7.4 Filter 的生命周期

在这里插入图片描述


7.4 FilterConfig 类
  • FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。
  • Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。

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

  1. 获取 Filter 的名称 filter-name 的内容
  2. 获取在 Filter 中配置的 init-param 初始化参数
  3. 获取 ServletContext 对象

java 代码:

public class AdminFilter implements Filter {

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

web.xml 配置:

    <!--filter 标签用于配置一个 Filter 过滤器-->
    <filter>
        <!--给 filter 起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置 filter 的全类名-->
        <filter-class>com.atguigu.filter.AdminFilter</filter-class>
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost3306/test</param-value>
        </init-param>
    </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>

在这里插入图片描述


在这里插入图片描述


7.5 Filter 的拦截路径

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


8.0 JSON、AJAX、i18n

8.1 什么是 JSON?
  • JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON 采用完全独立于语言的文本格式,而且很多语言都提供了对 json 的支持(包括 C, C++, C#, Java, JavaScript, Perl, Python 等)。 这样就使得 JSON 成为理想的数据交换格式。
  • json 是一种轻量级的数据交换格式。
  • 轻量级指的是跟 xml 做比较。
  • 数据交换指的是客户端和服务器之间业务数据的传递格式。

8.2 JSON 在 JavaScript 中的使用。
8.2.1 json 的定义
  • json 是由键值对组成,并且由花括号(大括号)包围。每个键由引号引起来,键和值之间使用冒号进行分隔, 多组键值对之间进行逗号进行分隔。

json 定义示例:

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

8.3 json 的访问
  1. json 本身是一个对象。
  2. json 中的 key 我们可以理解为是对象中的一个属性。
  3. json 中的 key 访问就跟访问对象的属性一样:
  4. json 对象.key

json 访问示例:

// alert(typeof(jsonObj));// object  json就是一个对象
// alert(jsonObj.key1); //12
// alert(jsonObj.key2); // abc
// alert(jsonObj.key3); // true
// alert(jsonObj.key4);// 得到数组[11,"arr",false]
//  // json 中 数组值的遍历
// for(var i = 0; i < jsonObj.key4.length; i++) {
// 	alert(jsonObj.key4[i]);
// }
// alert(jsonObj.key5.key5_1);//551
// alert(jsonObj.key5.key5_2);//key5_2_value
// alert( jsonObj.key6 );// 得到json数组
//
// // 取出来每一个元素都是json对象
// var jsonItem = jsonObj.key6[0];
// // alert( jsonItem.key6_1_1 ); //6611
// alert( jsonItem.key6_1_2 ); //key6_1_2_value

8.4 json 的两个常用方法

在这里插入图片描述

// 把json对象转换成为 json字符串
var jsonObjString = JSON.stringify(jsonObj); // 特别像 Java中对象的toString
//alert(jsonObjString)
// 把json字符串。转换成为json对象
var jsonObj2 = JSON.parse(jsonObjString);
alert(jsonObj2.key1);// 12
alert(jsonObj2.key2);// abc
alert((jsonObj2))
// json的访问
// json对象转字符串
// json字符串转json对象

8.5 JSON 在 java 中的使用

导入gson包
在这里插入图片描述

【Person.java】

public class Person {

    private Integer id;
    private String name;

javaBean 和 json 的互转

【JsonTest.java】

    //    1.2.1、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);
    }

运行结果:
{“id”:1,“name”:“国哥好帅!”}
Person{id=1, name=‘国哥好帅!’}


TypeToken类

public class PersonMapType extends TypeToken<HashMap<Integer, Person>> {
}

List 和 json 的互转

    //    1.2.2、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);
    }

运行结果:
[{“id”:1,“name”:“国哥”},{“id”:2,“name”:“康师傅”}]
[Person{id=1, name=‘国哥’}, Person{id=2, name=‘康师傅’}]
Person{id=1, name=‘国哥’}


map 和 json 的互转

    //    1.2.3、map 和json的互转
    @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());
        //避免创建过多的继承TypeToken的类,使用匿名内部类
        Map<Integer, Person> personMap2 = gson.fromJson(personMapJsonString, new TypeToken<HashMap<Integer, Person>>() {
        }.getType());
        System.out.println(personMap2);
        Person p = personMap2.get(1);
        System.out.println(p);
    }

运行结果:
{“1”:{“id”:1,“name”:“国哥好帅”},“2”:{“id”:2,“name”:“康师傅也好帅”}}
{1=Person{id=1, name=‘国哥好帅’}, 2=Person{id=2, name=‘康师傅也好帅’}}
Person{id=1, name=‘国哥好帅’}


8.6 AJAX 请求
8.6.1 什么是 AJAX 请求

在这里插入图片描述


6.7 原生 AJAX 请求的示例:
<head>
    <meta http-equiv="pragma" content="no-cache"/>
    <meta http-equiv="cache-control" content="no-cache"/>
    <meta http-equiv="Expires" content="0"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript">
        // 在这里使用javaScript语言发起Ajax请求,访问服务器AjaxServlet中javaScriptAjax
        function ajaxRequest() {
// 				1、我们首先要创建XMLHttpRequest 
            var xmlhttprequest = new XMLHttpRequest();
// 				2、调用open方法设置请求参数
            xmlhttprequest.open("GET", "http://localhost:8080/16_json_ajax_i18n/ajaxServlet?action=javaScriptAjax", true);
// 				4、在send方法前绑定onreadystatechange事件,处理请求完成后的操作。
            xmlhttprequest.onreadystatechange = function () {
                if (xmlhttprequest.readyState == 4 && xmlhttprequest.status == 200) {
                    alert("收到服务器返回的数据:" + xmlhttprequest.responseText);
                    var jsonObj = JSON.parse(xmlhttprequest.responseText);
                    // 把响应的数据显示在页面上
                    document.getElementById("div01").innerHTML = "编号:" + jsonObj.id + " , 姓名:" + jsonObj.name;
                }
            }
// 				3、调用send方法发送请求
            xmlhttprequest.send();


            alert("我是最后一行的代码");

        }
    </script>
</head>
<body>
<!--		<a href="http://localhost:8080/16_json_ajax_i18n/ajaxServlet?action=javaScriptAjax">非Ajax</a>-->
<button onclick="ajaxRequest()">ajax request</button>
<button onclick="ajaxRequest()">ajax request</button>
<button onclick="ajaxRequest()">ajax request</button>
<button onclick="ajaxRequest()">ajax request</button>
<button onclick="ajaxRequest()">ajax request</button>
<div id="div01">
</div>
<table border="1">
    <tr>
        <td>1.1</td>
        <td>1.2</td>
    </tr>
    <tr>
        <td>2.1</td>
        <td>2.2</td>
    </tr>
</table>
</body>

public class AjaxServlet extends BaseServlet {

    protected void javaScriptAjax(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Ajax请求过来了");
        Person person = new Person(1, "国哥");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // json格式的字符串
        Gson gson = new Gson();
        String personJsonString = gson.toJson(person);

        resp.getWriter().write(personJsonString);
    }

运行结果:
true为异步请求,点击按钮时,alert(“我是最后一行的代码”);先执行,AjaxServlet后执行,哪个先快哪个先执行。
false为同步请求,点击按钮时,先等待AjaxServlet执行,alert(“我是最后一行的代码”);才执行。

在这里插入图片描述


8.8 jQuery 中的 AJAX 请求

在这里插入图片描述

<script type="text/javascript">
    $(function () {
        // ajax请求
        $("#ajaxBtn").click(function () {
            $.ajax({
                url: "http://localhost:8080/16_json_ajax_i18n/ajaxServlet",
                // data:"action=jQueryAjax",
                data: {action: "jQueryAjax"},
                type: "GET",
                success: function (data) {
                    // alert("服务器返回的数据是:" + data);
                    // var jsonObj = JSON.parse(data);
                    $("#msg").html(" ajax 编号:" + data.id + " , 姓名:" + data.name);
                },
                dataType: "json"
            });
        });
    });
</script>
......
<div>
    <button id="ajaxBtn">$.ajax请求</button>
    <button id="getBtn">$.get请求</button>
    <button id="postBtn">$.post请求</button>
    <button id="getJSONBtn">$.getJSON请求</button>
</div>
    protected void jQueryAjax(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("  jQueryAjax == 方法调用了");
        Person person = new Person(1, "国哥");
        // json格式的字符串
        Gson gson = new Gson();
        String personJsonString = gson.toJson(person);

        resp.getWriter().write(personJsonString);
    }

运行结果:
在这里插入图片描述


在这里插入图片描述

<script type="text/javascript">
$(function () {
    // ajax--get请求
    $("#getBtn").click(function () {
     $.get("http://localhost:8080/16_json_ajax_i18n/ajaxServlet", "action=jQueryGet", function (data) {
            $("#msg").html(" get 编号:" + data.id + " , 姓名:" + data.name);
        }, "json");
    });
   });
</script>
    protected void jQueryGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("  jQueryGet  == 方法调用了");
        Person person = new Person(1, "国哥");
        // json格式的字符串
        Gson gson = new Gson();
        String personJsonString = gson.toJson(person);

        resp.getWriter().write(personJsonString);
    }

运行结果:
在这里插入图片描述

<script type="text/javascript">
$(function () {
    // ajax--post请求
    $("#postBtn").click(function () {
        // post请求
        $.post("http://localhost:8080/16_json_ajax_i18n/ajaxServlet", "action=jQueryPost", function (data) {
            $("#msg").html(" post 编号:" + data.id + " , 姓名:" + data.name);
        }, "json");
    });
    });
</script>
    protected void jQueryPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("  jQueryPost   == 方法调用了");
        Person person = new Person(1, "国哥");
        // json格式的字符串
        Gson gson = new Gson();
        String personJsonString = gson.toJson(person);

        resp.getWriter().write(personJsonString);
    }

运行结果:
在这里插入图片描述


在这里插入图片描述

<script type="text/javascript">
$(function () {
    // ajax请求
    $("#submit").click(function () {
        // 把参数序列化
        $.getJSON("http://localhost:8080/16_json_ajax_i18n/ajaxServlet", "action=jQuerySerialize&" + $("#form01").serialize(), function (data) {
            $("#msg").html(" Serialize 编号:" + data.id + " , 姓名:" + data.name);
        });
    });
   });
</script>
    protected void jQueryGetJSON(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("  jQueryGetJSON   == 方法调用了");
        Person person = new Person(1, "国哥");
        // json格式的字符串
        Gson gson = new Gson();
        String personJsonString = gson.toJson(person);

        resp.getWriter().write(personJsonString);
    }

在这里插入图片描述


在这里插入图片描述

<script type="text/javascript">
$(function () {
    // ajax请求
    $("#submit").click(function () {
        // 把参数序列化
        $.getJSON("http://localhost:8080/16_json_ajax_i18n/ajaxServlet", "action=jQuerySerialize&" + $("#form01").serialize(), function (data) {
            $("#msg").html(" Serialize 编号:" + data.id + " , 姓名:" + data.name);
        });
    });
   });
</script>
.....
<form id="form01">
    用户名:<input name="username" type="text"/><br/>
    密码:<input name="password" type="password"/><br/>
    下拉单选:<select name="single">
    <option value="Single">Single</option>
    <option value="Single2">Single2</option>
</select><br/>
    下拉多选:
    <select name="multiple" multiple="multiple">
        <option selected="selected" value="Multiple">Multiple</option>
        <option value="Multiple2">Multiple2</option>
        <option selected="selected" value="Multiple3">Multiple3</option>
    </select><br/>
    复选:
    <input type="checkbox" name="check" value="check1"/> check1
    <input type="checkbox" name="check" value="check2" checked="checked"/> check2<br/>
    单选:
    <input type="radio" name="radio" value="radio1" checked="checked"/> radio1
    <input type="radio" name="radio" value="radio2"/> radio2<br/>
</form>
<button id="submit">提交--serialize()</button>
    protected void jQuerySerialize(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("  jQuerySerialize   == 方法调用了");
        System.out.println("用户名:" + req.getParameter("username"));
        System.out.println("密码:" + req.getParameter("password"));

        Person person = new Person(1, "国哥");
        // json格式的字符串
        Gson gson = new Gson();
        String personJsonString = gson.toJson(person);
        resp.getWriter().write(personJsonString);
    }

在这里插入图片描述
jQuerySerialize == 方法调用了
用户名:admin
密码:123456


9.0 i18n 国际化(了解内容)

9.1 什么是 i18n 国际化?

在这里插入图片描述


9.2 国际化相关要素介绍

在这里插入图片描述

国际化资源 properties 测试

  • 配置两个语言的配置文件:
  • i18n_en_US.properties 英文
username=username
password=password
sex=sex
age=age
regist=regist
boy=boy
email=email
girl=girl
reset=reset
submit=submit

i18n_zh_CN.properties 中文

username=用户名 
password=密码 
sex=性别 
age=年龄 
regist=注册 
boy=男 
girl=女 
email=邮箱 
reset=重置 
submit=提交

国际化测试代码:

    @Test
    public void testLocale() {
        // 获取你系统默认的语言。国家信息
//        Locale locale = Locale.getDefault();
//        System.out.println(locale);
        //遍历可用的语言
//        for (Locale availableLocale : Locale.getAvailableLocales()) {
//            System.out.println(availableLocale);
//        }

        // 获取中文,中文的常量的Locale对象
        System.out.println(Locale.CHINA);
        // 获取英文,美国的常量的Locale对象
        System.out.println(Locale.US);

    }

    @Test
    public void testI18n() {
        // 得到我们需要的Locale对象
        Locale locale = Locale.CHINA;
        // 通过指定的basename和Locale对象,读取 相应的配置文件
        ResourceBundle bundle = ResourceBundle.getBundle("i18n", locale);

        System.out.println("username:" + bundle.getString("username"));
        System.out.println("password:" + bundle.getString("password"));
        System.out.println("Sex:" + bundle.getString("sex"));
        System.out.println("age:" + bundle.getString("age"));
    }

2运行结果:
username:用户名
password:密码
Sex:性别
age:年龄


9.3 通过请求头国际化页面
<%@ page import="java.util.ResourceBundle" %>
<%@ page import="java.util.Locale" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="pragma" content="no-cache"/>
    <meta http-equiv="cache-control" content="no-cache"/>
    <meta http-equiv="Expires" content="0"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>
<%
    // 从请求头中获取 Locale 信息(语言)
    Locale locale = request.getLocale();
    System.out.println(locale);
// 获取读取包(根据 指定的 baseName 和 Locale 读取语言信息)
    ResourceBundle i18n = ResourceBundle.getBundle("i18n", locale);
%>


<a href="">中文</a>|
<a href="">english</a>
<center>
    <h1><%=i18n.getString("regist")%></h1>
    <table>
        <form>
            <tr>
                <td><%=i18n.getString("username")%></td>
                <td><input name="username" type="text"/></td>
            </tr>
            <tr>
                <td><%=i18n.getString("password")%></td>
                <td><input type="password"/></td>
            </tr>
            <tr>
                <td><%=i18n.getString("sex")%></td>
                <td>
                    <input type="radio"/><%=i18n.getString("boy")%>
                    <input type="radio"/><%=i18n.getString("girl")%>
                </td>
            </tr>
            <tr>
                <td><%=i18n.getString("email")%></td>
                <td><input type="text"/></td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="reset" value="<%=i18n.getString("reset")%>" />&nbsp;&nbsp;
                    <input type="submit" value="<%=i18n.getString("submit")%>" /></td>
            </tr>
        </form>
    </table>
    <br/> <br/> <br/> <br/>
</center>
国际化测试:
<br /> 1、访问页面,通过浏览器设置,请求头信息确定国际化语言。
<br /> 2、通过左上角,手动切换语言
</body>
</html>

运行结果:
根据浏览器语言优先级最大的显示
在这里插入图片描述


9.4 通过显示的选择语言类型进行国际化
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.ResourceBundle" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
		 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		// 从请求头中获取Locale信息(语言)
		Locale locale = null;

		String country = request.getParameter("country");
		if ("cn".equals(country)) {
			locale = Locale.CHINA;
		} else if ("usa".equals(country)) {
			locale = Locale.US;
		} else {
			locale = request.getLocale();
		}

		System.out.println(locale);
		// 获取读取包(根据 指定的baseName和Locale读取 语言信息)
		ResourceBundle i18n = ResourceBundle.getBundle("i18n", locale);
	%>
	<a href="i18n.jsp?country=cn">中文</a>|
	<a href="i18n.jsp?country=usa">english</a>
	<center>
		<h1><%=i18n.getString("regist")%></h1>
		<table>
		<form>
			<tr>
				<td><%=i18n.getString("username")%></td>
				<td><input name="username" type="text" /></td>
			</tr>
			<tr>
				<td><%=i18n.getString("password")%></td>
				<td><input type="password" /></td>
			</tr>
			<tr>
				<td><%=i18n.getString("sex")%></td>
				<td>
					<input type="radio" /><%=i18n.getString("boy")%>
					<input type="radio" /><%=i18n.getString("girl")%>
				</td>
			</tr>
			<tr>
				<td><%=i18n.getString("email")%></td>
				<td><input type="text" /></td>
			</tr>
			<tr>
				<td colspan="2" align="center">
				<input type="reset" value="<%=i18n.getString("reset")%>" />&nbsp;&nbsp;
				<input type="submit" value="<%=i18n.getString("submit")%>" /></td>
			</tr>
			</form>
		</table>
		<br /> <br /> <br /> <br />
	</center>
	国际化测试:
	<br /> 1、访问页面,通过浏览器设置,请求头信息确定国际化语言。
	<br /> 2、通过左上角,手动切换语言
</body>
</html>

运行结果:
在这里插入图片描述


9.5 JSTL 标签库实现国际化

在这里插入图片描述

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="pragma" content="no-cache"/>
    <meta http-equiv="cache-control" content="no-cache"/>
    <meta http-equiv="Expires" content="0"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>
<%--1 使用标签设置Locale信息--%>
<fmt:setLocale value="${param.locale}"/>
<%--2 使用标签设置baseName--%>
<fmt:setBundle basename="i18n"/>


<a href="i18n_fmt.jsp?locale=zh_CN">中文</a>|
<a href="i18n_fmt.jsp?locale=en_US">english</a>
<center>
    <h1><fmt:message key="regist"/></h1>
    <table>
        <form>
            <tr>
                <td><fmt:message key="username"/></td>
                <td><input name="username" type="text"/></td>
            </tr>
            <tr>
                <td><fmt:message key="password"/></td>
                <td><input type="password"/></td>
            </tr>
            <tr>
                <td><fmt:message key="sex"/></td>
                <td>
                    <input type="radio"/><fmt:message key="boy"/>
                    <input type="radio"/><fmt:message key="girl"/>
                </td>
            </tr>
            <tr>
                <td><fmt:message key="email"/></td>
                <td><input type="text"/></td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="reset" value="<fmt:message key="reset" />"/>&nbsp;&nbsp;
                    <input type="submit" value="<fmt:message key="submit" />"/></td>
            </tr>
        </form>
    </table>
    <br/> <br/> <br/> <br/>
</center>
</body>
</html>

运行结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值