JSON和RESTful
1. JSON数据交互
JSON是近几年才流行的一种新的数据格式,它与XML非常相似,都是用于存储数据的;但JSON相对于XML来说,解析速度更快,占用空间更小。因此在实际开发中,使用JSON格式的数据进行前后台的数据交互是很常见的。
1.1 JSON概述
JSON(JavaScript Object Notation, JS对象标记)是一种轻量级的数据交换格式。它是基于JavaScript的一个子集,使用了C、C++、C#、Java、JavaScript、Perl、Python等其他语言的约定,采用完全独立于编程语言的文本格式来存储和表示数据。这些特性使JSON成为理想的数据交互语言,它易于阅读和编写,同时也易于机器解析和生成。
与XML一样,JSON也是基于纯文本的数据格式。初学者可以使用JSON传输一个简单的String、Number、Boolean,也可以传输一个数组或者一个复杂的Object对象。
JSON有如下两种数据结构
- 对象结构对象结构以“{”开始,以“}”结束。中间部分由0个或多个以英文“, ”分隔的name/value对构成(注意name和value之间以英文“:”分隔),其存储形式如图所示
对象结构的语法结构代码如下。
{
key1:value1,
key2:value2,
...
}
其中关键字(key)必须为String类型,值(value)可以是String、Number、Object、Array等数据类型。例如,一个address对象包含城市、街道、邮编等信息,使用JSON的表示形式如下
{"city":"beijing","street":"xisanqi","postcode":"100096"}
2.数组结构数组结构以“[”开始,以“]”结束。中间部分由0个或多个以英文“, ”分隔的值的列表组成,其存储形式如图所示。
数组结构的语法结构代码如下
[
value1,
value2,
...
]
例如,一个数组包含了String、Number、Boolean、null类型数据,使用JSON的表示形式如下
["abc",12345,false,null]
上述两种(对象、数组)数据结构也可以分别组合构成更为复杂的数据结构。例如:一个person对象包含name、hobby和address对象,其代码表现形式如下。
{
"name":"坤坤",
"hobby":["唱","跳","rap","篮球"]
"address":{
"city":"beijing",
"street":"xisanqi",
"postcode":"100096"
}
}
需要注意的是,如果使用JSON存储单个数据(如“abc”),一定要使用数组的形式,不要使用Object形式,因为Object形式必须是“名称:值”的形式。
1.2 JSON数据转换
为了实现浏览器与控制器类(Controller)之间的数据交互,Spring提供了一个HttpMessageConverter< T >接口来完成此项工作。该接口主要用于将请求信息中的数据转换为一个类型为T的对象,并将类型为T的对象绑定到请求方法的参数中,或者将对象转换为响应信息传递给浏览器显示。
Spring为HttpMessageConverter< T >接口提供了很多实现类,这些实现类可以对不同类型的数据进行信息转换。其中MappingJackson2HttpMessageConverter是Spring MVC默认处理JSON格式请求响应的实现类。该实现类利用Jackson开源包读写JSON数据,将Java对象转换为JSON对象和XML文档,同时也可以将JSON对象和XML文档转换为Java对象。
要使用MappingJackson2HttpMessageConverter对数据进行转换,就需要使用Jackson的开源包,开发时所需的开源包及其描述如下所示。
- jackson-annoations.jar:JSON转换注解包
- jackson-core-2.8.8.jar:JSON转换核心包
- jackson-databind-2.8.8.jar:JSON转换的数据绑定包
在使用注解式开发时,需要用到两个重要的JSON格式转换注解,分别为@RequestBody和@ResponseBody
1.springmvc-config.xml
//其他属性常规配置
<!-- 配置静态资源的访问路径,配置的路径不会被前端控制器拦截 -->
<mvc:resources location="/js/" mapping="/js/**"/>
由于在web.xml中配置的“/”会将页面中引入的静态文件也进行拦截,而拦截后页面中将找不到这些静态资源文件,这样就会引起页面报错。而增加了静态资源的访问映射配置后,程序会自动地去配置路径下找静态的内容
注意:另外需要注意的是,非rest风格的代码下,js资源一般为静态资源,不要放在web-inf下,否则会加载不上
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery-1.11.0.min.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
function testJSON() {
//获取用户名和密码
var username = $("#username").val();
var password = $("#password").val();
$.ajax({
url:"${pageContext.request.contextPath}/testJson",
type:"post",
//data表示发送的数据
data:JSON.stringify({username:username,password:password}),
//数据格式为JSON字符串
contentType:"application/json;charset=utf-8",
//定义回调相应数据格式为JSON,可省略
dataType:"json",
//成功响应结果
success:function(data){
if(data!=null){
alert("您输入的用户名为:"+data.username+"密码为:"+data.password);
}
}
});
}
</script>
</head>
<body>
<form>
用户名:<input type="text" name="username" id="username"/><br/>
密 码:<input type="password" name="password" id="password"/><br/>
<input type="button" value="测试JSON" onclick="testJSON()"/>
</form>
</body>
</html>
需要注意的是,在AJAX中包含了3个特别重要的属性,其说明如下。
- data:即请求时携带的数据,当使用JSON格式时,要注意编写规范
- contentType:当请求数据为JSON格式时,值必须为application/json
- dataType:当响应数据为JSON时,可以定义dataType属性,并且值必须为json。其中dataType : "json"也可以省略不写,页面会自动识别响应的数据格式
1.Controller,用来接收json数据
@Controller
public class UserController {
/**
* 接收页面请求的JSON数据、并返回JSON格式结果
*/
@RequestMapping("/testJson")
@ResponseBody
public User testJSON(@RequestBody User user) {
System.out.println(user);
return user;
}
}
1.3 配置静态资源访问的方式
- 使用< mvc:resources>元素
<mvc:resources location="/js/" mapping="/js/**"/>
- 使用< mvc:default-servlet-handler>标签
<mvc:default-servlet-handler/>
<mvc:default-servlet-handler default-servlet-name="servlet名称"/>
在springmvc-config.xml中配置< mvc:default-servlet-handler />后,会在Spring MVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler(即默认的Servlet请求处理器)。它对进入DispatcherServlet的URL进行筛查。如果发现是静态资源的请求,就将该请求转由Web服务器默认的Servlet处理,默认的Servlet就会对这些静态资源放行;如果不是静态资源的请求,才由DispatcherServlet继续处理
一般Web服务器默认的Servlet名称是"default",因此DefaultServletHttpRequestHandler可以找到它。如果使用的Web应用服务器默认的Servlet名称不是"default",则需要通过default-servlet-name属性显示指定
而Web服务器的Servlet名称是由使用的服务器确定的,常用服务器及其Servlet名称如下。
- Tomcat、Jetty、JBoss和and GlassFish默认Servlet的名称——“default”
- Google App Engine默认Servlet的名称——"_ah_default"
- Resin默认Servlet的名称——“resin-file”
- WebLogic默认Servlet的名称——“FileServlet”
- WebSphere默认Servlet的名称——“SimpleFileServlet”
- 激活Tomcat默认的Servlet来处理静态文件访问
激活Tomcat默认的Servlet时,需要在web.xml中添加以下内容
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
注:此种配置方式和上一种方式本质上是一样的,都是使用Web服务器默认的Servlet来处理静态资源文件的访问。其中Servelt名称(即< servlet-name>元素的值)也是由使用的服务器来确定的,不同的服务器需要使用不同的名称
方法比较:
- 第一和第三种配置方式可以选择性的释放静态资源
- 第二种配置方式配置相对简单,只需要一行代码,就可以释放所有静态资源
- 第二和第三种配置方式会导致项目移植性较差,需要根据具体的Web服务器来更改Servlet名称
- 第三种配置方式运行效率更高,因为服务器启动时已经加载了web.xml中的静态资源
在实际开发中,更为常用的配置还是第一种配置方式,这样就不需要考虑Web服务器的问题了
2. RESTful支持
2.1 什么是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不存在动词形式的路径,如queryItems表示查询订单,是一个动词,而items表示订单,为名词)
1.UserController增加代码
/**
* 接收RESTful风格的请求,其方式为get
*/
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
@ResponseBody
/**
* 方法中的@PathVariable("id")注解则用于接收并绑定请求参数,
* 它可以将请求URL中的变量映射到方法的形参上,如果请求路径为“/user/{id}”,
* 即请求参数中的id和方法形参名称id一样,则@PathVariable后面的“("id")”可以省略
*
* @param id
* @return
*/
public User selectUser(@PathVariable("id") String id) {
System.out.println("id: " + id);
User user = new User();
if (id.equals("1234")) {
user.setUsername("tom");
}
return user;
}
restful.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery-1.11.0.min.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
function search() {
var id = $("#number").val();
$.ajax({
url:"${pageContext.request.contextPath}/user/"+id,
type:"get",
datatype:"json",
success:function(data){
if(data.username!=null){
alert("您查的是:"+data.username);
}else{
alert("没有找到id:"+id)
}
}
});
}
</script>
</head>
<body>
<form action="">
编号:<input type="text" name="number" id="number"><br/>
<input type="button" value="搜索" onclick="search()"/>
</form>
</body>
</html>