一、实验一(发送简单请求参数)
1、导入 jar 包
在进行 Ajax 操作时,SpringMVC 会需要将 JSON 数据和 Java 实体类进行相互转换,为了实现这个效果,在 SpringMVC 基础 jar 包组合的基础上,再导入
jackson-all-1.9.11.jar
因为 SpringMVC 需要使用 jackson-all-1.9.11.jar 实现 JSON 字符串和 Java 对象的互转。
2、配置 xml
web.xml 还是常规配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
<filter> <filter-name>characterEncodingFilter</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter>
<filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
加入 characterEncodingFilter 和没有加入 characterEncodingFilter ,IDEA 输出效果:
配置 spring-mvc.xml 配置文件,配置自动扫描的包,同时打开注解驱动
1 2 3 4
| <context:component-scan base-package="com.atguigu.ajax.controller"/>
<mvc:annotation-driven/> <mvc:default-servlet-handler/>
|
关于<mvc:default-servlet-handler/>
通过 web.xml 中对 url-pattern 的配置,所有 URL 请求都将被 Spring MVC 的 DispatcherServlet 截获
在 spring-mvc.xml 中配置<mvc:default-servlet-handler />后,会在 Spring MVC 上下文中定义一个 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它会像一个检查员,对进入 DispatcherServlet 的 URL 进行筛查。如果发现是静态资源的请求,就将该请求转由 Web 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet 继续处理。
一般 Web 应用服务器默认的 Servlet 名称是”default”,因此 DefaultServletHttpRequestHandler 可以找到它。如果你所有的 Web 应用服务器的默认 Servlet 名称不是”default”,则需要通过 default-servlet-name 属性显示指定:
<mvc:default-servlet-handler default-servlet-name=”所使用的 Web 服务器默认使用的 Servlet 名称” />
3、配置 index.jsp
① 导入 jquery
jquery-1.7.2
放到 web/script/目录下
②index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Ajax</title> <script type="text/javascript" src="${pageContext.request.contextPath}/script/jquery-1.7.2.js" ></script> <script type="text/javascript"> $(function () {
$("#btn01").click(function () {
$.ajax({ "url":"${pageContext.request.contextPath}/ajax/exer/one", "type":"post", "dataType":"text", "contentType":"application/x-www-form-urlencoded", "data":{ "userName":"约翰", "userPwd":"123456" }, "success":function (response) { console.log(response); }, "error":function (response) { console.log(response); } }); }); </script> </head> <body> <button id="btn01">实验1</button> <button id="btn02">实验2</button> <button id="btn03">实验3</button> </body> </html>
|
③ 创建 AjaxController 类
在 com.atguigu.ajax.controller 包下创建,写出对应的后端程序,实现服务器端给响应体设置内容类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
@RestController public class AjaxController {
@RequestMapping(value = "/ajax/exer/one", produces = "text/html;charset=UTF-8") public String ajaxExerOne( @RequestParam("userName") String userName, @RequestParam("userPwd") String userPwd) {
System.out.println("userName = " + userName); System.out.println("userPwd = " + userPwd);
return "服务器端返回数据啦!"; } }
|
没有加入 produces 属性 和 加入 produces 属性,浏览器端 console.log 输出结果:
最后查看浏览器端发送的数据:
Form Data 就表示它是一个普通的表单数据。
二、实验二(服务器端返回 JSON 数据)
1 2 3 4 5 6 7 8
| // 实验2:服务器端返回JSON数据 $("#btn02").click(function () { $.ajax({ "url":"${pageContext.request.contextPath}/ajax/exer/two.json", "type":"post", "dataType":"json", // 这里设置为json后,jQuery会自动把JSON字符串转换为JSON对象,所以下面的方法中可以直接访问属性名 "success":function (response) { console.log(response); console.log(response.soldierId); console.log(response.soldierName); console.log(response.soldierSalary); }, "error":function (response) { console.log(response); } }); });
|
在 AjaxController 类下增加方法
1 2 3 4 5 6 7 8 9 10 11
|
@RequestMapping(value = "/ajax/exer/two", produces = "application/json;charset=UTF-8") public Soldier ajaxExerTwo() {
Soldier soldier = new Soldier(20, "杰克", 6000.00);
return soldier; }
|
三、实验三(浏览器端给服务器端发送 JSON 请求体)
测试数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $("#btn03").click(function () { // 1.创建JSON对象 var student = { "stuId":556, "stuName":"carl", "school":{ "schoolId":339, "schoolName":"atguigu" }, "subjectList":[ { "subjectName":"java", "subjectScore":50 }, { "subjectName":"PHP", "subjectScore":35 }, { "subjectName":"python", "subjectScore":24 } ], "teacherMap":{ "aaa":{ "teacherName":"zhangsan", "teacherAge":20 }, "bbb":{ "teacherName":"zhangsanfeng", "teacherAge":108 }, "ccc":{ "teacherName":"zhangwuji", "teacherAge":25 } } }; // 2.将JSON对象转换为JSON字符串★ var jsonStr = JSON.stringify(student); // 3.发送Ajax请求 $.ajax({ "url":"${pageContext.request.contextPath}/ajax/exer/three", "type":"post", "dataType":"text", "data":jsonStr, // 这里我们发送JSON字符串作为请求体 "contentType":"application/json;charset=UTF-8", // 这里必须设置请求体的内容类型 "success":function (response) { console.log(response); }, "error":function (response) { console.log(response); } }); });
|
在 AjaxController 类下增加方法
1 2 3 4 5 6 7 8 9 10 11 12
| // @ResponseBody注解。这个注解的作用是把当前handler方法的返回值直接作为响应数据返回给浏览器而不是进行视图名称的解析。 @RequestMapping("/ajax/exer/three") public String ajaxExerThree(
// 使用@RequestBody注解标记后,SpringMVC会自动将请求体的JSON数据转换为这里需要的Java实体类对象 // @RequestBody注解也需要jackson的支持 @RequestBody Student student) {
System.out.println("student = " + student);
return "success"; }
|
结果:
需要注意的点:
- Ajax 程序:
- 请求方式必须是 post
- 必须把 JSON 对象转换为 JSON 字符串
- 必须把 JSON 字符串赋值给 data 属性
- 请求体的内容类型(contentType 属性)必须是:application/json;charset=UTF-8
- handler 方法:
- 必须将 jackson 的 jar 包导入进来
- 必须使用@RequestBody 属性修饰 handler 方法形参位置的实体类对象
四、伪静态技术
在 DispatcherServlet 配置中把 url-pattern 设置为*.html,就要求所有普通请求必须以 html 作为扩展名。这样一来,访问 SpringMVC 的请求表面上看起来像是访问 HTML 静态页面,这样的效果我们称之为:伪静态。
伪静态的好处:
- 有利于 SEO 优化,让搜索引擎更容易找到我们的网站。
- 隐藏后端具体实现细节,让外界不容易猜到我们后端使用的技术体系,从而给黑客入侵增加难度。
但是如果要求请求扩展名为 html,但是实际上服务器端返回 JSON 数据,就会出现 406 错误,表示:请求的数据格式和实际返回的数据格式不一致,“挂羊头,卖狗肉”。
解决办法有两种:
- 方案 A:增加和实际返回数据格式一致的 url-pattern
- 方案 B:增加 HTTP 协议中没有定义的请求扩展名
1 2 3 4 5 6 7 8 9 10 11 12 13
| <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.json</url-pattern>
<url-pattern>*.atguigu</url-pattern> </servlet-mapping>
|