# JavaWeb学习 **Repository Path**: BY-KK/javaweb ## Basic Information - **Project Name**: JavaWeb学习 - **Description**: 此仓库用来学习javaweb相关知识 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2022-02-26 - **Last Updated**: 2022-04-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # JavaWeb学习 ## 介绍 此仓库用来学习javaweb相关知识 预计花费13h **JavaEE** **项目的三层架构** ![javaee三层架构](img/jee.png) # 2.26(Servlet\JSP) ## Servlet ### 1、什么是Servlet - 1、Servlet 是 JavaEE 规范之一。规范就是接口 - 2、Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。 - 3、Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。 ### 2、通过URL地址到Servlet程序的过程 ![访问过程](img/url.png) ### 3、Servlet的生命周期 1. 执行 Servlet 构造器方法 2. 执行 init 初始化方法 第一、二步,是在第一次访问,的时候创建 Servlet 程序会调用。 3. 执行 service 方法 第三步,每次访问都会调用。 4. 执行 destroy 销毁方法 第四步,在 web 工程停止的时候调用。 ### 4、Servlet类的继承体系 ![继承体系](img/jc.jpg) ### 5、ServletContext类 #### a)什么是ServletContext - ServletContext 是一个接口,它表示 Servlet 上下文对象 - 一个 web 工程,只有一个 ServletContext 对象实例。 - ServletContext 对象是一个域对象。 - ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。 > 什么是域对象? > > > 域对象是可以Map 一样存取数据的对象,叫域对象。 > > > > 这里的域指的是存取数据的操作范围,整个 web 工程。 | | 存数据 | 取数据 | 删除数据 | | :--------: | :-----: | :----: | :-----: | | Map | put() | get() | remove() | | 域对象 | serAttribute() | getAttribute() | removeAttribute() | #### b)ServletContext类的四个作用 - 1、获取 web.xml 中配置的上下文参数 context-param - 2、获取当前的工程路径,格式: /工程路径 - 3、获取工程部署后在服务器硬盘上的绝对路径 - 4、像 Map 一样存取数据 ### 6、HTTP协议 #### a)什么是HTTP协议 什么是协议? 协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。 所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。 HTTP 协议中的数据又叫报文。 #### b)请求的HTTP协议格式 客户端给服务器发送数据叫请求。 服务器给客户端回传数据叫响应。 请求又分为 GET 请求,和 POST 请求两种 ##### i、GET请求 - 1、请求行 - (1) 请求的方式 GET - (2) 请求的资源路径[+?+请求参数] - (3) 请求的协议的版本号 HTTP/1.1 - 2、请求头 - key : value 组成不同的键值对,表示不同的含义 ##### ii、POST请求 - 1、请求行 - (1) 请求的方式 POST - (2) 请求的资源路径[+?+请求参数] - (3) 请求的协议的版本号 HTTP/1.1 - 2、请求头 - key : value 不同的请求头,有不同的含义 - 3、请求体 ===>>> 就是发送给服务器的数据 ##### iii、常用的请求头的说明 **Accept**: 表示客户端可以接收的数据类型 **Accpet-Languege**: 表示客户端可以接收的语言类型 **User-Agent:** 表示客户端浏览器的信息 **Host**: 表示请求时的服务器 ip 和端口号 ##### iv、 哪些是GET请求,哪些是POST请求 GET 请求有哪些: 1. form 标签 method=get 2. a 标签 3. link 标签引入 css 4. Script 标签引入 js 文件 5. img 标签引入图片 6. iframe 引入 html 页面 7. 在浏览器地址栏中输入地址后敲回车 POST 请求有哪些: 1. form 标签 method=post #### c)响应的HTTP协议格式 - 1、响应行 - (1) 响应的协议和版本号 - (2) 响应状态码 - (3) 响应状态描述符 - 2、响应头 - (1) key : value 不同的响应头,有其不同含义 - 3、响应体 ---->>> 就是回传给客户端的数据 ![响应格式](img/xy.png) #### d)常用的响应码说明 **200** 表示请求成功 **302** 表示请求重定向(明天讲) **404** 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误) **500** 表示服务器已经收到请求,但是服务器内部错误(代码错误) #### e)MIME类型说明 MIME 是 HTTP 协议中数据类型。 MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小 类型”,并与某一种文件的扩展名相对应。 | 文件 | 文件格式 | MIME类型 | | :----------------: | :---------: | ------------------------ | | 超文本标记语言文本 | .html,.htm | text/html | | 普通文本 | .txt | text/plain | | RTF文本 | .rtf | application/rtf | | GIF图形 | .gif | image/gif | | JPEG图形 | .jpeg,.jpg | image/jpeg | | au声音文件 | .au | audio/basic | | MIDI音乐文件 | .mid,.midi | audio/midi,audio/x-midi | | RealAudio音乐文件 | .ra,.ram | audio/x-pn-realaudio | | MPEG文件 | .mpg,.mpeg | video/mpeg | | AVI文件 | .avi | video/x-msvideo | | GZIP | .gz | application/x-gzip | | TAR | .tar | application/x-tar | ### 7、HttpServletRequest类 #### 7.1、HttpServletRequest类有什么用 每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。 #### 7.2、HttpServletRequest类的常用方法 | 方法 | 描述 | | :----------------------: | :--------------------------------------------: | | getRequestURI() | 获取请求的资源路径 | | getRequestURL() | 获取请求的统一资源定位符(绝对路径) | | getRemoteHost() | 获取客户端的IP地址 | | getHeader() | 获取请求头 | | getParameter(String arg) | 获取请求的参数 | | getParameterValues() | 获取请求的参数(多个值的时候用,例如checkbox) | | getMethod() | 获取请求的方式GET或POST | | setAttribute(key,value) | 设置域数据 | | getAttribute(key) | 获取域数据 | | getRequestDispatcher() | 获取请求转发对象 | #### 7.3、如何解决乱码问题 doGet请求的中文乱码问题解决: ```java // 获取请求参数 String username = req.getParameter("username"); //1 先以 iso8859-1 进行编码 //2 再以 utf-8 进行解码 username = new String(username.getBytes("iso-8859-1"), "UTF-8"); ``` post请求中的中文乱码解决: ```java req.setCharacterEncoding("UTF-8"); ``` > 在post中用setCharacterEncoding()方法之前如果有使用获取参数方法则会转码失败! #### 7.4、请求转发 请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。 ![请求转发](img/zf.png) #### 7.5、Web中的相对路径和绝对路径 在 javaWeb 中,路径分为相对路径和绝对路径两种: **相对路径是**: - . 表示当前目录 - .. 表示上一级目录 - 资源名 表示当前目录/资源名 **绝对路径**: http://ip:port/工程路径/资源路径 #### 7.6、web中 / 斜杠的不同意义 在 web 中 / 斜杠 是一种绝对路径。 / 斜杠 如果被浏览器解析,得到的地址是:http://ip:port/ ```html 斜杠 ``` / 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径 1. <**url-pattern**>/servlet1 2. servletContext.getRealPath(“/”); 3. request.getRequestDispatcher(“/”); >特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到 http://ip:port/ ### 8、HttpServletResponse类 #### 8.1、HttpServletResponse类的作用 ​ HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息, 我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置 #### 8.2、两个输出流的说明 | 方法 | 描述 | 流类型 | | ------------------ | ---------------------------- | ------ | | getOutputStream(); | 常用于下载(传递二进制数据) | 字节流 | | getWriter(); | 常用于回传字符串(常用) | 字符流 | #### 8.3、往客户端回传数据 要求 : 往客户端回传 字符串 数据。 ```java 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!!!"); } } ``` #### 8.4、响应的乱码问题 解决响应中文乱码方案一(不推荐使用): ```java //* *设置服务器字符集为* *UTF-8* resp.setCharacterEncoding("UTF-8"); //* *通过响应头,设置浏览器也使用* *UTF-8* *字符集* resp.setHeader("Content-Type", "text/html; charset=UTF-8"); ``` 解决响应中文乱码方案二(推荐): ```java // 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头 // 此方法一定要在获取流对象之前调用才有效 resp.setContentType("text/html; charset=UTF-8"); ``` #### 8.5、请求重定向 请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)。 ![请求重定向](img/zdx.png) 请求重定向的第一种方案: ```java // 设置响应状态码 302 ,表示重定向,(已搬迁) resp.setStatus(302); // 设置响应头,说明 新的地址在哪里 resp.setHeader("Location", "http://localhost:8080"); ``` 请求重定向的第二种方案(推荐使用): ```java resp.sendRedirect("http://localhost:8080"); ``` ## JSP ### 1、JSP简介 jsp 的全称是 **J**ava **S**erver **P**ages。Java 的服务器页面。 jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据。 因为 Servlet 程序回传 html 页面数据是一件非常繁锁的事情。开发成本和维护成本都极高。 ### 2、JSP的本质 jsp 页面本质上是一个 Servlet 程序。 当我们第一次访问 jsp 页面的时候。Tomcat 服务器会帮我们把 jsp 页面翻译成为一个 java 源文件。并且对它进行编译成为.class 字节码程序。 >其底层实现,也是通过输出流。把 html 页面数据回传给客户端 ### 3、JSP的三种语法 #### a)jsp头部的page指令 jsp 的 page 指令可以修改 jsp 页面中一些重要的属性,或者行为。 ```jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> ``` | 属性 | 描述 | | ------------ | ------------------------------------------------------------ | | language | 表示jsp翻译后是什么语言文件,只支持java | | contentType | 表示jsp返回的数据类型是什么,response.setContentType()参数值 | | pageEncoding | 表示当前jsp页面文件本身的字符集 | | import | 导包 | | autoFlush | 设置当out输出流缓冲区满了之后,是否自动刷新冲级区,默认true | | buffer | 设置out缓冲区的大小,默认8kb | | errorPage | 设置当jsp页面运行时出错,自动跳转去的错误页面路径 | | isErrorPage | 设置当前jsp页面是否是错误信息页面。默认false。如果是true可以获取异常信息 | | session | 设置访问当前jsp页面,是否会创建HttpSession对象,默认true | | extends | 设置jsp翻译出来的java类默认继承谁 | #### b)jsp中的常用脚本 **i.** **声明脚本**(**极少使用**) 声明脚本的格式是: **<%!** 声明 java 代码 **%>** 作用:可以给 jsp 翻译出来的 java 类定义属性和方法甚至是静态代码块。内部类等。 **ii.** **表达式脚本(常用)** 表达式脚本的格式是:**<%=**表达式**%>** 表达式脚本的作用是:在 jsp 页面上输出数据。 表达式脚本的特点: 1. 所有的表达式脚本都会被翻译到_jspService() 方法中 2. 表达式脚本都会被翻译成为 out.print()输出到页面上 3. 由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象都可以直接使用。 4. 表达式脚本中的表达式不能以分号结束。 **iii.** **代码脚本** 代码脚本的格式是: **<%** java 语句 **%>** 代码脚本的作用是:可以在 jsp 页面中,编写我们自己需要的功能(写的是 java 语句)。 代码脚本的特点是: 1. 代码脚本翻译之后都在_jspService 方法中 2. 代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用。 3. 还可以由多个代码脚本块组合完成一个完整的 java 语句。 4. 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据 ### 4、JSP九大内置对象 jsp 中的内置对象,是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。 | 对象 | 描述 | | ----------- | ------------------ | | request | 请求对象 | | response | 响应对象 | | pageContext | jsp的上下文对象 | | session | 会话对象 | | application | ServletContext对象 | | config | ServletConfig对象 | | out | jsp输出流对象 | | page | 指向当前jsp的对象 | | exception | 异常对象 | ### 5、JSP四大域对象 | 对象 | 作用范围 | | ----------------------------------- | ---------------------------------------------------------- | | pageContext (PageContextImpl 类) | 当前 jsp 页面范围内有效 | | request (HttpServletRequest 类) | 一次请求内有效 | | session (HttpSession 类) | 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器) | | application (ServletContext 类) | 整个 web 工程范围内都有效(只要 web 工程不停止,数据都在) | 域对象是可以像 Map 一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存取范围。 虽然四个域对象都可以存取数据。在使用上它们是有优先顺序的。 四个域在使用的时候,优先顺序分别是,他们从小到大的范围的顺序。 pageContext ====>>> request ====>>> session ====>>> application # 2.27(EL&JSTL&MVC&分页&Filter) ## EL表达式 ### 1、EL表达式简介 EL 表达式的全称是:**E**xpression **L**anguage。是表达式语言。 **EL 表达式的什么作用**:EL 表达式主要是代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。 因为 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁很多。 EL 表达式的格式是:**${**表达式**}** EL 表达式在输出 null 值的时候,输出的是空串。jsp 表达式脚本输出 null 值的时候,输出的是 null 字符串。 ### 2、EL表达式搜索域数据的顺序 当四个域中都有相同的 key 的数据的时候,EL 表达式会按照四个域的从小到大的顺序去进行搜索,找到就输出。 ### 3、EL搜索写法 *输出Person类中普通属性,数组属性。List 集合属性和 map 集合属性。* ``` public class Person { // i.需求——输出 Person 类中普通属性,数组属性。list 集合属性和 map 集合属性。 private String name; private String[] phones; private List cities; private Map map; } ``` | 写法 | 描述 | | ---------------------------------------------- | ---------------------------- | | &{域中对象名} &{ p } | 输出对象 | | &{域中对象名.属性名} &{ p.name } | 输出该对象指定的属性值 | | &{域中对象名.数组名[索引]} &{ p.phones[2] } | 输出对象数组中某一个值 | | &{域中对象名.集合名} &{ p.cities } | 输出该对象集合 | | &{域中对象名.集合名[索引]} &{ p.cities[2] } | 输出对象集合中某一个值 | | &{域中对象名.map集合名} &{ p.map } | 输出该对象Map集合 | | &{域中对象名.map集合名.key} &{ p.map.key } | 输出该对象map集合中某个key值 | ### 4、EL表达式——运算 语法:${ 运算表达式 } , EL 表达式支持如下运算符 **关系运算** | 关系运算符 | 说明 | 规范 | 结果 | | :--------: | :------: | :--------------------------: | :---: | | == 或 eq | 等于 | ${ 5 == 5 } 或 ${ 5 eq 5 } | true | | != 或 ne | 不等于 | ${ 5 !=5 } 或 ${ 5 ne 5 } | false | | < 或 lt | 小于 | ${ 3 < 5 } 或 ${ 3 lt 5 } | true | | \> 或 gt | 大于 | ${ 2 > 10 } 或 ${ 2 gt 10 } | false | | <= 或 le | 小于等于 | ${ 5 <= 12 } 或 ${ 5 le 12 } | true | | \>= 或 ge | 大于等于 | ${ 3 >= 5 } 或 ${ 3 ge 5 } | false | **逻辑运算** | 关系运算符 | 说明 | 规范 | 结果 | | :--------: | :-------: | :----------------------------------------------------: | :---: | | && 或 and | && 或 and | ${ 12 == 12 && 12 < 11 } 或 ${ 12 == 12 and 12 < 11 } | false | | \|\| 或 or | 或运算 | ${ 12 == 12 \|\| 12 < 11 } 或 ${ 12 == 12 or 12 < 11 } | true | | ! 或 not | 取反运算 | ${ !true } 或 ${ not true } | false | **算数运算** | 关系运算符 | 说明 | 规范 | 结果 | | :--------: | :--: | :----------------------------------: | :--: | | + | 加法 | ${ 12 + 18 } | 30 | | - | 减法 | ${ 18 - 8 } | 10 | | * | 乘法 | ${ 12 * 12 } | 144 | | / 或 div | 除法 | ${ 144 / 12 } 或 ${ 144 **div** 12 } | 12 | | % 或 mod | 取模 | ${ 144 % 10 } 或 ${ 144 **mod** 10 } | 4 | **empty运算** empty 运算可以判断一个数据是否为空,如果为空,则输出 true,不为空输出 false。 以下几种情况为空: 1. 值为 null 值的时候,为空 2. 值为空串的时候,为空 3. 值是 Object 类型数组,长度为零的时候 4. list 集合,元素个数为零 5. map 集合,元素个数为零 **三元运算** 表达式 1?表达式 2:表达式 3 如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。 **“.”运算 和 [] 中括号运算符** .点运算,可以输出 Bean 对象中某个属性的值。 []中括号运算,可以输出有序集合中某个元素的值。 并且[]中括号运算,还可以输出 map 集合中 key 里含有特殊字符的 key 的值。 **EL表达式的11个隐含对象** | **隐含对象** | 类型 | **描述** | | :--------------- | :------------------: | :----------------------------------------------------------- | | pageScope | Map | page 作用域,它可以获取 pageContext 域中的数据 | | requestScope | Map | request 作用域,它可以获取 Request 域中的数据 | | sessionScope | Map | session 作用域,它可以获取 Session 域中的数据 | | applicationScope | Map | application 作用域,它可以获取 ServletContext 域中的数据 | | param | Map | Request 对象的参数,字符串,它可以获取请求参数的值 | | paramValues | Map | Request对象的参数,字符串集合,它也可以获取请求参数的值,获取多个值的时候使用。 | | header | Map | HTTP 信息头,字符串,它可以获取请求头的信息 | | headerValues | Map | HTTP 信息头,字符串集合,它可以获取请求头的信息,它可以获取多个值的情况 | | initParam | Map | 上下文初始化参数,它可以获取在 web.xml 中配置的上下文参数 | | cookie | Map | Cookie值,它可以获取当前请求的 Cookie 信息 | | pageContext | PageContextImpl | 当前页面的pageContext,它可以获取 jsp 中的九大内置对象 | **EL获取四个特定域中的属性** pageScope ====== pageContext 域 requestScope ====== Request 域 sessionScope ====== Session 域 applicationScope ====== ServletContext 域 ```html <% pageContext.setAttribute("key1", "pageContext1"); pageContext.setAttribute("key2", "pageContext2"); request.setAttribute("key2", "request"); session.setAttribute("key2", "session"); application.setAttribute("key2", "application"); %> ${ applicationScope.key2 } ``` ### 5、EL中域对象的使用 #### 5.1、pageContext对象的使用 1. 协议: **${** req.scheme **}** 2. 服务器 ip: **${** pageContext.request.serverName **}** 3. 服务器端口: **${** pageContext.request.serverPort **}** 4. **获取工程路径:** **${** pageContext.request.contextPath **}** 5. 获取请求方法: **${** pageContext.request.method **}** 6. 获取客户端 ip 地址:**${** pageContext.request.remoteHost **}** 7. 获取会话的 id 编号:**${** pageContext.session.id **}** #### 5.2、其他隐含对象的使用 | 隐含对象 | 返回值 | 说明 | | :---------: | :------------------: | :--------------------------------------------: | | param | Map | 它可以获取请求参数的值 | | paramValues | Map | 它也可以获取请求参数的值,获取多个值的时候使用 | - 输出请求参数 username 的值:**${** param.username **}** - 输出请求参数 password 的值:**${** param.password **}** - 输出请求参数 username 的值:**${** paramValues.username[0] **}** - 输出请求参数 hobby 的值:**${** paramValues.hobby[0] **}** - 输出请求参数 hobby 的值:**${** paramValues.hobby[1] **}** | 隐含对象 | 返回值 | 说明 | | :----------: | :------------------: | :--------------------------------------------: | | header | Map | 它可以获取请求头的信息 | | headerValues | Map | 它可以获取请求头的信息,它可以获取多个值的情况 | - 输出请求头【User-Agent】的值:**${** header[**'User-Agent'**] **}** - 输出请求头【Connection】的值:**${** header.Connection **}** - 输出请求头【User-Agent】的值:**${** headerValues\[**'User-Agent'**][0] } | 隐含对象 | 返回值 | 说明 | | :------: | :----------------: | :------------------------------: | | cookie | Map | 它可以获取当前请求的 Cookie 信息 | - 获取 Cookie 的名称:**${** cookie.JSESSIONID.name **}** - 获取 Cookie 的值:**${** cookie.JSESSIONID.value **}** | 隐含对象 | 返回值 | 说明 | | :-------: | :----------------: | :----------------------------------------------------: | | initParam | Map | 它可以获取在 web.xml 中配置的上下文参数 | ```xml username root url jdbc:mysql:///test ``` - 输出**<**Context-param**>**username 的值:**${** initParam.username **}** - 输出**<**Context-param**>**url 的值:**${** initParam.url **}** ## JSTL标签库 ### 1、JSTL标签库简介 JSTL 标签库 全称是指 JSP Standard Tag Library JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标签库。 EL 表达式主要是为了替换 jsp 中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个 jsp 页面变得更佳简洁。 JSTL 由五个不同功能的标签库组成。 | 功能范围 | URI | 前缀 | | -------------------- | -------------------------------------- | ----- | | **核心标签库--重点** | **http://java.sun.com/jsp/jstl/core** | **c** | | 格式化 | http://java.sun.com/jsp/jstl/fmt | fmt | | 函数 | http://java.sun.com/jsp/jstl/functions | fn | | 数据库(不使用) | http://java.sun.com/jsp/jstl/sql | sql | | XML(不使用) | http://java.sun.com/jsp/jstl/xml | x | 在 jsp 标签库中使用 taglib 指令引入标签库 ```html CORE 标签库 <%@ taglib prefix="c"uri="http://java.sun.com/jsp/jstl/core" %> XML 标签库 <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> FMT 标签库 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> SQL 标签库 <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> FUNCTIONS 标签库 <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> ``` ### 2、JSTL标签库的使用步骤 1. 先导入 jstl 标签库的 jar 包。 taglibs-standard-impl-1.2.1.jar taglibs-standard-spec-1.2.1.jar 2. 第二步,使用 taglib 指令引入标签库。 <%@ **taglib** **prefix**="**c**" **uri**="**http://java.sun.com/jsp/jstl/core**" %> ### 3、core核心库使用 #### **** 作用:set 标签可以往域中保存数据 ```jsp <%-- i. 作用:set 标签可以往域中保存数据 域对象.setAttribute(key,value); scope 属性设置保存到哪个域 page 表示 PageContext 域(默认值) request 表示 Request 域 session 表示 Session 域 application 表示 ServletContext 域 var 属性设置 key 是多少 value 属性设置值 --%> 保存之前:${ sessionScope.abc }
保存之后:${ sessionScope.abc }
``` #### **** if 标签用来做 if 判断。 ```jsp <%-- ii. if 标签用来做 if 判断。 test 属性表示判断的条件(使用 EL 表达式输出) --%>

