开头我先来两嗓子,这几篇的内容有点过多了,所以这部分是由几篇文章共同完成的,避免文章过长,影响阅读体验。

xml

什么是XML

XML 指可扩展标记语言(eXtensible Markup Language):XML是一种用于描述数据的标记语言。

XML有什么用

XML主要的作用:
1.用来保存数据,而且这些数据具有自我描述性。
2.可以作为项目或者模块的配置文件。
3.还可以作为网络传输的格式(JSON为主)。

XML语法

1.开始标签和结束标签。
2.注释
3.版本信息
4.根标签
5.标签名和属性
6.编码

xmL文档说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!-- xml声明
version版本号
encoding xml的文件编码
需要注意 <?xml 要连着一起写,否则报错
-->
<?xml version="1.0" encoding="utf-8" ?>
<books>
<!-- book标签描述的是一本图书信息
id属性 描述的是图书编号
name标签 描述的是图书的名称
author标签 描述的是作者信息
price标签 描述的图书的价格
-->
<book id="book1">
<name>java编程思想</name>
<author>詹姆斯</author>
<price>39.9</price>
</book>

<book id="book2">
<name>数据结构与算法</name>
<author>詹姆斯</author>
<price>99.9</price>
</book>

<!-- 单标签
<book id="book3" name="python" author="詹姆斯" price="59.9"/>
-->
</books>

文本区域(CDATA)

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

1
2
3
<![CDATA[
<<<<<<<<<<<<<<hell,xml>>>>>>>>>>>>
]]>

XML解析

概述

XML解析就是从XML获取到数据
常见的解析思想
DOM文档对象模型:就是把文档的各个组成部分看做成对应的对象。把XML文件全部加载到内存,在内存中形成一个树形结构,再获取对应的值。
早期JDK为我们提供了两种XML解析技术DML和SAX。
面试题:解析XML的方式

  • DOM解析:将标记语言一次性加载进内存,再内存中形成一颗DOM树。
    • 优点:操作方便,可以对文档进行CRUD的所有操作。
    • 缺点:占内存。
  • SAX解析:逐行读取,基于事件驱动。
    • 优点:不占内存。
    • 缺点:只能读取,不能增删改。

常用的解析工具包

jsoup:可以解析XML,更多用于解析HTML,用于网络爬虫
jdom:Jdom组织提供的工具包
dom4j:dom4j组织提供的工具包,使用的较多。

DOM4J

属于第三方公司的技术,我们需要使用dom4j,就需要再官网下载。

1
2
3
4
1.先加载xml文件创建document对象
2.通过document对象拿到根元素对象
3.通过根元素.elements(标签名),可以返回一个集合,指定的标签名的元素对象
4.找到你需要修改,删除的资源,进行操作

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.iweb.test;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

public class Test1 {

public static void main(String[] args) throws Exception{
// 要创建一个document对象,需要我们事先创建一个SAXReader对象
SAXReader reader=new SAXReader();
// reader对象用于读取xml文件,然后返回一个document对象
Document document = reader.read("src/books.xml");
// 通过document对象拿到xml的根元素对象
Element root = document.getRootElement();
// 将对象元素对象转换String对象
//System.out.println(root.asXML());
// 通过根元素对象,获取所有的book标签对象
// root.elements(标签名) 它可以拿到当前元素下指定的子元素集合
List<Element> books = root.elements("book");
// 遍历每个boos标签对象,然后获取book标签对象内的每一个元素
for(Element book : books){
// attributeValue获取已知属性名
String id=book.attributeValue("id");
// 获得指定标签名的元素
Element name=book.element("name");
Element author=book.element("author");
Element price=book.element("price");
// getText()方法拿到起始标签和结束标签之间的文本内容
System.out.println("id:"+id+",name:"+name.getText()+",author:"+author.getText()+",price:"+price.getText());
}
}
}

Maven

