JavaWeb基础总结学习笔记(下)
JavaWeb过滤器Filter、jQuery、Ajax、JSON的使用详解
计算机网络:https://www.nowcoder.com/discuss/342320
MySQL:https://www.nowcoder.com/discuss/353707
Java并发上:https://www.nowcoder.com/discuss/355081
Java并发下:https://www.nowcoder.com/discuss/355876
JDBC:https://www.nowcoder.com/discuss/356804
Linux:https://www.nowcoder.com/discuss/357410
JavaWeb上:https://www.nowcoder.com/discuss/358423
JavaWeb中:https://www.nowcoder.com/discuss/358741
JavaWeb下本篇内容原址:https://blog.csdn.net/qq_41112238/article/details/103751092
Filter:过滤器
概念
web中的过滤器:
当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
过滤器的作用:
一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤...
快速入门
@WebFilter("/index.jsp")//拦截index.jsp public class Filter1 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("过滤器执行了"); //chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
访问index.jsp,可以看到页面并无输出
打开doFilter方法中的注释,再次访问index.jsp
XML配置方式
去掉过滤器类的注解
在WEB-INF下的xml文件进行配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <filter> <filter-name>filter1</filter-name> <filter-class>filter.Filter1</filter-class> </filter> <filter-mapping> <filter-name>filter1</filter-name> <url-pattern>/index.jsp</url-pattern> </filter-mapping> </web-app>
过滤器执行流程
- 执行过滤器
- 执行放行后的资源
- 回来执行过滤器放行代码下边的代码
过滤器生命周期方法
- init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
- doFilter:每一次请求被拦截资源时,会执行。执行多次
- destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
拦截路径配置:
- 具体资源路径:
/index.jsp
只有访问index.jsp资源时,过滤器才会被执行 - 拦截目录:
/user/*
访问/user下的所有资源时,过滤器都会被执行 - 后缀名拦截:
*.jsp
访问所有后缀名为jsp资源时,过滤器都会被执行 - 拦截所有资源:
/*
访问所有资源时,过滤器都会被执行
拦截方式配置:资源被访问的方式
- 注解配置:
- 设置dispatcherTypes属性
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
- 设置dispatcherTypes属性
- web.xml配置
- 设置标签即可
例1:拦截请求
过滤器:
@WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.REQUEST}) public class Filter1 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("过滤器执行了"); } public void init(FilterConfig config) throws ServletException { } }
通过转发访问index.jsp的servlet
@WebServlet("/filterServlet") public class FilterServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/index.jsp").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
直接请求index.jsp被拦截
转发访问index.jsp正常
例2:拦截转发
过滤器:
@WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.FORWARD}) public class Filter1 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("过滤器执行了"); } public void init(FilterConfig config) throws ServletException { } }
转发访问index.jsp被拦截
直接请求index.jsp正常
例3:拦截请求和转发
过滤器:
@WebFilter(value = "/*",dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}) public class Filter1 implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("过滤器执行了"); chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
访问servlet将被拦截两次,因为拦截了请求和转发
过滤器链(配置多个过滤器)
执行顺序:
如果有两个过滤器:过滤器1和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
如: AFilter 和 BFilter,AFilter就先执行了。
@WebFilter( "/*") public class TestFilter implements javax.servlet.Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("过滤器1执行了"); chain.doFilter(req, resp); System.out.println("过滤器1执行结束"); } public void init(FilterConfig config) throws ServletException { } } @WebFilter( "/*") public class TestFilter1 implements javax.servlet.Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("过滤器2执行了"); chain.doFilter(req, resp); System.out.println("过滤器2执行结束"); } public void init(FilterConfig config) throws ServletException { } }
2. web.xml配置: <filter-mapping>
谁定义在上边,谁先执行
敏感词过滤案例
首先先了解一下动态***设计模式
实现步骤:
- ***对象和真实对象实现相同的接口
- ***对象 = Proxy.newProxyInstance();
- 使用***对象调用方法。
- 增强方法
增强方式:
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
通过一个例子来说明:
一个卖老婆的接口:
public interface SaleWife { //花钱买了一个老婆 String sale(double money); }
一个卖老婆的实现类,即真实对象
public class SaleWifeImpl implements SaleWife { @Override public String sale(double money) { System.out.println("buy a wife by $"+money); return "a wife"; } }
测试类
public class ProxyTest { public static void main(String[] args) { SaleWife saleWife=new SaleWifeImpl(); String gift = saleWife.sale(8000); System.out.println(gift); } }
结果:
buy a wife by $8000.0
a wife
使用动态***:
public class ProxyTest { public static void main(String[] args) { //真实对象 SaleWife saleWife=new SaleWifeImpl(); /* ***对象 参数1:真实对象的类加载器 参数2:真实对象实现的接口 参数3:具体***逻辑 */ SaleWife proxy_sale = (SaleWife) Proxy.newProxyInstance(SaleWifeImpl.class.getClassLoader(), SaleWifeImpl.class.getInterfaces(), new InvocationHandler() { /* 具体***逻辑 参数1:***对象 参数2:***对象调用的方法 参数3:***对象调用方法时传递的实际参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果是sale方法 if(method.getName().equals("sale")){ //增强参数 double money=(double)args[0]*0.8; //使用真实对象调用方法 String gift = (String) method.invoke(saleWife, money); //增强逻辑 System.out.println("送货上门:"); //增强返回值 return gift+" with 36D"; } //用真实对象调用方法 return method.invoke(saleWife,args); } }); //不使用*** String gift = saleWife.sale(8000); System.out.println(gift); System.out.println("----------------------"); //使用*** String gift2 = proxy_sale.sale(8000); System.out.println(gift2); } }
结果:
buy a wife by 6400.0
送货上门:
a wife with 36D
接下来用动态***实现敏感词过滤
过滤器:
@WebFilter("/*") public class WordFilter implements Filter { //敏感词集合 private List<String> words=new ArrayList<>(); public void init(FilterConfig config) throws ServletException { try { //读取敏感词汇文件 //1.获取真实路径 String realPath = config.getServletContext().getRealPath("/WEB-INF/classes/word.txt"); //2.创建输入流 BufferedReader reader=new BufferedReader(new FileReader(realPath)); //3.读取数据 String line; while((line=reader.readLine())!=null){ //存入敏感词集合 words.add(line); } }catch (Exception e){ e.printStackTrace(); } } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { ServletRequest newReq = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(),req.getClass().getInterfaces(), (proxy, method, args) -> { //如果是getParameter方法 if(method.getName().equals("getParameter")){ //获取原有字符串 String str = (String) method.invoke(req, args); System.out.println(words); //遍历敏感词汇集合,存在则替换 if(str!=null){ for(String word:words){ if(str.contains(word)){ str=str.replaceAll(word,"***"); } } } //返回处理后的字符串 System.out.println("已过滤敏感词"); return str; } return method.invoke(req,args); }); chain.doFilter(newReq, resp); } public void destroy() { } }
测试的Servlet
@WebServlet("/filterServlet") public class FilterServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String player=request.getParameter("player"); String word = request.getParameter("word"); System.out.println("玩家 :"+player); System.out.println("发言 : "+word); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
在src下新建一个敏感词文件,注意用GBK编码
启动服务器测试
结果:
Listener:***
概念:web的三大组件之一。
事件监听机制
- 事件 :一件事情
- 事件源 :事件发生的地方
- *** :一个对象
- 注册监听:将事件、事件源、***绑定在一起。 当事件源上发生某个事件后,执行***代码
ServletContextListener
监听ServletContext对象的创建和销毁
方法:void contextDestroyed(ServletContextEvent sce)
ServletContext对象被销毁之前会调用该方法void contextInitialized(ServletContextEvent sce)
ServletContext对象创建后会调用该方法
步骤
- 定义一个类,实现ServletContextListener接口
- 复写方法
- 配置
- 可以在xml中配置
指定初始化参数<context-param>
<listener> <listener-class>Listener</listener-class> </listener> <context-param> <param-name>config</param-name> <param-value>/WEB-INF/classes/applicationContext.xml</param-value> </context-param>
- 直接使用注解
@WebListener
- 可以在xml中配置
一般用于加载资源
public void contextInitialized(ServletContextEvent sce) { ServletContext servletContext = sce.getServletContext(); String config = servletContext.getInitParameter("config"); String realPath = servletContext.getRealPath(config); FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(realPath); } catch (FileNotFoundException e) { e.printStackTrace(); } System.out.println(fileInputStream); }
启动tomcat服务器时输出
JQuery
概念
- 一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。
- JQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。
- 它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
- JavaScript框架:本质上就是一些js文件,封装了js的原生代码
- 目前jQuery有三个大版本:
1.x:兼容ie678,使用最为广泛的,官方只做BUG维护, 功能不再新增。因此一般项目来说,使用1.x版本就可以了, 最终版本:1.12.4 (2016年5月20日) 2.x:不兼容ie678,很少有人使用,官方只做BUG维护, 功能不再新增。如果不考虑兼容低版本的浏览器可以使用2.x, 最终版本:2.2.4 (2016年5月20日) 3.x:不兼容ie678,只支持最新的浏览器。除非特殊要求, 一般不会使用3.x版本的,很多老的jQuery插件不支持这个版本。 目前该版本是官方主要更新维护的版本。最新版本:3.2.1(2017年3月20日)
入门示例
引入jQuery
用$("#标签id名")
获取对象 html()
方法获取内容
<html> <head> <title>Title</title> <script src="js/jquery-3.3.1.min.js"></script> </head> <body> <div id="tag1">aaa</div> <script> var tag1 = $("#tag1"); alert(tag1.html()); </script> </body> </html>
结果:
JQuery对象和JS对象区别与转换
- JQuery对象在操作时,更加方便。
- JQuery对象和js对象方法不通用的.
- 两者相互转换
- jq -- > js : jq对象[索引] 或者 jq对象.get(索引)
- js -- > jq : $(js对象)
<div id="tag1">aaa</div> <div id="tag2">aaa</div> <script> //通过js方式获取所有叫div的所有html对象 var divs = document.getElementsByTagName("div"); //改变所有标签体内容 for (var i=0;i<divs.length;i++){ divs[i].innerHTML="bbb"; //js对象转换为jQuery使用 // $(divs[i]).html("bbb"); } //通过jQuery方式 var $divs = $("div"); $divs.html("ccc"); //jquery对象转换为js使用 //$divs[0].innerHTML="ddd"; //$divs.get(1).innerHTML="eee"; </script>
基本语法
事件绑定
<script> $("#btn").click(function () { alert("我被点了"); }); </script>
入口函数
$(function () { //.... });
window.onload 和 $(function) 区别
- window.onload 只能定义一次,如果定义多次,后边的会将前边的覆盖掉
- $(function)可以定义多次的。
样式控制:css方法
方式一:$("#div1").css("background-color","red");
方式二:$("#div1").css("backgroundColor","pink");
html代码:
<html> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/jquery-3.3.1.min.js"></script> <script> $(function () { $("#div1").css("background-color","red"); $("#div2").css("backgroundColor","yellow"); }); </script> </head> <body> <div id="div1">区域1</div> <div id="div2">区域2</div> </body> </html>
结果:
选择器
基本选择器
- 标签选择器(元素选择器)
$("html标签名")
获得所有匹配标签名称的元素 - id选择器
$("#id的属性值")
获得与指定id属性值匹配的元素 - 类选择器
$(".class的属性值")
获得与指定的class属性值匹配的元素 - 并集选择器:
$("选择器1,选择器2....")
获取多个选择器选中的所有元素
//按钮1:改变 id 为 one 的元素的背景色为 红色" $("#b1").click(function () { $("#one").css("backgroundColor","red"); }); //按钮2: 改变元素名为 <div> 的所有元素的背景色为 红色" $("#b2").click(function () { $("div").css("backgroundColor","red"); }); //按钮3:改变 class 为 mini 的所有元素的背景色为 红色" $("#b3").click(function () { $(".mini").css("backgroundColor","red"); }); //按钮4: 改变所有的<span>元素和 id 为 two 的元素的背景色为红色 $("#b4").click(function () { $("span,#two").css("backgroundColor","red"); });
层级选择器
- 后代选择器
$("A B ")
选择A元素内部的所有B元素 - 子选择器
$("A > B")
选择A元素内部的所有B子元素
//<input type="button" value=" 改变 <body> 内所有 <div> 的背景色为红色" id="b1"/> $("#b1").click(function () { $("body div").css("backgroundColor","red"); }); //<input type="button" value=" 改变 <body> 内子 <div> 的背景色为 红色" id="b2"/> $("#b2").click(function () { $("body > div").css("backgroundColor","red"); });
属性选择器
- 属性名称选择器
$("A[属性名]")
包含指定属性的选择器 - 属性选择器
$("A[属性名='值']")
包含指定属性等于指定值的选择器 - 复合属性选择器
$("A[属性名='值'][]...")
包含多个属性条件的选择器
//<input type="button" value=" 含有属性title 的div元素背景色为红色" id="b1"/> $("#b1").click(function () { $("div[title]").css("backgroundColor","red"); }); //<input type="button" value=" 属性title值等于test的div元素背景色为红色" id="b2"/> $("#b2").click(function () { $("div[title='test']").css("backgroundColor","red"); }); //<input type="button" value=" 属性title值不等于test的div元素(没有属性title的也将被选中)背景色为红色" id="b3"/> $("#b3").click(function () { $("div[title!='test']").css("backgroundColor","red"); }); //<input type="button" value=" 属性title值 以te开始 的div元素背景色为红色" id="b4"/> $("#b4").click(function () { $("div[title^='te']").css("backgroundColor","red"); }); //<input type="button" value=" 属性title值 以est结束 的div元素背景色为红色" id="b5"/> $("#b5").click(function () { $("div[title$='est']").css("backgroundColor","red"); }); //<input type="button" value="属性title值 含有es的div元素背景色为红色" id="b6"/> $("#b6").click(function () { $("div[title*='es']").css("backgroundColor","red"); }); //<input type="button" value="选取有属性id的div元素,然后在结果中选取属性title值含有“es”的 div 元素背景色为红色" id="b7"/> $("#b7").click(function () { $("div[id][title*='es']").css("backgroundColor","red"); });
过滤选择器
- 首元素选择器
:first
获得选择的元素中的第一个元素 - 尾元素选择器
:last
获得选择的元素中的最后一个元素 - 非元素选择器
:not(selector)
不包括指定内容的元素 - 偶数选择器
:even
偶数,从 0 开始计数 - 奇数选择器
:odd
奇数,从 0 开始计数 - 等于索引选择器
:eq(index)
指定索引元素 - 大于索引选择器
:gt(index)
大于指定索引元素 - 小于索引选择器
:lt(index)
小于指定索引元素 - 标题选择器
:header
获得标题(h1~h6)元素,固定写法
//<input type="button" value=" 改变第一个 div 元素的背景色为 红色" id="b1"/> $("#b1").click(function () { $("div:first").css("backgroundColor","red"); }); //<input type="button" value=" 改变最后一个 div 元素的背景色为 红色" id="b2"/> $("#b2").click(function () { $("div:last").css("backgroundColor","red"); }); //<input type="button" value=" 改变class不为 one 的所有 div 元素的背景色为 红色" id="b3"/> $("#b3").click(function () { $("div:not(.one)").css("backgroundColor","red"); }); //<input type="button" value=" 改变索引值为偶数的 div 元素的背景色为 红色" id="b4"/> $("#b4").click(function () { $("div:even").css("backgroundColor","red"); }); //<input type="button" value=" 改变索引值为奇数的 div 元素的背景色为 红色" id="b5"/> $("#b5").click(function () { $("div:odd").css("backgroundColor","red"); }); //<input type="button" value=" 改变索引值为大于 3 的 div 元素的背景色为 红色" id="b6"/> $("#b6").click(function () { $("div:gt(3)").css("backgroundColor","red"); }); //<input type="button" value=" 改变索引值为等于 3 的 div 元素的背景色为 红色" id="b7"/> $("#b7").click(function () { $("div:eq(3)").css("backgroundColor","red"); }); //<input type="button" value=" 改变索引值为小于 3 的 div 元素的背景色为 红色" id="b8"/> $("#b8").click(function () { $("div:lt(3)").css("backgroundColor","red"); }); //<input type="button" value=" 改变所有的标题元素的背景色为 红色" id="b9"/> $("#b9").click(function () { $(":header").css("backgroundColor","red"); });
表单过滤选择器
- 可用元素选择器
:enabled
获得可用元素 - 不可用元素选择器
:disabled
获得不可用元素 - 选中选择器
:checked
获得单选/复选框选中的元素 - 选中选择器
:selected
获得下拉框选中的元素
//<input type="button" value=" 利用 jQuery 对象的 val() 方法改变表单内可用 <input> 元素的值" id="b1"/> $("#b1").click(function () { $("input[type='text']:enabled").val("aaa"); }); //<input type="button" value=" 利用 jQuery 对象的 val() 方法改变表单内不可用 <input> 元素的值" id="b2"/> $("#b2").click(function () { $("input[type='text']:disabled").val("bbb"); }); //<input type="button" value=" 利用 jQuery 对象的 length 属性获取复选框选中的个数" id="b3"/> $("#b3").click(function () { var length = $("input[type='checkbox']:checked").length; alert(length) }); //<input type="button" value=" 利用 jQuery 对象的 length 属性获取下拉框选中的个数" id="b4"/> $("#b4").click(function () { var length = $("#job > option:selected").length; alert(length) });
DOM操作
内容操作
html()
获取/设置元素的标签体内容<a><font>内容</font></a>
--><font>内容</font>
text()
获取/设置元素的标签体纯文本内容<a><font>内容</font></a>
-->内容
val()
获取/设置元素的value属性值
属性操作
- 通用属性操作
- `attr()`: 获取/设置元素的属性 - `removeAttr()`:删除属性 - `prop()`:获取/设置元素的属性 - `removeProp()`:删除属性 - attr和prop区别? - 如果操作的是元素的固有属性,则建议使用prop - 如果操作的是元素自定义的属性,则建议使用attr
//获取北京节点的name属性值 var name = $("#bj").attr("name"); alert(name); //设置北京节点的name属性的值为dabeijing $("#bj").attr("name","dabeijing"); //新增北京节点的discription属性 属性值是didu $("#bj").attr("discription","didu"); //删除北京节点的name属性并检验name属性是否存在 $("#bj").removeAttr("name"); //获得hobby的的选中状态 var prop = $("#hobby").prop("checked"); alert(prop);
- 对class属性操作
addClass()
:添加class属性值removeClass()
:删除class属性值toggleClass()
:切换class属性toggleClass("one")
: 判断如果元素对象上存在class="one",则将属性值one删除掉。 如果元素对象上不存在class="one",则添加
//<input type="button" value="采用属性增加样式(改变id=one的样式)" id="b1"/> $("#b1").click(function () { $("#one").prop("class","second"); }); //<input type="button" value=" addClass" id="b2"/> $("#b2").click(function () { $("#one").addClass("second"); }); //<input type="button" value="removeClass" id="b3"/> $("#b3").click(function () { $("#one").removeClass("second"); }); //<input type="button" value=" 切换样式" id="b4"/> $("#b4").click(function () { $("#one").toggleClass("second"); }); //<input type="button" value=" 通过css()获得id为one背景颜色" id="b5"/> $("#b5").click(function () { var color = $("#one").css("backgroundColor"); }); //<input type="button" value=" 通过css()设置id为one背景颜色为绿色" id="b6"/> $("#b6").click(function () { $("#one").css("backgroundColor","green"); });
Ajax
概念
ASynchronous JavaScript And XML 异步的JavaScript 和 XML
- 异步和同步:客户端和服务器端相互通信的基础上
- 同步:客户端必须等待服务器端的响应。在等待的期间客户端不能做其他操作。
- 异步:客户端不需要等待服务器端的响应。在服务器处理请求的过程中,客户端可以进行其他的操作。
- Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
- 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。
- 这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
- 传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。
- 提升用户的体验
- 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。
实现
原生JS(了解)
//1.创建核心对象 var xmlhttp; if (window.XMLHttpRequest)// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); else xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");// code for IE6, IE5 //2. 建立连接 /* 参数: 1. 请求方式:GET、POST * get方式,请求参数在URL后边拼接。send方法为空参 * post方式,请求参数在send方法中定义 2. 请求的URL 3. 同步或异步请求:true(异步)或 false(同步) */ xmlhttp.open("GET","../ajaxServlet?username=tom",true); //3.发送请求 xmlhttp.send(); //4.接受并处理来自服务器的响应结果 //获取方式 :xmlhttp.responseText //什么时候获取?当服务器响应成功后再获取 //当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。 xmlhttp.onreadystatechange=function() { //判断readyState就绪状态是否为4,判断status响应状态码是否为200 if (xmlhttp.readyState==4 && xmlhttp.status==200) { //获取服务器的响应结果 var responseText = xmlhttp.responseText; alert(responseText); } }
jQuery实现
$.ajax()
语法:$.ajax({键值对});
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../js/jquery-3.3.1.min.js"></script> <script> function f() { $.ajax({ url:"../ajaxServlet",//请求url type:"POST",//请求方式 data:{"username":"james"},//请求数据 success:function (data) {//响应成功的回调函数 alert(data); } , error:function () {//响应失败的回调函数 alert("error happened"); } , dataType:"text" //响应数据格式 }); } </script> </head> <body> <input id="test" type="button" value="ajax提交数据" onclick="f()"> <input> </body> </html>
结果:
$.get()
:发送get请求
语法:$.get(url, [data], [callback], [type])
参数:* url:请求路径
- data:请求参数
- callback:回调函数
- type:响应结果的类型
只需改动上例代码中的$.ajax()部分,运行结果不变
$.get("../ajaxServlet",{"username":"james"},function (data) { alert(data); },"text");
$.post()
:发送post请求
语法:$.post(url, [data], [callback], [type])
$.post("../ajaxServlet",{"username":"james"},function (data) { alert(data); },"text");
JSON
概念
JavaScript Object Notation JavaScript对象表示法
- JSON现在多用于存储和交换文本信息的语法
- 进行数据的传输
- JSON 比 XML 更小、更快,更易解析。
基本规则
数据在名称/值对中:json数据是由键值对构成的
键用引号(单双都行)引起来,也可以不使用引号
值的取值类型:
数字(整数或浮点数)
字符串(在双引号中)
逻辑值(true 或 false)
数组(在方括号中) {"persons":[{},{}]}
对象(在花括号中) {"address":{"province":"陕西"....}}
null数据由逗号分隔:多个键值对由逗号分隔
花括号保存对象:使用{}定义json 格式
方括号保存数组:[]
//普通格式 var person={name:"james",age:35,gender:"male"}; //{}嵌套[] var persons={ persons: [ {name:"james",age:35,gender:"male"}, {name:"kobe",age:38,gender:"male"}, {name:"kuzma",age:24,gender:"male"} ] }; //[]嵌套{} var persons1=[ {name:"james",age:35,gender:"male"}, {name:"kobe",age:38,gender:"male"}, {name:"kuzma",age:24,gender:"male"} ];
获取数据:
1.json对象.键名
2. json对象["键名"]
3. 数组对象[索引]
var person={name:"james",age:35,gender:"male"}; var name2 = person.name;//james var name3 = person["name"];//james var persons={ persons: [ {name:"james",age:35,gender:"male"}, {name:"kobe",age:38,gender:"male"}, {name:"kuzma",age:24,gender:"male"} ] }; var name1 = persons.persons[1].name;//kobe var persons1=[ {name:"james",age:35,gender:"male"}, {name:"kobe",age:38,gender:"male"}, {name:"kuzma",age:24,gender:"male"} ]; var name = persons1[0].name;//james
4.遍历
//普通格式 var person={name:"james",age:35,gender:"male"}; for (var key in person){ //alert(key+person.key);不能用这个方式 相当于person."name" //alert(key+person[key]); alert(key); } //遍历数组 var persons=[ {name:"james",age:35,gender:"male"}, {name:"kobe",age:38,gender:"male"}, {name:"kuzma",age:24,gender:"male"} ]; for(var i=0;i<persons.length;i++){ var person = persons[i]; for (var key in person){ alert(key+person[key]); } }
Java对象转换JSON
- 导入jackson的相关jar包
- 创建Jackson核心对象 ObjectMapper
- 调用ObjectMapper的相关方法进行转换
转换方法
writeValue(参数1,obj)
参数1:File
:将obj对象转换为JSON字符串,并保存到指定的文件中Writer
:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中OutputStream
:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中writeValueAsString(obj)
:将对象转为json字符串
封装数据的Person类
public class Person { private String name; private int age; private String gender; public Person(String name, int age, String gender) { this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
测试类:
public class JsonTest { @Test public void test() throws IOException { ObjectMapper mapper=new ObjectMapper(); Person p=new Person("james",35,"male"); String string = mapper.writeValueAsString(p); System.out.println(string);//{"name":"james","age":35,"gender":"male"} mapper.writeValue(new File("d://a.txt"),p); mapper.writeValue(new FileWriter("d://b.txt"),p); mapper.writeValue(new FileOutputStream("d://c.txt"),p); } }
在d盘下生成3个文件:
文件内容:
注解
@JsonIgnore
:排除属性。@JsonFormat
:属性值得格式化
给Person类添加一个Date属性
private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; }
不添加注解时:
public void test() throws IOException { ObjectMapper mapper=new ObjectMapper(); Person p=new Person("james",35,"male"); p.setDate(new Date()); String string = mapper.writeValueAsString(p); System.out.println(string); }
结果:
{"name":"james","age":35,"gender":"male","date":1577762339613}
添加
@JsonIgnore
:@JsonIgnore private Date date;
结果:
{"name":"james","age":35,"gender":"male"}
添加
@JsonFormat
:@JsonFormat(pattern = "yyyy-MM-dd") private Date date;
结果:
{"name":"james","age":35,"gender":"male","date":"2019-12-31"}
复杂java对象转换
List:数组
public void test() throws IOException { ObjectMapper mapper=new ObjectMapper(); Person p=new Person("james",35,"male"); List<Person> list=new ArrayList<>(); list.add(p); String string = mapper.writeValueAsString(list); System.out.println(string); //输出:[{"name":"james","age":35,"gender":"male","date":null}] }
Map:对象格式一致
public void test() throws IOException { ObjectMapper mapper=new ObjectMapper(); Map<String,Object> map=new HashMap<>(); map.put("name","james"); map.put("age",35); map.put("gender","male"); String string = mapper.writeValueAsString(map); System.out.println(string); //输出:{"gender":"male","name":"james","age":35} }
JSON转为Java对象
readValue(json字符串数据,Class)
@Test public void test() throws IOException { ObjectMapper mapper=new ObjectMapper(); String json_data="{\"name\":\"james\",\"age\":35,\"gender\":\"male\"}"; Person person = mapper.readValue(json_data, Person.class); System.out.println(person); //输出:json.Person@4cf777e8 }
Ajax和json综合案例:校验用户名是否存在
服务器响应的数据,在客户端使用时,要想当做json数据格式使用。
有两种解决方案:
$.get(type)
:将最后一个参数type指定为"json"- 在服务器端设置MIME类型
response.setContentType("application/json;charset=utf-8");
注册页:
<html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/jquery-3.3.1.min.js"></script> <script> $(function () { //给用户名输入框绑定离焦事件 $("#username").blur(function () { var $username = $(this).val(); //ajax方式发送get请求 $.get("ajaxServlet",{username:$username},function (data) { //如果exist为true,说明用户存在,错误提示,设置为红色 var $span = $("#span"); if(data.exist){ $span.css("color","red"); }else {//成功提示 设置为绿色 $span.css("color","green"); } $span.html(data.msg);//设置提示信息为msg内容 }); }); }); </script> </head> <body> 用户名:<input type="text" name="username" id="username" > <span id="span"></span><br> 密码:<input type="text" name="password" ><br> <input type="button" value="登陆"> </body> </html>
ajax处理请求servlet
@WebServlet("/ajaxServlet") public class AjaxServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); response.setContentType("application/json;charset=utf-8");//设置响应格式为json HashMap<String,Object> map=new HashMap<>(); ObjectMapper mapper = new ObjectMapper(); try { UserDao userDao=new UserDao(); if(userDao.exist(username)){//若存在 map.put("exist",true); map.put("msg","用户名已存在,请更换"); }else { map.put("exist",false);//若不存在 map.put("msg","用户名可用"); } } catch (Exception e) { e.printStackTrace(); } mapper.writeValue(response.getWriter(),map); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
UserDao类
class UserDao { private Connection conn; UserDao() throws Exception { } boolean exist(String username) { try{ conn=JDBCUtils.getConnection(); //1.编写sql String sql = "select * from user where username = ?"; //2.调用query方法 PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1,username); ResultSet resultSet = ps.executeQuery(); return resultSet.next(); }catch (Exception e){ e.printStackTrace(); return false; } } }
结果: