学习 JavaWeb 这一篇就够了
目录第一章 开发工具 1.1、JDK 安装 1.2、Tomcat 安装 1.3、IDEA 安装 1.4、IDEA 集成 Tomcat1.5、IDEA 运行 JavaWeb 第二章 XML2.1、XML 的概述 2.2、XML 的语法......
配套资料,免费下载 链接:pan.baidu.com/s/1DNouClLL… 提取码:dq2w 复制这段内容后打开百度网盘手机 App,操作更方便哦
1.1、JDK 安装
第一步:打开官网进行下载(www.oracle.com/java/techno…
第二步:运行程序进行安装
全部默认下一步即可,不用管路径是不是存在中文和空格,无碍!
注意:如果自己会配置 JDK,可以更改它的安装路径,那相应的环境变量也需要修改!
第三步:系统环境变量配置
此电脑 》 右键 》 属性 》 高级系统设置 》 环境变量 》 系统变量 》 新建(需要新建两个,然后修改一个)
新建两个:JAVA_HOME 代表 Java 的安装目录、CLASSPATH 代表程序运行的时候,优先加载当前目录中的类,然后再加载指定的类库
| 变量名 | 变量值 |
|---|---|
| JAVA_HOME | C:\Program Files\Java\jdk1.8.0_261 |
| CLASSPATH | .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; |
修改一个:编辑 PATH 环境变量,它会打开一个窗口,新添两条路径,如下图所示
- %JAVA_HOME%\bin
- %JAVA_HOME%\jre\bin
第四步:测试 JDK 是否安装成功
打开一个 cmd 命令行窗口,输入以下两个命令查看,如果有内容输出则证明已经配置成功!
- java -version
- javac -version
1.2、Tomcat 安装
第一步:打开官网进行下载和安装(tomcat.apache.org/)
第二步:系统环境变量配置
此电脑 》 右键 》 属性 》 高级系统设置 》 环境变量 》 系统变量 》 新建(需要新建两个,然后修改三个)
新建两个:CATALINA_BASE 和 CATALINA_HOME 均代表 Tomcat 的安装目录
| 变量名 | 变量值 |
|---|---|
| CATALINA_BASE | C:\DevTools\apache-tomcat-8.5.57 (输入自己解压的 Tomcat 目录,不要照抄我的) |
| CATALINA_HOME | C:\DevTools\apache-tomcat-8.5.57 (输入自己解压的 Tomcat 目录,不要照抄我的) |
修改一个:编辑 CLASSPATH 环境变量,它会打开一个窗口,具体修改,如下所示
- 未修改前:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
- 修改以后:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\lib\servlet-api.jar;
修改两个:编辑 PATH 环境变量,它会打开一个窗口,新添两条路径,如下所示
- %CATALINA_HOME%\bin
- %CATALINA_HOME%\lib
第三步:测试 Tomcat 是否安装成功
打开一个 cmd 命令行窗口,输入以下一个命令查看,如果有内容输出则证明已经配置成功!
- catalina run
- 打开浏览器,输入:http://localhost:8080/
如果看到上边这个界面了,就把刚才打开的 cmd 窗口关掉,否则可能会影响后边 IDEA 集成 Tomcat。
1.3、IDEA 安装
注意:官网的版本会隔一段时间更新一次,我这里只是告诉大家怎么下载,不一定要用最新的,我这套课程使用的是 IdeaIU-2020.1.2,如果你不是这个版本,那么我建议你改为这个版本,否则后边可能会出现一些问题。
第一步:打开官网进行下载和安装(www.jetbrains.com/idea/)
第二步:运行程序进行安装
全部默认下一步即可,如果遇到需要一页打勾的很多,就把有 64 的那个勾上,它代表在桌面创建一个 64 位的快捷方式,没勾选也没事,可以在开始菜单打开 IDEA!
第三步:关于激活的问题
由于 IDEA 是收费软件,请大家自行购买激活码,然后激活,不激活也可以试用 30 天!
第四步:常见的设置页面
第五步:最终的效果图
1.4、IDEA 集成 Tomcat
1.5、IDEA 运行 JavaWeb
注意:这个弹窗意思是你需不需要每天都让我提示你一些小技巧,我们选择关闭,不用搭理他!
注意:如果你有依赖的 JAR 包,就放到 lib 文件夹中,然后添加到工程中,方便项目移动的时候,不会丢失 JAR 包。
至于 classes 是否需要创建,在这里我个人认为是不需要创建的,因为编译器会自动创建,如果你创建了,还必须要修改配置信息,很麻烦,所以我建议就不要创建了,一般我们也不会创建。
注意:Fix 并不是所有电脑都需要点击的,如果它弹出了这个窗口你就点击,没弹出来就不用管了!
注意:只有上边点击了 Fix 才会出来这个页面,没有点击 Fix,这一步忽略即可,不用纠结!
一般浏览器也会正常显示刚才 JSP 中的文件内容
2.1、XML 的概述
XML 是可扩展标记语言(eXtensible Markup Language),它被设计用来传输和存储数据,我们一般使用 XML 文件来做应用程序的配置文件。
2.2、XML 的语法
案例演示:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
树状结构:
支持语法:
- 嵌套标签
- 单级标签
- 内含属性
注意:根节点只能有一个
注释语法:
<!-- comment -->
2.3、XML 的解析
解析方式:
- DOM(Document Object Model):在解析的时候,它会把整个 XML 文档读入内存中,形成一个树状结构。整个文档称之为 Document 对象,所有元素节点对应 Element 对象,属性对应 Attribute 对象,文本对应 Text 对象,以上所有对象都可以称之为 Node 节点。如果 XML 特别大,可能会造成内存溢出。这种解析方式可以对 XML 文档进行增删改查操作。
- SAX(Simple API For XML):它是基于事件驱动的一种解析方式,也就是读取一行,解析一行。在读取较大的 XML 文件的时候,也不会造成内存溢出,但是这种解析方式只能进行查询,不能进行增删改操作。
案例演示:
工程名称:XMLDemo
包的名称:com.caochenlei.xml.parse
依赖文件:dom4j-1.6.1.jar、jaxen-1.1-beta-6.jar、JUnit 4
测试文件:bookstore.xml(全路径:/XMLDemo/bookstore.xml)
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
代码名称:XMLParse.java(全路径:/XMLDemo/src/com/caochenlei/xml/parse/XMLParse.java)
package com.caochenlei.xml.parse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
public class XMLParse {
@Test
public void test1() {
try {
SAXReader domReader = new SAXReader();
Document document = domReader.read(new File("bookstore.xml"));
Element rootElement = document.getRootElement();
List<Element> bookElements = rootElement.elements("book");
for (Element bookElement : bookElements) {
Attribute category = bookElement.attribute("category");
String title = bookElement.element("title").getText();
String author = bookElement.element("author").getText();
String year = bookElement.element("year").getText();
String price = bookElement.element("price").getText();
System.out.println(Arrays.asList(category.getText(), title, author, year, price));
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
@Test
public void test2() {
try {
SAXReader domReader = new SAXReader();
Document document = domReader.read(new File("bookstore.xml"));
Element rootElement = document.getRootElement();
Element bookElement = rootElement.addElement("book");
bookElement.addAttribute("category", "Hibernate");
bookElement.addElement("title").addText("Learing Hibernate");
bookElement.addElement("author").addText("caochenlei");
bookElement.addElement("year").addText("1997");
bookElement.addElement("price").addText("99.99");
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("bookstore.xml"), OutputFormat.createPrettyPrint());
xmlWriter.write(document);
xmlWriter.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test3() {
try {
SAXReader domReader = new SAXReader();
Document document = domReader.read(new File("bookstore.xml"));
Element rootElement = document.getRootElement();
Node singleNode = rootElement.selectSingleNode("//book[@category='Hibernate']");
rootElement.remove(singleNode);
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("bookstore.xml"), OutputFormat.createPrettyPrint());
xmlWriter.write(document);
xmlWriter.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test4() {
try {
SAXReader domReader = new SAXReader();
Document document = domReader.read(new File("bookstore.xml"));
Element rootElement = document.getRootElement();
Node singleNode = rootElement.selectSingleNode("//book[@category='WEB']");
singleNode.selectSingleNode("title").setText("Learning JavaWeb");
singleNode.selectSingleNode("author").setText("张三");
singleNode.selectSingleNode("year").setText("2020");
singleNode.selectSingleNode("price").setText("09.09");
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("bookstore.xml"), OutputFormat.createPrettyPrint());
xmlWriter.write(document);
xmlWriter.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.1、YAML 的概述
YAML(YAML Ain’t Markup Language)是一种可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言,类似于 XML 但比 XML 更简洁。
3.2、YAML 的语法
YAML 语法:
- 大小写敏感
- 使用空格缩进表示层级关系
- 缩进不允许使用 tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- '#'表示注释
- 相同层级的键不能重复
YAML 对象:
对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格,也可以使用 key:{key1: value1, key2: value2, …},还可以使用缩进表示层级关系。
key:
child-key1: value1
child-key2: value2
较为复杂的对象格式,可以使用问号加一个空格代表一个复杂的 key,配合一个冒号加一个空格代表一个 value:
?
- complexkey1
- complexkey2
:
- complexvalue1
- complexvalue2
意思即对象的属性是一个数组 [complexkey1,complexkey2],对应的值也是一个数组 [complexvalue1,complexvalue2]
YAML 数组:
以 - 开头的行表示构成一个数组:
- A
- B
- C
YAML 支持多维数组,可以使用行内表示:
key: [value1, value2, ...]
数据结构的子成员是一个数组,则可以在该项下面缩进一个空格:
-
- A
- B
- C
一个相对复杂的例子:意思是 companies 属性是一个数组,每一个数组元素又是由 id、name、price 三个属性构成。
companies:
-
id: 1
name: company1
price: 200W
-
id: 2
name: company2
price: 500W
数组也可以使用流式 (flow) 的方式表示:
companies: [{id: 1,name: company1,price: 200W},{id: 2,name: company2,price: 500W}]
YAML 纯量:
纯量是最基本的,不可再分的值,包括:
- 字符串
- 布尔值
- 整数
- 浮点数
- Null
- 时间
- 日期
使用一个例子来快速了解纯量的基本使用:
boolean:
- TRUE
- FALSE
float:
- 3.14
- 6.8523015e+5
int:
- 123
- 0b1010_0111_0100_1010_1110
null:
nodeName: 'node'
parent: ~
string:
- 哈哈
- 'Hello World'
- comment1:
newline1
newline2
- comment2: >
newline3
newline4
- comment3: |
newline3
newline4
date:
- 2018-02-17 15:02:31
datetime:
- 2018-02-17T15:02:31+08:00
YAML 引用:
& 锚点和 * 别名,可以用来引用:
defaults: &defaults
adapter: postgres
host: localhost
development:
database: myapp_development
<<: *defaults
test:
database: myapp_test
<<: *defaults
上边的代码相当于:
defaults:
adapter: postgres
host: localhost
development:
database: myapp_development
adapter: postgres
host: localhost
test:
database: myapp_test
adapter: postgres
host: localhost
类型指定:
YAML 虽然有类型自动解析,但是有时候我们写了一个数字,但是我们想让它是字符串类型,就用到了类型指定,只要在值的前边写上相对应的类型标识就行了,常见的类型标识有以下几个:
!!null ''
!!bool 'yes'
!!int '3...'
!!float '3.14...'
!!binary '...base64...'
!!timestamp 'YYYY-...'
!!omap [ ... ]
!!pairs [ ... ]
!!set { ... }
!!str '...'
!!seq [ ... ]
!!map { ... }
3.3、YAML 的解析
工程名称:YAMLDemo
包的名称:com.caochenlei.yaml.parse
依赖文件:snakeyaml-1.17.jar、JUnit 4
测试文件:user.yaml(全路径:/YAMLDemo/user.yaml)、users.yaml(全路径:/YAMLDemo/users.yaml)
参考网站:bitbucket.org/asomov/snak…
User.java(全路径:/YAMLDemo/src/com/caochenlei/yaml/parse/User.java)
package com.caochenlei.yaml.parse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
public class User {
private long id;
private String name;
private String phone;
private List<String> hobby;
private Map<String, BigDecimal> balance;
private Address address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public List<String> getHobby() {
return hobby;
}
public void setHobby(List<String> hobby) {
this.hobby = hobby;
}
public Map<String, BigDecimal> getBalance() {
return balance;
}
public void setBalance(Map<String, BigDecimal> balance) {
this.balance = balance;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", phone=" + phone + ", hobby=" + hobby + ", balance=" + balance + ", address=" + address + "]";
}
}
Address.java(全路径:/YAMLDemo/src/com/caochenlei/yaml/parse/Address.java)
package com.caochenlei.yaml.parse;
public class Address {
private String county;
private String province;
private String city;
public String getCounty() {
return county;
}
public void setCounty(String county) {
this.county = county;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [county=" + county + ", province=" + province + ", city=" + city + "]";
}
}
YAMLDemo.java(全路径:/YAMLDemo/src/com/caochenlei/yaml/parse/YAMLDemo.java)
package com.caochenlei.yaml.parse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.yaml.snakeyaml.Yaml;
public class YAMLDemo {
@Test
public void test1() {
try {
Yaml yaml = new Yaml();
Object user = yaml.load(new FileInputStream(new File("user.yaml")));
System.out.println(user);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Test
public void test2() {
try {
Yaml yaml = new Yaml();
User user = yaml.loadAs(new FileInputStream(new File("user.yaml")), User.class);
System.out.println(user);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Test
public void test3() {
try {
Yaml yaml = new Yaml();
Map<String, Object> user = (Map<String, Object>) yaml.load(new FileInputStream(new File("user.yaml")));
System.out.println(user.get("id"));
System.out.println(user.get("name"));
System.out.println(user.get("phone"));
System.out.println(user.get("hobby"));
System.out.println(user.get("balance"));
System.out.println(user.get("address"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Test
public void test4() {
try {
Yaml yaml = new Yaml();
Iterable<Object> users = yaml.loadAll(new FileInputStream(new File("users.yaml")));
for (Object user : users) {
System.out.println(user);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Test
public void test5() {
try {
Yaml yaml = new Yaml();
User user = new User();
user.setId(123456);
user.setName("王五");
user.setPhone("15633029014");
user.setHobby(Arrays.asList("aaa", "bbb", "c"));
HashMap<String, BigDecimal> balance = new HashMap<String, BigDecimal>();
balance.put("wechat", new BigDecimal(19.99));
balance.put("alipay", new BigDecimal(29.99));
user.setBalance(balance);
Address address = new Address();
address.setCity("China");
address.setProvince("HeBei");
address.setCity("XingTai");
user.setAddress(address);
Writer output = new FileWriter("myuser.yaml");
yaml.dump(user, output);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test6() {
try {
Yaml yaml = new Yaml();
HashMap<String, Object> user = new HashMap<String, Object>();
user.put("id", 123456);
user.put("name", "王五");
user.put("phone", "15633029014");
user.put("hobby", Arrays.asList("aaa", "bbb", "c"));
HashMap<String, BigDecimal> balance = new HashMap<String, BigDecimal>();
balance.put("wechat", new BigDecimal(19.99));
balance.put("alipay", new BigDecimal(29.99));
user.put("balance", balance);
Address address = new Address();
address.setCity("China");
address.setProvince("HeBei");
address.setCity("XingTai");
user.put("address", address);
Writer output = new FileWriter("mymap.yaml");
yaml.dump(user, output);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.1、Servlet 概述
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
4.2、Servlet 语法格式
第一步:创建包(com.caochenlei.servlet.demo)
第二步:创建类(com.caochenlei.servlet.demo.MyServlet),并且需要实现 Servlet 接口中的所有方法
package com.caochenlei.servlet.demo;
import javax.servlet.*;
import java.io.IOException;
public class MyServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("MyServlet init ...");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse)
throws ServletException, IOException {
System.out.println("MyServlet service ...");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("MyServlet destroy ...");
}
}
方法介绍:
- init:Servlet 初始化时调用的方法
- getServletConfig:获取当前 Servlet 的配置信息
- service:调用 Servlet 真正去处理逻辑的方法
- getServletInfo:它提供有关 Servlet 的信息,如作者、版本、版权
- destroy:Servlet 销毁时调用的方法
第三步:配置映射(web.xml 中新增以下代码)
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.caochenlei.servlet.demo.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
配置介绍:
servlet 标签用于配置 Servlet 的基本信息
- servlet-class:代表当前 Servlet 的具体类路径,注意最后不包含. java
- servlet-name:代表当前 Servlet 的别名,可以和原 Servlet 名称一样,也可以不一样,一般我们就一样就行了
servlet-mapping 标签用于配置请求路径与具体处理 Servlet 的对应关系
- url-pattern:这里写你要匹配的地址路径
- servlet-name:如果匹配到请求,该交给哪一个 Servlet 处理,这里的 servlet-name 其实就是一个 Servlet 的别名
第四步:启动应用,然后浏览器输入地址访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyServlet)
第五步:正常关闭 Tomcat 服务器,我们会看到调用销毁方法,如下图所示:
4.3、Servlet 执行过程
4.4、Servlet 生命周期
Servlet 运行在 Servlet 容器中,其生命周期由容器来管理。
Servlet 的生命周期通过 javax.servlet.Servlet 接口中的 init()、service() 和 destroy() 方法来表示。
Servlet 的生命周期包含了下面 4 个阶段:
- 类加载和实例化
- 初始化:init()
- 请求处理:service()
- 销毁:destroy()
4.5、Servlet 继承体系
其实我们不难发现,现有的 Servlet 它的方法比较多,而且大多需要我们自己来实现,那有没有一种它的实现子类,把大部分方法都是实现了,而我们只要关注请求处理就行了,那答案肯定是有的,这个类就是 HttpServlet,我们只要继承这个类重写 GET、POST 方法就能实现一个简单的 Servlet 请求处理,Servlet 的继承体系如下图:
既然我们知道 HttpServlet 这个类了,我们就要使用一下:
第一步:创建类(com.caochenlei.servlet.demo.MyHttpServlet),并且需要继承 HttpServlet 实现 doPost、doGet 方法。
package com.caochenlei.servlet.demo;
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 MyHttpServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doPost method invoke ...");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doGet method invoke ...");
}
}
第二步:配置映射(在 web.xml 文件中新增以下代码)
<servlet>
<servlet-name>MyHttpServlet</servlet-name>
<servlet-class>com.caochenlei.servlet.demo.MyHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyHttpServlet</servlet-name>
<url-pattern>/MyHttpServlet</url-pattern>
</servlet-mapping>
第三步:重启应用,然后浏览器访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyHttpServlet)**,观察控制台**
注意:doPost 需要提交表单模拟,这里就不演示了,效果都一样!
我们注意 url-pattern 它可以有多种拦截形式:
- 全路径匹配:
/a - 前半段匹配:
/a/b/c/* - 扩展名匹配:
*.action
4.6、ServletContext
每个 web 工程都只有一个 ServletContext 对象,也就是不管在哪个 Servlet 里面,获取到的这个类的对象都是同一个,它用来获取 Servlet 的上下文,在服务器启动的时候,会为托管的每一个 web 应用程序,创建一个 ServletContext 对象,当从服务器移除托管或者是关闭服务器时,ServletContext 将会被销毁。它主要有以下几方面作用:
- 获取全局配置参数
- 获取 web 工程中的资源
- 在 servlet 间共享数据域对象
4.6.1、获取全局配置参数
第一步:在 web.xml 中新增以下代码
<context-param>
<param-name>username</param-name>
<param-value>zhangsan</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</context-param>
第二步:在 MyHttpServlet 的 doGet 方法中新增以下代码
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doGet method invoke ...");
Enumeration<String> initParameterNames = getServletContext().getInitParameterNames();
while(initParameterNames.hasMoreElements()){
String initParameterName = initParameterNames.nextElement();
String initParameterValue = getServletContext().getInitParameter(initParameterName);
System.out.println(initParameterName+":"+initParameterValue);
}
}
第三步:重启 Tomcat 服务器,在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyHttpServlet)
4.6.2、获取 web 工程中的资源
第一步:在 myJavaWebDemo 的 web 文件夹中右键创建 a.txt 文件,内容为 Hello,World!
第二步:在 MyHttpServlet 的 doGet 方法中新增以下代码
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doGet method invoke ...");
Enumeration<String> initParameterNames = getServletContext().getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String initParameterName = initParameterNames.nextElement();
String initParameterValue = getServletContext().getInitParameter(initParameterName);
System.out.println(initParameterName + ":" + initParameterValue);
}
String realPath = getServletContext().getRealPath("a.txt");
System.out.println(realPath);
InputStream resourceAsStream = getServletContext().getResourceAsStream("a.txt");
System.out.println(resourceAsStream);
}
第三步:重启 Tomcat 服务器,在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyHttpServlet)
注意:当你能拿到一个文件的绝对路径或者输入流以后,就可以对它进行操作了!
4.6.3、在 Servlet 间共享数据域对象
第一步:创建 LoginServlet 并配置请求映射
LoginServlet
package com.caochenlei.servlet.demo;
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 LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
web.xml
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.caochenlei.servlet.demo.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
第二步:在 LoginServlet 的 doGet 中实现登录次数的修改,默认为 1
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Integer count = (Integer) getServletContext().getAttribute("count");
if (count == null) {
getServletContext().setAttribute("count", 1);
} else {
getServletContext().setAttribute("count", count + 1);
}
}
第三步:在 MyHttpServlet 的 doGet 中新增以下查看代码,用于查看当前登录次数
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doGet method invoke ...");
Enumeration<String> initParameterNames = getServletContext().getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String initParameterName = initParameterNames.nextElement();
String initParameterValue = getServletContext().getInitParameter(initParameterName);
System.out.println(initParameterName + ":" + initParameterValue);
}
String realPath = getServletContext().getRealPath("a.txt");
System.out.println(realPath);
InputStream resourceAsStream = getServletContext().getResourceAsStream("a.txt");
System.out.println(resourceAsStream);
Integer count = (Integer) getServletContext().getAttribute("count");
if (count == null) {
response.getWriter().write("no login!");
} else {
response.getWriter().write("count:" + count);
}
}
第四步:重启 Tomcat 服务器
在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyHttpServlet)**,查看是否登录**
在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/LoginServlet)**,模拟登录场景**
在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyHttpServlet)**,查看登录次数**
4.7、ServletConfig
通过 ServletConfig 对象可以获取 servlet 在配置的时候一些信息。
第一步:创建类(HelloServlet)
package com.caochenlei.servlet.demo;
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 HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
第二步:在 web.xml 中配置映射关系
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.caochenlei.servlet.demo.HelloServlet</servlet-class>
<init-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
第三步:在 HelloServlet 的 doGet 方法中新增以下代码
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Enumeration<String> initParameterNames = getServletConfig().getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String initParameterName = initParameterNames.nextElement();
String initParameterValue = getServletConfig().getInitParameter(initParameterName);
System.out.println(initParameterName + ":" + initParameterValue);
}
}
第四步:重启 Tomcat 服务器,在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/HelloServlet)
4.8、HttpServletRequest
HttpServletRequest 这个对象封装了客户端提交过来的一切数据。
第一步:修改 index.jsp
<form action="RegisterServlet" method="get">
账户:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
<input type="submit" value="注册">
</form>
第二步:创建类(RegisterServlet)
package com.caochenlei.servlet.demo;
import javafx.print.Collation;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
System.out.println(headerName + ":" + headerValue);
}
System.out.println("====================");
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String parameterName = parameterNames.nextElement();
String parameterValue = request.getParameter(parameterName);
System.out.println(parameterName + ":" + parameterValue);
}
System.out.println("====================");
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> names = parameterMap.keySet();
for (String name : names) {
String[] value = parameterMap.get(name);
System.out.println(name + ":" + Arrays.toString(value));
}
System.out.println("====================");
StringBuffer requestURL = request.getRequestURL();
String requestURI = request.getRequestURI();
String servletPath = request.getServletPath();
String queryString = request.getQueryString();
System.out.println("requestURL:" + requestURL);
System.out.println("requestURI:" + requestURI);
System.out.println("servletPath:" + servletPath);
System.out.println("queryString:" + queryString);
}
}
第三步:在 web.xml 中新增映射信息
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.caochenlei.servlet.demo.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/RegisterServlet</url-pattern>
</servlet-mapping>
第四步:重启 Tomcat 服务器,在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/)
在表单输入数据,然后点击提交

查看 IDEA 的控制台信息
host:localhost:8080
connection:keep-alive
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site:same-origin
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
referer:http://localhost:8080/myJavaWebDemo_war_exploded/
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
cookie:JSESSIONID=4342FA7CB5F51C5E4A5251E485E36E38
====================
username:zhangsan
password:123456
====================
username:[zhangsan]
password:[123456]
====================
requestURL:http://localhost:8080/myJavaWebDemo_war_exploded/RegisterServlet
requestURI:/myJavaWebDemo_war_exploded/RegisterServlet
servletPath:/RegisterServlet
queryString:username=zhangsan&password=123456
如何解决请求数据中文乱码问题?
-
GET 方式
-
String newUsername = new String(username.getBytes("ISO-8859-1"), "UTF-8");
-
-
POST 方式
-
request.setCharacterEncoding("UTF-8");
-
4.9、HttpServletResponse
HttpServletResponse 这个对象负责返回数据给客户端。
第一步:创建类(DisplayServlet)
package com.caochenlei.servlet.demo;
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 DisplayServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().write("<h1>hello response 111 ...</h1>");
}
}
第二步:在 web.xml 文件中新增以下映射信息
<servlet>
<servlet-name>DisplayServlet</servlet-name>
<servlet-class>com.caochenlei.servlet.demo.DisplayServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DisplayServlet</servlet-name>
<url-pattern>/DisplayServlet</url-pattern>
</servlet-mapping>
第三步:重启 Tomcat 服务器,在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/DisplayServlet)
如何解决响应数据中文乱码问题?
-
以字符流输出:response.getWriter()
-
response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "text/html; charset=UTF-8"); response.getWriter().write("你好,世界!");
-
-
以字节流输出:response.getOutputStream()
-
response.setHeader("Content-Type", "text/html;charset=UTF-8"); response.getOutputStream().write("你好,世界!".getBytes("UTF-8"));
-
4.10、重定向和请求转发
- 重定向
// 第一种:使用示例
response.setStatus(302);
response.setHeader("Location", "login_success.html");*/
// 第二种:使用示例
response.sendRedirect("login_success.html");
1. 地址上显示的是最后的那个资源的路径地址。
2. 请求次数最少有两次,服务器在第一次请求后,会返回302以及一个地址,浏览器在根据这个地址,执行第二次访问。
3. 可以跳转到任意路径,不是自己的工程也可以跳。
4. 效率稍微低一点,执行两次请求。
5. 后续的请求,没法使用上一次的request存储的数据,或者没法使用上一次的request对象,因为这是两次不同的请求。
- 请求转发
// 使用示例:
request.getRequestDispatcher("login_success.html").forward(request, response);
1. 地址上显示的是请求servlet的地址,返回200ok。
2. 请求次数只有一次,因为是服务器内部帮客户端执行了后续的工作。
3. 只能跳转自己项目的资源路径。
4. 效率上稍微高一点,因为只执行一次请求。
5. 可以使用上一次的request对象。
4.11、Cookie
Cookie 其实是一份小数据,它是服务器给客户端并且存储在客户端上的一份小数据。
第一步:创建类(CookieServlet)
package com.caochenlei.servlet.demo;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
if (cookies.length == 1) {
System.out.println("没有其它Cookie存在,只有JSESSIONID这个Cookie存在!");
Cookie cookie = new Cookie("username", "zhangsan");
cookie.setComment("用户账号Cookie");
cookie.setMaxAge(60 * 60 * 24 * 7);
cookie.setValue("lisi");
cookie.setDomain("localhost");
cookie.setPath("/myJavaWebDemo_war_exploded/CookieServlet");
response.addCookie(cookie);
} else {
for (Cookie cookie : cookies) {
if ("username".equals(cookie.getName())) {
System.out.println(cookie.getName() + "====" + cookie.getValue());
}
}
}
}
}
第二步:在 web.xml 中新增映射信息
<servlet>
<servlet-name>CookieServlet</servlet-name>
<servlet-class>com.caochenlei.servlet.demo.CookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieServlet</servlet-name>
<url-pattern>/CookieServlet</url-pattern>
</servlet-mapping>
第三步:重启 Tomcat 服务器
在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/CookieServlet)
在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/DisplayServlet)