maven是一款用于管理和构建java项目工具,是apache旗下的一个开源项目。

依赖管理

管理项目依赖的jar包,避免版本冲突问题。

项目构建

开发一套系统,代码需要进行编译、测试、打包、发布等过程,这些操作是所有项目都需要做的,如果需要反复进行就显得特别麻烦,而maven提供了一套简单的命令就能够完成构建项目。

统一项目结构

maven提供了标准,统一的项目结构。
标准Maven项目结构

1
2
3
4
5
6
7
8
├───src
│ ├───main
│ │ ├───java
│ │ └───resources
│ └───test
│ ├───java
│ └───resources
└───target

maven项目的目录结构中,main目录下存放的是项目源码。test目录存放测试代码。无论是在main还是在test下,都有两个目录,一个是java用来存放源代码,一个是resources用来存放配置文件。

maven就是一款管理和构建java项目的工具

maven概述

maven是一个项目管理和构建工具,它基于项目对象模型(project Object model)简称pom,通过小段描述信息来管理项目的构建,报告和文档。
mavne作用:

  1. 方便依赖管理
  2. 统一项目结构
  3. 标准项目构建流程
1
2
3
4
<groupId>com.iweb</groupId>
<artifactId>springboot_day02</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

坐标:就是资源jar包的唯一标识,通过坐标可以定位到所需要的资源(jar)位置,坐标的组成部分:

  1. groupId:组织名
  2. artifactId:模板名
  3. version:版本号

maven仓库

仓库:用于存储资源,管理各种jar包

仓库的本质就是一个目录,这个目录被用来存储开发中所需要的依赖(jar包)

  • 本地仓库:自己计算上的一个目录(用来存储jar包)
  • 中央仓库:由maven团队维护的全球唯一的 https://mvnrepository.com/
  • 远程仓库:一般由公司团队团建的私有仓库

当项目中使用坐标引入对应依赖jar后,首先会在本地仓库中查找是否有对应的jar包。

  • 如果有,项目直接引用
  • 如果没有,去中央仓库下载对应的jar包到本地

还可以搭建远程仓库(私服),将jar包查找顺序变为:本地仓库—>远程仓库—>中央仓库。

maven安装

maven是一个绿色软件,解压即可。

bin:存放的是可执行命令
conf:存放maven的配置文件(settings.xml配置文件需要修改)
lib:存放maven依赖的jar包
配置本地仓库
1.在自己计算上新建一个目录(本地仓库,用来存储jar包)
2.进入到conf目录下修改settings.xml配置文件

  • 使用记事本软件打开settings.xml文件
  • 复制 <localRepository>粘贴到注释的外面
  • 复制之前新建的用来存储jar包的路径,替换掉<localRepository>标签体内容

配置阿里云私服
中央仓库在国外,所以下载jar包速度可能比较慢,阿里提供了一个远程仓库,里面基本也都有开源项目的jar包。
进入到conf目录下修改settings.xml配置文件

<mirror>标签下为其添加子标签,内容如下:

1
2
3
4
5
6
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>

注意配置的文件,在<mirrors>中间添加配置
配置环境变量
Maven环境的配置类似于JDK环境变量配置一样。
1.在系统变量新建一个变量

  • ​ MAVEN_HOME:D:\soft\apache-maven-3.6.0
    2.编辑系统变量 Path,添加变量值:
  • ​ %MAVEN_HOME%\bin
    打开DOS命令提示符进行验证,出现如图所示表示安装成功:
    1
    mvn -v

    pom.xml文件详解

    POM项目对象模型,用来描述当前maven项目,使用pom.xml文件来描述当前项目。
    maven坐标
    通过坐标可以唯一定位资源位置。
    依赖管理
    依赖:只当前项目运行所需要的jar包,一个项目可以引入多个依赖。
    在当前工程中,我们需要用到junit来继续测试,此时我们在maven工程的pom.xml文件中,引入junit的依赖。步骤如下:

