JSON数据交互
JSON与XML非常相似,都是用于存储数据的,但JSON相对于XML来说,解析速度更快,占用空间更小。
JSON概述
JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交互格式。采用完全独立于编程语言的文本格式来存储和表示数据。
与XML一样,JSON也是基于纯文本的数据格式。我们可以使用JSON传输一个简单的String、Number、Boolean,也可以传输一个数组或者一个复杂的Object对象。JSON有两种数据结构:对象结构和数组结构。
对象结构
对象结构的语法结构代码如下:
{
key1:value1,
key2:value2,
....
}
其中关键字(key)必须为String类型,值(value)可以是String、Number、Object、Array等数据类型。例如,一个address对象包含城市、街道等信息,使用JSON的表示形式如下:
{"city":"邵阳","street":"北塔区"}
数组结构
数组结构的语法结构如下:
{
value1,
values2,
.....
}
例如,一个数组包含String、Number、Boolean、null类型数据,使用JSON的表示形式如下:
{"jack",27,false,null}
JSON这两种数据结构可以分别组合构成更为复杂的数据结构。例如,一个person对象包含name、hobby和address对象,其代码表示形式如下:
{
"name":"小鑫",
"hobby":["编程","UI"],
"address":{
"city":"邵阳",
"street":"北塔区"
}
}
JSON数据转换
为了实现浏览器与控制器类(Controller)之间的数据交互,Spring提供了HttpMessageConverter接口,该接口主要用于将请求消息中的数据转换为一个类型为T的对象,并将类型为T的对象绑定到请求方法的参数中,或者将对象转换为响应消息传递给浏览器显示。
Spring为HttpMeesageConverter< T>接口提供了很多实现类,这些实现类可以对不同类型的数据进行信息转换。其中MappingJacksona2HttpMessageConverter是SpringMVC默认处理JSON格式请求响应的实现类。该实现类利用jackson开源包读写Json数据,将Java对象转换为JSON对象和XML文档,同时可以将JSON对象和XML文档转换为Java对象。
因此我们需要再pom.xml中导入jackson相关的坐标,代码如下:
<!--json和javabean对象相互转换所需要的jar包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
在使用注解式开发时,需要用到两个重要的JSON格式转换注解@RequestBody和@ResponseBody。
- @RequestBody:用于将请求体的数据绑定到方法的形参中,该注解用在方法的形参上。
- @ResponseBody:用于直接返回return对象,该注解用在方法上。
代码实现
构造环境
创建Maven项目,并导入pom.xml坐标。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- 版本锁定 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.6.RELEASE</version> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!--json和javabean对象相互转换所需要的jar包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--配置编码过滤器-->
<filter>
<filter-name>CharacterEncodeingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodeingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<!--配置前端过滤器-->
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--初始化时加载配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<!--表示容器来启动时立即加载Servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
springmvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--定义扫描器-->
<context:component-scan base-package="com.ssm.controller"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置注解驱动-->
<mvc:annotation-driven/>
<!--配置静态资源的访问映射,此配置中的文件将不被前端控制器拦截-->
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
</beans>
上述代码中,不仅配置了组件扫描器和视图解析器,还配置了Spring MVC的注解驱动< mvc:annotation-driven/>和静态资源访问映射< mvc:resources…/>。
其中< mvc:annotation-driven/>配置会自动注册RequestMappingHandlerMapping和RequestMappingHandlerAdapter两个Bean,并提供对读写XML和读写JSON等功能的支持。
< mvc:resources…/>元素用于配置静态资源的访问路径。由于在web.xml中配置的"/"会对页面中引入的静态文件进行拦截,而拦截后页面中将找不到这些静态资源文件,因此会引起页面报错。而增加了静态资源的访问映射配置后,程序会自动地去配置路径下找静态的内容。
< mvc:resources…/>中两个重要属性location和mapping
- location:用于定位需要访问的本地静态资源文件路径,具体到某个文件夹。
- mapping:匹配静态资源全路径,其中"/"表示文件夹及其子文件下的某个具体文件。
Customer.java
创建Customer类,该类用于封装Customer类型的请求参数,代码如下:
package com.ssm.po;
//客户类Customer
public class Customer {
private Integer id;
private String loginname; //客户登录名
private String nickname; //昵称
private String password;//密码
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", loginname='" + loginname + '\'' +
", nickname='" + nickname + '\'' +
", password='" + password + '\'' +
'}';
}
}
json.jsp
在webapp目录下创建文件json.jsp来测试JSON数据交互,这样可以直接在浏览器中访问json.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试JSON交互</title>
<script type="text/javascript" src="https://www.imooc.com/static/lib/jquery/1.9.1/jquery.js"></script>
<script type="text/javascript">
$(function () {
$("#btn").click(function () {
//获取输入的客户信息
var loginname=$("#loginname").val();
var password=$("#password").val();
$.ajax({
url:"${pageContext.request.contextPath}/testJson",
type:"post",
//data表示发送的数据
data:JSON.stringify({loginname:loginname,password:password}),
//定义发送请求的数据格式为JSON字符串
contentType:"application/json;charset=UTF-8",
//定义回调响应的数据格式为JSON字符串,该属性可以省略
dataType:"json",
//成功响应的结果
success:function (data) {
if(data!=null){
alert("您输入的登录名为:"+data.loginname+"密码为 "+data.password);
}
}
})
})
})
</script>
</head>
<body>
登录名:<input type="text" name="loginname" id="loginname"/><br/>
密码: <input type="text" name="password" id="password"/> <br/>
<input type="button" value="测试JSON" id="btn">
</body>
</html>
当点击"测试JSON交互"按钮时,我们使用了JQuery的AJAX方式将JSON格式的登录名和密码传递到以"/testJson"结尾的请签字。
在AJAX有3个特别重要的属性
- data: 请求时携带的数据,当使用JSON格式时,需要注意编写规范
- contentType: 当请求数据为JSON格式时,值必须为application/json
- dataType: 当响应数据为JSON时,可以定义dataType属性,并且值必须为json。其中dataType:“json” 可以省略不写,页面会自动识别响应的数据格式
注意: json.jsp还需要引入jquery.js文件。
CustomerController.java
package com.ssm.controller;
import com.ssm.po.Customer;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class CustomerController {
//接收页面请求的JSON数据,并返回JSON数据格式
@RequestMapping(value = "/testJson",method = RequestMethod.POST)
public @ResponseBody Customer testJson (@RequestBody Customer customer){
//打印接收到的JSON格式数据
System.out.println(customer);
return customer;
}
}
方法中的@RequestBody注解用于将前端请求体中的JSON格式数据绑定到形参customer上,@ResponseBody注解用于直接返回Custome对象(当返回POJO对象时,会默认转换为JSON格式数据进行响应)。
启动项目,访问地址"http://localhost:8081/json.jsp", 显示效果如下:
当我们输入用户名和密码后,点击"测试JSON"按钮,如果页面弹出一个对话框,说明我们已经实现了JSON数据交互,可以将JSON格式的请求数据转换为方法中的Java对象,也可以将Java对象转换为JSON格式的响应数据。
RESTful支持
什么是RESTful
RESTful也称为REST(Representational State Transfer),可以将它理解为一种软件架构风格或设计风格。
RESTful风格就是把请求参数变成请求路径的一种风格。例如:传统的URL请求格式如下:
http://...//queryitems?id=1
而采用RESTful风格后,其URL请求为:
http://..../items/1
从上述两个请求中可以看出,RESTful风格中的URL将请求参数id=1变成了请求路径的一部分,并且URL中的queryItems也变成了items(RESTful风格中的URL不存在动词形式的路径).
RESTful风格在HTTP请求中使用put、delete、post和get方法分别对应添加、删除、修改和查询的操作。
代码实现—查询客户信息
CustomerController.java
//接收RESTful风格的请求,其接收方式为GET
@RequestMapping(value = "/customer/{id}",method = RequestMethod.GET)
@ResponseBody
public Customer selectCustomer(@PathVariable("id") Integer id){
//查看接收数据
System.out.println(id);
Customer customer = new Customer();
//模拟根据id查询出客户对象数据
if(id==10){
customer.setLoginname("xiaoxin");
}
//返回JSON格式的数据
return customer;
}
在上述代码中,value="/user/{id}“表示可以匹配以”/user/{id}"结尾的请求,id为请求中的动态参数;method=RequestMethod.Get表示只接收GET方式的请求。
方法中的@PathVariable(“id”)注解则用于接收并绑定请求参数,它可以将请求URL中的变量映射到方法的形参上,如果请求参数中的id和方法形参名称id一样,则@PathVariable后面的(“id”)可以省略。
例如,在浏览器中访问 http://localhost:8081/user/1,那么方法中的id就为1,如果访问的是user/2,那么方法中的id就为2。
restful.jsp
在webapp下创建restful.jsp文件,这样浏览器可以直接访问restful.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>RESTful测试</title>
<script type="text/javascript" src="https://www.imooc.com/static/lib/jquery/1.9.1/jquery.js"></script>
<script type="text/javascript">
$(function () {
$("#btn").click(function () {
//获取输入查询编号
var id = $("#number").val();
//发送ajax请求
$.ajax({
url:"${pageContext.request.contextPath}/customer/"+id,
type:"GET",
//定义回调响应的数据格式为JSON字符串,该属性可以省略
dataType:"json",
success:function (data) {
if(data.loginname!=null){
alert("查询的客户为"+data.loginname)
}else{
alert("没找到客户编号为"+id+"的客户")
}
}
})
})
})
</script>
</head>
<body>
客户编号:<input type="text" name="number" id="number"/> <br/>
<input type="button" value="查询" id="btn">
</body>
</html>
启动项目,访问地址http://localhost:8081/restful.jsp,页面如下:
点击查询按钮,浏览器会弹出客户信息窗口,说明我们已经成功地使用RESTful风格的请求查询出了客户信息。