Spring3MVC和jQuery的集成
在本教程.我们将使用Spring MVC建立一个简单的基于jQuery的计算器AJAX应用.
为了便于对比.
我们将创建两个页面.
一个传统的页面.
一个是基于AJAX的页面.
什么是jQuery?
一张是AJAX版本.
两者没有什么不同.但是非AJAX版本的将会在另外一个页面显示结果.
我们会看到明显的页面刷新过程
而AJAX版本将在同一个页面上显示结果.
我们几乎感觉不到页面刷新.
在此之前我们添加Spring MVC所必须的配置.
web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app id="WebApp_ID" version="2.4"xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><servlet><servlet-name>spring</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>spring</servlet-name><url-pattern>/</url-pattern></servlet-mapping><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener></web-app>
在web.xml中我们定义servlet:spring.
按照惯例,我们必须声明一个spring-servle.xml
spring-servle.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><!-- 定义一个视图解析器 --><bean id="viewResolver"p:suffix=".jsp" /></beans>
这个XML配置声明一个视图解析器.在控制器中会根据JSP名映射到/ WEB-INF/jsp中相应的位置.
然后创建一个applicationContext.xml.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"><!-- 激活spring的注解. --><context:annotation-config /><!-- 扫描注解组件并且自动的注入spring beans中. 例如,他会扫描@Controller 和@Service下的文件.所以确保此base-package设置正确. --><context:component-scan base-package="org.liukai.tutorial" /><!-- 配置注解驱动的Spring MVC Controller 的编程模型.注:次标签只在 Servlet MVC工作! --><mvc:annotation-driven /></beans>
在webapp下创建一个resources的文件夹用于放置JS和CSS等静态文件.
如下图

然后就是在pom.xml添加必须的jar包

实现一个简单的 POJO service层
ArithmeticService.java
package org.liukai.tutorial.service;import org.apache.log4j.Logger;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Service("arithmeticService")@Transactionalpublic class ArithmeticService {protected static Logger logger = Logger.getLogger("service");/** * 实现一个加法运算 */public Integer add(Integer operand1,Integer operand2){logger.debug("Adding two numbers");return operand1 + operand2;}}这是一个非常简单的POJO service,其中包含了一个实现加法运算的方法:add().
非AJAX版本
首先我们编写一个非AJAX版本的SpringMVC应用程序.
写一个处理用户请求的controller类:NonAjaxController.java
NonAjaxController.java
package org.liukai.tutorial.controller;import javax.annotation.Resource;import org.apache.log4j.Logger;import org.liukai.tutorial.service.ArithmeticService;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;/** * 用于处理非AJAX运算. */@Controller@RequestMapping("/main/nonajax")public class NonAjaxController {protected static Logger logger = Logger.getLogger("controller");@Resource(name = "arithmeticService")private ArithmeticService arithmeticService;/** * 根据请求映射跳转到nonajax-add-page.jsp */@RequestMapping(value = "/add", method = RequestMethod.GET)public String getNonAjaxAddPage() {logger.debug("Received request to show non-AJAX, ordinary add page");// 他将会解析 /WEB-INF/jsp/nonajax-add-page.jspreturn "nonajax-add-page";}/** * 提交表单并进行运算. * @RequestParam表示从JSP页面接收值. * 是springMVC重要的传递参数手段之一. */@RequestMapping(value = "/add", method = RequestMethod.POST)public String add(@RequestParam(value = "inputNumber1", required = true) Integer inputNumber1,@RequestParam(value = "inputNumber2", required = true) Integer inputNumber2,Model model) {logger.debug("Received request to add two numbers");// 实现运算Integer sum = arithmeticService.add(inputNumber1, inputNumber2);// 添加到model返回到页面model.addAttribute("sum", sum);// 他将会解析 /WEB-INF/jsp/nonajax-add-result-page.jsp//并把model传递到该JSP页面.return "nonajax-add-result-page";}}这个controller声明了2个映射:
/main/nonajax/add (GET) - 用于跳转到add页面
/main/nonajax/add (POST) -计算值并将结果返回到指定的页面
下面是JSP页面
nonajax-add-page.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Spring MVC - jQuery 整合教程</title></head><body><h3>Spring MVC - jQuery 整合教程</h3><h4>Non-AJAX version</h4><c:url var="addUrl" value="/main/nonajax/add" /><form method="POST" action="${addUrl}">Demo 1 <div style="border: 1px solid #ccc; width: 250px;">Add Two Numbers: <br/><input id="inputNumber1" name="inputNumber1" type="text" size="5"> +<input id="inputNumber2" name="inputNumber2" type="text" size="5"><input type="submit" value="Add" /> <br/>Sum: (Result will be shown on another page)</div></form></body></html>nonajax-add-result-page.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Spring MVC - jQuery 整合教程</title></head><body><h3>Spring MVC - jQuery 整合教程</h3><h4>Non-AJAX version</h4>Demo 1 Result<div style="border: 1px solid #ccc; width: 250px;">Sum: ${sum}</div></body></html>启动web服务器.
我们添加两个数字:12和13.我们预期为25.
输入URL地址
http://localhost:8080/spring-jquery/main/nonajax/add

得到的结果如下:

注意:结果是在另外一个页面显示的.
AJAX版本
现在让我们使用AJAX版本来实现该功能.
首先还是controller
AjaxController.java
package org.liukai.tutorial.controller;import javax.annotation.Resource;import org.apache.log4j.Logger;import org.liukai.tutorial.service.ArithmeticService;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;@Controller@RequestMapping("/main/ajax")public class AjaxController {protected static Logger logger = Logger.getLogger("controller");@Resource(name = "arithmeticService")private ArithmeticService arithmeticService;/** * 根据映射跳转到指定的页面 */@RequestMapping(value = "/add", method = RequestMethod.GET)public String getAjaxAddPage() {logger.debug("Received request to show AJAX, add page");// 解析 /WEB-INF/jsp/ajax-add-page.jspreturn "ajax-add-page";}/** * 提交表单并进行运算. */@RequestMapping(value = "/add", method = RequestMethod.POST)public @ResponseBodyInteger add(@RequestParam(value = "inputNumber1", required = true) Integer inputNumber1,@RequestParam(value = "inputNumber2", required = true) Integer inputNumber2,Model model) {logger.debug("Received request to add two numbers");// 实现运算Integer sum = arithmeticService.add(inputNumber1, inputNumber2);// @ResponseBody 会自动的将返回值转换成JSON格式// 但是你必须添加jackson的jar包!!!return sum;}}该controll还是声明了两个映射:
/main/ajax/add (GET) - 跳转到指定页面.
/main/ajax/add (POST) - 实现加法的过程.
注意:
POST方法的映射将返回一个注解了@ResponseBody的Integer类型的整数.
这个注解(@ResponseBody)的意思表示:
Spring将返回的数据自动的转换为Json格式.
要实现@ResponseBody的注解必须导入Jackson的包.
Jackson是什么?
JSONArray array = JSONArray.fromCollection(list);PrintWriter out = response.getWriter();out.write("{datalist:" + array + ",totalPages:" + totalPages+ ",curPage:" + toPage + ",pageCount:" + pageSize + ",total:"+ total + "}");out.flush();out.close();return null;
而现在我们只需要在方法返回对象前添加@ResponseBody即可,极大的简化了代码量.
关于JSP页面
ajax-add-page.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><script type="text/javascript" src="/spring-jquery/resources/js/jquery/jquery-1.4.4.min.js"></script><title>Spring MVC - jQuery 整合教程</title></head><body><h3>Spring MVC - jQuery 整合教程</h3><h4>AJAX version</h4>Demo 1<div style="border: 1px solid #ccc; width: 250px;">Add Two Numbers: <br/><input id="inputNumber1" type="text" size="5"> +<input id="inputNumber2" type="text" size="5"><input type="submit" value="Add" onclick="add()" /> <br/>Sum: <span id="sum">(Result will be shown here)</span></div><script type="text/javascript"> function add() {$(function() {$.post("/spring-jquery/main/ajax/add",{ inputNumber1: $("#inputNumber1").val(), inputNumber2: $("#inputNumber2").val() },function(data){// data contains the result// Assign result to the sum id$("#sum").replaceWith('<span id="sum">'+ data + '</span>');});});}</script></body></html>让我们运行web服务器.
http://localhost:8080/spring-jquery/main/ajax/add

输入结果后页面将没有任何动静.如果是用firebug.将会得到 $未定义的错误.
实际上就是jquery没有导入.
可是我们导入的路径的确是正确的啊!
出现这个结果的原因在于web.xml中的
<servlet-mapping><servlet-name>spring</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
他能使得我们的URL没有后缀.做到和JavaEye一样的REST风格的URL
而不是类似以前的http://****/**.do
但是这就有个问题了:
他会把所有的资源文件通过DispatcherServlet进行转发.
可是后缀是.js或.css的你转发给谁?
我们以前是用UrlRewriteFilter来进行URL的重定向.
现在我们通过
<mvc:resources location="/resources/" mapping="/resources/**"/>
来避免DispatcherServlet对静态资源的处理.
但是注意一点.
此功能是在spring3.0.4出现的!所以spring3.0.4之前的版本是没有此注解的
关于这些方面的信息可以看JavaEye一位同学的Blog:
spring3.0.4 新增加的注解(mvc:resources)
所以在applicationContext.xml中我们还需要添加
<mvc:resources location="/resources/" mapping="/resources/**"/>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"><!-- 激活spring的注解. --><context:annotation-config /><!-- 扫描注解组件并且自动的注入spring beans中. 例如,他会扫描@Controller 和@Service下的文件.所以确保此base-package设置正确. --><context:component-scan base-package="org.liukai.tutorial" /><!-- 配置注解驱动的Spring MVC Controller 的编程模型.注:次标签只在 Servlet MVC工作! --><mvc:annotation-driven /><!-- resources下的静态资源不被DispatcherServlet接收处理 --><mvc:resources location="/resources/" mapping="/resources/**"/></beans>
重新输入得到的结果:

可以看到结果是显示在同一页上,极大的提高的用户的体验.而不像非AJAX版本那样需要在另外一个页面显示.
总结:
这样,我们完成了预定的目标:成功的用SpringMVC搭建起了一个简单的基于jQuery的AJAX应用程序.我们还了解了如何利用@ResponseBody和Jackson来进行简便的Json操作.
BTW:附件为本次教程源码.你可以下载后直接在tomcat或其他web服务器启动.也可以自行添加
maven插件启动. 1 楼 rocketball 2011-04-21 好贴,今天看到说得最清楚的,要是有spring mvc juery整合的原始资料提供,那就更好了 2 楼 runjia1987 2011-04-22 支持,很清晰明了! 3 楼 zwt2001267 2011-05-02 不错,支持楼主的分享精神和辛苦写作。 4 楼 bushkarl 2011-05-10 rocketball 写道好贴,今天看到说得最清楚的,要是有spring mvc juery整合的原始资料提供,那就更好了
这篇文章也很原始 5 楼 wuliaolll 2011-05-11 我觉得楼主写springmvc教程是好,但最好是纯净的教学,不应用maven,对于没用过maven的人来说,是看得一头雾水,教程没有有效地组织起来形成连贯 6 楼 lshoo 2011-05-22 为什么不用Maven?知识点比较简单,容易理解啊。如果用Spring,最好还是用SpringSource Site Tools(sts)。
英文好的可以参考原文:krams915.blogspot.com 7 楼 mojunbin 2011-11-21 很不错嘛~~呵呵。喜欢这类帖子,虽然不算深入,但是至少清晰条理