1.在pom.xml中编写<dependencys>标签
2.在<dependencys>标签中使用<dependency>引入坐标
3.定义坐标的groupIdartifactId

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>

点击刷新按钮,引入最新加入的坐标
刷新依赖:保证每一次引入新的依赖,或者修改现有的依赖配置,都可以加入最新的坐标。

如果引入的依赖,在本地仓库不存在,将会连接远程仓库或者中央仓库,然后下载依赖,这个过程会比较耗时。
如果不知道依赖的坐标,可以到mvn的(中央仓库)[https://mvnrepository.com/]

查找依赖

利用中央仓库搜索依赖的坐标,以mysql为例
在项目的pom.xml文件中添加项目资源依赖

1
2
3
4
5
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>

Serlvet

这是个至关重要的技术,用于处理客户端请求和响应。

web服务器

服务器软件是基于请求和响应来开发,在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目。

什么是请求

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

什么是响应

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

请求和响应的关系

请求和响应都是成对出现的,有请求就有响应
常见的java相关的web服务器软件

  • Tomcat:apache基金组织中小型的JavaEE服务器,支持servlet/jsp规范,开源免费。
  • webLogic:oralce公司,大型的JavaEE服务器,收费的。
  • Jboss:Jboss公司,大型的JavaEE服务器,收费的。
  • websphere:IBM公司,大型的JavaEE服务器,收费的。

Tomcat的使用

Tomcat是一个开源的免费的web服务器软件,支持servlet/jsp规范。
我们可以通过这个网站来获得:[点这里](https://tomcat.apache.org/)
获得后直接就可以通过执行startup.bat文件来启动tomcat服务器。

对于中文乱码的问题,在tomcat的conf目录下的server.xml文件中,修改Connector标签的属性:

1
2
3
4
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>

如果你所在的地域或者机器属性不支持UTF-8编码,那么可以修改为GBK编码。

但是为了方便我们一般会将tomcat集成到IDEA等中进行使用,具体的操作如下:
1.在IDEA中打开项目
2.点击项目结构(Project Structure)
3.点击模块(Modules)
4.点击依赖(Dependencies)
5.点击加号(+)
6.点击Maven
7.点击OK
8.在弹出的对话框中,选择Tomcat服务器
9.点击OK
10.点击运行(Run)按钮
11.选择Tomcat服务器
12.点击OK
13.等待服务器启动完成
14.在浏览器中输入localhost:8080,即可访问项目。

本站为了节省资源,并不予以图片截图等的示例,若是不了解具体操作细节,请参考官方文档。或者借鉴他人博客来帮助自己学习

在tomcat中,存在以下文件布局:

  • bin:存放的是可执行命令
  • conf:存放maven的配置文件(settings.xml配置文件需要修改)
  • lib:存放maven依赖的jar包
  • webapps:存放的是项目文件,每个项目文件都是一个文件夹,文件夹的名称就是项目的名称。
  • work:存放的是项目的临时文件,在项目运行过程中,会生成一些临时文件,这些文件会被存放到work目录下。
  • logs:存放的是日志文件,在项目运行过程中,会生成一些日志文件,这些文件会被存放到logs目录下。
  • temp:存放的是临时文件,在项目运行过程中,会生成一些临时文件,这些文件会被存放到temp目录下。

若是你想要在tomcat中部署项目,那么需要将项目文件放到webapps目录下。
想要停止该服务器运行,只需要在DOS命令提示符中执行shutdown.bat文件即可,或者使用ctrl+c来停止,在idea中则更加简单,只需要点击停止按钮即可。

如果你发现自己有一个端口被占用了,那么可以在conf目录下的server.xml文件中,修改Connector标签的属性:

1
2
3
4
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>

将port属性的值修改为其他的端口号,即可。毕竟8080端口过于热门

若是您想要将现有的web项目部署到tomcat中,那么需要将项目文件放到webapps目录下。
在webapps目录下,每个项目文件都是一个文件夹,文件夹的名称就是项目的名称。
在浏览器中输入localhost:8080/项目名称,即可访问项目。

什么是Serlvet

  1. serlvet是JavaEE规范之一,规范就是接口
  2. servlet是JavaWeb三大组件之一,三大组件分别是servlet程序、Filter过滤器、Listener监听器。
  3. servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的请求,并响应数据给客户端

实现Serlvet程序

导入servlet依赖坐标,这个坐标宁可以在maven的中央仓库中找到。点这里

1
2
3
4
5
6
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>

其他的您想要添加的依赖都可以通过中央仓库的途径来增加

我们若是想要高效的实现Serlvet首先我们得编写一个类,这个类需要实现Serlvet接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  package com.iweb.servlet;

import javax.servlet.*;
import java.io.IOException;


public class MyServlet implements Servlet {



public MyServlet(){
System.out.println("构造函数");
}

// 对servlet进行初始化
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init");
}

// 获取servlet配置信息
@Override
public ServletConfig getServletConfig() {
System.out.println("getServletConfig");
return null;
}

// service方法专门用于处理请求和响应的方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service");
}

@Override
public String getServletInfo() {
System.out.println("getServletInfo");
return null;
}

@Override
public void destroy() {
System.out.println("destroy");

}
}