12 等于 12

12 不等于 12

``` #### **\ \ \标签** 多路判断。跟 switch ... case .... default 非常接近 ```jsp <%-- iii. 标签 作用:多路判断。跟 switch ... case .... default 非常接近 choose 标签开始选择判断 when 标签表示每一种判断情况 test 属性表示当前这种判断情况的值 otherwise 标签表示剩下的情况 标签使用时需要注意的点: 1、标签里不能使用 html 注释,要使用 jsp 注释 2、when 标签的父标签一定要是 choose 标签 --%> <% request.setAttribute("height", 180); %> <%-- 这是 html 注释 --%>

小巨人

很高

还可以

大于 160

大于 150

大于 140

其他小于 140
``` #### **** 作用:遍历输出使用。 **1. 遍历 1 到 10,输出** ```jsp <%-- 1.遍历 1 到 10,输出 begin 属性设置开始的索引 end 属性设置结束的索引 var 属性表示循环的变量(也是当前正在遍历到的数据) for (int i = 1; i < 10; i++) --%>
第${i}行
``` **2. 遍历Object数组** ```jsp <%-- 2.遍历 Object 数组 for (Object item: arr) items 表示遍历的数据源(遍历的集合) var 表示当前遍历到的数据 --%> <% request.setAttribute("arr", new String[]{"18610541354","18688886666","18699998888"}); %> ${ item }
``` **3.遍历Map集合** ```jsp <% Map map = new HashMap(); map.put("key1", "value1"); map.put("key2", "value2"); map.put("key3", "value3"); request.setAttribute("map", map); %>

