Xml &Tomcat

Xml

eXtendsible markup language 可扩展的标记语言

XML有什么用?

  1. 可以用来保存数据;

  2. 可以用来做配置文件;

  3. 数据传输载体;

(xml是一个倒置的树形结构)

定义xml

其实就是一个文件,文件后缀为.xml

. 文档声明

简单声明 version:解析这个xml的时候,使用什么版本的解析器解析

<?xml version="1.0"?>

encoding: 解析xml中的文字的时候,使用什么编码来翻译

<?xml version="1.0" encoding="gbk"?>

standalone:no–表示该文档关联其他文件;yes–表示这是一个独立的文档

<?xml version="1.0" encoding="gbk" standalone="no"?>

encoding详解

在解析xml的时候,使用什么编码去解析 ----解码(默认计算机编码:gbk)

计算机存储的不是文字,而是存储这些文字所对应的二进制,文字所对应的二进制到底是什么?根据文件使用的编码来得到

默认文件保存的时候,使用的是GBK编码保存

所以要想让我们的xml能够正常的现实中中文,有两种解决办法:

  1. 让encoding也是gbk或者gb2312;

  2. 如果encoding是utf-8,那么保存文件的时候也必须使用 utf-8;

  3. 保存文件的时候见到的 ANSI 对应的其实是我们的本地编码 GBK。

(为了通用,建议使用utf-8 编码保存,以及encoding都是utf-8。)

元素的定义(标签)

  1. 其实就是里面的标签, <> 括起来的都叫做标签,成对出现,如下:<stu> </stu>

  2. 文档声明下来的第一个元素叫做根元素(根标签)

  3. 标签里面可以嵌套标签
    <stu> <name>张三</name> <age/> </stu>

  4. 空标签(既是开始,又是结束)例如:
    <age/>

  5. 标签可以自己定义(html中标签不能自己定义),所以xml是可扩展标记语言

  6. 标签的命名规则(命名尽量简单,做到见名知意):

    名字可以含有字母、数字以及其他的字符;

    名字不能以数字或者标点符号开始;

    名字不能以字符“xml"(或者XML、Xml)开始;

    名字不能包含空格

简单标签 & 复杂标签

  • 简单标签

元素里面包含了普通的文字

  • 复杂标签

元素里面还可以嵌套其他的元素

属性的定义

定义在元素里面<元素名称 属性名称=“属性的值”></元素名称> 如下:

<?xml version="1.0" encoding="UTF-8"?>
<stus><stu1 id="10086"><name>张三</name><age>18</age></stu1><stu2><id>10087</id><name>李四</name><age>19</age></stu2>
</stus>

xml注释

与html注释一样,如下:(快捷键Ctrl+shift+/)

<!-- 这里有两个学生:张三 李四 -->

注释不能再文档的第一行,必须在文档声明的下面

CDATA区

(一般很少出现,配置文件中就不会出现;出现在服务器向客户端传输数据)

  • 非法字符

严格的讲, 在xml中仅有字符"<“和”&"是非法的,省略号、引号、大于号是合法的,但是把它们替换成实体引用是好的习惯。

<   &lt;
&   &amp;
>   &gt;
  • 如果某段字符串里面有过多的字符,并且里面包含了类似标签或者关键字的这种文字,不想让xml解析器去解析,那么可以使用CDATA来包装,不过这个CDATA一般比较少看到,通常在服务器给客户端返回数据的时候看到
    <des><![CDATA[<a href="http://www.baidu.com">黑马训练营</a>]]></des>

xml解析

其实就是获取元素里面的字符数据或者属性元素

xml的解析方式(面试常问)

有很多种,但是常用的有两种:

  • DOM: (document object model)把整个xml全部读到内存当中,形成树形结构,整个文档(即整个树结构)称之为document对象, 属性(如:id)对应Attribute对象,所有的元素节点(如:name age)对应Element对象,文本(如:张三)也可以称之为Text对象。以上所有对象都可以称之为Node节点;

缺点:如果xml特别大,那么就会造成内存溢出.

优点:可以对文档进行增删操作。

  • SAX:(Simple API for xml) 基于事件驱动,读一行,解析一行。

优点: 不会造成内存溢出。

缺点:不可以进行增删,只能查询。

###针对这两种解析方式的API

一些组织或者公司,针对以上两种解析方式,给出的解决方案有哪些?

jaxp  (sun公司做的,比较繁琐)
jdom
dom4j  (使用比较广泛)