并对web.xml文件进行配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 <!-- 通过servlet标签给tomcat配置servlet程序 -->
<servlet>
<!-- servlet-name标签 给servlet程序取个一个别名(一般写类名) -->
<servlet-name>MyServlet</servlet-name>

<!-- servlet-class标签 是servlet程序的全类名 包名.类名 -->
<servlet-class>com.iweb.servlet.MyServlet</servlet-class>

</servlet>

<!-- servlet-mapping标签是给servlet程序配置访问地址 -->
<servlet-mapping>
<!-- servlet-name标签的作用是告诉服务器,我当前配置的路径给哪个servlet程序使用 -->
<servlet-name>MyServlet</servlet-name>

<!-- url-pattern 标签配置访问地址
/myServlet 在服务器解析的时候,表示地址为 http://127.0.0.1:8081/myServlet
-->
<url-pattern>/myServlet</url-pattern>

</servlet-mapping>

这种手动置入的行为很容易出现错误
1
2
3
4
5
6
7
8
9
10
  1.url-pattern中配置的路径没有以斜杠打头
java.lang.IllegalArgumentException:
Invalid <url-pattern> [myServlet] in servlet mapping

2.servlet-name配置的值不存在
Caused by: java.lang.IllegalArgumentException:
Servlet mapping specifies an unknown servlet name [MyServlet1]

3.servlet-class标签的全类名配置错误
java.lang.ClassNotFoundException: com.iweb.servlet.MyServlet1

Serlvet的生命周期

1.执行servlet构造方法
2.执行init方法

  • 第一步和第二步在第一次访问的时候创建servlet会被调用
    3.service方法
    ● 每次访问都会被调用
    4.执行destroy销毁方法
  • 在web工程停止的时候调用

HttpServlet实现servlet程序

一般在实际项目开发中,都是使用继承HttpServlet类的方式去实现servlet程序。
1.编写一个类去继承HttpServlet类
2.编写业务需要重写doGet或者doPost方法
3.到web.xml中配置servlet程序的访问地址

  • 配置servlet的名称
  • 配置servlet的全类名
  • 配置servlet的访问地址
    4.在浏览器中访问servlet程序的访问地址,即可访问servlet程序。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
      package com.iweb.servlet;

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

    public class MyServlet1 extends HttpServlet {

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

    // doPost()在post请求的时候调用
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("doPost...");
    }
    }
    对应的xml配置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <servlet>
    <servlet-name>MyServlet1</servlet-name>

    <servlet-class>com.iweb.servlet.MyServlet1</servlet-class>

    </servlet>

    <servlet-mapping>
    <servlet-name>MyServlet1</servlet-name>

    <url-pattern>/myServlet1</url-pattern>

    </servlet-mapping>

