HTML和CSS
- ctrl + shift + / 在同一行代码中的后半截产生注释
HTML标签的介绍
- 标签拥有自己的属性,分为 基本属性 和 事件属性
- 标签的基本属性 :
bgcolor="red
可以修改简单的样式效果 - 标签的事件属性 :
onclick="alert('你好');"
单标签:
- br/ 换行
- hr/ 水平线
常用标签介绍:
- foot标签是字体标签,可以用来修改文本的 字体face,颜色color,大小size
- 特殊字符 :小于号,空格,和号&,引号",撇号’ 等
我是<br>标签
- 标题标签 :h1 到 h6, 属性align控制左对齐left(默认),中间center,右对齐(会随着窗口大小自动调整)
- 超链接标签 :属性href控制链接,属性target控制当前(_self),和另一个页面(_blank)
- 无序列表ul :属性type可以修改列表项前面的符号(兼容)
- img标签 :属性src设置图片的路径,width,height,border设置边框大小,alt
- 表格标签table,tr是行标签,th(相当于td加上b加粗)是表头标签,td是单元格标签,align设置单元格文本对齐方式;bordr,width,height,align设置表格相对于页面的对齐方式,cellspacing设置单元格间距
- 跨行跨列表格,colspan属性设置跨列(用了以后要把其他同一行的单元格删掉部分,否则表格会突出);rowspan属性设置跨行
- iframe框架标签(内嵌窗口),可以在一个html页面上打开一个小窗口小区域,去加载一个单独的页面;iframe标签和a标签组合使用的步骤 :1.在iframe标签中使用name属性定义一个名称;2.在a标签的target属性上设置iframe的name属性值
- 表单标签form :
- 表单格式化 :form里面嵌套table
- 表单提交的细节 :
- 其他标签 :
div
标签默认独占一行;span
标签 它的长度是封装数据的长度;p
段落标签 默认会在段落的上方或下方各空出一行来(如果已经有就不再空)
CSS技术
常用样式:
- 字体颜色
color: red;
- 宽度;高度;(像素值 / 百分比值)
- 背景颜色
background-color
- 字体大小
font-size
- 红色1像素实线边框
border: 1px solid red;
- DIV居中
margin-left: auto; margin-right: auto;
- 文本居中
text-align: center;
- 超链接去下划线
text-decoration: none;
- 表格细线 :
- 列表去除修饰
ul {list-style: none;}
JavaScript语言入门
- JS是弱类型(类型可变),Java是强类型
- 特点 :1.信息的动态交互;2.安全性,不允许直接访问本地硬盘;3.跨平台性,只要是可以解释js的浏览器都可以执行,和平台无关
- src属性专门用来引入js文件路径(可以是相对路径或者绝对路径)
变量
typeof()
函数 判断变量的类型
比较运算
逻辑运算
数组
var arr = [];
var arr = [1,'abc',true];
- js语言中的数组,只要我们通过数组下标赋值,那么最大的下标值,就会自动给数组做扩容操作
函数
- 在java中函数允许重载,但是在js中函数的重载会直接覆盖掉上一次的定义
- 函数的隐形参数
arguments
(只在function函数内)
JS中的自定义对象
js中的事件
- 事件 : 电脑输入设备与页面进行交互的响应
常用的事件 :
- onload 加载完成事件;页面加载完成后,常用于做页面js代码初始化操作
- onclick 单击事件;常用于按钮的点击响应操作
- onblur 失去焦点事件;常用于输入框失去焦点后验证其输入内容是否合法
- onchange 内容发生改变事件;常用于下拉列表和输入框内容发生改变后操作
- onsubmit 表单提交事件;常用于表单提交前,验证所有表单项是否合法
- 阻止表单提交 :
- 静态注册 : 在标签属性中的onsubmit中 不仅要在函数中return false,在调用函数的前面,还要加上一个return!
- 动态注册 : 直接在 标签对象 的函数中return false 即可
DOM模型
- DOM全称是 Document Object Model 文档对象模型
- 就是把文档中的 标签,属性,文本 转换成对象来管理
- document对象 的理解 :
1.document管理了所有的html文档内容
2.document是一种 树结构 的文档,有层级关系
3.它让我们把所有的标签 都 对象化
4.我们可以通过document访问所有的标签对象 - 正则表达式RegExp :
1.表示要求字符串中,是否包含字母e :
1)var patt = new RegExp(“e”);
2)var patt = /e/;
3)以上两种皆为 正则表达式对象
4)验证方法 :
var str = “abcd”;
alert(patt.test(str));
2.表示要求字符串中,是否包含字母a或b或c :var patt = /[abc]/;
3.表示要求字符串中,是否包含任意小写字母 :var patt = /[a-z]/;
4.表示要求字符串中,是否包含任意数字 :var patt = /[0-9]/;
5.元字符中 \w 用于查找单词字符(a-z,A-Z,0-9,下划线);因此,var patt = /\w/;
表示要求字符串中,是否包含字母,数字,下划线; \W 查找 非单词字符
6.量词中 a+ ,var patt = /a+/;
表示要求字符串中,是否包含至少一个a;var patt = /a*/;
表示字符串中是否包含零个 或 多个a;var patt = /a?/;
表示字符串中是否包含零个 或 一个a;var patt = /a{3}/;
表示字符串中是否包含连续三个a
- document.getElementByName() :根据指定的name属性查询返回多个标签对象集合;这个集合的操作和数组一样;集合中每个元素都是dom对象;这个集合中的元素顺序是他们在html页面中从上到下的顺序
- document.getElementByTagName() :按照指定标签名来进行查询并返回集合;同上
- document对象的三个查询方法,如果有id属性,优先使用ById;如果没有id属性,则优先使用ByName;最后才用TagName
- 以上三个方法一定要在页面加载完成之后执行,才能查询到标签对象
节点的常用属性和方法
- 方法 :
appendChild(divObj)
document.createElement(tagName) 通过给定的标签名,创建一个标签对象 - 属性 :
childNodes 获取当前节点的所有子节点
firstChild
lastChild
parentNode
nextSibling
previousSibling
className 获取或设置标签的class属性值
innerHtml 内容
innerText 文本
jQuery
- 引入jQeury库,
<script type="text/javascripy" src="../script/jquery-1.7.2.js"></script>
$(function () {});
表示 页面加载完成之后,相当于window.onload = function () {}
var $btnObj = $("#btnId");
表示按id查询标签对象$btnObj.click(function () {alert("");});
绑定单击事件
$是jQeury的核心函数
传入参数为 函数 时 :表示页面加载完成之后,相当于window.onload = function () {}
传入参数为 HTML字符串 时 :会对我们创建这个html标签对象
传入参数为 选择器字符串 时 :id选择器、标签名选择器、类型选择器
传入参数为 DOM对象 时 : 会把这个dom对象转换为jQeury对象
jQeury对象和dom对象区分
- jQeury对象的本质 :是dom对象的数组 + jQeury提供的一系列功能函数
- jQeury对象不能使用DOM对象的属性和方法;DOM对象也不能使用jQeury…
dom对象转化为jQeury对象
1.先有dom对象
2.$(dom对象);就可以
jQeury对象转化为dom对象
1.先有jQeury对象
2.jQeury对象[下标]取出相应的dom对象
基础选择器
层级选择器
基本过滤选择器
内容过滤选择器
属性过滤选择器
表单过滤选择器
筛选元素
属性的操作
dom的增删改
CSS样式操作
jQeury动画
jQeury事件操作
jQeury中其他事件的处理方法
事件冒泡
事件对象
XML
<?xml version="1.0" encoding="utf-8" ?>
<!--
<?xml version="1.0" encoding="utf-8" ?>
以上内容就是xml文件的声明
version="1.0" version表示xml的版本
encoding="utf-8" encoding表示xml文件本身的编码
-->
<books>
<book sn="1">
<name>时间简史</name>
<author>霍金</author>
<price>100</price>
</book>
<book sn="2">
<name>java</name>
<author>teacher</author>
<price>120</price>
</book>
</books>
xml解析技术介绍
- 不管是html文件还是xml文件它们都是标记型文档,都可以使用w3c组织制定的dom技术来解析
package com.atguigu.pojo;
import java.math.BigDecimal;
public class Book {
private String sn;
private String name;
private BigDecimal price;
private String author;
// control + enter 快速生成函数
// constructor -> a全选 -> ok
public Book(String sn, String name, BigDecimal price, String author) {
this.sn = sn;
this.name = name;
this.price = price;
this.author = author;
}
@Override
public String toString() {
return "Book{" +
"sn='" + sn + '\'' +
", name='" + name + '\'' +
", price=" + price +
", author='" + author + '\'' +
'}';
}
// constructor -> select none
public Book() {
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
package com.atguigu.pojo;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;
import java.util.List;
public class Dom4jTest {
@Test
public void test1() throws DocumentException {
SAXReader saxReader = new SAXReader();
// Document document = saxReader.read("src/books.xml");
Document read = saxReader.read("src/books.xml");
// System.out.println(document);
}
@Test
public void test2() throws DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read("src/books.xml");
Element rootElement = document.getRootElement();
// System.out.println(rootElement);
List<Element> books = rootElement.elements("book");
for (Element book : books) {
// System.out.println(book.asXML());
// Element name = book.element("name");
// System.out.println(name.asXML());
// String text = name.getText();
// System.out.println(text);
String price = book.elementText("price");
System.out.println(price);
}
}
}
JavaWeb
Web资源的分类
- web资源按实现的技术和呈现的效果的不同,又分为静态资源和动态资源两种
- 静态资源 :html、css、js、txt、mp4视频、jpg图片
- 动态资源 :jsp页面、Servlet程序
常用的Web服务器
Tomcat :一种Web服务器,提供对jsp和Servlet的支持,它是一种轻量级的javaWeb容器(服务器),也是当前应用最广的JavaWeb容器(服务器)
Tomcat服务器和Servlet版本的对应关系
Tomcat目录介绍
bin 专门用来存放tomcat服务器的可执行程序
conf 专门用来存放tomcat服务器的配置文件
lib 专门用来存放tomcat服务器的jar包
logs 专门用来存放tomcat服务器运行时输出的日记信息
temp 专门用来存放tomcat服务器运行时产生的临时数据
webapps 专门用来存放部署的web工程
work 是tomcat工作时的目录,用来存放tomcat运行时jsp翻译为servlet的源码,和session钝化的目录
如何在idea中部署工程到tomcat上运行
建议修改web工程对应的tomcat运行实例名称
Servlet 01
0.jsp,servlet,tomcat的关系
- tomcat是web服务器(javaweb项目常用tomcat),servlet在tomacat中能运行,jsp是一种servlet
- 浏览器是向服务器(tomcat)发出请求,然后tomcat根据浏览器的请求,派出对应的servlet去处理这些请求,在处理后,servlet得到一系列处理后的数据,然后将这个数据交给jsp,让jsp显示出来给用户看到
- 在servlet中通过流将html代码输出给客户端(然后由客户端也就是浏览器渲染结果,所以并不是浏览器执行java代码),为了方便就诞生了jsp(本质上就是servlet),jsp中可以抛开java代码,直接使用html标签编写代码,这样就很好的将java代码和html代码分离,但其实jsp最终运行时会被编译成servlet
什么是Servlet
Servlet是JavaEE规范之一。规范 就是 接口
Servlet是JavaWeb三大组件之一。三大组件分别是 :Servlet程序、Filter过滤器、Listener监听器
Servlet是运行在服务器上的一个java小程序,它可以接收客户端发来的请求,并相应数据给客户端
手动实现Servlet程序
1.编写一个类去实现Servlet接口
2.实现service方法,处理请求,并相应数据
3.到web.xml中去配置servlet程序的访问地址
package com.atguigu.servlet;
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
@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("HelloServlet 被访问了");
System.out.println("this is the service method");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
<?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标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
/hello 表示地址为:http://ip:port/工程路径/hello
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
<!-- 常见错误1:url-pattern中配置的路径没有以斜杠打头 Invalid <url-pattern> hello in servlet mapping -->
<!-- 常见错误2:servlet-name配置的值不存在 Servlet mapping specifies an unknown sevlet name HelloServlet1 -->
<!-- 常见错误3:servlet-class标签的全类名配置错误 java.lang.ClassNotFoundException: com.atguigu.sssss.HelloServlet(写的时候直接输入Hello就会自己补全) -->
url地址如何定位到Servlet程序去访问 :
- 在localhost中,一个程序可以占用多个端口号,但是一个端口号唯一标识一个程序
Servlet的生命周期
1.执行Servlet构造器方法
2.执行init初始化方法
第一、二步是在,第一次访问的,的时候 创建servlet程序会调用
3.执行service方法
第三步,每次访问都会调用
4.执行destroy销毁方法
第四步,在web工程停止的时候调用
package com.atguigu.servlet;
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
// Constructor方法(一开始点“实现方法”后这个不会出现,要另外再添加)
public HelloServlet() {
System.out.println("1 构造器方法");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 init初始化方法");
}
@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("HelloServlet 被访问了");
System.out.println("3 service方法 -- HelloServlet被访问了");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4 destroy销毁方法");
}
}
// console output
1 构造器方法
2 init初始化方法
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
- 因此发现是 单例模式
请求的分发处理
- 问题 :service方法只有一个,而我们的请求有两种,一种是get,一种是post
- 第1步,在 webapp 下创建一个 a.html ,里面有一个form表单,填入action属性(/hello)和method属性,form表单中有一个提交按钮
- 第2步,启动服务器后,在工程后面加上/a.html,进入了
http://localhost:8080/_servlet/a.html
,然后按下提交按钮,就会进入hello,也就是http://localhost:8080/_servlet/hello?
- 只有在点下按钮,进入到hello以后,Server才会输出“11111 Constructor
22222 init
33333 service – HelloServlet被访问啦“
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/_servlet/hello" method="get">
<!-- input:submit 然后tab -->
<input type="submit">
</form>
</body>
</html>
- 将get改成post后,要记得刷新网页(但居然不需要重启服务器)
- 改成post后,同样的操作,点了按钮后,会进入
http://localhost:8080/_servlet/hello
,同时,Server会输出"33333 service – HelloServlet被访问啦",service一样的被使用了 - 问题 :一般情况下,get和post请求是不一样的,因此,在service方法中要写不同
- 发现ServletRequest类无法直接使用getMethod方法
查看子类 快捷键
:在HelloServlet.java中 鼠标选中 service方法中的ServletRequest
,然后control + h
,然后显示该类(?)的层次结构,可以看到ServletRequest还有一个HttpServletRequest子类,点击后,看到里面有一个String getMethod()
方法,也就是说子类可以- 因此,
类型转换
,将它转换为子接口(注意到这里是向下转型?,但本质上还是向上转型,接口的实现类就是它的子类,子类的对象就是该接口的子类对象),(快捷方式,先打出HttpServletRequest httpServletRequest = servletRequest;
,然后option + enter
,自动补全为HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
httpServletRequest.getMethod()
后再option + enter
然后补全为String method = httpServletRequest.getMethod();
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// 类型转换(因为它有getMethod()方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
// 获取请求的方式
String method = httpServletRequest.getMethod();
System.out.println(method);
}
- 然后 重启服务器,再在a.html中点击按钮后,Server中就会输出“POST“
- 因此说明我们已经可以得到method了,那么就可以根据method的不同类型来作出不同代码
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
if ("POST".equals(method)) {
System.out.println("post请求");
} else {
System.out.println("get请求");
}
}
- 如果if里执行的语句太多,显得很臃肿;因此,我们采用 封装 的思想,将if中语句换成函数
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
if ("POST".equals(method)) {
doPost();
} else {
doGet();
}
}
public void doPost()
{
System.out.println("this is Post");
System.out.println("ohayo!");
}
public void doGet()
{
System.out.println("this is Get");
System.out.println("ohayo!");
}
通过继承HttpServlet类来实现Servlet程序
- 实际开发中,很少通过 “通过实现Servlet接口” 的方式来实现Servlet程序
- 开发时,一般都是导入他的子类去继承即可
- 一般在实际开发中,都是使用继承HttpServlet类的方法去实现Servlet程序
1.编写一个类来继承HttpServlet类
2.根据业务需求重写doGet()和doPost()方法
3.到web.xml中配置Servlet程序的访问地址
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet2 extends HttpServlet {
/**
* 第一步,control + enter 然后点击 "重写方法"也就是 Overrride Methods
* 第二部,按住 command ,然后就可以同时选择doGet()和doPost()
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("this is HelloServlet2 - get");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
System.out.println("this is HelloServlet2 - post");
}
}
<!-- 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>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HelloServlet2</servlet-name>
<servlet-class>com.atguigu.servlet.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
</web-app>
<!-- 修改html中表单的action属性 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/_servlet/hello2" method="post">
<!-- input:submit 然后tab -->
<input type="submit">
</form>
</body>
</html>
- 然后 重启服务器;就可以显示啦
- 我们注意到在这个编写的继承类中,我们直接只需要重写doGet方法即可,不需要再得到method,然后ifelse
使用IDEA创建Servlet程序
- 第一步,点击要在哪个包中编写这个类,然后
- 会自动创建这个类(里面有准备好doGet方法和doPost方法的重写),以及在web.xml中自动配置(但要自行写serlet-mapping)
整个Servlet类的继承体系
ServletConfig类使用介绍
关于初始化参数init-param
- 且这个init-param在一个servlet标签中可以有多对
- servletConfig可以在HelloServlet的init初始化方法中使用
HelloServlet程序的别名是:HelloServlet
初始化参数username的值是:root
org.apache.catalina.core.ApplicationContextFacade@7602e52f
ServletConfig类的补充说明
- Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用
- Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象
- servletconfig还可以在除了init外使用 :
- 重写 init方法后(init中只放了一个sout),在doGet方法中通过servletConfig获得init-param就会有 空指针异常
- 注意,在重写了init方法后,一定要在里面调用
super.init(config);
,就不会报空指针异常 - 原因 :doGet方法中的
getServletConfig()
是从哪里来的呢?发现是从GenericServlet这个类的方法,而GenericServlet类持有一个ServletConfig类的引用;发现在GenericServlet类中的init方法有一个this.config = config;是将config保存起来,那我们如果重写不就没有了吗,那么父类中init的保存就消失了,因此,要写上super
按住command 鼠标移到方法上
就可以查看 所在的类中这个方法的位置
ServletContext对象的介绍
ServletContext对象作用的演示
- 先在web.xml中配置好ContextServlet程序的mapping 以及 上下文参数context-param
<?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">
<!-- context-param是上下文参数(它属于整个web工程,与servlet并列) -->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<!-- context-param也可以拥有多对 -->
<context-param>
<param-name>password</param-name>
<param-value>root</param-value>
</context-param>
<servlet>
...
</web-app>
- 然后,通过 ServletConfig 来获得 ServletContext 对象
- 有一个小细节,这个代码只能写在doGet中,写在doPost中是不会在Server中输出语句的
context.getInitParameter()
只能得到context-param
,不能得到servlet中的init-param
(只能由ServletConfig的getInitParameter()得到)
package com.atguigu.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class ContextServlet extends HttpServlet {
@Override
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目录
*/
System.out.println("工程部署的路径是:" + context.getRealPath("/"));
System.out.println("工程下css目录的绝对路径是:" + context.getRealPath("/css"));
// System.out.println("工程下imgs目录1.jpg的绝对路径是:" + context.getRealPath("/imgs/1.jpg"));
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
<!-- Server输出的内容 -->
context-param的参数username的值是:context
context-param的参数password的值是:root
当前工程路径:/_servlet
工程部署的路径是:/Users/fieldxia/Desktop/JavaWeb/_servlet/target/_servlet-1.0-SNAPSHOT/
工程下css目录的绝对路径是:/Users/fieldxia/Desktop/JavaWeb/_servlet/target/_servlet-1.0-SNAPSHOT/css
ServletContext像map一样存取数据
public class ContextServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取ServletContext对象
ServletContext context = getServletContext();
System.out.println("保存之前:Context1 获取key1的值为:" + context.getAttribute("key1"));
context.setAttribute("key1", "value1");
System.out.println("Context1 中获取域数据key1的值为:" + context.getAttribute("key1"));
System.out.println("Context1 中获取域数据key1的值为:" + context.getAttribute("key1"));
}
}
public class ContextServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = getServletContext();
System.out.println("Context2 中获取域数据key1的值为:" + context.getAttribute("key1"));
}
}
<!-- 只访问了/context1 -->
保存之前:Context1 获取key1的值为:null
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
<!-- 在访问了/context1后再访问了/context2 -->
保存之前:Context1 获取key1的值为:null
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
14-Mar-2022 19:45:37.570 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]
14-Mar-2022 19:45:37.601 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]的部署已在[30]毫秒内完成
Context2 中获取域数据key1的值为:value1
<!-- 再访问一次/context1 -->
保存之前:Context1 获取key1的值为:null
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
14-Mar-2022 19:45:37.570 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]
14-Mar-2022 19:45:37.601 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]的部署已在[30]毫秒内完成
Context2 中获取域数据key1的值为:value1
保存之前:Context1 获取key1的值为:value1
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
- 因为 “ServletContext是在web1工程部署启动的时候创建。在web工程停止的时候销毁“
- 因此, 如果 重新部署一次,或者重启这个工程,那么web工程就停止了,里面的数据就没有了
public class ContextServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取ServletContext对象
ServletContext context = getServletContext();
System.out.println(context);
}
}
public class ContextServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = getServletContext();
System.out.println(context);
}
}
<!-- 一个web工程,只有一个ServletContext对象实例 -->
org.apache.catalina.core.ApplicationContextFacade@4f419be1
14-Mar-2022 19:53:39.424 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]
14-Mar-2022 19:53:39.467 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]的部署已在[43]毫秒内完成
org.apache.catalina.core.ApplicationContextFacade@4f419be1
什么是HTTP协议
GET请求HTTP协议内容介绍
POST请求HTTP协议内容介绍
- 注意要点了提交按钮以后才会是POST请求,直接在a.html录制还是GET请求
常用请求头
哪些是GET请求,哪些是POST请求
响应的HTTP协议介绍
常见的响应状态码说明
MIME数据类型
谷歌浏览器和火狐浏览器如何查看HTTP协议内容
状态码304
点击Disable Cache停用缓存
状态码200
Servlet 02
HttpServletRequest类的介绍
Request常用API的演示
public class RequestAPIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的资源路径
System.out.println("URI => " + req.getRequestURI());
// 获取请求的统一资源定位符(绝对路径)
System.out.println("URL => " + req.getRequestURL());
// 获取客户端的ip地址
/**
* 在IDEA中 使用 localhost 访问时 得到的客户端ip地址是 => 127.0.0.1
* 因此 将 "http://localhost:8080/_servlet02/requestAPIServlet"
* 改成 "http://127.0.0.1:8080/_servlet02/requestAPIServlet" 也可以访问
* 在IDEA中 使用 127.0.0.1 访问时 得到的客户端ip地址是 => 127.0.0.1
* 在IDEA中 使用 真实ip 访问时 得到的客户端ip地址是 => 真实的客户端 ip地址
*/
System.out.println("客户端 ip地址 => " + req.getRemoteHost());
// 获取请求头
System.out.println("请求头User-Agent => " + req.getHeader("User-Agent"));
// 获取请求的方式 GET 或 POST
System.out.println("请求的方式 => " + req.getMethod());
}
}
URI => /_servlet02/requestAPIServlet
URL => http://localhost:8080/_servlet02/requestAPIServlet
客户端 ip地址 => 0:0:0:0:0:0:0:1
请求头User-Agent => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
请求的方式 => GET
获取请求的参数值-补充
<!-- form.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/_servlet02/parameterServlet" method="get">
用户名:<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">JS<br/>
<input type="submit">
</form>
</body>
</html>
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String hobby = req.getParameter("hobby");
System.out.println("username: " + username);
System.out.println("password: " + password);
System.out.println("hobby: " + hobby);
}
}
跳转至http://localhost:8080/_servlet02/parameterServlet?username=javaweb&password=123456&hobby=cpp&hobby=java
<!-- Server -->
username: javaweb
password: 123456
hobby: cpp
- 以上hobby的做法是错的,这样兴趣爱好多选只会返回一个值,应该将getParameter换成getParameterValues
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("username: " + username);
System.out.println("password: " + password);
System.out.println("hobby: " + Arrays.asList(hobby));
}
}
http://localhost:8080/_servlet02/parameterServlet?username=123&password=123456&hobby=cpp&hobby=java&hobby=js
<!-- Server -->
username: 123
password: 123456
hobby: [cpp, java, js]
解决POST请求中文乱码问题
- 如果在
用户名text
中输入中文的时候,如果method="get"
不会有问题,但如果method="post"
,不是中文没有问题,但一旦是中文,getParameter时输出就变成乱码 - 我们只需要一个操作
- 注意!!!必须在获取请求参数之前调用才有效。比如说我先调用pasword的参数,然后才设置utf-8,然后再调用username,如果是post且中文,还是会乱码
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
// 也要在获取请求参数之前调用才有效
req.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("username: " + username);
System.out.println("password: " + password);
System.out.println("hobby: " + Arrays.asList(hobby));
}
请求的转发
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目录
*/
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
// 走向Servlet2(柜台2)
requestDispatcher.forward(req,resp);
}
}
public class Servlet2 extends HelloServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取请求的参数(办事的材料)查看
String username = request.getParameter("username");
System.out.println("在Servlet2(柜台2)中查看参数(材料): " + username);
Object key1 = request.getAttribute("key1");
System.out.println("柜台1是否有章:" + key1);
// 处理自己的业务
System.out.println("Servlet2 处理自己的业务");
}
}
<!-- Server -->
在Servlet1(柜台1)中查看参数(材料): null
在Servlet2(柜台2)中查看参数(材料): null
柜台1是否有章:柜台1的章
Servlet2 处理自己的业务
- 发现输入的前两句为null,因为我们在转入/servlet1的时候,没有传入参数
- 若输入
http://localhost:8080/_servlet02/servlet1?username=wzg168
来访问,则Server打印 :
在Servlet1(柜台1)中查看参数(材料): wzg168
在Servlet2(柜台2)中查看参数(材料): wzg168
柜台1是否有章:柜台1的章
Servlet2 处理自己的业务
-
第三个特点体现在上述代码中key1的传递
-
web-inf是受服务器保护的,客户端不能直接访问,但可以通过服务器中的资源进行间接访问
-
比如如果我们把form.html放到web-inf下
-
这样的话,访问/servlet1也显示form.html的表单的内容 :
base标签的作用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- base标签设置页面相对路径工作时参照的地址 -->
<base href="http://localhost:8080/_servlet02/a/b/c.html">
<!-- 可以省略为“http://localhost:8080/_servlet02/a/b/“,但斜杠不能去掉,因为斜杠说明b是一个目录,而不是一个资源路径 -->
</head>
<body>
这是a下的b下的c.html页面 <br>
<a href="../../index.html">跳回首页</a>
<!-- http://localhost:8080/_servlet02/a/b/c.html../../index.html -->
<!-- http://localhost:8080/_servlet02/index.html -->
</body>
</html>
回顾javaweb中的路径
斜杠在web中的不同意义
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
这是Web下的index.html <br>
<a href="a/b/c.html">a/b/c.html</a> <br>
<a href="http://localhost:8080/_servlet02/forwardC">请求转发:a/b/c.html</a>
<a href="/">斜杠</a>
</body>
</html>
- 点击后跳转至
http://localhost:8080/
HttpServletResponse类的介绍
两个响应流的介绍
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getOutputStream();
resp.getWriter();
}
}
给客户端回传字符串数据
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 要求 :往客户端回传 字符串 数据
PrintWriter writer = resp.getWriter();
writer.write("response's content!!!");
}
}
解决响应的中文乱码
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 要求 :往客户端回传 字符串 数据
PrintWriter writer = resp.getWriter();
writer.write("即将出现中文乱码");
}
}
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(resp.getCharacterEncoding());
}
}
- 访问页面后,Server输出
ISO-8859-1
- 说明,默认是ISO-8859-1,这个字符集是不支持中文的
- 因此,我们要设置支持中文的字符集
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置 服务器 字符集为UTF-8
resp.setCharacterEncoding("UTF-8");
// 通过响应头,设置 浏览器 也使用UTF-8字符集(一般是GBK
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("这不是中文乱码");
}
}
解决响应中文乱码问题方案二
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头
// 此方法一定要在获取流对象(PrintWriter writer = resp.getWriter();)之前使用才有效
resp.setContentType("text/html; charset=UTF-8");
System.out.println(resp.getCharacterEncoding()); // output:"UTF-8"
}
}
请求重定向
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("曾到此一游 Response1");
// 设置响应状态码302,表示重定向(已搬迁)
resp.setStatus(302);
// 设置响应头,说明 新的地址在哪里
resp.setHeader("Location", "http://localhost:8080/_servlet02/response2");
}
}
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("response2's result!!!");
}
}
- 然后访问
http://localhost:8080/_servlet02/response1
,会自动跳转至http://localhost:8080/_servlet02/response2
,
- 关于第三个特点的解释 :
如果在Response1中保存一些数据,比如req.setAttribute("key1", "value1");
,然后在Response2中System.out,println(req.getAttribute("key1"));
会得到null
原因 :tomcat每次收到请求,就会把请求到的数据解析好,每次请求都会封装 - 关于第四个特点 :
原因 :
第二次请求还是客户端给服务器发的,而WEB-INF目录是受保护的,浏览器无法直接访问,第二次请求还是浏览器发过来的,还是进不来 - 第五个特点 :
请求重定向第二种实现方案
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("http://localhost:8080/_servlet02/response2");
}
}