${entry.key} = ${entry.value}

``` **4. 遍历 List 集合--List中存放 Student 类,有属性:编号,用户名,密码,年龄,电话信息** ```jsp <%--4.遍历 List 集合---list 中存放 Student 类,有属性:编号,用户名,密码,年龄,电话信息--%> <% List studentList = new ArrayList(); for (int i = 1; i <= 10; i++) { studentList.add(new Student(i,"username"+i ,"pass"+i,18+i,"phone"+i)); } request.setAttribute("stus", studentList); %> <%-- items 表示遍历的集合 var 表示遍历到的数据 begin 表示遍历的开始索引值 end 表示结束的索引值 step 属性表示遍历的步长值 varStatus 属性表示当前遍历到的数据的状态 for(int i = 1; i < 10; i+=2) --%>
编号 用户名 密码 年龄 电话 操作
${stu.id} ${stu.username} ${stu.password} ${stu.age} ${stu.phone} ${status.step}
``` ## MVC MVC 全称:Model 模型、 View 视图、 Controller 控制器。 MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 Web 层的代码如何有效分离,单独工作。 **View 视图**:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作—— JSP/HTML。 **Controller 控制器**:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个“调度者”的角色——Servlet。 转到某个页面。或者是重定向到某个页面。 **Model 模型**:将与业务逻辑相关的数据封装为具体的 JavaBean 类,其中不掺杂任何与数据处理相关的代码—— JavaBean/domain/entity/pojo。 **MVC** **是一种思想** MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(**目的还是为了降低耦合度**)。 ![MVC](img/mvc.png) **MVC** **的作用还是为了降低耦合。让代码合理分层。方便后期升级和维护。** ## 分页实现 ### 1、分页模块的分析 ![分页分析](img/fy1.png) ### 2、分页模型Page的抽取 当前页数,总页数,总记录数, 当前页数据,每页记录数 ```java /*** Page 是分页的模型对象 * @param 是具体的模块的 javaBean 类 */ public class Page { public static final Integer PAGE_SIZE = 4; // 当前页码 private Integer pageNo; // 总页码 private Integer pageTotal; // 当前页显示数量 private Integer pageSize = PAGE_SIZE; // 总记录数 private Integer pageTotalCount; // 当前页数据 private List items; } ``` ## Filter过滤器 ### 1、Filter过滤器简介 1. Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器 2. Filter 过滤器它是 JavaEE 的规范。也就是接口 3. Filter 过滤器它的作用是:**拦截请求**,过滤响应。 拦截请求常见的应用场景有: 1. 权限检查 2. 日记操作 3. 事务管理 ​ ……等等 ### 2、Filter工作流程 **要求**:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必须是**用户登录之后才允许访问**。 **思考**:用户登录之后都会把用户登录的信息保存到 Session 域中。所以要**检查用户是否登录**,可以**判断 Session 中否包含有用户登录的信息即可**! ```jsp <% Object user = session.getAttribute("user"); // 如果等于 null,说明还没有登录 if (user == null) { request.getRequestDispatcher("/login.jsp").forward(request,response); return; } %> ``` Filter的工作流程图: ![Filter](img/filter.png) ```java public class AdminFilter implements Filter { /*** doFilter 方法,专门用于拦截请求。可以做权限检查 */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; HttpSession session = httpServletRequest.getSession(); Object user = session.getAttribute("user"); // 如果等于 null,说明还没有登录 if (user == null) { servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse); return; } else { // 让程序继续往下访问用户的目标资源 filterChain.doFilter(servletRequest,servletResponse); } } } ``` web.xml中的配置: ```xml AdminFilter com.atguigu.filter.AdminFilter AdminFilter /admin/* ``` Filter 过滤器的使用步骤: 1. 编写一个类去实现 Filter 接口 2. 实现过滤方法 doFilter() 3. 到 web.xml 中去配置 Filter 的拦截路径 ### 3、Filter的生命周期 Filter 的生命周期包含几个方法 1. 构造器方法 2. init 初始化方法 第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建) 3. doFilter 过滤方法 第 3 步,每次拦截到请求,就会执行 4. destroy 销毁 第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器) ### 4、FilterConfig类 FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。 Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。 FilterConfig 类的作用是获取 filter 过滤器的配置内容 1. 获取 Filter 的名称 filter-name 的内容 2. 获取在 Filter 中配置的 init-param 初始化参数 3. 获取 ServletContext 对象 ### 5、FilterChain过滤器链 Filter 过滤器 Chain 链,链条 FilterChain 就是过滤器链(多个过滤器如何一起工作) ![FilterChain](img/filter2.png) **在多个Filter过滤器执行的时候,它们执行的优先顺序是由他们在web.xml中从上到下配置的顺序决定** ### 6、Filter的拦截路径 **精准匹配** <**url-pattern**>/target.jsp 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp **目录匹配** <**url-pattern**>/admin/* 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/* **后缀名匹配** - <**url-pattern**>*.html 以上配置的路径,表示请求地址必须以.html 结尾才会拦截到 - <**url-pattern**>*.do 以上配置的路径,表示请求地址必须以.do 结尾才会拦截到 - <**url-pattern**>*.action 以上配置的路径,表示请求地址必须以.action 结尾才会拦截到 > **Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在** # 2.28(Cookie&Session&验证码问题&JSON&AJAX) ## Cookie ### 1、Cookie简介 1. Cookie 翻译过来是饼干的意思。 2. Cookie 是服务器通知客户端保存键值对的一种技术。 3. 客户端有了 Cookie 后,每次请求都发送给服务器。 4. 每个 Cookie 的大小不能超过 4kb ### 2、创建Cookie ![cookie创建](img/c.png) Servlet 程序中的代码 ```java protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1 创建 Cookie 对象 Cookie cookie = new Cookie("key4", "value4"); //2 通知客户端保存 Cookie resp.addCookie(cookie); //1 创建 Cookie 对象 Cookie cookie1 = new Cookie("key5", "value5"); //2 通知客户端保存 Cookie resp.addCookie(cookie1); resp.getWriter().write("Cookie 创建成功"); } ``` ### 3、服务器获取Cookie 服务器获取客户端的 Cookie 只需要一行代码:req.getCookies():Cookie[] ![服务器获取Cookie](img/c1.png) ### 4、Cookie值的修改 方案一: 1. 先创建一个要修改的同名(指的就是 key)的 Cookie 对象 2. 在构造器,同时赋于新的 Cookie 值。 3. 调用 response.addCookie( Cookie ); ```java Cookie cookie = new Cookie("key1","newValue1"); response.addCookie( Cookie ); ``` 方案二: 1. 先查找到需要修改的 Cookie 对象 2. 调用 setValue()方法赋于新的 Cookie 值。 3. 调用 response.addCookie()通知客户端保存修改 ```java // 1、先查找到需要修改的 Cookie 对象 Cookie cookie = CookieUtils.findCookie("key2", req.getCookies()); if (cookie != null) { // 2、调用 setValue()方法赋于新的 Cookie 值。 cookie.setValue("newValue2"); // 3、调用 response.addCookie()通知客户端保存修改 resp.addCookie(cookie); } ``` ### 5、Cookie生命控制 Cookie 的生命控制指的是如何管理 Cookie 什么时候被销毁(删除) setMaxAge() - 正数,表示在指定的秒数后过期 - 负数,表示浏览器一关,Cookie 就会被删除(默认值是-1) - 零,表示马上删除 Cookie ```java /** * 设置存活1小时的Cookie */ Cookie cookie = new Cookie("life3600", "life3600"); cookie.setMaxAge(60 * 60); // 设置 Cookie 一小时之后被删除。 resp.addCookie(cookie); resp.getWriter().write("已经创建了一个存活一小时的 Cookie") ``` ```java /** *马上删除一个Cookie */ // 先找到你要删除的 Cookie 对象 Cookie cookie = CookieUtils.findCookie("key4", req.getCookies()); if (cookie != null) { // 调用 setMaxAge(0); cookie.setMaxAge(0); // 表示马上删除,都不需要等待浏览器关闭 // 调用 response.addCookie(cookie); resp.addCookie(cookie); resp.getWriter().write("key4 的 Cookie 已经被删除"); } ``` ```java /** *默认的会话级别的Cookie */ Cookie cookie = new Cookie("defalutLife","defaultLife"); cookie.setMaxAge(-1);//设置存活时间 resp.addCookie(cookie); ``` ### 6、Cookie有效路径 Path 的设置 Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。 path 属性是通过请求的地址来进行有效的过滤。 **CookieA path=/工程路径** **CookieB path=/工程路径/abc** 请求地址如下: **http://ip:port/工程路径/a.html** CookieA 发送 CookieB 不发送 **http://ip:port/工程路径/abc/a.html** CookieA 发送 CookieB 发送 ### 7、Cookie练习——免用户名登录 ![](img/c2.png) **login.jsp页面** ```html
用户名:
密码:
``` **LoginServlet程序** ```java @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); if ("wzg168".equals(username) && "123456".equals(password)) { //登录 成功 Cookie cookie = new Cookie("username", username); cookie.setMaxAge(60 * 60 * 24 * 7);//当前 Cookie 一周内有效 resp.addCookie(cookie); System.out.println("登录 成功"); } else { // 登录 失败 System.out.println("登录 失败"); } } ``` ## Session会话 ### 1、Session简介 1. Session 就一个接口(HttpSession)。 2. Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术。 3. 每个客户端都有自己的一个 Session 会话。 4. Session 会话中,我们经常用来保存用户登录之后的信息。 ### 2、创建Session以及获取 如何创建和获取 Session。它们的 API 是一样的。 **request.getSession()** - 第一次调用是:创建 Session 会话 - 之后调用都是:获取前面创建好的 Session 会话对象。 **isNew() ** 判断到底是不是刚创建出来的(新的) - true 表示刚创建 - false 表示获取之前创建 > 每个会话都有一个身份证号。也就是 ID 值。而且这个 ID 是唯一的。 **getId() 得到 Session 的会话 id 值** ### 3、Session域数据的存取 | 方法 | 描述 | | ----------------------- | ----------------------------------------------------- | | setAttribute(key,value) | 往Session域中存放一个键值对 | | getAttribute(key) | 取出Session域中存放的key所对应的value值,无则返回null | ### 4、Session生命周期控制 | 方法 | 描述 | | ------------------------------------ | ------------------------------------------------------------ | | setMaxInactiveInterval(int interval) | 设置 Session 的超时时间(以秒为单位),超过指定的时长,Session 就会被销毁。**值为正数的时候,设定 Session 的超时时长。 负数表示永不超时(极少使用)** | | getMaxInactiveInterval() | 获取 Session 的超时时间 | | public void invalidate() | 让当前 Session 会话马上超时无效。 | **Session 默认的超时时间长为 30 分钟。** 设置默认的 Session 的超时时长为其他时长。可以web.xml 配置文件中做配置。就可以修改该 web 工程所有 Seession 的默认超时时长。 ```xml 20 ``` ### 5、Session与浏览器之间底层实现 ![Session与浏览器之间底层实现](img/s.png) ## 验证码 ### 1、为什么要有验证码 - 注册环节:防止无效垃圾注册 - 登录环节:防止撞库攻击、暴力破解、保障用户数据 - 互动环节:防止批量垃圾互动信息破坏用户UGC内容生态 **追根接地验证码是解决表单重复提交问题** ### 2、解决表单重复提交 表单重复提交有三种常见的情况: 一:提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。 造成表单重复提交问题。**解决方法:使用重定向来进行跳转** 二:用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败,就会着急,然后多点了几次提交操作,也会造成表单重复提交。 **解决方法:验证码** 三:用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复提交。**解决方法:验证码** ![验证码底层原理](img/yzm.png) ## JSON ### 1、JSON简介 **JSON** (JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式,而且很多语言都提供了对 json 的支持(包括 C, C++, C#, Java, JavaScript, Perl, Python等)。 这样就使得 JSON 成为理想的数据交换格式。 json 是一种轻量级的数据交换格式。 轻量级指的是跟 xml 做比较。 数据交换指的是客户端和服务器之间业务数据的传递格式。 ### 2、JSON在JavaScript中的使用 json 是由键值对组成,并且由花括号(大括号)包围。每个键由引号引起来,键和值之间使用冒号进行分隔,多组键值对之间进行逗号进行分隔。 ```js var jsonObj = { "key1": 12, "key2":"value2", .... } ``` **json的访问** json 本身是一个对象。 json 中的 key 我们可以理解为是对象中的一个属性。 json 中的 key 访问就跟访问对象的属性一样: json 对象.key **json的两个常用方法** json 的存在有两种形式。 - 对象的形式存在,我们叫它 json 对象。 - 字符串的形式存在,我们叫它 json 字符串。 一般我们要操作 json 中的数据的时候,需要 json 对象的格式。 一般我们要在客户端和服务器之间进行数据交换的时候,使用 json 字符串。 **JSON.stringify()** 把 json 对象转换成为 json 字符串 **JSON.parse()** 把 json 字符串转换成为 json 对象 ### 3、JSON在java中的使用 **JavaBean 和 json 的互转** ```java @Test public void test1(){ Person person = new Person(1,"哈哈哈!"); // 创建 Gson 对象实例 Gson gson = new Gson(); // toJson 方法可以把 java 对象转换成为 json 字符串 String personJsonString = gson.toJson(person); System.out.println(personJsonString); // fromJson 把 json 字符串转换回 Java 对象 // 第一个参数是 json 字符串 // 第二个参数是转换回去的 Java 对象类型 Person person1 = gson.fromJson(personJsonString,Person.class); System.out.println(person1); } ``` **List 和 json 的互转** ```java @Test public void test2() { List personList = new ArrayList<>(); personList.add(new Person(1, "哈哈哈")); personList.add(new Person(2, "康师傅")); Gson gson = new Gson(); // 把 List 转换为 json 字符串 String personListJsonString = gson.toJson(personList); System.out.println(personListJsonString); List list = gson.fromJson(personListJsonString, new PersonListType().getType()); System.out.println(list); Person person = list.get(0); System.out.println(person); } ``` **map 和 json 的互转** ```java @Test public void test3(){ Map personMap = new HashMap<>(); personMap.put(1, new Person(1, "好帅")); personMap.put(2, new Person(2, "康师傅也好帅")); Gson gson = new Gson(); // 把 map 集合转换成为 json 字符串 String personMapJsonString = gson.toJson(personMap); System.out.println(personMapJsonString); Map personMap2 = gson.fromJson(personMapJsonString, new TypeToken>(){}.getType()); System.out.println(personMap2); Person p = personMap2.get(1); System.out.println(p); } ``` ## AJAX ### 1、AJAX请求简介 AJAX 即**A**synchronous **J**avascript **A**nd **X**ML(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。 **ajax 是一种浏览器通过 js 异步发起请求,局部更新页面的技术。** **Ajax 请求的局部更新,浏览器地址栏不会发生变化** **局部更新不会舍弃原来页面的内容** ### 2、原生js中AJAX的运用 ```html Insert title here
``` ### 3、jQuery中的AJAX请求 **$.ajax **方法 | 参数 | 描述 | | -------- | ------------------------------------------------------------ | | url | 表示请求的地址 | | type | 表示请求的类型 GET 或 POST 请求 | | data | 表示发送给服务器的数据 格式有两种: 一:name=value&name=value 二:{key:value} | | success | 请求成功,响应的回调函数 | | dataType | 响应的数据类型**text** 表示纯文本,**xml** 表示 xml 数据,**json** 表示 json 对象 | ```js $("#ajaxBtn").click(function(){ $.ajax({ url:"http://localhost:8080/16_json_ajax_i18n/ajaxServlet", // data:"action=jQueryAjax", data:{action:"jQueryAjax"}, type:"GET", success:function (data) { // alert("服务器返回的数据是:" + data); // var jsonObj = JSON.parse(data); $("#msg").html("编号:" + data.id + " , 姓名:" + data.name); }, dataType : "json" }); }); ``` **$.get** 方法 和 **$.post** 方法 | 参数 | 描述 | | -------- | ------------------------------------------------------------ | | url | 表示请求的地址 | | data | 表示发送给服务器的数据 格式有两种: 一:name=value&name=value 二:{key:value} | | callback | 请求成功,响应的回调函数 | | type | 响应的数据类型**text** 表示纯文本,**xml** 表示 xml 数据,**json** 表示 json 对象 | **$.getJSON** 方法 | 参数 | 描述 | | -------- | ------------------------------------------------------------ | | url | 表示请求的地址 | | data | 表示发送给服务器的数据 格式有两种: 一:name=value&name=value 二:{key:value} | | callback | 请求成功,响应的回调函数 | 表单序列化 **serialize()** **serialize()可以把表单中所有表单项的内容都获取到,并以 name=value&name=value 的形式进行拼接。**