Dom4j基本用法

  1. 创建SaxReader对象;

  2. 指定解析的xml文件;

  3. 获取根元素;

  4. 根据根元素获取子元素(或者再根据子元素获取子孙元素)。

     try {//1.创建SAX读取对象,还有DOMReader()SAXReader reader = new SAXReader();//2.指定解析的xml源:reader.read(path|file+inputtStream)Document document = reader.read(new File("src/xml/demo.xml"));//3.得到元素//3.1得到根元素Element rootelement=document.getRootElement();//3.2得到根元素下面的子元素,元素名称stu1rootelement.element("stu1");//3.3 得到根元素下面的子孙元素//System.out.print(rootelement.element("stu1").element("age").getText());//3.4得到根元素下面的所有元素List<Element> elements=rootelement.elements();for(Element element:elements) {String name =element.element("name").getText();String age=element.element("age").getText();String id=element.element("id").getText();System.out.print("name"+name+";age"+age+";id"+id);}} catch (Exception e) {e.printStackTrace();}
    

Dom4j的Xpath使用

dom4j里面支持Xpath的写法,Xpath其实是xml的路径语言;

支持我们在解析xml的时候,能够快速的定位到具体的一个元素

  1. 添加jar包依赖;

    jaxen-1.1-beta-6 jar

  2. 在查找指定的节点的时候,根据Xpath语法规则来查找;

  3. 后续的代码和之前的解析代码一样。

     try {//1.创建SAX读取对象SAXReader reader = new SAXReader();//2.指定解析的xml源Document document = reader.read(new File("src/xml/demo.xml"));//3.得到元素//3.1得到根元素Element rootelement=document.getRootElement();// 要想使用Xpath,还得添加支持的jar//获取指定元素Element element=(Element) rootelement.selectSingleNode("//name");System.out.println(element.getText());//获取所有name元素//获取第一个name节点(这里用Element这种类型的对象调用selectNodes()方法,但是定义这个selectNodes的方法是定义在一个接口Node中的,请问这么写有没有错? -----没错:element、attribute、text都是node的子接口,体现了Java的多态)List<Element> list=rootelement.selectNodes("//name");for (Element element2 : list) {System.out.println(element2.getText());}} catch (Exception e) {e.printStackTrace();}
    

xml约束(了解)

如下的xml文档,属性的ID是一样的,这在生活中是不可能出现的;并且第二个学会说呢过的姓名出现了好几个,这种情况一般也很少。那么如何规定ID的值唯一,或者元素只出现一次,不能出现多次?甚至规定里面只能具体出现的元素的名字

<?xml version="1.0" encoding="UTF-8"?>
<stus><stu id="10086"><name>李武</name><age>67</age></stu><stu id="10086"><name>李六</name><name>李七</name><name>李八</name><age>67</age></stu>
</stus>

文档约束有两大类:DTD,Schema(面试:了解区别,优缺点)
小结(下面):

  1. DTD:语法自成一派,早期就出现,可读性差
  2. schema:使用xml的语法规则,xml解析器解析起来比较方便它的出现是为了替代DTD,但是schema约束的文本内容比DTD的内容还要多,所以目前也没有真正意义上的替代DTD
  3. 一个xml可以引用多个schema约束,但只能引用一个dtd约束。

DTD

**语法自成一派,早期就出现,可读性差**
  1. 引入网络上的DTD

    <?xml version="1.0" encoding="UTF-8"?>

    引入dtd来约束这个xml:<!文档类型 根标签的名字 网络上的dtd dtd的名称 dtd的路径>

  2. 引入本地的DTD

  3. 直接在xml里面嵌入dtd的约束规则 :

 <!DOCTYPE stus [<!ELEMENT stus(stu)><!ELEMENT stu(name,age)><!ELEMENT name(#PCDATA)><!ELEMENT age(#PCDATA)>]><stus><stu><name>李武</name><age>67</age></stu></stus>

dtd文档中的内容:

<!ELEMENT stus (stu) +>: 如果没有+号(stus下面有一个元素stu,但是只有一个)
<!ELEMENT stu (name, age)>: stu下面有两个元素name,age,顺序必须是name age
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST stu id ID #IMPLIED>: stu有一个属性id 属性类型 属性的默认值(IMPLIED 表示属性可有可无)

元素个数:(类似于正则表达式)

+ 表示一个或多个
* 表示零个或多个
?表示零个或一个

属性类型的定义:

CDATA: 属性是普通的文字
ID:属性的值必须唯一

元素的顺序:

<!ELEMENT stu (name , age)>: 按照name age的顺序来
<!ELEMENT stu (name | age)>: 两个中只能包含一个子元素

schema

schema其实是一个xml,使用xml的语法规则,xml解析器解析起来比较方便它的出现是为了替代DTD,但是schema约束的文本内容比DTD的内容还要多,所以目前也没有真正意义上的替代DTD

约束文档:

<?xml version="1.0" encoding="UTF-8"?>
<!-- xmlns(xml namespace):表示名称空间/命名空间
targetNamespace: 目标名称空间下面定义的那些元素都与这个名称空间绑定上
elementFormDefault:元素的格式化情况--><schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/teacher"
elementFormDefault="qualified"><!-- teachers和teacher是复杂元素,
需要标签complexType:表示这个元素是复杂元素;
需要标签sequence:表示下面的元素是有序的 -->
<element name="teachers"><complexType><sequence maxOccurs="unbounded"><element name="teacher"><complexType><sequence><!-- name和age是简单元素 --><element name="name" type="string"></element><element name="age" type="int"></element></sequence></complexType></element></sequence></complexType>
</element>
</schema>

实例文档:

<?xml version="1.0" encoding="UTF-8"?><!-- xnlns:xsi:这里必须是这样的写法,也就是这个值已经是固定的了
xmlns:这里是名称空间,也是固定了, 写的是schema里面的顶部项目名称空间
xsi:schemaLocation:有两段,前半段是名称空间,也就是目标空间的值,后面是约束文档的路径 --><teachersxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.example.org/teacher"xsi:schemaLocation="http://www.example.org/teacher teacher.xsd"
><teacher><name>历史</name><age>26</age></teacher><teacher><name>物理</name><age>22</age></teacher>
</teachers>

名称空间的作用

一个xml如果指定它的约束规则,假设使用的是dtd,则这个xml只能使用一个dtd,不能指定多个dtd; 但是如果一个xml的约束是定义在schema里面,并且是多个schema,那么是可以的;(简言之:一个xml可以引用多个schema约束,但只能引用一个dtd约束)。

名称空间的作用是:在写元素的时候,可以指定该元素使用的是那一套约束规则。默认情况下,如果只有一套规则,那么都可以这么写

xmlns:aa="http://www.baidu.com/teacher"
xmlns:bb="http://www.baidu.com/teacher"<teacher><aa:name>历史</aa:name><age>26</age>
</teacher>
<teacher><bb:name>物理</bb:name><age>22</age>
</teacher>

程序架构

  • C/S(client/server)

例如 QQ 微信 LOL就是使用 C/S架构
优点:

有一部分代码写在客户端,用户体验比较好

缺点:

服务器更新,客户端也要跟着更新,占用资源大(比较吃硬盘)
  • B/S(browser/server)目前很多程序朝着B/S的方向发展

例如 网页游戏,网页QQ… 是使用B/S架构
优点:

客户端只要有浏览器就可以了,占用资源少,不用更新

缺点:

用户体验不佳

服务器

实质上服务器就是一台配置比较高的电脑

###Web服务器软件

客户端在浏览器的地址栏上输入地址,然后web服务器软件,接收请求,然后响应消息。

接收并处理客户端的请求,返回资源或信息

web应用 需要服务器支撑 index.html

比较常见的web服务器软件有:

Tomcat apache(免费)
weblogic BEA
WebSphere IBM
IIS 微软

Tomcat安装

  1. 直接解压,然后找到 bin/startup.bat(双击) [startup.sh是在Linux操作系统中使用的];

  2. 可以安装:

启动之后,如果能够正常看到黑窗口,表明安装成功;为了确保万无一失,最好在浏览器的地址栏上输入:http://localhost:8080,如果有看到内容,就表明成功了;

  1. 如果双击了startup.bat 看到一闪而过的情形,一般都是JDK的环境变量没有配置成功

Tomcat目录介绍

bin

包含了一些jar,bat文件(常用startup.bat)

conf

tomcat 的配置 (常用的 server.xml / web.xml /)

lib

Tomcat 运行所需的jar文件

logs

运行的日志文件

temp

临时文件

webapps

发布在Tomcat服务器上的项目,就存放在这个目录(想让另外一台访问哪个项目,就把该项目放到这个文件夹下面)

work(目前不用管)

jsp 翻译成class文件存放地

如何把一个项目发布到Tomcat中

需求:如何能让其他电脑访问我这台电脑上的资源(例如:stus.xml)。

有三种方法解决这个需求:

1. 拷贝这个文件stus.xml到webapps/ROOT文件夹下面,客户端在浏览器中访问:

http://localhost:8080/stus.xml

或者在webapps下面新建一个文件夹xml,然后把stu.xml拷贝到这个新建的文件夹中(先关闭Tomcat,注意浏览器把webapps下的每个文件夹当做是一个项目,所以需要新建文件夹),客户端在浏览器中访问:

http://localhost:8080/xml/stus.xml

注意:这里

http://localhost:8080:其实对应的是到webapps/ROOT下面访问
http://localhost:8080/xml:其实对应的是到webapps/xml下面访问
localhost:本机地址
8080:对应的是Tomcat服务器在这台电脑对应的端口(默认)

或者使用IP地址访问:

http://192.168.37.48:8080/xml/stus.xml

2. 配置虚拟路径

使用localhost:8080打开tomcat首页,在找到tomcat的documentation入口,点击进去后,点击configuration,然后在左侧接着找到Context入口,点击进去。找到Defining a context定义一个虚拟的路径(Inside a Host element in the main conf/server.xml).

http://localhost:8080/docs/config/context.html
  1. 在conf/server.xml 中找到 Host元素节点;

  2. 加入以下内容:

         <!-- docBase:项目的路径地址,如:C:\Java\workspace\XmlDemo\src\xmlpath :对应的虚拟路径,一定要以 / 开头;对应的访问方式为:http:localhost:8080/teacher.xml--><Context docBase="C:\Java\workspace\XmlDemo\src\xml" path="/a"></Context>
    
  3. 在浏览器地址栏上输入:

    http://localhost:8080/a/teacher.xml

3. 配置虚拟路径

  1. 在Tomcat/conf/catalina/localhost/文件夹下新建一个xml文件,名字可以自己定义person.xml。

  2. 在这个文件里面写入一下内容:

    <?xml version="1.0" encoding="utf-8"?>

  3. 在浏览器上面访问

http://localhost:8080/teacher/teacher.xml

给Eclipse 配置Tomcat

  1. 在server里面 右键新建一个服务器,选择到apache分类,找到对应的Tomcat版本,接着一步步配置即可;

  2. 配置完成后,在server里面右键刚才的服务器,然后open,找到上面的 Server Location,选择中间的 Use Tomcat installation;

  3. 新建一个动态的web工程(other下),在webContent下定义html文件,右键web工程,run as server

总结

xml:
会定义xml;
会解析xml(dom4j解析);

Tomcat:
会安装,会启动,会访问;
会设置虚拟路径;
会给eclipse配置Tomcat。

HTTP协议 & Servlet

HTTP协议

  • 什么是协议

双方在交互、通信的时候,遵守的一种规范、规则;

  • HTTP协议

针对网络上的客户端 与 服务器在执行http请求的时候,遵守的一种规范:
其实就是规定了客户端在访问服务器的时候,需要带上那些东西;服务器返回数据的时候,也要带上什么东西

  • http协议的版本:

1.0 (请求数据,服务器返回后,将会断开连接)

1.1(请求数据,服务器返回后,连接还会保持,除非服务器或客户端关掉。有一定的时间限制,如果都空着这个连接,那么后面会自己断掉)

演示客户端 如何 与服务器通讯

在浏览器地址栏中键入网络地址,回车;或者是平常注册的时候,点击了注册按钮,浏览器都会现实出来一些东西。那么底层的浏览器和服务器是怎么通讯的,它们都传递了那些数据?怎么看呢?如下步骤:

  1. 安装抓包工具 HttpWatch(IE插件)
  2. 打开Tomcat。输入 localhost:8080 打开首页
  3. 在首页上找到examples字样,然后找到 servlets example,点击;
  4. 点击Request Parameters 的 Execute ;到达页面,键入first name和 last name;
  5. 在点击提交之前,先打开HttpWatch抓包工具(位于IE浏览器右上角的小箭头),点击record;再点击提交;然后选中抓包页面的有颜色的进度条,然后点击stream,就可以看到浏览器(左边)和服务器(右边)的交互。

HTTP请求(浏览器向服务器请求)数据解释

请求的数据里面包括三个部分内容:请求行、请求头、请求体

  • 请求行:(第一行)
    POST/examples/servlets/servlet/RequestParamExample HTTP/1.1

POST: 请求方式(以post去提交数据);get也是请求方式;另外还有很多其他的请求方式,如OPTIONS/Delete/trace/put请求方式

/examples/servlets/servlet/RequestParamExample:请求的地址路径,就是要访问哪个地方

HTTP/1.1: 协议版本

  • 请求头:(出来第一行,一直到空行之前,都是请求头)
Accept: application/x-ms-application, image/jpeg,application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Referer: Http://localhost:8080/examples/servlets/servlet/RequestParamExample
Accept-Language:zh-CN
User-Agent:Mozilla/4.0(compatible; MSIE 8.0;Windoms NT 6.1; Wow64; Trident/4.0;SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 31
Connection: Keep-Alive
Cache-control: no-cache

Accept: 客户端向服务器端表示:“我能支持什么类型的数据”。

Referer: 真正请求的地址路径,全路径.

Accept-Language:支持语言格式

User-Agent:向服务器表明,当前来访的客户端信息(是PC端,还是Android/IOS端访问)

Content-Type:提交的数据类型,经过urlencoding编码的form表单数据

Accept-Encoding: gzip, deflate:压缩算法

Host: 主机地址

Content-Length: 内容、数据长度

Connection: 保持连接

Cache-control:对缓存的操作(no-cache:每一次请求这个地址路径,不从缓存中拿数据,而是直接越过缓存,向服务器请求新的数据访问)

  • 请求体:(最后一行)

浏览器真正发送给服务器的数据,发送的数据呈现的是key=value的形式; 如果存在多个数据,那么使用 &;

firstname=zhang&lastname=sansan

HTTP响应(服务器响应浏览器)数据解释

响应的数据里面包含三个部分的内容:响应行,响应头,响应体

HTTP/1.1 200 OK
Server: Apache-Copyto/1.1
Content-Type: text/html;charset=ISO-8859-1
ContenT-LENGTH:673
Date: Fri, 17 Feb 2017 02:53:02 GMT
... ...(这里还有很多数据)
  • 响应行:(第一行)

    HTTP/1.1 200 OK

HTTP/1.1: 协议版本

200: 代表状态码(状态码是指:咱们这次交互到底是什么结果的一个code)
200:表示成功,正常出来,得到数据;
3打头的代表重定向;
403: Forbiddern 拒绝;404: NOT Found; (4打头的代表客户端有问题)
500:(5打头的代表服务器端有问题)

OK: 对应前面的状态码

  • 响应头:

Server: 服务器的类型(tomcat)

Content-Type: 服务器返回给客户端的内容类型

Content-Length: 返回的数据长度

Date: 通讯的日期,响应的时间

post 和 get请求的区别

  1. 请求路径不同:

post请求在URL后面不跟任何的数据;get请求在URL后面跟上数据;

  1. 数据传输方式不同:

带上的数据不同,post请求会使用流的方式写数据;get请求是在地址栏上跟数据(即请求体不同);

  1. 由于post请求使用流的方式写数据,所以一定需要一个Content.Length 的头来说明数据的长度

!小结:(面试会问)

  • post:

-1. 数据以流的方式写过去,不会再地址栏上面显示。现在一般客户端/浏览器 向 服务器 提交数据的都使用post;

-2. 以流的方式写数据,所以数据没有大小限制

  • get:

-1. 会在地址栏后面拼接数据,所以有安全隐患。现在一般从服务器获取数据,并且客户端也不要提交上面数据的时候,可以使用get。

-2. 能够带的数据有限(1kb大小)

web资源

在我们的应用体系(或者http协议)中,规定了请求和响应的双方:客户端/浏览器 和 服务器端。与web相关的资源。

(服务器可以返回的一切东西都可以看做是web资源)

有两种分类:

  • 静态资源:(即使请求访问的时间点不同,产生这份数据的源代码是不变的)
    如: html,js, css

  • 动态资源

如:servlet/jsp [jsp:比如说注册 或者 登录 时输入数据]

注意!!!!(经验总结)

  • 小结1:
  1. 运行web工程前,需要先关掉tomcat server(即叉掉startup.bat窗口);
  2. 如果电脑上装载了两个tomcat,并且都运行过;那么可能会出现startup.bat窗口闪退的情况。这是因为tomcat端口被占用,解决这个问题需要:

打开命令窗口:win+R,然后键入cmd->确定

在窗口输入:C: (敲回车键)

再输入: cd\windows\system32 (敲回车键)

再运行命令: 输入 netstat -ano | findstr 8080 查看占用8080端口的进程;(这里可以看到占用端口的进程PID(进程标识符)为6668)

再运行命令: 输入 tasklist|findstr 6668 查看进程6668的运行程序(这里查到进程的名称为 javaw.exe)

再运行命令: 输入 taskkill /f /t /im javaw.exe 杀死这个进程就可以了。

  • 小结2:myeclipse开启自动提示功能的方法:
  1. 打开MyEclipse,然后单击“window”→“Preferences”。

  2. 单击“java”,展开“Editor”,单击“ContentAssist”。

  3. 找到右下的“Auto activation triggers for Java”这个选项,该选项用来设置触发代码提示的符号。

  4. 在“.”后加上abc字母,然后单击“apply”→“OK”。

  5. 单击“File”→“Export”,在弹出的窗口中选择“Perferences”,点击“下一步”。

  6. 选择导出文件路径,并为文件命名,点击“保存”,例如保存在D盘,名字为java.epf

  7. 用记事本打开java.epf文件按“ctrl+F”快捷键,输入“.abc”,点击“查找下一个”,查找到“.abc”的配置信息。

  8. 把“.abc”改成“.abcdefghijklmnopqrstuvwxyz@(,”,保存并关闭java.epf。

  9. 回到MyEclipse界面,单击“File”→“Import”,在弹出的窗口中选择“Perferences”,点击“下一步”,选择刚已经修改的java.epf文件,点击“打开”,点击“Finish”。

Servlet

  • servlet 是什么?

其实就是一个Java程序运行在我们的web服务器上,用于接收和响应客户端的http请求。

更多的是配合动态资源来做。当然静态资源也需要使用到servlet,,只不过tomcat里面已经定义好了一个DafaultServlet。(Tomcat其实就是一个容器,里面放置servlet。

Hello Servlet

  1. 得写一个web工程,要有一个服务器;
  2. 测试运行web工程。
  1. 新建一个类,实现一个Servlet接口;如下:
public class helloServlet implements Servlet{public void destroy() {}public ServletConfig getServletConfig() {return null;}public String getServletInfo() {return null;}public void init(ServletConfig arg0) throws ServletException {}public void service(ServletRequest arg0, ServletResponse arg1)throws ServletException, IOException {System.out.print("HelloServlet");}}
  1. 配置Servlet. 用意就是:告诉服务器,我们的应用有这么一个servlet.(在webcontent/WEB-INF/web.xml 里面写上一下内容:)
 <!-- 向tomcat报告:我这个应用里面有一个servlet,名字叫做helloServlet, 具体的路径com.itheima.servlet.helloServlet --><servlet><servlet-name>helloServlet</servlet-name><servlet-class>com.itheima.servlet.helloServlet</servlet-class></servlet><!-- 注册servlet的映射,servlet-name:找到上面注册的具体servlet;url-pattern:在地址栏上的path,一定要以 / 开头--><servlet-mapping><servlet-name>helloServlet</servlet-name><url-pattern>/a</url-pattern></servlet-mapping>

Servlet的执行过程

URL:http://localhost:8080/Helloweb/a

  1. 找到tomcat应用;
  2. 找到项目Helloweb(其实就是将web项目放入tomcat应用的wtpwebapps文件夹中);
  3. 找到web.xml配置文件,然后在里面找到 url-pattern, 看看里面有没有 pattern 的内容是 /a 的;
  4. 在配置文件中,找到servlet-mapping中与pattern对应的那个servlet-name[helloServlet];
  5. 在配置文件中,找到servlet元素中的 与上面找到的servlet-name相同的 servlet-name[helloServlet];
  6. 然后根据 对应的 servlet-class (路径)找到类helloServlet, 并开始创建该类的实例;
  7. 继而执行该servlet实例中的service()方法;

Servlet的通用写法:

因为在上面创建Servlet类是实现Servlet接口,必须重写改接口的所有方法,很不方便;所以考虑实现了该接口的类:GenericServlet 和 HttpServlet,创建Servlet类的时候可以继承这两个类,不需要重写所有方法。

Servlet(接口)
|
|
GenericServlet(Servlet的子类,是一个抽象类,实现了Servlet接口/ServletConfig/java.io.Serializable)
|
|
HttpServlet(抽象类,继承GenericServlets, 实现 java.io.Serializable; 用于处理处理http的请求的类)
  1. 定义一个类,继承HttpServlet 复写 doGet 和 doPost 方法;如下:(为什么会执行dopost和doget,而不是service();因为service() 方法的内部,对来访的请求,首先是对 get还是post进行判断,然后分别调用doGet和doPost)
public class helloServlet02 extends HttpServlet{//get请求就会到这来@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {super.doGet(req, resp);System.out.print("get请求");}//post请求就会到这来@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {super.doPost(req, resp);System.out.print("post请求");}
}

servlet的生命周期

  • 生命周期:指从创建到销毁的一段时间

从创建(初始化)、接受和响应消息、到销毁,一定会执行的那些方法,就是servlet的生命周期方法;

  • servlet的生命周期的方法:
  1. init():
/* 1. 在**创建该Servlet的实例的时候,就执行该方法**(类似于构造方法);* 一个servlet只会初始化一次,即init()方法只会执行一次;* 默认情况下是:初次访问该servlet,才会创建实例*/public void init(ServletConfig arg0) throws ServletException {System.out.println("helloServlet03 初始化");}
  1. service():
/* 2. 只有客户端来了一个请求,就会执行这个方法service();*      该方法可以调用很多次,一次请求,对应一次service()方法的调用;*/
public void service(ServletRequest arg0, ServletResponse arg1)throws ServletException, IOException {System.out.println("helloServlet03 service()方法调用了");}
  1. destroy():
/* 3. 销毁servlet的时候,就会调用该方法destroy();*   什么时候调用该方法? 如下情形:*    (1)该项目从tomcat服务器的里面移除的时候;*   (2)正常关闭服务器(点击shutdown.bat); 注意,使用console界面的红色按钮停止tomcat属于非正常手段关闭;*/public void destroy() {System.out.println("helloServlet03 destroy()方法调用了");}

doGet 和 doPost 不算是生命周期的方法(它们不一定会执行)

让servlet创建实例的时机提前

为什么需要提前呢?(以下几个原因)

  1. 默认情况下,只有在初次访问servlet的时候,才会执行init方法;有的时候,我们可能需要在这个方法里面执行一些初始化工作,甚至做一些比较耗时的逻辑;

  2. 那么初次访问,可能会在init方法中逗留太久的时间,那么有没有方法可以让这个初始化的时机提前一些;

  3. 在配置的时候,使用 load-on-startup 元素来指定让servlet提前创建实例(即提前初始化);给定的数字越小,启动的时机就越早;一般 不写负数,从2开始即可。

  <servlet><servlet-name>helloServlet04</servlet-name><servlet-class>com.itheima.servlet.helloServlet04</servlet-class><load-on-startup>2</load-on-startup></servlet>

ServletConfig(使用频率不高)

servlet的配置,通过这个ServletConfig对象,可以获取servlet在配置的时候一些信息

(先说,再说怎么做;最后再写有什么用;)
(新建一个动态web项目,演示servletConfig)

public class helloServletConfig extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {//1. 得到servlet配置对象;ServletConfig config = getServletConfig();//2. 获取到的是配置servlet里面servlet-name的文本内容;String servletName=config.getServletName();System.out.println("servletName---"+servletName);//3. 可以获取具体的某一个参数;String adress=config.getInitParameter("adress");System.out.println("adress---"+adress);//4. 可以获取所有的参数Enumeration<String> initParameterNames = config.getInitParameterNames();while (initParameterNames.hasMoreElements()) {String elem = (String) initParameterNames.nextElement();String key=config.getInitParameter(elem);System.out.println("elem="+elem+";key="+key);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {doGet(req, resp);}}

(将上面的servletconfig web项目导出为jar文件,即右击项目,点击 export-export–java/JAR file–选择保存路径保存–finish)

为什么需要有这个servletConfig?

  1. 未来我们自己开发的一些应用,使用到一些技术,或者一些代码,我们不会,但是有人写出来了,它的代码放置在了自己的servlet类里面;
  2. 刚好这个servlet里面需要一个数字或者叫做变量值。但是这个值不能是固定的。所以要求使用到这个servlet的公司,在注册servlet的时候,必须要在web.xml里面,声明init-params
  1. 请在你的web工程里面,添加jar(具体步骤是:复制上面路径下的jar文件;粘贴到 新建的web项目下的webContent/WEB-INF/lib下);

  2. 在web.xml里面,注册servlet(注意这里servlet-class:是jar包中class文件的路径)

  3. 请添加如下参数

     <init-param><param-name>number</param-name><param-value>44</param-value></init-param>
    

总结:

  • http协议:

1.使用httpWatch 抓包看看http请求背后的细节

2.基本了解 请求和响应的数据内容: (请求行 请求头 请求体;响应行 响应头 响应体;)

3.get和post的区别

  • Servlet:

1.会使用简单的servlet:

写一个类,实现接口servlet(或者继承httpservlet)

配置servlet(在web.xml文件中)

会访问servlet

2.servlet的生命周期

— init(): 只运行一次,默认初次访问就会调用;或者通过配置,让它提前 load-on-startup;

— service(): 多次执行,一次请求对应一次service();

— destroy(): 执行一次:销毁的时候、从服务器移除 或者 正常关闭服务器;

3.ServletConfig(对象,类)

获取配置的信息,参数等;

HttpServletRequest 和 HttpServletResponse

Servlet 配置方式

  1. 全路径配置

以 / 开头,例如 /a 或者 /a/bb;
localhost:8080/项目名称/a

  1. 路径匹配,前半段匹配

以 / 开头,但是以 * 结束;例如 /a/* 或者 /*

(*号:其实是通配符;表示该位置及后面位置可以匹配任意文字)

localhost:8080/项目名称/a/bbb

  1. 以扩展名匹配,后半段匹配

写法:(没有/,以*开头。) .扩展名;例如:.aa

ServletContext(使用频率较高)

servlet上下文

虚拟机中的每个web工程都只有一个servletContext对象,说白了就是不管在哪个servlet里面,获取这个servletContext类的对象都是同一个。

servletContext如何得到对象:

 //1. 获取servletContext对象ServletContext context = getServletContext();

servletContext有什么用

  1. 可以获取全局配置参数;
  2. 可以获取web工程中的资源;
  3. 存取数据,servlet间共享数据(域对象);
    (具体如下)

1. 可以获取全局配置参数;

web.xml中配置全局参数:

<!-- context-param是全局参数,哪个servlet都可以拿,通过servletContext拿全局参数 -->
<context-param>
<param-name>adress</param-name>
<param-value>陕西西安---</param-value>

servletContext对象获取全局参数:

public class ServletContext02 extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 获取servletContext对象ServletContext context = getServletContext();String adress=context.getInitParameter("adress");System.out.println("这是02发布的数据--adress="+adress);}   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);
}

2. 可以获取web应用中的资源:

方式1:获取资源在tomcat里面的绝对路径: getRealPath()方法;(利用servletContext先获取绝对路径,然后自己new InputStream()

首先,在下面的类中使用FileInputStream()在web项目中是不OK,如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 创建属性对象Properties properties=new Properties();/*2. 指定载入的数据源* 此处,如果想获取web工程下的资源,用普通的FileInputStream写法是不OK的;* 因为路径不对了。FileInputStream的相对路径,其实是根据jre来确定的。* 但是我们这是一个web工程,jre后面会由tomcat管理;* 所以这里真正的相对路径应该是tomcat里面的bin目录;* 因此,需要将config.properties文件复制到tomcat的斌目录下(可以新建一个classes文件夹* ,把文件粘贴进去;并将下面改为new FileInputStream("classes/config.properties");)*/InputStream is= new FileInputStream("src/config.properties");properties.load(is);//3.获取name属性的值String name = properties.getProperty("name");System.out.println("name="+name);}

修改上面的代码,添加如下servletContext对象获取绝对路径:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取servletContext对象ServletContext context= getServletContext();//获取给定的文件在服务器上面的绝对路径String path = context.getRealPath("file/config.properties");//1. 创建属性对象Properties properties=new Properties();//2. 指定载入的数据源InputStream is= new FileInputStream(path);properties.load(is);//3.获取name属性的值String name = properties.getProperty("name");System.out.println("name="+name);}

注意:这里String path = context.getRealPath(“”),得到的是项目在tomcat里面的根目录;

方式2: 获取资源,并转化为流对象,getResourceAsStream();如下:(根据相对路径直接获取流对象

     //1.获取servletContext对象ServletContext context = getServletContext();//2. 创建属性对象Properties properties = new Properties();//3. 获取web工程下的资源,转化成流对象,前面隐藏当前工程的根目录InputStream is= context.getResourceAsStream("file/config.properties");properties.load(is);//4.获取name属性的值String name = properties.getProperty("name");System.out.println("name2=" + name);is.close();} catch (Exception e) {e.printStackTrace();}

方式3:(不是利用servletContext去获取web资源的方式)通过classLoad去获取web工程下的资源。 如下:this.getClass().getClassLoader(). getResource AsStream("…/…/file/config.properties")

/*** 利用classLoad获取web资源*/
private void test3() {try {/** 注意:* 1. 对servletContext对象而言: 相对路径是---工程在tomcat里面的目录*     即:C:\Users\RenJuan\Desktop\努力\tomcat服务器\apache-tomcat-6.0.39\wtpwebapps\ServletContext03*     * 2. 对classLoad而言: 相对路径是---工程中类所在目录*     即:C:\Users\RenJuan\Desktop\努力\tomcat服务器\apache-tomcat-6.0.39\wtpwebapps\ServletContext03\WEB-INF\classes*     * 3. 默认的classLoad 的路径是上面的这个路径,我们必须得回到ServletContext03这个目录下面,才能进入file目录。如何返回上一级目录呢?* 利用 ../ 可以返回到上一级; ../../可以返回到上两级;* * 这里 ../../ -----返回到了 C:\Users\RenJuan\Desktop\努力\tomcat服务器\apache-tomcat-6.0.39\wtpwebapps\ServletContext03* * ../../file/config.properties----达到了C:\Users\RenJuan\Desktop\努力\tomcat服务器\apache-tomcat-6.0.39\wtpwebapps\ServletContext03file/config.properties*///.getClass():表示获取该Java文件的类文件;.getClassLoad():表示获取对应类文件的类加载器InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../file/config.properties");Properties properties = new Properties();properties.load(is);String name = properties.getProperty("name");System.out.println("name3=" + name);} catch (Exception e) {e.printStackTrace();}}

小知识:

相对路径:有参照物,相对谁?这里相对的是工程在tomcat里面的根目录:(有以下两种形式)

a路径---工程在tomcat里面的目录;例如: C:\Users\RenJuan\Desktop\努力\tomcat服务器\apache-tomcat-6.0.39\wtpwebapps\ServletContext03b路径---file/config.properties

绝对路径:没有参照物

 C:\Users\RenJuan\Desktop\努力\tomcat服务器\apache-tomcat-6.0.39\wtpwebapps\ServletContext03\file\config.properties

3. 使用servletContext存取数据(资源存取)

!注意:1 2 属于准备工作,并没有使用servletContext存取数据

1.定义一个登录的html页面,定义一个form表单:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body><form action="ServletContext04" method="get"><h2>请按照下面内容填写,并登录</h2>账户:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/><input type="submit" value="提交"></form>
</body>
</html>

2.定义一个Servlet,如下:

public class ServletContext04 extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
/* request: 包含请求的信息*  reponse: 响应数据给浏览器,就靠这个对象*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 获取数据String username=request.getParameter("username");String password=request.getParameter("password");System.out.println("username="+username+";password="+password);PrintWriter writer = response.getWriter();//2. 校验数据if("zhangsan".equals(username)&&"123".equals(password)){//(1)仅向console输出内容: System.out.println("登录成功");//(2)向客户端输出内容//PrintWriter writer = response.getWriter();//writer.write("login success...");//(3)//<1>成功的次数累加Object obj = getServletContext().getAttribute("count");//默认就是0次int totalCount=0;if(obj!=null){totalCount=(Integer) obj;}System.out.println("已经登录成功的次数是:"+totalCount);   getServletContext().setAttribute("count", totalCount+1);//<2>成功就跳转至success.html;//首先,设置状态码(重新定位,设置状态码)response.setStatus(302);//然后,定位跳转的位置是那个页面response.setHeader("Location", "success.html");}else{//System.out.println("登录失败");writer.write("login faied...");}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);
}

}

3.针对成功或者失败,进行判断,然后跳转到不一样的页面;(response.setStatus(302); response.setHeader(“Location”, “success.html”);)

(首先新建一个跳转页面success.html 如下; 然后再servlet中利用response.setStatus 和 respons.setHeader完成页面的跳转)

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body><h2>登录成功了</h2><a href="">获取网站登录成功的总数</a>
</body>
</html>
//(3)成功就跳转至success.html;//首先,设置状态码(重新定位,设置状态码)
response.setStatus(302);//然后,定位跳转的位置是那个页面
response.setHeader("Location", "success.html");

4.ServletContext获取登录成功总数(存取数据)getServletContext().getAttribute()

新建另一个CountServlet对象, 来获取上面servletContext04对象中得到的登录成功总数.

public class CountServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.取值int count = (Integer) getServletContext().getAttribute("count");//2.输出到界面response.getWriter().write("the number of loginning successful:"+count);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

细节

  • load.html文档表单中的 action 对应的实际是 web.xml 文档中的servlet注册时内容(即所需要的servlet的路径)

    相对路径:

    a路径:servlet的路径 http://localhost:8080/(web.xml 文档中的内容

    b路径: 当前这个html的路径: http://localhost:8080/(success.html即html文档名

ServletContext何时创建?何时销毁?

创建: 服务器启动的时候,会为每一个web应用程序,创建一个ServletContext对象;

销毁: 从服务器移除托管,或者是关闭服务器,则ServletContext销毁

  • ServletContext 的作用范围:

只要在同一个项目里面,都可以取(即同一个项目中的servlet之间可以共享数据,但不同项目之间的servlet之间却不能取数据)。

HttpServletRequest

这个对象封装了客户端提交过来的一切数据(包括 请求行,请求头,请求体)

  1. 可以获取头信息(利用getHeaderNames(); getHeaderName(); getHeader();)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 得到一个枚举集合,detHeaderNames():获得全部的请求头的名字;getHeader():获得某请求头对应的请求头的值Enumeration <String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {String name = (String) headerNames.nextElement();String value =request.getHeader(name);System.out.println("请求头name:"+name+";请求头value:"+value);}
}
  1. 可以获取客户端提交过来的数据,即获取请求体(利用getParameter(); getParameterNames(); getParameterMap()

    web工程的读书笔记相关推荐

    1. 图像工程的读书笔记 形状分析

      图像工程的读书笔记  形状分析 形状分析是图像分析的一个重要的分支,其重点是刻画图像中的目标的各种形状特性, 形状描述符在其中起重要的作用. 对形状的描述常采用三类方法:即特征的方法,形状变换的方法, ...

    2. 深入分析Java Web技术内幕读书笔记(二)浅析DNS域名解析过程

      上一篇文章<浅析Web请求过程>讲述的是如何发起HTTP请求,对于请求发起过程中很重要的一个步骤--DNS解析过程的描述是一带而过,本篇文章将跟着DNS解析过程来分析域名是如何解析的. 一 ...

    3. 图像工程的读书笔记 图像成像过程

      图像工程的读书笔记  图像成像过程 成像是一个复杂的过程,当成像的目的是图像分析时,常需考虑下面的三个问题: 1几何关系:在图像中什么地方可发现目标,这需要了解图像的成像的变换的知识. 2放射性质:图 ...

    4. 深入分析Java Web技术内幕读书笔记(一)浅析Web请求过程

      随着Web技术的快速发展,互联网的网络架构已经从传统的C/S架构转变为B/S架构,B/S架构相较于传统的C/S架构,有诸多优点,例如:提供了统一的操作方式,简化了用户的学习成本:便捷的开发方式大大提高 ...

    5. 图像工程的读书笔记 运动分析

      图像工程的读书笔记 运动分析 运动分析的工作内容有运动检测,运动目标检测和定位,运动目标的分割和分析, 立体景物重建和行动/场景的理解. 序列图像是由一系列时间上连续的2维图像组成的.常说的视频图像是 ...

    6. 《响应式web设计》读书笔记(一)入门

      写在开始之前 2013年的夏天,我算是正式加入了前端开发的队伍,作为一名新手,关注了很多知名网站.牛人博客,时时刻刻感觉要学的东西太多太多,一路不断的收藏收藏,攒了好多文章来看,心里还想着在前端世界里 ...

    7. 深入分析java web技术内幕----读书笔记(三)

       claasloader读书笔记 claasloader 1.classloader将class加载到jvm中. 2.父优先的等级加载,双亲委派模型. 3.defineclass用于将字节流解析成 ...

    8. 《PWA实战:面向下一代的Progressive Web APP》读书笔记

      前言 之前自己根据网上的教程学习写了几个PWA的小Demo,觉得PWA很有意思,想要更多的了解一下PWA,所以读了这本书.这本书是MANNIN出版社出的,所以书里的代码都有非常棒的注释,因此这篇笔记不 ...

    9. 《白帽子讲web安全》读书笔记以及读后感

      因为本书作于2010年前,书中所使用的部分技术版本已经过于老旧,很多书中提到的攻击方法和绕过思路都已经严重落后,但之所以本书会成为安全界的经典必读书目,就是因为本书所讨论的安全思想尤为精华,对于企业来 ...

    最新文章

    1. jvm的那些设置参数你都知道吗
    2. 绝症老父亲即将说不了话,儿子用AI技术挽留他的声音
    3. 【程序员的英语】出奇制胜-那你得乖乖学英语啊!
    4. 数据泄漏保护:你的企业的投资是否足够?
    5. LeetCode-链表-206. 反转链表
    6. 前后端完全分离出现跨域、无法访问后台解决方案
    7. 14-项目开发总结报告(GB8567——88)
    8. Laravel核心解读--Console内核
    9. 计算机编译原理 张,计算机编译原理概念总结
    10. Android BLE蓝牙详细解读
    11. 我的docker随笔16:构建一个特定的nodejs镜像
    12. 4. Linux 高性能服务器编程 --- TCP/IP 通信
    13. boost升压电路工作原理
    14. reimage许可证密钥_2019年7月24日,绝对真实的许可证密钥
    15. 【图片上传与图片显示】 SpringBoot ajax (跨域问题)
    16. 大数据入门-大数据技术概述(一)
    17. Microsoft Edge闪退问题解决方案:
    18. 高通 qca-wifi 移植
    19. 第21章、系统设定工具(网络与打印机)与硬件侦测
    20. object.getClass()和Object.class的区别

    热门文章

    1. 玫瑰花的python程序代码_python玫瑰花代码讲解,怎样用程序编写编写玫瑰花的代码,c程序或gava或者python...
    2. 【Python】 网格策略回测(日内高频数据)
    3. SF25 | 日内交易策略开发(一)黄金日内交易模型
    4. VUE2版本引入Element UI
    5. Python Diary - Day 4 运算符
    6. STM8L 设置输入模式读取PIN脚高低电平就是个坑
    7. 利用JS实现简易ATM机
    8. Web端如何引用iconfont,iconfont所有的引用方式。
    9. OpenCL与OpenACC的安装
    10. 电脑防火墙未使用推荐的设置来保护计算机,防火墙无法使用推荐设置,