这里做一个面试题,GET和POST的区别

  • GET请求:
    • 1.请求参数在URL中显示
    • 2.请求参数的大小有限制
    • 3.请求参数的类型只能是文本类型
  • POST请求:
    • 1.请求参数在请求体中显示
    • 2.请求参数的大小没有限制
    • 3.请求参数的类型没有限制

GenericServlet实现servlet程序

1
2
3
4
5
6
7
8
9
  package com.iweb.servlet;

public class MyServlet2 extends GenericServlet {
// 处理请求和响应的
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service...");
}
}

web.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
 <servlet>
<servlet-name>MyServlet2</servlet-name>

<servlet-class>com.iweb.servlet.MyServlet2</servlet-class>

</servlet>

<servlet-mapping>
<servlet-name>MyServlet2</servlet-name>

<url-pattern>/myServlet2</url-pattern>

</servlet-mapping>

Servlet继承体系

我用一句话来说明白这个过程吧,servlet程序是继承自HttpServlet类的,HttpServlet类是继承自GenericServlet类的,GenericServlet类是继承自Servlet接口的。(阿巴阿巴我自己都不清楚)

ServletContext类

1.ServletContext是一个接口,表示servlet上下文对象。
2.一个web工程,只有一个ServletContext实例。
3.ServletContext对象是一个域对象。
4.ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁
什么是域对象?
域对象,是可以像Map一样存取数据的对象,叫做域对象。
域对象是指存取数据的操作范围,整个web工程。
ServletContext类有四个作用
1.获取web.xml中配置的上下文参数
2.获得当前的工程路径
3.获取工程部署后在服务器硬盘上的绝对路径
4.像Map一样存取数据

注意一下啊这个存储数据的范围是整个web工程,所以在不同的servlet程序中,获取的ServletContext对象是同一个。并且这些数据都是在服务器启动的时候就已经加载好的,所以在servlet程序中可以直接获取到。和项目强制绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 <!-- context-param是上下参数(属于这个web工程)
当web项目启动,可以通过它来实现初始化数据加载效果
-->
<context-param>
<param-name>username</param-name>

<param-value>root</param-value>

</context-param>

<context-param>
<param-name>password</param-name>

<param-value>root123</param-value>

</context-param>

对应构造类java示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  package com.iweb.servlet;

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


public class MyServlet implements Servlet {
ServletContext servletContext=null;

// service方法专门用于处理请求和响应的方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// 获取web.xml中配置的上下文参数 context-param
// 获得username参数
String username = servletContext.getInitParameter("username");
String password = servletContext.getInitParameter("password");
System.out.println(username+"\t"+password);
// 获取当前的工程路径
String contextPath = servletContext.getContextPath();
System.out.println(contextPath);
System.out.println("当前的工程路径-->"+contextPath);
// 获取工程部署后在服务器硬盘上的绝对路径
System.out.println("工程部署的路径-->"+servletContext.getRealPath("/"));

}




public MyServlet(){
System.out.println("构造函数");
}

// 对servlet进行初始化
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init");
servletContext = servletConfig.getServletContext();
}

// 获取servlet配置信息
@Override
public ServletConfig getServletConfig() {
System.out.println("getServletConfig");
return null;
}



@Override
public String getServletInfo() {
System.out.println("getServletInfo");
return null;
}

@Override
public void destroy() {
System.out.println("destroy");
}
}

Servlet3.0规范

可以看见,我们在对servlet进行配置的时候,需要在web.xml中进行配置,这过于繁琐和复杂,但是在Servlet3.0规范中,我们可以不使用web.xml进行配置,而是使用注解的方式进行配置。

