java web
一.XML
①.概述
概念:可扩展标记语言
- 可扩展:标签都是自定义的。
功能
- 存储数据
- 配置文件
- 在网络中传输
properties
name=zhangsan age=23 gender=nanxml
<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)]