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 $8000.0
a wife
----------------------
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)如果需要更新内容,必须重载整个网页页面。
- 提升用户的体验
实现
原生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;
}
}
}
结果: