一、JSON
1. 什么是 JSON
- JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。
- JSON 采用完全独立于语言的文本格式,而且很多语言都提供了对 JSON 的支持(包括 C, C++, C#, Java, JavaScript, Perl, Python 等)。 这样就使得 JSON 成为理想的数据交换格式。
- JSON 是一种轻量级的数据交换格式。
- 轻量级指的是跟 xml 做比较。
- 数据交换指的是客户端和服务器之间业务数据的传递格式
2. JSON 在 JavaScript 中的使用
2.1 JSON 的定义
JSON 是由键值对组成,并且由花括号(大括号)包围。每个键由引号引起来,键和值之间使用冒号进行分隔,
多组键值对之间进行逗号进行分隔。
var jsonObj = {
"key1": 12,
"key2": "abc",
"key3": true,
"key4": [11,"arr",false],
"key5": {
"key5_1": 551,
"key5_2": "key5_2_value"
},
"key6": [{
"key6_1_1": 6611,
"key6_1_2": "key6_1_2_value"
},{
"key6_2_1": 6621,
"key6_2_2": "key6_2_2_value"
}]
};
2.2 JSON 的访问
JSON 本身是一个对象。
JSON 中的 key 我们可以理解为是对象中的一个属性。
JSON 中的 key 访问就跟访问对象的属性一样: JSON 对象.key
alert(typeof(jsonObj));// object json 就是一个对象
alert(jsonObj.key1); //12
alert(jsonObj.key2); // abc
alert(jsonObj.key3); // true
alert(jsonObj.key4);// 得到数组[11,"arr",false]
// json 中 数组值的遍历
for(var i = 0; i < jsonObj.key4.length; i++) {
alert(jsonObj.key4[i]);
}
alert(jsonObj.key5.key5_1);//551
alert(jsonObj.key5.key5_2);//key5_2_value
alert( jsonObj.key6 );// 得到 json 数组
// 取出来每一个元素都是 json 对象
var jsonItem = jsonObj.key6[0];
// alert( jsonItem.key6_1_1 ); //6611
alert( jsonItem.key6_1_2 ); //key6_1_2_value
2.3 JSON 的两个常用方法
- JSON 的存在有两种形式
-
- 对象的形式存在,我们叫它 JSON 对象
- 字符串的形式存在,我们叫它 JSON 字符串
- 一般我们要操作 JSON 中的数据的时候,需要 JSON 对象的格式
- 一般我们要在客户端和服务器之间进行数据交换的时候,使用 JSON 字符串
- JSON.stringify():把 JSON 对象转换成为 JSON 字符串
- JSON.parse():把 JSON 字符串转换成为 JSON 对象
// 把 json 对象转换成为 json 字符串
var jsonObjString = JSON.stringify(jsonObj); // 特别像 Java 中对象的 toString
alert(jsonObjString)
// 把 json 字符串。转换成为 json 对象
var jsonObj2 = JSON.parse(jsonObjString);
alert(jsonObj2.key1);// 12
alert(jsonObj2.key2);// abc
3. JSON 在 Java 中的使用
- 在 Java 中,我们可以实现将 Java 的各种对象与 JSON 字符串之间进行转换。
- 后面,我们学习了 Ajax 之后,后端给前端响应的数据一般都是 JSON 字符串的。
- 再后面,到了微服务阶段,前后端分离中,我们进行数据传输都是使用 JSON 字符串的。
- 在 Java 中,将 Java 对象、集合等与 JSON 字符串进行互相转换,有很多技术:
-
- fastjson:阿里巴巴
- Gson:谷歌
- Jackson 等等
- 我们使用最近很流行的工具库:Hutool,它比上面的都简单,而且功能更丰富!
3.1 JavaBean 和 JSON 的互转
Emp
实体类
package com.xszx.bean;
public class Emp {
private Integer id;
private String name;
private Integer age;
public Emp() {
}
public Emp(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.xszx.test;
import cn.hutool.json.JSONUtil;
import com.xszx.bean.Emp;
public class Demo1 {
public static void main(String[] args) {
Emp emp = new Emp(1, "苏明玉", 20);
// 将 JavaBean 转为 json 字符串
String jsonStr = JSONUtil.toJsonStr(emp);
System.out.println(jsonStr); // {"id":1,"name":"苏明玉","age":20}
// 将 json 字符串转为 JavaBean
Emp emp2 = JSONUtil.toBean(jsonStr, Emp.class);
System.out.println(emp2); // Emp{id=1, name='苏明玉', age=20}
}
}
3.2 List 和 JSON 的互转
package com.xszx.test;
import cn.hutool.json.JSONUtil;
import com.xszx.bean.Emp;
import java.util.ArrayList;
import java.util.List;
public class Demo2 {
public static void main(String[] args) {
List<Emp> list = new ArrayList<>();
list.add(new Emp(1, "张三", 20));
list.add(new Emp(2, "李四", 25));
// 将 list 集合转为 json 字符串
String jsonStr = JSONUtil.toJsonStr(list); // [{"id":1,"name":"张三","age":20},{"id":2,"name":"李四","age":25}]
System.out.println(jsonStr);
// 将 json 字符串转为 list 集合
List<Emp> list2 = JSONUtil.toList(jsonStr, Emp.class);
System.out.println(list2);
}
}
3.3 map 和 JSON 的互转
package com.xszx.test;
import cn.hutool.json.JSONUtil;
import com.xszx.bean.Emp;
import java.util.HashMap;
import java.util.Map;
public class Demo3 {
public static void main(String[] args) {
Map<String, Emp> map = new HashMap<>();
map.put("1", new Emp(1, "张三", 20));
map.put("2", new Emp(2, "李四", 25));
// 将 Map 集合转为 json 字符串
String jsonStr = JSONUtil.toJsonStr(map);
System.out.println(jsonStr); // {"1":{"id":1,"name":"张三","age":20},"2":{"id":2,"name":"李四","age":25}}
// 将 json 字符串转为 Map 集合
Map map2 = JSONUtil.toBean(jsonStr, Map.class);
System.out.println(map2);
}
}
二、Ajax 请求
1. 什么是 Ajax 请求
- Ajax 即 “Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。
- Ajax 是一种浏览器通过 js 异步发起请求,局部更新页面的技术。
- Ajax 请求的局部更新,浏览器地址栏不会发生变化
- 局部更新不会舍弃原来页面的内容
2. jQuery 中的 Ajax 请求
- $.get(url, data, callback, type) 方法发送 get 请求
- $.post(url, data, callback, type) 方法发送 post 请求
- 参数说明:
-
- url:请求的 url 地址
- data:发送的数据,可以有两种格式:
第一种:name=value&name=value
第二种:{key:value, key:value}
-
- callback:成功的回调函数
- type:返回的数据类型,有以下几种:
text:表示纯文本
xml:表示 xml 数据
json:表示 json 对象
3. Ajax 案例
3.1 需求
实现浏览器中发送 Ajax 请求到后端,后端响应回来一个 json 数据,在前端页面中展示出来。
效果:
3.2 创建数据库及表
3.3 创建项目及导入相关 jar 包
3.4 编写数据库工具类
package com.xszx.util;
import java.sql.*;
public class JDBCUtil {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
String url = "jdbc:mysql:///xszx2?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "root";
Connection connection = null;
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void close(ResultSet rs, Statement st, Connection connection){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st != null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.5 编写实体类
Dept
实体类
package com.xszx.bean;
public class Dept {
private Integer id;
private String dname;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
Emp
实体类
package com.xszx.bean;
import java.util.Date;
public class Emp {
private Integer id;
private String name;
private Integer sex;
private Integer age;
private Date birthday;
private String hobby;
private Dept dept;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
3.6 编写 dao 层代码
EmpDao
接口
package com.xszx.dao;
import com.xszx.bean.Emp;
public interface EmpDao {
Emp getById(Integer id);
}
EmpDaoImpl
实现类
package com.xszx.dao.impl;
import com.xszx.bean.Dept;
import com.xszx.bean.Emp;
import com.xszx.dao.EmpDao;
import com.xszx.util.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class EmpDaoImpl implements EmpDao {
@Override
public Emp getById(Integer id) {
Connection connection = JDBCUtil.getConnection();
String sql = "select e.*, d.id did, d.dname from emp e, dept d where e.did=d.id and e.id=?";
PreparedStatement ps = null;
ResultSet rs = null;
Emp emp = null;
try {
ps = connection.prepareStatement(sql);
ps.setInt(1, id);
rs = ps.executeQuery();
emp = new Emp();
if(rs.next()){
emp.setId(rs.getInt("id"));
emp.setName(rs.getString("name"));
emp.setSex(rs.getInt("sex"));
emp.setAge(rs.getInt("age"));
emp.setBirthday(rs.getDate("birthday"));
emp.setHobby(rs.getString("hobby"));
Dept dept = new Dept();
dept.setId(rs.getInt("did"));
dept.setDname(rs.getString("dname"));
emp.setDept(dept);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.close(rs, ps, connection);
}
return emp;
}
}
3.7 编写 service 层代码
EmpService
接口
package com.xszx.service;
import com.xszx.bean.Emp;
public interface EmpService {
Emp getById(Integer id);
}
EmpServiceImpl
实现类
package com.xszx.service.impl;
import com.xszx.bean.Emp;
import com.xszx.dao.EmpDao;
import com.xszx.dao.impl.EmpDaoImpl;
import com.xszx.service.EmpService;
public class EmpServiceImpl implements EmpService {
@Override
public Emp getById(Integer id) {
EmpDao empDao = new EmpDaoImpl();
Emp emp = empDao.getById(id);
return emp;
}
}
3.8 编写 controller 层代码
BaseServlet
类
package com.xszx.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
String action = req.getParameter("action");
try {
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
EmpServlet
类
package com.xszx.controller;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.xszx.bean.Emp;
import com.xszx.service.EmpService;
import com.xszx.service.impl.EmpServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
@WebServlet("/emp")
public class EmpServlet extends BaseServlet {
protected void getById(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String idStr = req.getParameter("id");
Integer id = Integer.parseInt(idStr);
EmpService empService = new EmpServiceImpl();
Emp emp = empService.getById(id);
// 因为JsonUtil工具类将对象转为json字符串的时候,会将对象中的日期类的值,转为毫秒数的情况;
// 所以,我们在转换前,设置好转为json字符串时日期的格式,这样它就会按照我们指定的格式转换。
JSONConfig jsonConfig = new JSONConfig();
jsonConfig.setDateFormat("yyyy-MM-dd");
String jsonStr = JSONUtil.toJsonStr(emp, jsonConfig);
resp.getWriter().write(jsonStr);
}
}
3.9 编写页面
index.jsp
页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script src="js/jquery-1.7.2.js"></script>
<script>
$(function(){
$('#btn').click(function(){
var id = $('#id').val();
$.get('emp?action=getById', {id: id}, function(res){ // res 就是后端响应回来的json字符串,jQuery的ajax自动帮我们转为json对象了
console.log(res);
var s = "<p>编号:"+res.id+"</p>\n" +
" <p>姓名:"+res.name+"</p>\n" +
" <p>性别:"+(res.sex == 1 ? "男" : "女")+"</p>\n" +
" <p>年龄:"+res.age+"</p>\n" +
" <p>生日:"+res.birthday+"</p>\n" +
" <p>爱好:"+res.hobby+"</p>\n" +
" <p>部门:"+res.dept.dname+"</p>";
$('#content').empty();
$(s).appendTo($('#content'));
}, 'json');
})
})
</script>
</head>
<body>
员工编号: <input type="text" id="id">
<button id="btn">查询</button>
<br>
<div id="content">
</div>
</body>
</html>y
3.10 效果
三、三级联动案例
1. 需求
实现省市县三级联动效果。效果图如下:
2. 创建数据库及表
DROP TABLE IF EXISTS `address`;
CREATE TABLE `address` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`pid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
INSERT INTO `address` VALUES ('1', '山西省', '0');
INSERT INTO `address` VALUES ('2', '山东省', '0');
INSERT INTO `address` VALUES ('3', '河南省', '0');
INSERT INTO `address` VALUES ('4', '太原市', '1');
INSERT INTO `address` VALUES ('5', '晋中市', '1');
INSERT INTO `address` VALUES ('6', '济南市', '2');
INSERT INTO `address` VALUES ('7', '青岛市', '2');
INSERT INTO `address` VALUES ('8', '郑州市', '3');
INSERT INTO `address` VALUES ('9', '洛阳市', '3');
INSERT INTO `address` VALUES ('10', '迎泽区', '4');
INSERT INTO `address` VALUES ('11', '小店区', '4');
INSERT INTO `address` VALUES ('12', '榆次区', '5');
INSERT INTO `address` VALUES ('13', '太谷区', '5');
INSERT INTO `address` VALUES ('14', '历城区', '6');
INSERT INTO `address` VALUES ('15', '历下区', '6');
INSERT INTO `address` VALUES ('16', '崂山区', '7');
INSERT INTO `address` VALUES ('17', '黄岛区', '7');
INSERT INTO `address` VALUES ('18', '金水区', '8');
INSERT INTO `address` VALUES ('19', '中原区', '8');
INSERT INTO `address` VALUES ('20', '老城区', '9');
INSERT INTO `address` VALUES ('21', '西工区', '9');
3. 创建项目及导入相关 jar 包
4. 编写数据库工具类
package com.xszx.util;
import java.sql.*;
public class JDBCUtil {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
String url = "jdbc:mysql:///xszx2?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "root";
Connection connection = null;
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void close(ResultSet rs, Statement st, Connection connection){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st != null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
5. 编写实体类
Address
实体类
package com.xszx.bean;
public class Address {
private Integer id;
private String name;
private Integer pid;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
}
6. 编写 dao 层代码
AddressDao
接口
package com.xszx.dao;
import com.xszx.bean.Address;
import java.util.List;
public interface AddressDao {
List<Address> findAddress(Integer pid);
}
AddressDao
实现类
package com.xszx.dao.impl;
import com.xszx.bean.Address;
import com.xszx.dao.AddressDao;
import com.xszx.util.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class AddressDaoImpl implements AddressDao {
@Override
public List<Address> findAddress(Integer pid) {
Connection connection = JDBCUtil.getConnection();
String sql = "select * from address where pid = ?";
PreparedStatement ps = null;
ResultSet rs = null;
List<Address> list = null;
try {
ps = connection.prepareStatement(sql);
ps.setInt(1, pid);
rs = ps.executeQuery();
list = new ArrayList<>();
while(rs.next()){
Address address = new Address();
address.setId(rs.getInt("id"));
address.setName(rs.getString("name"));
address.setPid(rs.getInt("pid"));
list.add(address);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtil.close(rs, ps, connection);
}
return list;
}
}
7. 编写 service 层代码
AddressService
接口
package com.xszx.service;
import com.xszx.bean.Address;
import java.util.List;
public interface AddressService {
List<Address> findAddress(Integer pid);
}
AddressServiceImpl
实现类
package com.xszx.service.impl;
import com.xszx.bean.Address;
import com.xszx.dao.AddressDao;
import com.xszx.dao.impl.AddressDaoImpl;
import com.xszx.service.AddressService;
import java.util.List;
public class AddressServiceImpl implements AddressService {
@Override
public List<Address> findAddress(Integer pid) {
AddressDao addressDao = new AddressDaoImpl();
List<Address> list = addressDao.findAddress(pid);
return list;
}
}
8. 编写 controller 层代码
BaseServlet
类
package com.xszx.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
String action = req.getParameter("action");
try {
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
AddressServlet
类
package com.xszx.controller;
import cn.hutool.json.JSONUtil;
import com.xszx.bean.Address;
import com.xszx.service.AddressService;
import com.xszx.service.impl.AddressServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/address")
public class AddressServlet extends BaseServlet {
protected void findAddress(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pidStr = req.getParameter("pid");
Integer pid = Integer.parseInt(pidStr);
AddressService addressService = new AddressServiceImpl();
List<Address> list = addressService.findAddress(pid);
String jsonStr = JSONUtil.toJsonStr(list);
resp.getWriter().write(jsonStr);
}
}
9. 编写页面代码
index.jsp
页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script src="js/jquery-1.7.2.js"></script>
<script>
$(function(){
// 查询所有的省份
function findProvince(){
$.get('address?action=findAddress', {pid: 0}, function(res){
console.log(res);
var s = "";
for(var i = 0; i < res.length; i++){
s += "<option value='"+res[i].id+"'>"+res[i].name+"</option>";
}
$(s).appendTo($('#province'));
}, 'json');
}
// 调用查询省份的方法,对省份数据进行初始化
findProvince();
// 给省份下拉框绑定内容改变事件,一旦省份内容改变,就查询相应的城市
$('#province').change(function(){
$.get('address?action=findAddress', {pid: $(this).val()}, function(res){
console.log(res);
var s = "";
for(var i = 0; i < res.length; i++){
s += "<option value='"+res[i].id+"'>"+res[i].name+"</option>";
}
// 将之前的城市清空掉
$('#city option:not(:first)').remove();
// 将之前的县区清空掉
$('#area option:not(:first)').remove();
$(s).appendTo($('#city'));
}, 'json');
});
// 给城市下拉框绑定内容改变事件,一旦城市发生改变,查询相应的县区
$('#city').change(function(){
$.get('address?action=findAddress', {pid: $(this).val()}, function(res){
console.log(res);
var s = "";
for(var i = 0; i < res.length; i++){
s += "<option value='"+res[i].id+"'>"+res[i].name+"</option>";
}
// 将之前的县区清空掉
$('#area option:not(:first)').remove();
$(s).appendTo($('#area'));
}, 'json');
});
})
</script>
</head>
<body>
<div>
省份:
<select id="province">
<option value="">请选择省份</option>
</select>
</div>
<div>
城市:
<select id="city">
<option value="">请选择城市</option>
</select>
</div>
<div>
县区:
<select id="area">
<option value="">请选择县区</option>
</select>
</div>
</body>
</html>
四、综合案例
1. 需求
在上面 Ajax 案例
代码的基础之上,继续编写关于员工的:
- 列表展示+条件查询+分页功能
- 添加员工功能
- 修改员工功能
- 删除员工功能
要求:
所有发送给后端的请求都必须使用 Ajax 。