@WebServlet注解用于将一个类声明为servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置相应的类部署为servlet。该注解具体常用属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  package com.iweb.servlet;

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

/**
* urlPatterns 指定一组servlet的url匹配等价于 <url-pattern>
* loadOnStartup 指定servlet的加载顺序
* name 指定servlet的name属性,如果没有指定则以该servlet的取值为类的全类名 <servlet-name>
* value 该属于等价于 urlPatterns属性,两个属性不能同时使用
*/
@WebServlet("/myServlet3")
public class MyServlet3 extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet..MyServlet3");
}

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

}
}

以上配置之后,就不需要在web.xml中配置响应的标签了。
但是请一定要注意书写的数据类型和路径格式等细节问题,很容易造成错误。

HTTP协议

HTTP协议

HTTP:Hypertext Transfer Protocol超文本传输协议,规定了浏览器和服务器之间数据传输的规则。

  • HTTP是互联网应用最广泛的一种网络协议
  • HTTP协议要求:浏览器向服务器发送请求数据时,或者服务器在向浏览器响应数据时,都必须按照固定的格式进行数据传输。
    我们学习HTTP协议,就是学习请求和响应数据的具体格式内容。

就我个人而言很喜欢HTTP,方便且强大。而且依托于html的强大功能,我们可以很方便的实现一个简单的网站。

HTTP协议的特点:
基于TCP协议:面向连接,安全
TCP是一种面向连接的(建立连接之前需要经过三次握手),可靠的,基于字符流的传输层通信协议,在数据传输方便更安全
基于请求-响应:一次请求对应一次响应(先请求后响应)
请求和响应是一一对应的关系,没有请求就没有响应

HTTP协议的格式

● 客户端给服务器发送数据叫请求
● 服务器给客户端回传数据叫响应
○ 请求又分为Get请求,和Post请求中。
请求协议:浏览器将数据以请求格式发送给服务器,包括请求行,请求头,请求体。

请求行:HTTP请求中的第一行数据,由请求方式、资源路径、协议/版本组成。
请求方式:GET
资源路径:/web_project02_war/myServlet3
请求参数:username=admin123&password=123456

  • 请求参数是以key=value形式组成
  • 多个请求参数之间使用&连接
    请求头:第二行开始,格式为key:value,在请求头设置浏览器的一些自身信息和响应的形式
  • host:请求的主机名
  • User-Agent:浏览器版本
  • Accept:表示浏览器能接受的资源类型
  • Accept-Language:浏览器支持的语言,服务器可以根据此返回不同语言的网页
  • Accept-Encoding:浏览器支持压缩类型
    请求体:存储请求参数
    GET请求的请求体参数在请求行中
    Post方式的请求协议:
    请求行:包含请求方式Post,资源路径,协议/版本
    请求头
    请求体:存储请求参数

GET&POST

GET:GET请求的参数直接附加在URL上,以?号分隔路径于参数,多个参数使用&连接,这种方式使参数在URL中可见。
例如:

1
http://localhost:8081/web_project02_war/myServlet3?username=admin123&password=123456

可以看见,GET请求的参数直接附加在URL上,以?号分隔路径于参数,多个参数使用&连接,这种方式使参数在URL中可见。在开发过程中这种调试可以更加的直观,但是在实际开发运用中这种行为过于危险
POST:POST请求的参数不直接附加在URL上,而是存储在请求体中。
例如:
1
http://localhost:8081/web_project02_war/myServlet3

可以看见,POST请求的参数不直接附加在URL上,而是存储在请求体中。在开发过程中这种调试相对GET请求来说更加的安全,但是在实际开发运用中这种行为相对GET请求来说更加的安全。
那些是GET请求,那些是POST请求
● get请求有那些:
○ form标签method=get
○ a标签
○ 在浏览器地址中输入地址后敲回车
● post请求有那些:
○ form标签method=post

HttpServletRequest

