医院网站制作好吗,新乡网站优化公司,怎么通过域名访问网站,企业网站建设的技术指标和经济指标文章目录 一、Tomcat1. BS 与 CS 开发介绍1.1 BS 开发1.2 CS 开发 2. 浏览器访问 web 服务过程详解(面试题)2.1 回到前面的 JavaWeb 开发技术栈图2.2 浏览器访问 web 服务器文件的 UML时序图(过程) #xff01; 二、动态 WEB 开发核心-Servlet1. 为什么会出现 Servlet2. 什么是… 文章目录 一、Tomcat1. BS 与 CS 开发介绍1.1 BS 开发1.2 CS 开发 2. 浏览器访问 web 服务过程详解(面试题)2.1 回到前面的 JavaWeb 开发技术栈图2.2 浏览器访问 web 服务器文件的 UML时序图(过程) 二、动态 WEB 开发核心-Servlet1. 为什么会出现 Servlet2. 什么是 Servlet3. Servlet 在 JavaWeb 项目位置4. Servlet 基本使用4.1 Servlet开发方式说明4.2浏览器调用 Servlet 流程分析[重点]4.3 Servlet 生命周期 6. ServletConfig6.1 基本介绍6.2 ServletConfig 能干什么 7. ServletContext7.1 为什么需要 ServletContext7.2 应用实例-简单的网站访问次数计数器 8. HttpServletRequest8.1 HttpServletRequest介绍8.2 HttpServletRequest 常用方法8.3 应用实例8.4 注意事项和细节8.5 请求转发[重要]8.5.1 为什么需要请求转发8.5.2 请求转发声明8.5.3 实现请求转发原理图8.5.4 请求转发注意事项和细节 9. HttpServletResponse9.1 HttpServletResponse介绍9.2 HttpServletResponse 类图9.3 向客户端返回数据方法9.4 请求重定向[重要]9.4.1 请求重定向原理示意图9.4.2 请求重定向注意事项和细节 三、WEB开发通信协议-HTTP 协议1. HTTP请求包分析(GET)2. HTTP请求包分析(POST)3. GET 请求和 POST请求分别有哪些4. HTTP 请求中怎么选择 GET 和 POST 方式5. HTTP响应包分析6. 状态码6.1 状态码 3016.2 状态码 304 7. MIME 类型7.1 MIME 介绍7.2 常见的 MIME 类型 8. HTTP 作业 四、WEB 工程路径专题1. 解决方案 base 标签1.1 base 基本介绍1.2 应用实例1.3 WEB工程路径注意事项和细节 五、Web 开发会话技术 -CookieSession1. 会话1.1 基本介绍1.2 会话的两种技术 2. cookie 介绍3. Cookie 生命周期4 . Cookie 有效路径5. Cookie注意事项和细节6. Session 有什么用7. Session 基本原理7.1 Session 原理示意图7.2 Session 可以做什么7.3 如何理解 Session 8. session 常用方法9. session 底层实现机制 *9.1 原理分析图9.2 代码演示1.7.3 Session 实现原理动画 10. Session 生命周期10.1 session 生命周期-说明10.2 Session 生命周期-应用实例 11. Session 经典案例-防止非法进入管理页面11.1 作业布置11.2 作业代码 六、JavaWeb三大组件之监听器 Listener1. Listener 监听器介绍2. JavaWeb 的监听器2.1 ServletContextListener 监听器2.2 ServletContextAttributeListener 监听器2.3 其他监听器-使用较少2.3.1 HttpSessionListener 监听器2.3.2 HttpSessionAttributeListener 监听器2.3.3 **ServletRequestListener** **监听器**2.3.4 **ServletRequestAttributeListener** **监听器**2.3.5 HttpSessionBindingListener 感知监听器2.3.6 **HttpSessionActivationListener** **感知监听器** 七、JavaWeb 三大组件之 过滤器 Filter1. Filter 过滤器说明2. Filter 过滤器基本原理3. Filter 应用案例4. Filter 过滤器 url-pattern5. Filter 过滤器生命周期6. FilterConfig7. FilterChain 过滤器链 八、数据交换和异步请求 - JSON Ajax1. JSON 介绍2. JSON 规则3. JSON 在 java 中使用1. 说明2. JSON 在 java中 应用场景3. 应用实例 JSON 在 java中应用场景 九、Ajax 基本介绍1. Ajax 是什么2. Ajax 经典应用场景3. Ajax 原理示意图4. JavaScript 原生 Ajax 请求 十、线程数据共享和安全 ThreadLocal1. 什么是 ThreadLocal2. 快速人门 ThreadLocal3. ThreadLocal 源码解读画图 一、Tomcat
1. BS 与 CS 开发介绍
1.1 BS 开发
B: browser(浏览器, 种类太多 ff, chrome, ie, edge,)S: Server(服务端, 考虑很多)示意图 对 BS 的解读
(1) 兼容性 , 因为浏览器的种类很多发现你写的程序在某个浏览器会出现问题其它浏览器正常 (2) 安全性, 通常情况下BS 安全性不如 CS 好控制 (3) 易用性, BS 好于 CS, 浏览器电脑有 (4) 扩展性, BS 相对统一只需要写 Server 1.2 CS 开发
1. C: Client(客户端)
2. S: Server(服务端)
示意图 2. 浏览器访问 web 服务过程详解(面试题)
2.1 回到前面的 JavaWeb 开发技术栈图 2.2 浏览器访问 web 服务器文件的 UML时序图(过程) 二、动态 WEB 开发核心-Servlet
1. 为什么会出现 Servlet
引入我们动态网页(能和用户交互)技术 -- Servlet对 JavaWeb 技术体系的流程图改造说明(细化).[整体的概念] 2. 什么是 Servlet
什么是 Servlet
Servlet 在开发动态 WEB 工程中得到广泛的应用掌握好 Servlet 非常重要了, Servlet(基石)是 SpringMVC 的基础
Servlet(Java 服务端小程序)它的特点
他是由服务器端调用和执行的(一句话是Tomcat解析和执行)他是用java语言编写的, 本质就是Java类他是按照Servlet规范开发的(除了tomcat-Servlet weblogic-Servlet)功能强大可以完成几乎所有的网站功能(在以前我们老程员使用Servlet开发网站) 技术栈要求高
3. Servlet 在 JavaWeb 项目位置 4. Servlet 基本使用
4.1 Servlet开发方式说明
servlet3.0 前使用 web.xml , servlet3.0 版本以后(包括 3.0)支持注解 同时支持 web.xml配置如何看 servlet 版本 4.2浏览器调用 Servlet 流程分析[重点] 4.3 Servlet 生命周期
主要有三个方法
init() 初始化阶段service() 处理浏览器请求阶段destroy() 终止阶段
示意图(比较重要而且形象) 初始化阶段(init 方法)
Servlet 容器(比如Tomcat) 加载 Servlet加载完成后Servlet 容器会创建一个 Servlet 实例并调用 init()方法init()方法只调用一次。 Servlet 容器如果遇到上面的情况会重新装载 Servlet
Servlet 容器(Tomcat)启动时自动装载某些 servlet实现这个需要在 web.xml 文件中添加 1 1 表示装载的顺序在 Servlet 容器启动后浏览器首次向 Servlet 发送请求(这个前面说过)Servlet 重新装载时(比如 tomcat 进行 redeploy【redeploy 会销毁所有的 Servlet 实例】)浏览器再向 Servlet 发送请求时相当于第 1 次请求先实例化Servlet --》 再调用 init(…) 方法 --》 调用service(…)方法
处理浏览器请求阶段(service 方法)
每收到一个 http 请求服务器就会产生一个新的线程取处理[线程]创建一个用于封装 HTTP请求 消息的 ServletRequest 对象和一个代表 HTTP响应 消息的 ServletResponse 对象然后调用 Servlet 的 service() 方法并将请求和响应对象作为参数传递进去
终止阶段 destroy方法(体现 Servlet 完整的生命周期)
当 web 应用被终止或者 Servlet 容器终止运行或者 Servlet 类重新装载时会调用 destroy() 方法比如重启 Tomcat、或者 redeploye web (重新发布)应用。
上个图切记一定要自己练习一遍
工程路径D:\IDEA_code\xjz_javaweb\servlet 6. ServletConfig
6.1 基本介绍
ServletConfig 类是为 Servlet 程序的配置信息的类Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建Servlet 程序默认是第 1 次访问的时候创建ServletConfig 在 Servlet 程序创建时就创建一个对应的 ServletConfig 对象
6.2 ServletConfig 能干什么 获取 Servlet 程序的 servlet-name 的值 获取初始化参数 init-param 获取 ServletContext 对象
应用实例…
示意图(思路分析) 7. ServletContext
7.1 为什么需要 ServletContext 先看一个需求 如果我们希望统计某个 web 应用的所有 Servlet 被访问的次数怎么办 方案 1-DB 方案 2-ServletContext 由于一个 WEB 应用中的所有 Servlet 共享同一个 ServletContext 对象因此 Servlet 对象之间可以通过 ServletContext 对象来实现多个 Servlet 间通讯。ServletContext 对象通常也被称之为域对象。【示意图】 详情看 韩顺平JavaWeb-笔记
7.2 应用实例-简单的网站访问次数计数器
需求完成一个简单的网站访问次数计数器 使用 Chrome 访问 payServlet, 每访问一次就增加 1 访问次数在后台输出并将结果返回给浏览器显示使用火狐访问 OrderServlet每访问一次就增加 1 访问次数在后台输出并将结果返回给浏览器显示 代码如下D:\IDEA_code\xjz_javaweb\servlet\src\com\xjz\servlet\servletcontext
运行结果 8. HttpServletRequest
8.1 HttpServletRequest介绍
HttpServletRequest 对象代表客户端的请求当客户端/浏览器通过 HTTP 协议访问服务器时HTTP 请求头中的所有信息都封装在这个对象中通过这个对象的方法可以获得客户端这些信息。
我们是OOP程序员第一步看它的类图(继承关系和方法)
8.2 HttpServletRequest 常用方法 getRequestURI() 获取请求的资源路径 http://localhost:8080**/servlet/loginServlet** getRequestURL() 获 取 请 求 的 统 一 资 源 定 位 符 绝 对 路 径 http://localhost:8080/servlet/loginServlet getRemoteHost() 获取客户端的 主机, getRemoteAddr() getHeader() 获取请求头 getParameter() 获取请求的参数 getParameterValues() 获取请求的参数多个值的时候使用 , 比如 checkbox, 返回的数组 getMethod() 获取请求的方式 GET 或 POST setAttribute(key, value); 设置域数据 getAttribute(key); 获取域数据 getRequestDispatcher() 获取请求转发对象, 请求转发的核心对象
8.3 应用实例
package com.xjz.servlet.request;import com.sun.org.apache.regexp.internal.RE;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** author xjz_2002* version 1.0*/
public class HttpServletRequestMethods extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//这里我们使用 request 对象获取表单提交的各种数据System.out.println(HttpServletRequestMethods doPost() 被调用...);/************************************ 获取和 http 请求头相关信息***********************************/System.out.println(请求的资源路径 URI request.getRequestURI()); ///servlet/requestMethods//http://主机/uriSystem.out.println(请求的统一资源定位符(决定路径) URL request.getRequestURL());// http://localhost:8080/servlet/requestMethodsSystem.out.println(请求的客户端 ip地址 request.getRemoteAddr());//本地就是 127.0.0.1//思考题如发现某个 ip 在 10s 中访问的次数超过 100 次就封 ip//实现思路1 用一个集合 concurrentHashmap[ip:访问次数] 2[线程/定时扫描]3 做成处理System.out.println(http 请求头 HOST request.getHeader(Host)); //HOSTlocalhost:8080//说明如果我们希望得到请求头的相关信息可以使用request.getHeader(请求头字段)System.out.println(该请求的发起地址是 request.getHeader(Referer));////请获取访问网站的浏览器是什么String userAgent request.getHeader(User-agent);System.out.println(userAgent userAgent);String[] s userAgent.split( );System.out.println(浏览器 s[s.length - 1].split(\\/)[0]);// 主要是 Get / PostSystem.out.println(http 请求方式 request.getMethod());/************************************ 获取和请求参数相关信息, 注意要求在返回数据前获取参数***********************************///1. 获取表单的数据[单个数据]//usernametompwd123hobbylylhobbylzqString username request.getParameter(username);String pwd request.getParameter(pwd);//2. 获取表单的一组数据String[] hobbies request.getParameterValues(hobby);System.out.println(username username);System.out.println(pwd pwd);//增强 for 循环的快捷键 iter-回车即可 , 能使用快捷键就使用快捷键for (String hobby : hobbies) {System.out.println(hobby hobby);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//合并doPost(request, response);}
}8.4 注意事项和细节 获 取 doPost 参 数 中 文 乱 码 解 决 方 案 , 注 意 setCharacterEncoding(“utf-8”) 要 写 在request.getParameter()前 注意如果通过 PrintWriter writer, 有返回数据给浏览器建议将获取参数代码写在writer.print() 之前否则可能获取不到参数值(doPost) 处理 http 响应数据中文乱码问题 再次理解 Http 协议响应 Content-Type 的含义, 比如 text/plain application/x-tar** 8.5 请求转发[重要]
8.5.1 为什么需要请求转发
目前我们学习的都是一次请求对应一个 Servlet如图 但是在实际开发中往往业务比较复杂需要在一次请求中使用到多个 Servlet 完成一个任务(Servlet 链, 流水作业) 如图: 8.5.2 请求转发声明
实现请求转发请求转发指一个 web 资源收到客户端请求后通知服务器去调用另外一个 web 资源进行处理HttpServletRequest 对象(也叫 Request 对象)提供了一个 getRequestDispatcher 方法该方法返回一个 RequestDispatcher 对象调用这个对象的 forward 方法可以实现请求转发request 对象同时也是一个域对象开发人员通过 request 对象在实现转发时把数据通过 request 对象带给其它 web 资源处理
setAttribute方法getAttribute方法removeAttribute方法getAttributeNames方法
8.5.3 实现请求转发原理图
请求转发原理示意图 8.5.4 请求转发注意事项和细节
浏览器地址不会变化(地址会保留在第 1 个 servlet 的 url)在同一次 HTTP 请求中进行多次转发仍然是一次 HTTP 请求在同一次 HTTP 请求中进行多次转发多个 Servlet 可以共享 request 域/对象的数据(因为始终是同一个 request 对象)可以转发到 WEB-INF 目录下(后面做项目使用)不能访问当前 WEB 工程外的资源因为浏览器地址栏会停止在第一个 servlet ,如果你刷新页面会再次发出请求(并且会带数据), 所以在支付页面情况下不要使用请求转发否则会造成重复支付[演示]
9. HttpServletResponse
9.1 HttpServletResponse介绍 每次 HTTP 请求Tomcat 会创建一个 HttpServletResponse 对象传递给 Servlet 程序去使用。 HttpServletRequest 表示请求过来的信息HttpServletResponse 表示所有响应的信息如果需要设置返回给客户端的信息通过 HttpServletResponse 对象来进行设置即可 9.2 HttpServletResponse 类图 9.3 向客户端返回数据方法 字节流 getOutputStream(); 常用于下载处理二进制数据字符流 getWriter(); 常用于回传字符串(细节)两个流同时只能使用一个。 使用了字节流就不能再使用字符流反之亦然否则就会报错
9.4 请求重定向[重要]
9.4.1 请求重定向原理示意图 请求重定向指一个 web 资源收到客户端请求后通知客户端去访问另外一个 web资源这称之为请求重定向 请求重定向原理示意图 相关代码路径D:\IDEA_code\xjz_javaweb\servlet\src\com\xjz\servlet\response\DownServlet.java
D:\IDEA_code\xjz_javaweb\servlet\src\com\xjz\servlet\response\DownServletNew.java
9.4.2 请求重定向注意事项和细节
最佳应用场景网站迁移比如原域名是 www.baidu.com 迁移到 www.baidu.cn 但是百度抓取的还是原来网址.浏览器地址会发生变化本质是两次 http 请求.不能共享 Request 域中的数据本质是两次 http 请求会生成两个 HttpServletRequest对象不能重定向到 /WEB-INF 下的资源可以重定向到 Web 工程以外的资源 比如 到 www.baidu.com 【在前面的案例演示】重定向有两种方式, 推荐使用第 1 种.
response.sendRedirect(/servlet/downServletNew);//第二种重定向的写法
response.setStatus(302);//设置 http响应的状态码
//设置http响应的 Location /servlet/downServletNew
response.setHeader(Location,/servlet/downServletNew);动态获取到 application context
//5. 动态获取到 application context
String contextPath getServletContext().getContextPath();
System.out.println(contextPath contextPath);//servlet
//response.sendRedirect(/servlet/downServletNew);
response.sendRedirect(contextPath /downServletNew);三、WEB开发通信协议-HTTP 协议
1. HTTP请求包分析(GET) 2. HTTP请求包分析(POST) 3. GET 请求和 POST请求分别有哪些 4. HTTP 请求中怎么选择 GET 和 POST 方式 5. HTTP响应包分析 HTTP响应包括3个部分 响应行响应头响应体 HTTP响应包分析图 6. 状态码
6.1 状态码 301 6.2 状态码 304 7. MIME 类型
7.1 MIME 介绍 7.2 常见的 MIME 类型 8. HTTP 作业 四、WEB 工程路径专题
先看一个问题 怎么解决访问资源的问题 工程路径解决方案
说明: 使用相对路径来解决 一个非常重要的规则页面所有的相对路径在默认情况下都会参考当前浏览器地址栏的路径 http://ip:port/工程名/ 资源来进行跳转。所以我们可以直接这样写 相对路径带来的问题举例 示意图 如果需要指定页面相对路径参考的的路径可以使用 base 标签来指定
1. 解决方案 base 标签
1.1 base 基本介绍
base 标签是 HTML 语言中的基准网址标记它是一个单标签位于网页头部文件的 head标签内一个页面最多只能使用一个 base 元素用来提供一个指定的默认目标是一种表达路径和连接网址的标记。常见的 url 路径形式分别有相对路径与绝对路径如果 base 标签指定了目标浏览器将通过这个目标来解析当前文档中的所有相对路径包括的标签有a、img、link、form也就是说浏览器解析时会在路径前加上 base 给的目标而页面中的相对路径也都转换成了绝对路径。使用了 base 标签就应带上 href 属性和 target 属性
1.2 应用实例
D:\IDEA_code\xjz_javaweb\webpath\src\com\xjz\servlet
1.3 WEB工程路径注意事项和细节
Web 工程的相对路径和绝对路径 在实际开发中路径都使用绝对路径而不是相对路径在 web 中 / 斜杠 如果被浏览器解析得到的地址是http://ip[域名]:port/ 比如: ahref“/”斜杠在 web 中 / 斜杠 如果被服务器解析得到的地址是http://ip[域名]:port/工程路径/你也可以理解成 /工程路径/ 下面的几种情况就是如此: 在 javaWeb 中 路径最后带 / 和 不带 / 含义不同, 一定要小心, 比如 网址 : servlet03 表示资源
网址 : servlet03 表示路径
特别说明重定向 response.sendRediect(“/”); 这条语句虽然是在服务器执行的但是,服务器是把斜杠 / 发送给浏览器解析。因此得到地址 http://ip[域名]:port/
小结 在编写资源路径时: , 考虑这么几点 (1) 这个路径 前面有没有 / (2) 这个路径 在哪里被解析 [服务器还是浏览器] , 如果前面有 / , 并且是在 浏览器被解析的 被解析成 http://ip:port/ , 如果在服务器端被解析 , 被解析成 /工程路径/ (3) 如果这个路径前面没有 / , 并且在浏览器被解析则以浏览器当前的地址栏 去掉资源部分作为一个相对路径.
(4) 这个路径最后有没有 / , 如果最后有/ 表示路径 如果没有 / 表示资源
五、Web 开发会话技术 -CookieSession
1. 会话
1.1 基本介绍 会话可简单理解为用户开一个浏览器点击多个超链接访问服务器多个 web 资源然后关闭浏览器整个过程称之为一个会话。 会话过程中要解决的一些问题
每个用户在使用浏览器与服务器进行会话的过程中不可避免各自会产生一些数据服务器要想办法为每个用户保存这些数据例如多个用户点击超链接通过一个 servlet 各自购买了一个商品服务器应该想办法把每一个用户购买的商品保存在各自的地方以便于这些用户点结帐 servlet 时结帐servlet 可以得到用户各自购买的商品为用户结帐。
1.2 会话的两种技术
Cookie(小甜饼)是客户端技术服务器把每个用户的数据以 cookie 的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的 web 资源时就会带着各自的数据去。这样web 资源处理的就是用户各自的数据了。【简单示意图】 2. cookie 介绍
Cookie 是服务器在客户端保存用户的信息比如登录名浏览历史等, 就可以以 cookie方式保存.Cookie 信息就像是小甜饼(cookie 中文)一样数据量并不大服务器端在需要的时候可以从客户端/浏览器读取(http 协议)可以通过图来理解 演示 Cookie 底层实现机制**,** 创建和读取 Cookie
D:\IDEA_code\xjz_javaweb\cookie-session\src\com\xjz\cookie\CreateCookie.java 3. Cookie 生命周期 Cookie 的生命周期指的是如何管理 Cookie 什么时候被销毁删除 setMaxAge()
● 正数表示在指定的秒数后过期 ● 负数表示浏览器关闭Cookie 就会被删除默认值是-1 ● 0表示马上删除 Cookie
4 . Cookie 有效路径 Cookie 有效路径 Path 的设置 Cookie 的 path 属性可以有效的过滤哪些 Cookie 可以发送给服务器。哪些不发。 path属性是通过请求的地址来进行有效的过滤 规则如下
5. Cookie注意事项和细节
一个 Cookie 只能标识一种信息它至少含有一个标识该信息的名称NAME和设置值VALUE。一个 WEB 站点可以给一个浏览器发送多个 Cookie一个浏览器也可以存储多个 WEB 站点提供的 Cookie。cookie 的总数量没有限制但是每个域名的 COOKIE 数量和每个 COOKIE 的大小是有限制的 (不同的浏览器限制不同, 知道即可) , Cookie 不适合存放数据量大的信息。注意删除 cookie 时path 必须一致否则不会删除Java servlet 中 cookie 中文乱码解决 [代码演示 EncoderCookie.java ReadCookie2.java]
说明如果存放中文的 cookie, 默认报错, 可以通过 URL 编码和解码来解决, 不建议存放中文的 cookie 信息
package com.xjz.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;/*** author xjz_2002* version 1.0*/
public class EncoderCookie extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(EncoderCookie 被调用...);//1. 创建 Cookie有中文//代码解读//1) 如果直接存放中文的 cookie报错 Control character in cookie value or attribute.//2) 解决办法就是将中文 编码成 URL编码 英文: Encode编码//3) 编码后再保存即可String name URLEncoder.encode(程序员老徐, utf-8);Cookie cookie new Cookie(name, name);//2. 保存到浏览器response.addCookie(cookie);//3. 给浏览器返回信息response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.print(h1设置中文cookie成功~/h1);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}解码
package com.xjz.cookie;import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;/*** author xjz_2002* version 1.0*/
public class ServletReadCookie2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();Cookie[] cookies request.getCookies();//找到带有中文的 cookieCookie name CookieUtils.readCookieByName(name, cookies);//处理的中文乱码问题writer.println(Cookie[ name.getName() URLDecoder.decode(name.getValue(), utf-8) ] br/);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}6. Session 有什么用
不同的用户登录网站后不管该用户浏览该网站的哪个页面都可显示登录人的名字还可以随时去查看自己的购物车中的商品, 是如何实现的?也就是说一个用户在浏览网站不同页面时服务器是如何知道是张三在浏览这个页面还是李四在浏览这个页面? ● 解决之道—session 技术, 简单说
Session 是服务器端技术服务器在运行时为每一个用户的浏览器创建一个其独享的session 对象/集合由于 session 为各个用户浏览器独享所以用户在访问服务器的不同页面时可以从各自的 session 中读取/添加数据, 从而完成相应任务
7. Session 基本原理
7.1 Session 原理示意图 当用户打开浏览器访问某个网站, 操作 session 时服务器就会在内存(在服务端)为该浏览器分配一个 session 对象该 session 对象被这个浏览器独占, 如图这个 session 对象也可看做是一个容器/集合,session 对象默认存在时间为 30min(这是在tomcat/conf/web.xml)也可修改 7.2 Session 可以做什么
网上商城中的购物车保存登录用户的信息将数据放入到 Session 中供用户在访问不同页面时实现跨页面访问数据防止用户非法登录到某个页面
7.3 如何理解 Session
session 存储结构示意图 你可以把 session 看作是一容器类似 HashMap有两列(K-V)每一行就是 session 的一个属性。每个属性包含有两个部分一个是该属性的名字(String)另外一个是它的值(Object)
8. session 常用方法 创建和获取 SessionAPI 一样HttpSession hsrequest.getSession();第 1 次调用是创建 Session 会话 之后调用是获取创建好的 Session 对象 向 session 添加属性 hs.setAttribute(String name,Object val); 从 session 得到某个属性 Object objhs.getAttribute(String name); 从 session 删除调某个属性:
hs.removeAttribute(String name); isNew(); 判断是不是刚创建出来的 Session 每个 Session 都有 1 个唯一标识 Id 值。通过 getId() 得到 Session 的会话 id 值
9. session 底层实现机制 *
9.1 原理分析图
session 底层实现机制图解(重要) 9.2 代码演示
创建Session
package com.xjz.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;/*** author xjz_2002* version 1.0*/
public class CreateSession extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// System.out.println(CreateSession 被调用..);//1. 获取session同时也可以创建sessionHttpSession session request.getSession();//2. 给session 获取idSystem.out.println(当前sessionId session.getId());//3. 给session 存放数据session.setAttribute(key1, value1);//4. 给浏览器发送一个回复response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.println(h1创建/操作 session成功~);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}运行结果 第二次刷新后 读session
package com.xjz.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;/*** author xjz_2002* version 1.0*/
public class ReadSession extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// System.out.println(ReadSession 被调用..);//演示读取 session//1. 获取session如果没有session也会创建HttpSession session request.getSession();//2. 读取属性Object key1 session.getAttribute(key1);if (key1 ! null){System.out.println(session属性 key1 (String) key1);} else {System.out.println(session中没有 key1属性 );}//给浏览器回复一下response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.println(h1读取session成功~/h1);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}我们可以看出两个servlet的JSEESIONID是同一JSESSIONID 有了代码支撑我们在回头看 Session 的原理图就有更深刻的理解
1.7.3 Session 实现原理动画
服务器是如何实现一个 session 为一个用户浏览器服务的 10. Session 生命周期
10.1 session 生命周期-说明
public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间以秒为单位超过指定的时长Session 就会被销毁。值为正数的时候设定 Session 的超时时长。负数表示永不超时public int getMaxInactiveInterval()获取 Session 的超时时间public void invalidate() 让当前 Session 会话立即无效如果没有调用 setMaxInactiveInterval() 来指定 Session 的生命时长Tomcat 会以 Session默认时长为准Session 默认的超时为 30 分钟 可以在 tomcat 的 web.xml 设置 Session 的生命周期指的是 客户端/浏览器两次请求最大间隔时长而不是累积时长。即当客户端访问了自己的 sessionsession 的生命周期将从 0 开始重新计算。(代码解读: 指的是同一个会话两次请求之间的间隔时间)底层: Tomcat 用一个线程来轮询会话状态如果某个会话的空闲时间超过设定的最大值则将该会话销毁
10.2 Session 生命周期-应用实例
需求代码演示说明 Session 的生命周期
创建
package com.xjz.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;/*** author xjz_2002* version 1.0*/
public class CreateSession2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(CreateSession2 被调用..);//1. 创建 sessionHttpSession session request.getSession();System.out.println(CreateSession2 sid session.getId());//2. 设置生命周期为 60ssession.setMaxInactiveInterval(60);session.setAttribute(u,jack);//3. 回复一下浏览器response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.println(h1创建session成功设置生命周期 60s/h1);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}读 Session
package com.xjz.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;/*** author xjz_2002* version 1.0*/
public class ReadSession2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(ReadSession2 被调用..);//1.获取到sessionHttpSession session request.getSession();System.out.println(ReadSession2 sid session.getId());//2. 读取session的属性Object u session.getAttribute(u);if (u ! null){System.out.println(获取到session属性 u (String) u);} else {System.out.println(读取不到session属性 u 说明原来的session被销毁);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}删除session 使用 invalidate() 方法
package com.xjz.session;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;/*** author xjz_2002* version 1.0*/
public class DeleteSession extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(DeleteSession 被调用..);//1. 演示如何删除sessionHttpSession session request.getSession();session.invalidate();//2. 如果我们要删除的是 session的某个属性//session.removeAttribute(xxx);//3. 回复一下浏览器response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.println(h1删除session成功/h1);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}总结Session 的生命周期
指的是两次访问 session 的最大间隔时间如果你在 session 没有过期的情况下(默认30分钟)操作 session, 则会重新开始计算生命周期session 是否过期是由服务器来维护和管理如我们调用了 invaliate() 会直接将该 session 删除/销毁如果希望删除 session 对象的某个属性, 使用 removeAttribute(“xx”)
11. Session 经典案例-防止非法进入管理页面
11.1 作业布置
需求说明完成防止用户登录管理页面应用案例(如图) 说明:
只要密码为 666666, 我们认为就是登录成功用户名不限制如果验证成功则进入管理页面 ManageServelt.java ,否则进入 error.html如果用户直接访问 ManageServet.java , 重定向到到 login.html
11.2 作业代码
D:\IDEA_code\xjz_javaweb\cookie-session\src\com\xjz\session\homework
login.html
!DOCTYPE html
html langen
headmeta charsetUTF-8title登录页面/title
/head
body
h1用户登录/h1
form action/cs/loginCheckServlet methodpost用户名input typetext nameusernamebr/密 码input typepassword namepwdbr/input typesubmit value登录/
/form
/body
/html
error.html
!DOCTYPE html
html langen
headmeta charsetUTF-8title登录失败/titlebase href/cs/
/head
body
h1登录失败/h1
a hreflogin.html点击返回重新登录/a
!-- 如果没有bese标签可以用如下返回带/ 为绝对路径我们一般使用绝对路径不带 / 为相对路径不安全 --
!--a href/login.html点击返回重新登录/a--
/body
/htmlLoginCheckServlet.java
package com.xjz.session.homework;import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;/*** author xjz_2002* version 1.0*/
public class LoginCheckServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//System.out.println(LoginCheckServlet 被调用..);//1. 获取提交表单的用户名和密码String username request.getParameter(username);String pwd request.getParameter(pwd);// //2. 将用户名 存放到 cookie中并响应给浏览器 Cookie方法
// Cookie cookie new Cookie(username,username);
// response.addCookie(cookie);//3. 只要密码为 66666我们认为就是登录成功用户名不限制if (pwd ! null pwd.length() ! 0) {if (666666.equals(pwd)) {//2. 将用户名 存放到 session 中并响应给浏览器 Session方法 (生命周期默认30min)//把用户名保存到 sessionHttpSession session request.getSession();session.setAttribute(loginuser,username);//超时1s 即销毁否则在超时时间内直接访问manageServlet2 可直接查看 管理员session.setMaxInactiveInterval(1);System.out.println(验证成功~);//请求转发//注意请求转发 是在服务端请求的默认路径是 http://localhost:8080/工程路径// 所以不需要带 /工程路径 如果带了访问地址为http://localhost:8080/cs/cs/login.html// 请求转发 不能访问 web以外的资源如果是访问 servlet则需要使用重定向
// request.getRequestDispatcher(/manageServlet.html).forward(request, response);// session 方法request.getRequestDispatcher(/manageServlet2).forward(request, response);} else {//验证失败密码不是666666请求转发到 error.htmlSystem.out.println(验证失败);request.getRequestDispatcher(/error.html).forward(request, response);}} else {// 回复给浏览器response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.println(h1密码不能为 null请重新输入/h1);writer.flush();writer.close();}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}**ManageServlet.java **
使用 Cookie方法用户直接访问 ManageServlet.java , 重定向到到 login.html
package com.xjz.session.homework;import com.xjz.cookie.CookieUtils;import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;/*** author xjz_2002* version 1.0* 使用 Cookie方法用户直接访问 ManageServlet.java , 重定向到到 login.html*/
public class ManageServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// System.out.println(ManageServlet 被调用..);//获取referer即从哪个网址请求过来的 urlString referer request.getHeader(Referer);System.out.println(referer referer);//判断打过来的请求 url是否是 login.html如果不是重定向到loginif (http://localhost:8080/cs/login.html.equals(referer)) {//获取提交表单的 usernameCookie[] cookies request.getCookies();//读取key为 username 的 cookieCookie usernameCookie CookieUtils.readCookieByName(username, cookies);//获取该 cookie 的 value值String usernameVal usernameCookie.getValue();System.out.println(usernameCookie usernameVal);//xjz_2002// 给浏览器返回消息response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.println(h1恭喜你管理员 usernameVal /h1);writer.flush();writer.close();} else {//如果用户直接访问 /manageServlet重定向到 login.html//注意请求重定向是 response响应到服务器的 所以路径前必须加 /工程路径//String contextPath request.getContextPath();// 工程路径 /csresponse.sendRedirect(request.getContextPath() /login.html);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}ManageServlet2.java
将用户名 存放到 cookie中并响应给浏览器 Session方法 (生命周期默认30min)
package com.xjz.session.homework;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;/*** author xjz_2002* version 1.0* 将用户名 存放到 session中并响应给浏览器 Session方法 (生命周期默认30min)*/
public class ManageServlet2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//判断该用户是否登录过HttpSession session request.getSession();Object userlogin session.getAttribute(loginuser);System.out.println(userlogin userlogin);if (userlogin null) { //说明该用户没有登录//重新登录 - 请求重定向
// response.sendRedirect(/cs/login.html);response.sendRedirect(request.getContextPath() /login.html);return;}response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.println(h1恭喜你管理员 userlogin.toString() /h1);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
六、JavaWeb三大组件之监听器 Listener
1. Listener 监听器介绍 Listener 监听器它是 JavaWeb 的三大组件之一。JavaWeb 的三大组件分别是Servlet 程序、Listener 监听器、Filter 过滤器 Listener 是 JavaEE 的规范就是接口 监听器的作用是监听某种变化(一般就是对象创建/销毁, 属性变化), 触发对应方法完成相应的任务 JavaWeb 中的监听器共八个, 目前最常用的是ServletContextListener
2. JavaWeb 的监听器
2.1 ServletContextListener 监听器 作用监听 ServletContext 创建或销毁(当我们 Web 应用启动时就会创建 ServletContext)即生命周期监听应用场景(1)加载初始化的配置文件比如 spring 的配置文件 (2)任务调度配合定时器 Timer/TimerTask) 相关方法 配置 web.xml 2.2 ServletContextAttributeListener 监听器 作用监听 ServletContext 属性变化 相关方法 2.3 其他监听器-使用较少
2.3.1 HttpSessionListener 监听器
1. 作用监听 Session 创建或销毁即生命周期监听
2. 相关方法 使用方法和前面一样, 可以用于监控用户上线离线
2.3.2 HttpSessionAttributeListener 监听器
作用监听 Session 属性的变化相关方法 使用少 使用方法和前面一样。
2.3.3 ServletRequestListener 监听器
1. ServletRequestListener 监听器
2. 作用监听 Request 创建或销毁即 Request 生命周期监听
相关方法 可以用来监控, 某个 IP 访问我们网站的频率, 日志记录 ,访问资源的情况.
2.3.4 ServletRequestAttributeListener 监听器
1. 作用监听 Request 属性变化
2. 相关方法 使用方法和前面类似
2.3.5 HttpSessionBindingListener 感知监听器
2.3.6 HttpSessionActivationListener 感知监听器
七、JavaWeb 三大组件之 过滤器 Filter
1. Filter 过滤器说明 过滤器介绍
**1. Filter 过滤器它是 JavaWeb 的三大组件之一(Servlet 程序、Listener 监听器、Filter 过滤器)
Filter 过滤器是 JavaEE 的规范是接口 Filter 过滤器它的作用是拦截请求过滤响应。应用场景
权限检查日记操作事务管理
2. Filter 过滤器基本原理 3. Filter 应用案例
D:\IDEA_code\xjz_javaweb\filter
4. Filter 过滤器 url-pattern
1、url-pattern : Filter 的拦截路径, 即浏览器在请求什么位置的资源时过滤器会进行拦截过滤 2.、精确匹配 /a.jsp 对应的 请求地址 http://ip[域名]:port/工程路径/a.jsp 会拦截 3、目录匹配 /manage/*对应的 请求地址http://ip[域名]:port/工程路径/manage/xx , 即 web 工程 manage 目录下所有资源 会拦截
4、后缀名匹配 *.jsp 后缀名可变比如 *.action *.do 等等对应的 请求地址 http://ip[域名]:port/工程路径/xx.jsp , 后缀名为 .jsp 请求会拦截 5、Filter 过滤器它只关心请求的地址是否匹配不关心请求的资源是否存在
5. Filter 过滤器生命周期
Filter 过滤器生命周期 图解 6. FilterConfig
FilterConfig 接口图 FilterConfig 说明
FilterConfig 是 Filter 过滤器的配置类Tomcat 每次创建 Filter 的时候也会创建一个 FilterConfig 对象这里包含了 Filter 配置文件的配置信息。FilterConfig 对象作用是获取 filter 过滤器的配置内容
应用实例
D:\IDEA_code\xjz_javaweb\filter\src\com\xjz\filter\XjzFilterConfig.java
7. FilterChain 过滤器链
FilterChain 简介
一句话: FilterChain: 在处理某些复杂业务时一个过滤器不够可以设计多个过滤器共同完成过滤任务形成过滤器链。
基本原理试示意图 应用实例
D:\IDEA_code\xjz_javaweb\filter\src\com\xjz\filter\AFilter.java/BFilter.java
运行结果 FilterChain 注意事项和细节 多个 filter 和目标资源在一次 http 请求在同一个线程中 当一个请求 url 和 filter 的 url-pattern 匹配时, 才会被执行, 如果有多个匹配上就会顺序执行形成一个 filter 调用链(底层可以使用一个数据结构搞定) 多个 filter 共同执行时,因为是一次 http 请求, 使用同一个 request 对象 多个 filter 执行顺序和 web.xml 配置顺序保持一致. chain.doFilter(req, resp)方法 将执行下一个过滤器的 doFilter 方法, 如果后面没有过滤器则执行目标资源。 小结注意执行过滤器链时, 顺序是(用前面的案例分析) Http请求 - A 过滤器 dofilter() - A 过滤器前置代码 - A 过滤器 chain.doFilter() - B 过滤器 dofilter() - B 过滤器前置代码 - B过滤器 chain.doFilter() - 目标文件 - B过滤器后置代码 - A过滤器后置代码 - 返回给浏览器页面/数据
八、数据交换和异步请求 - JSON Ajax
1. JSON 介绍 JSON 指的是 JavaScript 对象表示法JavaScript Object Notation JSON 是轻量级的文本数据交换格式 JSON 独立于语言 [老韩解读即 java 、php、asp.net , go 等都可以使用 JSON] JSON 具有自我描述性更易理解, 一句话非常的好用…
2. JSON 规则
映射(元素/属性)用冒号 : 表示“名称”:值 , 注意名称是字符串因此要用双引号引起来并列的数据之间用逗号 , 分隔。“名称 1”:值,“名称 2”:值映射的集合(对象)用大括号 {} 表示。{“名称 1”:值,“名称 2”:值}并列数据的集合数组用方括号 [] 表示。 [{“名称 1”:值,“名称 2”:值}, {“名称 1”:值, 名称 2:值}]元素值类型string, number, object, array, true, false, null
3. JSON 在 java 中使用
1. 说明 java 中使用 json需要引入到第 3 方的包 gson.jar Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。 可以对 JSON 字符串 和 Java 对象相互转换
2. JSON 在 java中 应用场景
Javabean 对象和 json 字符串 的转换List 对象和 json 字符串 的转换map 对象和 json 字符串 的转换应用场景示意图 3. 应用实例 JSON 在 java中应用场景
JavaJson.java
package com.xjz.json;import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** author xjz_2002* version 1.0*/
public class JavaJson {//代码解读//1. 要把复杂的 json 字符串转换成为 java 对象。需要继承 TypeToken 类//2. TypeToken 是一个自定义泛型类,在创建时需要指定具体类型,这里我们指定为 ListBook// ,如果同学们忘记了回去看 java 基础的泛型知识点//3. TypeToken 是由 gson 包提供的static class BookType extends TypeTokenListBook {}public static void main(String[] args) {// new 一个 gson 对象。引入 gson 包Gson gson new Gson();// java 对象和 json 的转换System.out.println(\n 1. java 对象 和 json 的转换 );Book book new Book(100, 我爱学Java);//1. 演示把 javabean - json字符串String strBook gson.toJson(book);System.out.println(strBook strBook);//2. json字符串 - javabean//代码解读//(1) strBook 就是 json字符串//(2) Book.class 指定将 json字符串转成 Book对象//(3) 底层是反射机制Book book2 gson.fromJson(strBook, Book.class);System.out.println(book2 book2);//2. List 集合 和 json 的转换System.out.println(\n 2. List 集合 和 json 的转换 );ListBook bookList new ArrayList();bookList.add(new Book(200, 男人帮));bookList.add(new Book(300, 女人帮));// 将 list 转成 json对象String bookListStr gson.toJson(bookList);System.out.println(bookListStr bookListStr);//将 json 字符串 转成 List 集合方式 1Type type new BookType().getType();System.out.println(type type); // java.util.Listcom.xjz.json.BookListBook bookList2 gson.fromJson(bookListStr, type);System.out.println(bookList2 bookList2);//将 json 字符串 转成 List 集合方式 2//代码解读//(1) 如果我们 new TypeTokenListBook() 提示// TypeToken() has protected access in com.google.gson.reflect.TypeToken//(2) 因为 TypeToken 的无参构造器是 protected 而 new TypeTokenListBook() 就是调用其无参构造器//(3) 根据java基础如果一个方法是 protected而且不在同一个包中是不能直接访问的因此报错//(4) 为什么 new TypeTokenListBook(){} 使用就可以这里就涉及到 匿名内部类的知识点.//(5) 当 new TypeTokenListBook(){} 其实这个类型不是 TypeToken而是一个 匿名内部类(可以理解为TypeToken的子类)//(6) 而且这个匿名内部类是有自己的无参构造器(隐式)根据java基础规则当执行子类的无参构造器时默认super()//Type type new TypeTokenListBook(){}.getType(); // java.util.Listcom.xjz.json.BookListBook bookList3 gson.fromJson(bookListStr, new TypeTokenListBook() {}.getType());System.out.println(bookList3 bookList3);//3. map 集合 - json 字符串MapString, Book bookMap new HashMap();bookMap.put(k1,new Book(10,三国演义));bookMap.put(k2,new Book(20,水浒传));// 把 map 集合 - json 字符串String strBookMap gson.toJson(bookMap);System.out.println(strBookMap strBookMap 类型 strBookMap.getClass());// 把 json 字符串 - map 集合// new TypeTokenMapString, Book() {}.getType() java.util.Mapcom.xjz.json.BookMapString, Book bookMap2 gson.fromJson(strBookMap,new TypeTokenMapString, Book() {}.getType());System.out.println(bookMap2 bookMap2);}
}九、Ajax 基本介绍
1. Ajax 是什么
AJAX 即Asynchronous Javascript And XML(异步 JavaScript 和 XML)Ajax 是一种浏览器异步发起请求(指定发哪些数据)局部更新页面的技术
2. Ajax 经典应用场景
搜索引擎根据用户输入关键字自动提示检索关键字动态加载数据按需取得数据【树形菜单、联动菜单…】改善用户体验。【输入内容前提示、带进度条文件上传…】电子商务应用。 【购物车、邮件订阅…】访问第三方服务。【访问搜索服务、rss 阅读器】页面局部刷新, https://piaofang.maoyan.com/dashboard
3. Ajax 原理示意图
传统的WEB应用 Ajax 原理示意图 4. JavaScript 原生 Ajax 请求
在线文档https://www.w3school.com.cn/js/js_ajax_intro.asp
应用实例-验证用户名是否存在
演示 javascript 发送原生 ajax 请求的案例 在输入框输入用户名 点击验证用户名, 使用 ajax 方式 服务端验证该用户名是否已经占用了, 如果该用户 已经占用, 以 json 格式返回该用户信息 假定用户名为 king , 就不可用, 其它用户名可以》 后面我们接入 DB[MysqlJDBC] 对页面进行局部刷新, 显示返回信息 小思考: 为什么直接返回用户名是否可用信息, 完成案例后, 再思考? 十、线程数据共享和安全 ThreadLocal
1. 什么是 ThreadLocal
ThreadLocal 的作用可以实现在同一个线程数据共享, 从而解决多线程数据安全问题.ThreadLocal 可以给当前线程关联一个数据(普通变量、对象、数组)set 方法 [源码!]ThreadLocal 可以像 Map 一样存取数据key 为当前线程, get 方法每一个 ThreadLocal 对象只能为当前线程关联一个数据如果要为当前线程关联多个数据就需要使用多个 ThreadLocal 对象实例每个 ThreadLocal 对象实例定义的时候一般为 static 类型ThreadLocal 中保存数据在线程销毁后会自动释放 2. 快速人门 ThreadLocal
ThreadLocalTest.java
package com.xjz.threadlocal;/*** author xjz_2002* version 1.0*/
public class ThreadLocalTest {public static ThreadLocalObject threadLocal1 new ThreadLocal();public static ThreadLocalObject threadLocal2 new ThreadLocal();public static class Task implements Runnable{Overridepublic void run() {Dog dog new Dog();Pig pig new Pig();/*** set源码分析 只要明白这个机制后面的 set get 全部通透** public void set(T value) {* //获取当前线程* Thread t Thread.currentThread();* //获取当前线程的 ThreadLocal.ThreadLocalMap 属性 threadLocals* // 类型是 ThreadLocal 的静态内部类* //threadLocals 有一个属性 Entry[]类型 }ThreadLocal.ThreadLocalMap.Entry* // k- ThreadLocal 对象 v - 值* ThreadLocalMap map getMap(t);* if (map ! null)* map.set(this, value); //存放这里的 this 就是 ThreadLocal1可以 debug源码一目了然* else* createMap(t, value); //创建* }** getMap 方法源码* ThreadLocalMap getMap(Thread t) { //获取当前线程的 ThreadLocal.ThreadLocalMap* return t.threadLocals;* }** 说明* 1. ThreadLocalMap 对象对象是和当前 Thread对象的绑定属性* 2. ThreadLocalMap 对象含有 Entry[] table; 这个 Entry(K,V)* 3. 这个 key 就是 ThreadLocal 对象, V 就是你要在放入的对象,比如 dog* 4. 当执行了 了 threadLocal.set(dog) 后内存布局图为 wps[看图]**/threadLocal1.set(dog);threadLocal2.set(pig);// 会替换 dog//如果希望在同一个线程共享多个对象/数据就只能再创建一个 ThreadLocal 对象//threadLocal2.set(pig);System.out.println(在 run方法中 线程 name Thread.currentThread().getName() 放入 ThreadLocal 的数据 dog );new T1Service().update();}}public static void main(String[] args) {for (int i 0; i 1; i) {new Thread(new Task()).start();//启动一个新的线程注意不是主线程}System.out.println(在 main 方法中 ThreadLocal 的数据 threadLocal1.get());}
}T1Service.java
package com.xjz.threadlocal;/*** author xjz_2002* version 1.0*/
public class T1Service {public void update(){String name Thread.currentThread().getName();/*** ThreadLocalTest.threadLocal.get() 源码* public T get() {* Thread t Thread.currentThread();* ThreadLocalMap map getMap(t);* if (map ! null) {* ThreadLocalMap.Entry e map.getEntry(this);* if (e ! null) {* SuppressWarnings(unchecked)* T result (T)e.value;* return result;* }* }* return setInitialValue();* }** 代码解读* 1. 先得到当前线程对象* 2. 获取当前对象绑定的 ThreadLocalMap 对象* 3. 根据 threadLocal对象(key)获取 ThreadLocalMap 对象的 Entry数组的 Entry对象 [hash]* 4. 取出 Entry对象的 value 就是放入到 ThreadLocal对象的数据 dog**/System.out.println(在 T1Service 的 update() 线程 name name threadLocal 的数据 ThreadLocalTest.threadLocal1.get());System.out.println(在 T1Service 的 update() 线程 name name threadLocal 的数据 ThreadLocalTest.threadLocal2.get());new T2DAO().update();}
}T2DAO.java
package com.xjz.threadlocal;/*** author xjz_2002* version 1.0*/
public class T2DAO {public void update(){String name Thread.currentThread().getName();System.out.println(在 T2DAO 的 update() 线程是 name threadlocal 数据是 ThreadLocalTest.threadLocal1.get());System.out.println(在 T2DAO 的 update() 线程是 name threadlocal 数据是 ThreadLocalTest.threadLocal2.get());}}6. 完成测试, 检测 ThreadLocal 可以实现在同一个线程数据安全共享 3. ThreadLocal 源码解读画图
ThreadLocal 原理分析图(重点 set 和 get) Debug 源码图非常重要