java web
一.XML
①.概述
-
概念:可扩展标记语言
- 可扩展:标签都是自定义的。
-
功能
- 存储数据
- 配置文件
- 在网络中传输
properties
name=zhangsan age=23 gender=nan
xml
<user id="1"> <name>zhangsan</name> <age>23</age> </user> <user id="2"> <name>zhangsan</name> <age>23</age> </user>
- 存储数据
-
xml与html的区别
-
xml标签都是自定义的,html标签是预定义的
-
xml的语法严格,html语法松散
-
xml是存储数据的,html是展示数据的
-
w3c 万维网联盟
-
②.快速入门
-
基本语法
- xml文档的后缀名 .xml
- xml第一行必须定义为文档声明
- xml文档中有且只有一个根标签
- 属性值必须使用引号(单双都可以)
- 标签必须正确关闭
- xml标签名称区分大小写
-
快速入门
<?xml version="1.0" ?> <users> <user id="1"> <name>张三</name> <age>23</age> </user> <user id="2"> <name>李四</name> <age>23</age> </user> </users>
-
组成部分
-
文档声明
-
格式:<? xml 属性列表 ?>
-
属性列表:
-
version:版本号,必须的属性
-
encoding:编码方式。告知解析引擎当前文档使用的字符集,默认为:ISO-8869-1
-
standalone:是否独立
-
取值:
yes:不依赖其他文件
no:依赖其他文件
-
-
-
-
指令(了解):结合css
- <? xml-stylesheet type="text/css" href="a.css" ?>
-
标签:标签名称自定义的
- 规则
- 名称可以包含字母,数字以及其他的字符
- 名称不能以数字或者标点符号开始
- 名称不能以字母 xml(或者 XML,xml等等)开始
- 名称不能包含空格
- 规则
-
属性:
-
id属性值唯一
-
文本:
-
CDATA区:在该区域中的数据会被原样展示
- 格式:<![CDATA [数据]]>
-
-
③.约束
- 作用: 规定xml文档的书写规则
谁编写xml? --用户(程序员)
谁编译xml? --软件(框架)
- 作为框架的使用者程序员:
- 能够在xml中引入约束文档
- 能够简单的读懂约束文档
- 分类:
- DTD:一种简单的约束技术
- Schema:一种复杂的约束技术
④.DTD 约束技术
-
DTD的引入
-
内部dtd
-
外部dtd
- 本地:
- 网络:
-
-
DTD语法
- 元素定义
<!ELEMENT 元素名称 (元素内容)> 元素内容的5种形式: 1)#PCDATA:表示元素中嵌套的内容是普通文本字符串 2)子元素:说明元素包含的元素。student(id,name,age) 3)混合内容:表示元素既可以包含字符数据,也可以包含子元素。student(#PCDATA|name) 4)EMPTY:表示元素即不包含字符数据,也不包含子元素。是一个空元素 5)ANY:表示元素可以包含任何字符数据和子元素
- 定义元素时元素内容中可以包含一些符号
- ?: 表示该对象可以出现0次或1次
- * : 表示该对象可以出现0次或多次
- + : 表示该对象可以出现1次或多次
- | : 表示在列出的对象中选择一个
- , : 表示对象必须按照指定的顺序出现
- () : 用于给元素进行分组
- 属性定义
<!ATTLIST 元素名 属性名1 属性类型 设置说明 属性名2 属性类型 设置说明 ... > 元素名 是属性所属元素的名字,属性名 是属性的名称,属性类型 用来指定该属性属于哪种类型,设置说明 用来说明该属性是否必须出现
-
设置说明
定义元素属性时,有四种设置说明可以选择设置说明 含义 #REQUIRED 表示该属性是必须的 #IMPLIED 表示元素可以包含该属性,也可以不包含该属性 #FIXED 表示一个固定的属性默认值 默认值 和FIXED一样 -
属性类型
属性名 含义 CADATA 字符数据 Enumerated 枚举类型 ID 一个ID类型的属性,用于唯一标识xml文档中的一个元素 IDREF和IDREFS 使元素之间建立关系
⑤.Schema约束
-
引入:
-
填写xml文档的根元素
-
引入xsi前缀。 xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
-
引入xsd文件命名空间 xsi:schemalocation=“http://www.itcast.cn/xml student.xsd”
-
为每一个xsd约束声明一个前缀,作为标识
xmlns:a=“http://www.itcast.cn/xml”
<?xml version="1.0" encoding="UTF-8" ?> <xsd:schema xmlns = "http://www.itcast.cn/xml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.itcast.cn/xml" elementFormDefault="qualified"> <xsd:element name="students" type="studentsType"/> <xsd:complexType name="studentsType"> <xsd:sequence> <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="studentType"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="age" type="ageType"/> <xsd:element name="sex" type="sexType"/> </xsd:sequence> <xsd:attribute name="number" type="numberType" use="required"/> </xsd:complexType> <xsd:simpleType name="ageType"> <xsd:restriction base="xsd:int"> <xsd:minInclusive value="0"/> <xsd:maxInclusive value="150"/> </xsd:restriction> </xsd:simpleType> <xsd:simpleType name="sexType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="male"/> <xsd:enumeration value="female"/> </xsd:restriction> </xsd:simpleType> <xsd:simpleType name="numberType"> <xsd:restriction base="xsd:string"> <xsd:pattern value="[a~z]"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>
<?xml version="1.0" encoding="UTF-8" ?> <students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.itcast.cn/xml student.xsd " xmlns="http://www.itcast.cn/xml" > <student number="z"> <name>tom</name> <age>19</age> <sex>female</sex> </student> </students>
-
-
语法
- 元素定义
<xs:element name="xxx" type="yyy"> element用于声明一个元素,xxx指元素的名称,yyy指元素的数据类型 在XML Schema中还有很多内建的数据类型, xs:String:表示字符串类型 xs:decimal:表示小数类型 xs:integer:表示整数类型 xs:boolean:表示布尔类型 XS:date:表示日期类型 XS:time:表示时间类型
- 属性的定义
<xs:attribute name="xxx" type="yyy"> attribute表示声明一个属性,xxx表示属性名称,yyy表示属性类型
- 简单类型
⑥.解析
-
操作xml文档
- 解析(读取):将文档中的数据读取到内存中
- 写入:将内存中的数据保存在xml文档中。持久化的存储
-
解析xml的方式
-
DOM:将标记语言一次性加载进内存,在内存中形成一颗dom树
- 优点:操作方便,可以对文档进行CRUD的所有操作
- 缺点:占内存
-
SAX:逐行读取,基于事件驱动的
- 优点:不占内存
- 缺点:只能读取,不能增删改
-
xml常见的解析器
1.JAXP:sun公司提供的解析器,支持dom和sax两种思想
2.DOM4J:一款优秀的解析器
3.Jsoup:是一款java的HTML解析器,可直接解析某个URL地址,HTML文本内容。
4.PULL:Android操作系统内置的解析器,sax方式的
Ⅰ.Jsoup解析器
-
快速入门
- 导入jar包
- 获取Document对象
- 获取对应的标签Element对象
- 获取数据
-
代码实现
/**
* jsoup入门
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
//1.引入jar包
//2.1 获取xml文件的url地址
String path = Demo01.class.getClassLoader().getResource("students.xml").getPath();
//2.2获取Document对象
Document document = Jsoup.parse(new File(path),"utf-8");
//3.获取元素对象
Elements elements = document.getElementsByTag("name");
//打印元素个数
System.out.println(elements.size());
Element element = elements.get(0);
//4.获取元素文本
String name = element.text();
System.out.println(name);
}
}
Ⅱ.对象
-
Jsoup:工具类,可以解析HTML或xml文档,返回Document
-
parse():解析html或xml文档,返回Document
-
parse(File in,String charsetName):解析xml或html文件
//2.1 获取xml文件的url地址 String path = Demo01.class.getClassLoader().getResource("students.xml").getPath(); //2.2获取Document对象 Document document = Jsoup.parse(new File(path),"utf-8");
-
parse(String html):解析xml或html字符串
public class Demo02 { public static void main(String[] args) throws IOException { String str = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" + "<students>\n" + " <student>\n" + " <name>tom</name>\n" + " <age>16</age>\n" + " <gender>male</gender>\n" + " </student>\n" + " <student>\n" + " <name>jack</name>\n" + " <age>21</age>\n" + " <gender>female</gender>\n" + " </student>\n" + "</students>"; Document document = Jsoup.parse(str); System.out.println(document); } }
-
parse(URL url,int timroutMillis):通过网络路径获取指定的html或xml文档对象
URL url = new URL("https://www.sina.com.cn/"); Document document = Jsoup.parse(url, 10000); System.out.println(document);
-
Document:文档对象。代表内存中的dom树
-
获取Element对象
- getElementById(String id) : 根据Id属性值获取唯一的element对象
Element element = document.getElementById("1"); System.out.println(element);
- getElementsByTag(String tagName) : 根据标签名获取元素对象集合
Elements elements = document.getElementsByTag("age"); System.out.println(elements);
- getElementsByAttribute(String key) : 根据属性名称获取元素对象集合
Elements elements1 = document.getElementsByAttribute("name"); System.out.println(elements1);
- getElementsByAttributeValue(String key,String value) : 根据对应的属性名和属性名获取元素对象集合
Elements elements2 = document.getElementsByAttributeValue("name", "lz_001"); System.out.println(elements2);
-
-
Elements:元素Element对象的集合。可以当作ArrayList<Element>来使用
-
Element:元素对象
- 获取子元素对象
- getElementById(String id) : 根据Id属性值获取唯一的element对象
- getElementsByTag(String tagName) : 根据标签名获取元素对象集合
- getElementsByAttribute(String key) : 根据属性名称获取元素对象集合
- getElementsByAttributeValue(String key,String value) : 根据对应的属性名和属性名获取元素对象集合
- 获取属性值
- String attr(String key) : 根据属性名称获取属性值
- 获取元素文本内容
- String text() : 获取元素纯文本内容
- String html() : 获取标签体的所有内容(包括子标签)
- 获取子元素对象
-
Node:节点对象
- 是Document对象和Element对象的父类
- 执行增删改的操作
-
Ⅲ.快速查询
-
selector:选择器
- 使用方法:Elements select(String cssQuery)
- 语法:参考Selector类定义的语法
-
Xpath:
- 需要额外导入jar包
- 查询w3cshool参考手册
二.Tomcat
①.wed服务器软件
- 服务器:安装了服务器软件的计算机
- 服务器软件:接收用户的请求,处理请求,做出响应
- wed服务器软件:接收用户的请求,处理请求,做出响应
②.Tomcat
-
tomcat
-
下载:http://tomcat.apache.org/
-
安装:解压压缩包,安装目录不要有中文和空格
-
目录结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RxjqdjFq-1603158978887)(C:\Users\谜语菌\Documents\img\目录结构.jpg)]
-
-
卸载:删除目录
-
启动:
-
bin/startup.bat,双击运行文件
-
访问:浏览器输入:http://locahost:8080 回车自己访问自己
http://别人ip:8080 访问别人 -
可能遇到的问题:
1. 窗口闪退
-
原因:没有正确配置JAVA_HOME环境变量
解决方案,将JDK根目录配置在JAVA_HOME中2. 启动报错(端口号被占用)
-
解决:关闭占用端口号的程序,更改自己的端口号
netstat -ano 查看程序端口—》PID
- 启动任务处理器-关闭PID
- 关闭
- 正常关闭
- bin/shutdown.bat
- Ctrl+c
- 强制关闭
- 直接关闭窗口
- 配置
-
部署项目的方式
- 直接将项目放在wedapp目录中
- 简化部署:将项目打包成一个war包,将war包放置到wedapp下会自动解压缩。
- 配置conf/server.xml文件
在<Host>标签中 <Context dovNase="xxx" path="yyy" /> xxx:项目存放路径 yyy:虚拟目录
- 在conf\Catalina\localhost创建任意名称的xml文件,在里面编写
<Context dovNase="xxx" /> xxx:项目存放路径 虚拟目录:xml文件名称
-
静态项目和动态项目
-
目录结构
- Java动态项目的目录结构
-- 项目的根目录 -- WED-INF目录 -- wed.xml: wed项目的核心配置文件 -- classes目录:放置字节码文件的目录 -- lib目录:放置依赖的jar包
-
-
-
将Tomcat集成到IDEA中,并且创建JavaEE项目,部署项目
Run ---> Edit... ---> Defaults ---> Tomcat Server ---> Local Configure... ---> 配置安装目录 ---> OK
解决web目录下没有web.xml文件 Ctrl+Shift+Alt+S 快捷键进入Project structure管理界面 先择左边菜单栏的Facet,点击后,看到Deployment的输入框 点击右面加号,添加web.xml文件,文件目录设置在web下
-
IDEA与Tomcat的相关配置
IDEA会为每一个Tomcat部署的项目单独建立一份配置文件
三.Servlet
①.简介
-
概念:运行在服务器端的小程序
- Servlet就是一个接口,定义了java类被浏览器访问到(tomcat识别)的规则。
- 将来我们定义一个类,实现Servlet接口,复写方法
-
快速入门
-
创建JavaEE项目
-
定义一个类,实现Servlet接口
-
实现接口中的抽象方法
public class ServletDemo implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("init..."); } @Override public ServletConfig getServletConfig() { System.out.println("getServletConfig..."); return null; } //提供服务的类 @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"); } }
-
配置Servlet
<!-- <servlet>用于注册Servlet,他的两个子元素<servlet-name>和<servlet-class>分别指定Servlet的名称和全类名 --> <servlet> <servlet-name>demo</servlet-name> <servlet-class>cn.lczy.wed.servlet.HelloServlet</servlet-class> </servlet> <!-- <servlet-mapping>用于映射Servlet对外访问的虚拟路径 --> <servlet-mapping> <servlet-name>demo</servlet-name> <url-pattern>/demo</url-pattern> </servlet-mapping>
-
-
实现原理
- 当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
- 查找web.xml文件,是否对应的<url-pattern>标签体内容
- 如果有,则找到对应的<servlet-class>全类名
- tomcat会将字节码文件加载进内存,并且创建对象
- 调用其方法
②.servlet的生命周期
-
生命周期
- 创建===执行init方法,只执行一次
- 什么时候被创建
- 默认情况下,第一次被访问时,Servlet被创建
- 可以配置执行Servlet的创建时机
- 在web.xml标签下配置
- 第一次被访问时创建,默认
- 的值为负数
- 在服务器启动时创建
- 的值为0或正整数
- 第一次被访问时创建,默认
- 在web.xml标签下配置
- Servlet的init(),只执行一次,说明Servlet在内存中只有一个对象,Servlet是单例的
- 多个用户同时访问时,可能出现线程安全问题
- 解决:尽量不要在Servlet中定义成员变量,即使定义了成员变量,也不要对值进行修改
- 什么时候被创建
- 提供服务===执行service方法,执行多次
- 每次访问Servlet时,Service方法都会被调用一次
- 销毁===执行destroy方法,只执行一次
- Serlet被销毁时执行。服务器关闭时,Servlet被销毁
- 只有服务器正常关闭时,才会执行destroy方法
- destroy方法在Servlet被销毁之前执行,一般用于释放资源
- 创建===执行init方法,只执行一次
-
方法
/** * 初始化方法 * 在Servlet创建时执行init(),并且只执行一次 */ @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("init..."); } /** * 获取ServletConfig对象 * ServletConfig:Servlet的配置对象 * @return */ @Override public ServletConfig getServletConfig() { return null; } /** * 提供服务的方法 * 每一次Servlet被访问时执行,执行多次 */ @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("Servlet..."); } /** * 获取Servlet的一些信息,版本,作者等等 * @return */ @Override public String getServletInfo() { return null; } /** * 销毁方法 * 当服务器正常关闭时执行,并且执行一次 */ @Override public void destroy() { System.out.println("destroy..."); }
③.Servlet3.0
-
好处
- 支持注解配置。可以不需要web.xml了
-
步骤
- 创建JavaEE项目,选择Servlet的版本3.0以上
- 定义一个类,实现Servlet接口
- 复写方法
- 在类上使用@webServlet注解,进行配置
- @webServlet(“虚拟路径”)
@WebServlet("/demo")
- @webServlet(“虚拟路径”)
④.Servlet的体系结构
Servlet – 接口
|
GenericServlet – 抽象类
|
HttpServlet – 抽象类
-
GenericServlet:将Servlet接口中的方法做了默认空实现,只将service()方法作为抽象
- 将来定义Servlet类时可以继承GenericServlet,实现service()即可
-
HttpServlet:对HTTP协议的一种封装,简化操作
- 定义类继承HttpServlet
- 复写doGet/doPost方法
<body> <form action="/demo1" method="post"> <input type="text"/> <input type="submit" value="提交" /> </form> </body>
@WebServlet("/demo1") public class ServletDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doGet..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doPost..."); } }
⑤.Servlet相关配置
- urlpartten : Servlet访问路径
- 一个Servlet可以定义多个访问路径:@wedServlet({"/demo1","/demo2"…})
- 路径定义规则
- /xxx
- /xxx/xxx
- *.do
四.HTTP
①.概述
- 概念:Hyper Text Transfer Protocol 超文本传输协议
- 传输协议:定义了,客户端和服务器通信时,发送数据的格式
- 特点:
- 基于TCP/IP的高级协议
- 默认端口号:80
- 基于请求/响应模型:一次请求对应一次响应
- 无状态的:每次请求之间相互独立,不能交互数据
- 历史版本
- 1.0 : 每一次请求响应都会建立新的连接
- 1.1 : 复用连接
②.请求消息
客户端发送给服务器端的数据
-
请求消息数据格式
-
请求行
| 请求方式 | 请求url | 请求协议/版本|
| POST | /login.html | HTTP/1.1 |- 请求方式:
- HTTP协议有七种请求方式,常用的有两种
- GET:
- 请求参数在请求行中,在url后
- 请求的url长度有限制
- 不太安全
- POST:
- 请求参数在请求体中
- 请求的url长度没有限制
- 相对安全
- GET:
- HTTP协议有七种请求方式,常用的有两种
- 请求方式:
-
请求头:客户端浏览器给服务器的一些信息
请求头名称: 请求头值-
常见的请求头
- User-Agent:浏览器告诉服务器,我访问你是哦那个的浏览器版本信息
- 可以在服务器端获取该头信息,解决浏览器兼容性问题
- Referer:告诉服务器,当前请求从哪里来?
- 作用
- 防盗链
- 统计工作
- 作用
-
-
请求空行
空行,用于分割POST请求的请求头和请求体 -
请求体(正文)
- 封装POST请求消息的请求参数
- 字符串格式
//请求行 POST /login.html HTTP/1.1 //请求头 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 17 Origin: http://localhost Connection: keep-alive Referer: http://localhost/Servlet1/login.html Cookie: Idea-5c063c53=8e0ad809-17a7-4a3b-94a6-f8f4b166358e Upgrade-Insecure-Requests: 1 //请求空行 //请求体 username=zhangsan
-
③.响应消息
服务器端发送给客户端的数据
-
响应数据格式
-
响应行
- HTTP/1.1 200 OK
- 组成:协议/版本 响应状态码 状态码描述
- 响应状态码:服务器告诉客户端浏览器本次请求和响应的状态
- 分类
- 1xx:服务器等待接收客户端消息,没有接收完成,等待一段时间发送1xx状态码
- 2xx:成功
- 3xx:重定向。代表302(重定向) 304(访问缓存)
- 4xx:客户端错误。代表404(请求路径没有对应的资源)405(没有对应的doxxx方法)
- 5xx:服务器端错误。代表:500(服务器内部错误)
- 分类
-
响应头
- 格式:头名称:值
- 常见的响应头
- Content-Type: 服务器告诉客户端本次响应体数据格式以及编码格式
- Content-disposition:服务器告诉客户端以什么格式打开响应体数据
- 值:in-line:默认值当前页面打开
- 值:attachment;filename=xxx:以附件形式打开响应体
-
响应空行
-
响应体:传输的数据
-
字符串表示形式
//响应行 HTTP/1.1 200 OK //响应头 Content-Type: text/html;charset=UTF-8 Content-Length: 98 Date: Fri, 07 Aug 2020 02:28:05 GMT Keep-Alive: timeout=20 Connection: keep-alive //响应空行 //响应体 <html> <head> <title>标题</title> </head> <body> hello 响应 </body> </html>
-
五.Request和Response
- 请求和响应
- 原理
- Tomcat服务器,会根据请求的url中的资源路径,创建对应的ServletDemo的对象。
- Tomcat服务器,会创建request和response对象,request对象中封装请求消息数据
- Tomcat将request和response两个对象传递给service方法,并且调用
- 程序员,通过request对象获取请求消息数据,通过response对象设置响应消息数据。
- 服务器在浏览器做出响应之前,会从response对象中拿程序员设置的响应消息数据,进行响应
- request和response对象是由服务器创建的。我们来使用他们
- request对象是用来获取请求消息,response对象是用来设置响应消息
①.Request
1.继承体系结构
ServletRequest – 接口
| 继承
HttpServletRequest – 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)
2.方法
-
request:获取请求行消息
GET /Setvlet1/demo?name=zhangsan HTTP/1.1返回值类型 方法 功能 String getMethod() 获取请求方式:GET String getContextPath() 获取虚拟目录:/Setvlet1 String getServletPath() 获取Servlet路径:/demo String getQueryString() 获取GET方式请求参数:name=zhangsan String getRequestURI() 获取请求URI:/Servlet1/demo StringBuffer getRequestURL() 获取请求URL:http://localhost/Servlet1/demo String getProtocol() 获取协议及版本:HTTP/1.1 String getRemoteAddr() 获取客户机的IP地址 - URL:统一资源定位符 : http://localhost/Servlet1/demo – 中华人民共和国
-
URI:统一资源标识符 : /Servlet1/demo – 共和国
-
获取请求头数据
返回值类型 方法 功能 String getHeader(String name) 通过请求头的名称获取请求头的值 Enumeration<String> getHeaderNames() 获取所有的请求头名称 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取全部头名称 Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()){ String headername = headerNames.nextElement(); String header = request.getHeader(headername); System.out.println(headername+" = "+header); } }
-
获取请求体数据
-
请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
-
步骤:
-
获取流对象
返回值类型 方法 功能 BufferedReader getReader() 获取字符输入流,只能操作字符数据 ServletInputStream getInputStream() 获取字节输入流,可以操作所有类型数据(文件上传) protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取流对象 BufferedReader reader = request.getReader(); //2. 读取流对象 String line = null; while ((line=reader.readLine())!=null){ System.out.println(line); } }
- 再从流对象中拿数据
-
-
3.其他方法
-
获取请求参数,通用方式
返回值 方法 作用 String getParameter(String name) 根据参数名称获取参数值 String[] getParameterValues(String name) 根据参数名称获取参数值的数组 Enumeration<String> getParameterNames() 获取所有请求的参数名称 Map<String,String[]> getParameterMap() 获取所有参数的map集合
-
中文乱码问题
-
get方式:Tomcat 8 已经解决
-
post方式:会乱码
- 解决:在获取参数前,设置request的编码request.setCharacterEncoding(utf-8);
-
<form action="/ServletDemo4" method="post">
<input type="text" placeholder="请输入用户名" name="username"/><br/>
<input type="password" placeholder="请输入密码" name="password"/><br/>
<input type="checkbox" name="hobby" value="学习"/>学习
<input type="checkbox" name="hobby" value="运动"/>运动
<input type="checkbox" name="hobby" value="看书"/>看书
<input type="checkbox" name="hobby" value="电子游戏"/>电子游戏 <br/>
<input type="submit" value="提交" />
</form>
@WebServlet("/ServletDemo4")
public class ServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//修改编码
request.setCharacterEncoding("utf-8");
//1. 获取username
String username = request.getParameter("username");
System.out.println(username);
System.out.println("========================");
//2. 获取hobby
String[] hobbys = request.getParameterValues("hobby");
for(String hobby:hobbys){
System.out.println(hobby);
}
System.out.println("========================");
//3. 获取请求参数名称
Enumeration<String> names = request.getParameterNames();
while (names.hasMoreElements()){
String name = names.nextElement();
System.out.println(name);
}
System.out.println("========================");
//4. 获取所有参数集合
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> keys = parameterMap.keySet();
for(String key:keys){
String[] values = parameterMap.get(key);
System.out.println(key+"=");
for(String value:values){
System.out.println(value);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
运行结果:
4365456456
========================
运动
看书
电子游戏
========================
username
password
hobby
========================
username=4365456456
password=31231231
hobby=运动
看书
电子游戏
2. 请求转发:一种服务器内部的资源跳转方式
-
步骤
-
通过request对象获取请求转发器对象:getRequestDispatcher(String path)
-
使用RequestDispatcher对象来进行转发:forward(ServletRequest request,ServletResponse response)
返回值类型 方法名 功能 RequestDispatcher getRequestDispatcher(String path) 过request对象获取请求转发器对象 void forward(ServletRequest request,ServletResponse response) 使用RequestDispatcher对象来进行转发 @WebServlet("/ServletDemo5") public class ServletDemo5 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("/ServletDemo5被访问了..."); //获取转发对象 /*RequestDispatcher dispatcher = request.getRequestDispatcher("/ServletDemo6"); dispatcher.forward(request,response);*/ request.getRequestDispatcher("/ServletDemo6").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
@WebServlet("/ServletDemo6") public class ServletDemo6 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("/ServletDemo6被访问了..."); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } } 结果打印: /ServletDemo5被访问了... /ServletDemo6被访问了...
- 特点
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中
- 转发只用到一次请求
-
共享数据
-
域对象:一个有作用范围的对象,可以在范围内共享数据
-
request域:代表一次请求的范围,一般用于请求转发多个资源中贡献数据
-
方法
返回值 方法 功能 void setAttribute(String name,Objet obj) 存储数据 Object getAttitude(String name) 通过键获取值 void removeAttribute(String name) 通过键移除键值对 @WebServlet("/ServletDemo5") public class ServletDemo5 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("/ServletDemo5被访问了..."); //存储数据 request.setAttribute("msg","hello"); //获取转发对象 /*RequestDispatcher dispatcher = request.getRequestDispatcher("/ServletDemo6"); dispatcher.forward(request,response);*/ request.getRequestDispatcher("/ServletDemo6").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } } @WebServlet("/ServletDemo6") public class ServletDemo6 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Object msg = request.getAttribute("msg"); System.out.println(msg.toString()); System.out.println("/ServletDemo6被访问了..."); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } } 输出结果: /ServletDemo5被访问了... hello /ServletDemo6被访问了...
-
-
获取ServletContext
- ServletContext getServletContext()
-
②.Response
-
功能(方法):设置响应消息
-
设置响应行
-
格式:HTTP/1.1 200 0k
返回值 方法名 功能 void setStatus(int sc) 设置状态码
-
-
设置响应头
返回值 方法名 功能 void setHeader(String name,String value) 设置响应头 -
设置响应体
-
步骤
-
获取输出流
返回值 方法名 功能 PrintWriter getWriter() 获取字符输出流 ServletOutputStream getOutputStream() 获取字节输出流 -
使用输出流,将数据输出到客户端浏览器
-
-
-
-
案例:
/** * 重定向 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setStatus(302); response.setHeader("location","/ServletDemo1"); //重定向专属方法 String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"/ServletDemo1"); } /* forward 和 redirect 的区别 ·转发特点:forward 1. 浏览器地址栏路径不发生变化 2. 只能转发到当前服务器内部资源中 3. 转发只用到一次请求,可以使用request对象来共享数据 ·重定向特点:redirect 1. 地址栏发生变化 2. 重定向可以访问其他站点(服务器)的资源 3. 重定向是两次请求,不可以使用request对象来共享数据 */ /* 路径的写法 1. 路径的分类 a.相对路径:通过绝对路径可以确定唯一资源 如: ./index.html 不以/开头以.开头路径 规则:找到当前资源与目标资源之间的相对位置关系 b.绝对路径:通过绝对路径可以确定唯一资源 如:http://localhost/day/Demo /day/Demo 以/开头的路径 规则:判断定义的路径给谁用 i. 给客户端用:需要加虚拟目录、建议动态获取 ii.给服务器用:不需要加虚拟目录 */
/* *输出字符到浏览器 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 设置编码 response.setCharacterEncoding("GBK"); //2. 服务器要求浏览器的解码规则 response.setContentType("text/html Charset=utf-8"); //3. 获取字符输出流 PrintWriter writer = response.getWriter(); //4. 输出字符 writer.write("Demo运行了..."); }
/* *验证码 *本质: *目的:防止恶意表单操作 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int w = 100; int h = 50; //1. 创建图片对象 BufferedImage bi = new BufferedImage(w,h,BufferedImage.TYPE_3BYTE_BGR); //2. 获取画笔对象 Graphics graphics = bi.getGraphics(); //3. 设置画笔颜色 graphics.setColor(Color.pink); //4. 填充颜色 graphics.fillRect(0,0,w,h); //5. 画边框 graphics.setColor(Color.blue); graphics.drawRect(0,0,w-1,h-1); //6. 设置循环字符 String str = "ABCDEFGHIJKMLNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; Random random = new Random(); for(int i = 1;i<5;i++){ int index = random.nextInt(str.length()); char ch = str.charAt(index); //7. 画验证码 graphics.drawString(ch+"",w/5*i,25); } //8. 画干扰线 graphics.setColor(Color.GREEN); //9. 随机生成坐标点 for(int i = 0;i<10;i++){ int x1 = random.nextInt(w); int x2 = random.nextInt(w); int y1 = random.nextInt(h); int y2 = random.nextInt(h); graphics.drawLine(x1,y1,x2,y2); } //输出图片 ImageIO.write(bi,"jpg",response.getOutputStream()); }
<body> <img id="checkCode" src="/ServletDemo2" /> <a id = "change" href="">看不清楚...</a> <script> var img = document.getElementById("checkCode"); img.onclick = function () { var date = new Date().getTime(); img.src = "/ServletDemo2?"+date; } </script> </body>
六.ServletContext对象
-
概念:代表整个web应用,可以和程序的容器(服务器)来通信
-
获取
-
通过request对象获取
request.getServletContext();
-
HttpServlet获取
this.getServletContext()
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext servletContext1 = request.getServletContext(); System.out.println(servletContext1); ServletContext servletContext2 = this.getServletContext(); System.out.println(servletContext2); } // org.apache.catalina.core.ApplicationContextFacade@d762a41 org.apache.catalina.core.ApplicationContextFacade@d762a41
-
-
功能
-
获取MIME类型
-
MIME类型:在互联网通信过程中定义的一种文件数据类型
- 格式: 大类型/小类型 text/html image/ipeg
- 获取:String getMimeType(String file)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = request.getServletContext(); String fileName = "aaa.html"; String mimeType = context.getMimeType(fileName); System.out.println(mimeType); } // text/html
-
-
域对象:共享数据
返回值 方法 功能 void setAttribute(String name,Objet obj) 存储数据 Object getAttitude(String name) 通过键获取值 void removeAttribute(String name) 通过键移除键值对 - ServletContext对象范围:所有用户所有请求的数据
-
获取文件的真实(服务器)路径
-
方法:String getRealPath(String path)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = request.getServletContext(); String realPath = context.getRealPath("/b.txt");//web目录下的资源访问 File file = new File(realPath); System.out.println(file); String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问 File file = new File(c); System.out.println(file); String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问 File file = new File(a); System.out.println(file); } //D:\Test\utu\out\artifacts\utu_war_exploded\b.txt //D:\Test\utu\out\artifacts\utu_war_exploded\WEB-INF\c.txt
-
-
-
下载案例
<body> <a href="/ServletDemo7?fileName=树.png">下载</a> <a href="/ServletDemo7?fileName=二比小姐姐.mp4">下载</a> </body>
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求的文件名称 String name = request.getParameter("fileName"); ServletContext context = this.getServletContext(); //获取文件路径 String realPath = context.getRealPath("/img/"+name); //设置编码 String mimeType = context.getMimeType(name); response.setHeader("Content-Type",mimeType); //解决中文文件名问题 //获取浏览器信息 String header = request.getHeader("User-Agent"); String fileName = DownUitl.getFileName(header, name); //设置下载形式 response.setHeader("Content-disposition","attachment;filename="+fileName); //关联字节流 FileInputStream fis = new FileInputStream(realPath); ServletOutputStream ops = response.getOutputStream(); byte[] bytes = new byte[1024 * 8]; int len = 0; while ((len = fis.read(bytes))!=-1){ ops.write(bytes,0,len); } fis.close(); ops.close(); }
public class DownUitl { public static String getFileName(String agent,String filename) throws UnsupportedEncodingException { if(agent.contains("MSIE")){ //IE浏览器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+"," "); }else if(agent.contains("Firefox")){ //火狐 BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8"))+ "?="; }else { //其他 filename = URLEncoder.encode(filename, "utf-8"); } return filename; } }
七.会话技术
- 会话的概念
一次会话中包含多次请求和响应
一次会话:浏览器第一次给服务器资源,发送请求,会话建立,直到一方断开为止- 功能:在一次会话范围内的多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术Session
①.Cookie
-
概念
客户端会话技术:将数据保存在客户端 -
快速入门
-
使用步骤
- 创建Cookie对象,绑定数据
- new Cookie(String name,String value)
- 发送Cookie对象
- response.addCookie(Cookie cookie)
- 获取Cookie,拿到数据
- Cookie[] request.getCookies()
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 创建Cookie对象 Cookie cookie = new Cookie("name","zhangsan"); //2. 发送Cookie对象 response.addCookie(cookie); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取Cookie对象 Cookie[] cookies = request.getCookies(); if(cookies != null){ for (Cookie cookie : cookies) { String name = cookie.getName(); String value = cookie.getValue(); System.out.println(name+"---"+value); } } } name---zhangsan
- 创建Cookie对象,绑定数据
-
-
原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gpBJ3xQU-1603158978891)(C:\Users\谜语菌\Documents\img\cookie.jpg)]
基于响应头set-cookie和请求头cookie实现 -
cookie细节
-
一次可不可以发送多个cookie?
- 可以
- 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可
-
cookie在浏览器中保存多长时间?
-
默认情况下,当浏览器关闭后Cookie信息销毁
-
持久化存储:
setMaxAge(int Seconds) 1. 正数:将Cookie数据写到硬盘文件中,持久化存储。cookie存活时间 2. 负数:默认值 3. 零:删除cookie信息 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 创建Cookie对象 Cookie cookie = new Cookie("name","zhangsan"); cookie.setMaxAge(30); //2. 发送Cookie对象 response.addCookie(cookie); }
-
-
cookie能不能存中文?
在tomcat8 之前 cookie中不能直接存储中文 需要将中文数据转码---一般采用URL编码(%E3) 在tomcat8 之后 cookie中可以直接存储中文
- cookie共享问题?
假设在一个tomcat服务器中,部署了多个web项目,在这些项目中Cookie能否共享? ·默认情况下不可共享 ·setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录 如果可以共享,则可以将path设置为"/"
不同的tomcat服务器间cookie的共享问题 ·setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享 setDomain(".baidu.com"),那么tieba.baidu.com 和 news.baidu.com中的Cookie可以共享
-
-
Cookie的特点和作用
- cookie存储数据在客户端浏览器(安全性低)
- 浏览器对于单个cookie 的大小有限制(4kb),以及 对同一个域名下的总cookie数量(20)也有限制
- 作用
cookie一般用于存储少量的不太敏感的数据 在不登录的情况下,完成服务器对客户端的身份识别
-
案例:记住上一次访问时间
/** *需求 *1. 访问一个Servlet,如果是第一次访问,则提示:您好欢迎您首次访问 *2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:xxx */ @WebServlet("/cookieDemo2") public class CookieDemo2 extends HttpServlet { boolean b = false; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("GBK"); response.setContentType("text/html utf-8"); //获取全部的Cookie对象 Cookie[] cookies = request.getCookies(); if(cookies == null ||b == false){ //第一次访问 //获取当前时间 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String date_v = sdf.format(date); //设置URL编码 date_v = URLEncoder.encode(date_v, "utf-8"); //创建Cookie Cookie cookie = new Cookie("Time",date_v); //设置存活时间 cookie.setMaxAge(60*60*24); //发送 response.addCookie(cookie); //响应数据 response.getWriter().write("首次访问"); System.out.println("嘿嘿"); } if(cookies != null && cookies.length > 0){ //遍历Cookies for(Cookie cookie:cookies){ //获取cookie名称 String name = cookie.getName(); if("Time".equals(name)){ b = true; //非第一次访问 //设置时间 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String date_v = sdf.format(date); //URL编码 date_v = URLEncoder.encode(date_v,"utf-8"); cookie.setValue(date_v); cookie.setMaxAge(60*60*24); response.addCookie(cookie); //URL解码 String value = cookie.getValue(); value = URLDecoder.decode(value, "utf-8"); response.getWriter().write("您好上次访问时间为:"+value); } } } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
②.Session
-
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端对象中。HttpSession
-
快速入门
-
获取HttSession对象
HttpSession session = request.getSession();
-
使用HttSession对象
返回值类型 方法 功能 Object getAttribute(String name) 获取数据 void setAttribute(String name,Object value) 存储数据 void temoveAttribute(String name) 删除数据 @WebServlet("/SessionDemo") public class SessionDemo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取Session对象 HttpSession session = request.getSession(); session.setAttribute("msg","Holl,Session"); }S protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } } @WebServlet("/SessionDemo1") public class SessionDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取Session HttpSession session = request.getSession(); //获取数据 Object msg = session.getAttribute("msg"); response.getWriter().write(msg.toString()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
-
-
Session原理
- Session的实现依赖于Cookie
- Cookie响应头,请求头携带Session的内存ID
-
细节
- 客户端关闭后,服务器不关闭,两次获取session是否为同一个?
//默认情况下不是 /* *如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让Cookie持久化存储 */ @WebServlet("/SessionDemo") public class SessionDemo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取Session对象 HttpSession session = request.getSession(); session.setAttribute("msg","Holl,Session"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } } @WebServlet("/SessionDemo2") public class SessionDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取Session HttpSession session = request.getSession(); //获取cookie对象 Cookie cookie = new Cookie("JSESSIONID",session.getId()); cookie.setMaxAge(60*60); response.addCookie(cookie); response.getWriter().write(session.toString()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
- 客户端不关闭,服务器关闭后,两次获取的Session是同一个吗?
不是同一个,但是要确保数据不丢失 a.session的钝化: 在服务器正常关闭之前,将session对象序列化到硬盘上 b.session的活化: 在服务器启动后,将session文件转化为内存中的session对象即可
- session什么情况下被销毁
1. 服务器关闭 2. session对象调用invalidate() 3. session默认失效时间 30分钟 选择性配置修改 <session-config> <session-timeout>60</session-timeout> </session-config>
-
session特点
- session用于存储一次会话的多次请求的数据,存在服务器
- session可以存储任意类型,任意大小的数据
- session与cookie的区别
a. session存储数据在服务器端,cookie在客户端 b. session没有数据大小限制,cookie有 c. session数据安全,cookie相对不安全
-
案例:验证码
八.JSP
①JSP入门学习
-
概念
Java Server Pages:Java服务器端页面
可以理解为:一个特殊的页面,其中既可以定义HTML标签,也可以写Java代码
用于简化书写 -
原理
JSP本质上是一个Servlet a. 服务器解析请求消息,找是否存在index.jsp资源 b. 找到后,将index.jsp转换为.java文件 c. 编译.Java文件,生成.class字节码文件 d.由字节码文件提供访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-znQR1BXz-1603158978896)(C:\Users\谜语菌\Documents\img\jsp.jpg)]
-
JSP的脚本:JSP定义Java代码的方式
- <% 代码 %>:定义的Java代码,在service方法中
- <%! 代码 %>:定义的Java代码,类的成员位置
- <%= 代码 %>:定义的Java代码,会输出到页面上
-
JSP内置对象
- 在JSP中可以直接使用的对象
- request
- response
- out:字符输出流对象,可以将数据输出到页面上
- response.getWrier()和out的区别
- 在tomcat服务器真正给客户端做出响应之前,会先找到response缓冲区数据,再找out缓冲区数据
- response.getWriter()数据输出永远在out.write()之前
- response.getWrier()和out的区别
练习
<html> <head> <title>Title</title> </head> <body> <%!//时间参数 String lastTime = null; %> <% //获取全部的Cookie对象 Cookie[] cookies = request.getCookies(); //遍历Cookies for(int i = 0;cookies != null&&i<cookies.length;i++){ if("lastTime".equals(cookies[i])){ lastTime = cookies[i].getValue(); break; } } if(lastTime == null){ out.write("欢迎首次访问"); }else { //URL解码 lastTime = URLDecoder.decode(lastTime,"utf-8"); out.write("欢迎回家,您上次访问时间为:"+lastTime); } //记录访问时间 Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); lastTime = sdf.format(date); //URL编码 lastTime = URLEncoder.encode(lastTime, "utf-8"); //创建Cookie对象 Cookie cookie = new Cookie("lastTime",lastTime); //发送Cookie response.addCookie(cookie); %> </body> </html>
②.指令
-
作用:配置JSP页面,导入资源文件
-
格式
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
-
分类
a. page :配置JSP页面 i. contentTyoe:等同于response.setContentType() 1. 设置响应体的mime类型以及字符集 2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面字符集) ii. import:导包 iii. errorPage:当前页面发生异常后,会自动跳转到指定的错误页面 iiii. isErrorPage:标识当前页面是否是错误页面 1. ture:是,可以使用内置对象exception 2. false:否,默认值,不可以使用内置对象exceotion b. include :页面包含的。导入页面的资源文件 i. <%@include file="top.jsp"%> c. taglib :导入资源 i. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> prefix:前缀,自定义的
③.注释
-
HTML注释:只能注释html
-
JSP注释:注释所有
<%-- --%>
④.内置对象
在JSP页面中不需要创建就可以直接使用的对象,有九个
变量名 | 真实类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其他八个对象 |
requst | HttpServletRequest | 一次请求访问的多个资源(转发) |
session | HttpSession | 一次会话的多个请求间 |
application | ServletContext | 所有用户间共享数据 |
response | HttpServletResponse | 响应对象 |
page | Object | 当前页面的对象(this) |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 异常对象 |
九.EL和JSTL
①.EL表达式
Ⅰ.概述
- 概念:Expression Language 表达式
- 作用:替换和简化jsp页面中的java代码的编写
- 语法:
${表达式}
- 注意:
- jsp默认支持默认表达式,如果忽略el表达式
- 设置jsp中page指令中:isELIgnored=“true” 忽略当前jsp页面中所有的el表达式
- ${表达式}:忽略当前这个el表达式
- jsp默认支持默认表达式,如果忽略el表达式
- 使用
- 运算
- 获取值
Ⅱ.EL的使用
-
运算
i. 运算符1. 算数运算符: + - * /(div) %(mod) 2. 比较运算符: > < >= <= == != 3. 逻辑运算符: &&(and) ||(or) !(not) 4. 空运算符: empty - 功能:用于判断字符串、集合、数组对象是否为null并且长度是否为0 - ${empty list} - ${not empty list}
-
获取值
-
el表达式只能从域对象中获取值
-
语法
- ${域名称.键名}:从指定域中获取指定键的值
pageScope --> pageContext requstScope -->request sessionScope -->session applicationScope -->application(ServletContext) //举例 //存储键值对 request.setAttribute("name","张三"); request.getRequestDispatcher("/el.jsp").forward(request,response); //获取值 ${requestScope.name}
-
${键名}:表示依次从最小到大的域中查找该键对应的值,直到找到位置
-
获取对象.List集合.Map集合的值
- 对象
${域名.键名.属性名} | 本质上去调用对象的方法 通过对象的属性来获取 i. setter或getter方法,去掉set或get,在剩余部分,首字母变为小写 ii. setName ---> Name ---> name
- List集合
${域名.键名[索引]}
- Map集合
${域名.键名.key名称} ${域名.键名["key名称"]}
-
Ⅲ.隐式对象
el表达式中有11个隐式对象
1. pageConntext
获取jsp其他八个对象
${pageContext.qequest.contextPath}:动态获取虚拟目录
②.JSTL
-
概念:Javaserver Pages Tag Library JSP标准标签库
是由Apache组织提供的开源的免费的jsp标签 <标签>
-
作用:用于简化和替换jsp页面上的Java代码
-
使用步骤
a. 导入jstl相关jar包 b. 引入标签库:taglib指令 <%@ taglib %> c. 使用标签
-
常用的JSTL标签
- if :相当于if语句
a. 属性 test 必须属性,接收boolean表达式 i. 如果表达式为true,则显示if标签体的内容,false不显示 ii. 一般情况下,test属性值会结合el表达式一起使用 iii. if标签没有else情况,想要else情况,重新定义一个if标签 <c:if test="true"> <h1>你好</h1> </c:if>
- choose :相当于switch语句
<%-- 完成数字编号对应的星期几 1. 域中存储数字 2. 使用choose标签 相当于switch声明 3. 使用when标签做数字判断 相当于case 4. otherwise标签做其他情况的声明 相当于default --%> <% request.setAttribute("numder",44); %> <c:choose> <c:when test="${requestScope.numder == 1}"><h1>星期一</h1></c:when> <c:when test="${requestScope.numder == 2}"><h1>星期二</h1></c:when> <c:when test="${requestScope.numder == 3}"><h1>星期三</h1></c:when> <c:when test="${requestScope.numder == 4}"><h1>星期四</h1></c:when> <c:when test="${requestScope.numder == 5}"><h1>星期五</h1></c:when> <c:when test="${requestScope.numder == 6}"><h1>星期六</h1></c:when> <c:when test="${requestScope.numder == 7}"><h1>星期日</h1></c:when> <c:otherwise>数字输入错误</c:otherwise> </c:choose>
- foreach :相当于for语句
<%-- foreach:相当于Java代码的for语句 1. 完成重复操作 for(int i = 0;i<10;i++){ } 属性: begin:开始值 end:结束值 var:临时变量 step:步长 varStatus:循环状态对象 i. index:容器中元素的索引,从零开始 ii. count:循环次数,从1开始 2. 遍历容器 List<User> list; for(User user:list){ } 属性: items:容器对象 var:容器中元素的临时变量 varStatus:循环状态对象 i. index:容器中元素的索引,从零开始 ii. count:循环次数,从1开始 --%> <% List<String> list = new ArrayList<>(); list.add("zhansan"); list.add("lisi"); list.add("wangwu"); request.setAttribute("list",list); %> <c:forEach items="${list}" var="name"> ${name}<br> </c:forEach> <c:forEach begin="1" end="10" var="i" step="1"> ${i}<br> </c:forEach>
-
练习
<body> <% Date date = new Date(); ArrayList<User> list = new ArrayList<>(); list.add(new User("张三",17,date)); list.add(new User("李四",14,date)); list.add(new User("王五",19,date)); list.add(new User("赵六",21,date)); request.setAttribute("list",list); %> <table border="1" width="500"> <tr> <th>编号</th> <th>姓名</th> <th>年龄</th> <th>日期</th> </tr> <c:forEach items="${requestScope.list}" var="user" varStatus="s"> <c:if test="${s.count % 2 == 0}"> <tr bgcolor="#98fb98"> <td>${s.count}</td> <td>${user.name}</td> <td>${user.age}</td> <td>${user.birstr}</td> </tr> </c:if> <c:if test="${s.count % 2 != 0}"> <tr bgcolor="#ffc0cb"> <td>${s.count}</td> <td>${user.name}</td> <td>${user.age}</td> <td>${user.birstr}</td> </tr> </c:if> </c:forEach> </table> </body>
十. Servlet高级
①.Filter:过滤器
Ⅰ.过滤器概念
当访问服务器资源时,过滤器可以将请求拦截下来,完成一些特殊功能
- 过滤器的作用
一般用于完成通用的操作,如登录验证,统一编码设置,敏感字符过滤
Ⅱ.过滤器的快速入门
-
步骤
- 定义一个类,实现接口Filter
- 复写方法
- 配置拦截路径
- web.xml
- 注解
@WebFilter("/index.jsp") public class FilterDemo implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("doFilter..."); //放行 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
Ⅱ.过滤器的细节
-
web.xml配置
<filter> <filter-name>FiltDemo</filter-name> <filter-class>com.wed.Filter.FilterDemo</filter-class> </filter> <filter-mapping> <filter-name>FiltDemo</filter-name> <!-- 拦截路径 --> <url-pattern>/index.jsp</url-pattern> </filter-mapping>
-
过滤器执行流程
1. 执行过滤器 2. 执行放行后的资源 3. 回来执行放行后的代码 @WebFilter("/*") public class FilterDemo1 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("FilterDemo1过去了..."); //放行 chain.doFilter(req, resp); System.out.println("FilterDemo1回来了..."); } public void init(FilterConfig config) throws ServletException { } } /* FilterDemo1过去了... index.jsp FilterDemo1回来了... */
-
过滤器生命周期方法
@WebFilter("/*") public class FilterDemo2 implements Filter { //服务器正常关闭后,销毁Filter对象,执行destroy方法,一般用于释放资源 public void destroy() { System.out.println("destroy..."); } //每一次请求拦截资源时执行, public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("doFilter..."); chain.doFilter(req, resp); } //服务器启动后会创建Filter对象,然后调用init方法,一般用于加载资源 public void init(FilterConfig config) throws ServletException { System.out.println("init"); } }
-
过滤器配置详解
-
拦截路径配置
a. 具体资源路径 /index.jsp 只有访问index.jsp资源时,过滤器才会执行 b. 拦截目录 /user/* 访问/user下所有资源时,过滤器都会执行 c. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行 d. 拦截所有资源 /* 访问所有资源时过滤器都会被执行
-
拦截方式配置:资源被访问的方式
1. 注解配置 * 设置dispatcherTypes属性 a. REQUEST:默认值。浏览器直接请求资源 b. FORWARD:转发访问资源 c. INCLUDE:包含访问资源 d. ERROR :错误跳转 e. ASYNC :异步访问资源 2. web.xml配置 * 设置<dispatcher></dispatcher>标签即可
-
-
过滤器链(配置多个过滤器)
执行顺序:如果有两个过滤器:过滤器1 过滤器2 过滤器1 过滤器2 资源执行 过滤器2 过滤器1 过滤器先后顺序 a. 注解配置:按照类名的字符串比较规则,值小的先执行 如:AFilter和BFilter,A先执行 Demo6 和 Demo18 , 18先执行 b.web.xml配置:<filter-mpping>上面的先执行
十一.MVC开发模式和三层架构
①.MVC开发模式
-
JSP演变历史
早期只有servlet,只能使用response输出标签数据,非常麻烦 后来出现jsp,简化了servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,又写html标签,造成难于维护,难于分工协作 再后来,java的web开发,倡圣mVc开发模式,使得程序的设计更加合理性
-
MVC:
a. Model,模型。javaBean- 完成具体的业务操作,如:查询数据库,封装对象
b. View,视图。JSP
- 展示数据
c. Controller,控制器。Servlet
-
获取用户的输入
-
调用模型
-
将数据交给视图进行展示
-
优点
- 耦合性低,方便维护,有利于分工合作
- 重用性低
-
缺点
- 使的项目结构变得复杂,对开发人员要求高
②.三层架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6yYimHPP-1603158978901)(C:\Users\谜语菌\Documents\img\三层架构.jpg)]