每次只要有请求进入tomcat服务器,tomcat服务器就把请求过来的http协议信息解析好封装到request对象,然后传递到service(doGet和doPost)方法中给我们使用,我们可以通过HttpServletRequest对象,获取请求中的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  package com.iweb.servlet;

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

/**
* urlPatterns 指定一组servlet的url匹配等价于 <url-pattern>
* loadOnStartup 指定servlet的加载顺序
* name 指定servlet的name属性,如果没有指定则以该servlet的取值为类的全类名 <servlet-name>
* value 该属于等价于 urlPatterns属性,两个属性不能同时使用
*/
@WebServlet("/myServlet3")
public class MyServlet3 extends HttpServlet {

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

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("绝对路径-->"+req.getRequestURL());
System.out.println("获取请求的参数-->"+req.getParameter("username"));
System.out.println("获取客户端的IP地址-->"+req.getRemotePort());
}
}

如何获取请求参数

获取请求行中的参数:

1
2
3
4
5
6
req.getRequestURL();//获取请求的绝对路径
req.getRequestURI();//获取请求的资源路径
req.getMethod();//获取请求的方式
req.getProtocol();//获取请求的协议
req.getServerName();//获取请求的服务器名
req.getServerPort();//获取请求的服务器端口

获取请求头中的参数:
1
req.getHeader("key");//获取请求头中的key值

获取请求体中的参数:
1
req.getParameter("key");//获取请求体中的key值

获取请求参数的名称:
1
req.getParameterNames();//获取请求参数的名称

获取请求参数的名称和值:
1
req.getParameterMap();//获取请求参数的名称和值

获取请求参数的值:
1
req.getParameterValues("key");//获取请求参数的值

获取请求参数的值:
1
req.getParameter("key");//获取请求参数的值

OK打住,再写下去我要炸了。我直接用一个典型的案例来给大家做介绍吧
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>

</head>

<body>
<form action="paramsServlet" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
性别:<input type="radio" value="man" name="sex" checked/>
<input type="radio" value="woman" name="sex"/><br/>
兴趣爱好:<input type="checkbox" name="hobby" value="java"/>java
<input type="checkbox" name="hobby" value="python"/>python
<input type="checkbox" name="hobby" value="c++"/>c++<br/>
<input type="submit" value="提交"/>
</form>

</body>

</html>

servlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  package com.iweb.servlet;

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

@WebServlet("/paramsServlet")
public class ParamsServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求中的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String sex = req.getParameter("sex");
String[] hobby = req.getParameterValues("hobby");
System.out.println(username+"\t"+password+"\t"+sex);
System.out.println(Arrays.toString(hobby));
}
}

你要是直接截取上述代码,你会发现在中文传递上会存在一些问题,所以我们需要单独去对这个问题进行解决
doGet请求的中文乱码解决
1
2
3
4
5
6
7
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求中的参数
String username = req.getParameter("username");
// 先以iso-8859-1进行编码,再以UTF-8进行解码
username=new String(username.getBytes("iso-8859-1"),"utf-8");
}

doPost请求的中文乱码解决
1
2
3
4
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求体的字符集为UTF-8解决post请求的中文乱码问题
req.setCharacterEncoding("utf-8");
}

请求转发

什么是请求转发?
请求转发是指,服务器收到请求后,从一次资源跳转到另外一个资源的操作叫做请求转发。
请求转发特点:
1.浏览器地址栏没有变化
2.他们是一次请求
3.他们共享request域中的数据
4.不可以访问工程以外的资源
5.request域中的数据只能是一次请求

实现方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  @WebServlet("/servletTest1")
public class ServletTest1 extends HttpServlet {

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

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求中的参数(办事的材料)
String username = req.getParameter("username");
System.out.println("在servlet1柜台查看参数(材料):"+username);
// 给材料盖个章,并传递到servlet2(柜台)绑定上request域对象中
req.setAttribute("key",username);
// 问路,走向servlet2
// 请求转发必须以/打头
req.getRequestDispatcher("/servletTest2").forward(req,resp);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  @WebServlet("/servletTest2")
public class ServletTest2 extends HttpServlet {

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

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 检查柜台1是否有盖章
Object key = req.getAttribute("key");
System.out.println("检查柜台1是否有盖章:"+key);
// 处理业务
System.out.println("servlet2处理自己的业务");
}
}

HttpServletResponse

HttpServletResponse和HttpServletRequest类一样,每次请求进来,tomcat服务器都会创建一个Response对象传递给servlet程序去使用,
HttpServletRequest类表示请求过来的信息,HttpServletResponse表示所有响应的信息,如果我们需要设置返回给客户端的信息,可以通过HttpServletResponse对象来设置。

字有点多,我一句话用大白话说清楚:
HttpServletResponse类表示响应的信息,我们可以通过HttpServletResponse对象来设置响应的信息。

两个输出流的说明

字节流 getOutputStream():用于下载
字符流 getWriter():用于回传字符串(常用)
两个流同时只能使用一个,使用了字节流就不能使用字符流,反之亦然,否则会报错。

有点难记啊,打多了写多了就记得了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  package com.iweb.servlet;

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

@WebServlet("/responseServlet")
public class ResponseServlet extends HttpServlet {

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

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 接受客户端传递过来的参数
int age =Integer.parseInt(req.getParameter("age"));
System.out.println(age);
// 往客户端回传字符串(数据)
PrintWriter writer = resp.getWriter();
writer.write("客户端你好,已经收到了你的数据");
}
}

响应的乱码问题

因为各种软件,地域的标准不同,所以在不同的地域,会有不同的编码标准,在中文的地域,会使用gbk编码,在英文的地域,会使用utf-8编码,所以在回传字符串时,需要注意编码问题,否则会出现乱码问题。
下面就是个姐姐乱码问题的典型实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  package com.iweb.servlet;

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

@WebServlet("/responseServlet")
public class ResponseServlet extends HttpServlet {

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

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 处理请求中文乱码
req.setCharacterEncoding("utf-8");
// 处理响应中文乱码
// 同时设置服务器和客户端使用UTF-8字符集,还设置响应头
// 方法一定要在获取流对象之间调用才有效
resp.setContentType("text/html;charset=utf-8");
// 接受客户端传递过来的参数
int age =Integer.parseInt(req.getParameter("age"));
System.out.println(age);
// 往客户端回传字符串(数据)
PrintWriter writer = resp.getWriter();
writer.write("客户端你好,已经收到了你的数据");
}
}

请求中定向

重定向行为,是指客户端给服务器发请求,然后服务器告诉客户端,之前的访问地址已经被废弃,去新的地址访问,叫做请求重定向。

因为我认为转换页面等行为本质上是路径选取,所以我认为重定向可以做到很多的功能,比如:
1.访问一个页面,但是这个页面需要登录才能访问,那么我们就可以在servlet中判断用户是否登录,如果没有登录,就可以重定向到登录页面。
2.访问一个页面,但是这个页面的访问地址已经被废弃,我们可以重定向到新的地址。
3.访问一个页面,但是这个页面的访问地址已经被废弃,我们可以重定向到新的地址。

请求重定向的特点:
1.浏览器地址会发生改变
2.两次请求
3.不能共享request域中的数据
4.不能访问web-inf下的资源
以下是一个重定向的案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  package com.iweb.servlet;

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

@WebServlet("/servletTest3")
public class ServletTest3 extends HttpServlet {

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

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 绑定数据到request域中
req.setAttribute("username","admin123");
// 重定向
resp.sendRedirect("servletTest4");
}
}

最终要的部分来自最后的那一行:
1
resp.sendRedirect("servletTest4");

更多请转下一篇:前端学习【3】