REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。

最近尝试了一下springmvc框架和google的angularjs进行整合,发现了很多的问题,并且有很多问题无法在网络上找到。幸运的是最后成功把问题都调通了。那么下面我来把自己遇到的问题总结一下。

首先我们要搭建我们的springmvc框架,最初遇到的这个框架感觉很高端,但其实项目的搭建是非常简单的。多的不说先来看一下,最早加载的web.xml吧!


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>springmvc</display-name>
    <!--配置springmvc并加载spring的xml配置文件 -->
    <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:applicationContext.xml,classpath:spring/**/spring-*.xml</param-value>
            <!--<param-value>classpath:spring/spring-mvc.xml</param-value> -->
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--配置springmvc的url访问路径 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--默认的访问文件类型,配置后这些拓展名结尾的不被收录为访问请求 -->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpg</url-pattern>
    </servlet-mapping>
    <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>
    <!--自己写的过滤器,可以使用spring自带的,详细的情况大家自己查阅一下 -->
    <!-- <filter> <filter-name>encodingFilter</filter-name> <filter-class>com.ice.springmvc.filter.MyFilter</filter-class>
        </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern>
        </filter-mapping> -->
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>



上面已经有比较详细的注释,我就不在这里赘述了。不过有一点需要简单说明一下,contextConfigLocation配置的使用了通配符的形式,这样就我们可以使用以spring-开头来命名spring配置文件,并且放到指定的目录下,这样就可以一劳永逸了。

下面来看一下,spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    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">
    <!--该配置为自动扫描配置的包下所有使用@Controller注解的类 -->
    <context:component-scan base-package="com.ice.personnel.controller" />
    <!--注解驱动,使spring的controller全部生效 -->
    <mvc:annotation-driven />
    <!--跳转页面使用,如果不配置的话,那么我们springmvc返回页面的时候,会被认为是请求url处理,所以就无法到达想要跳转的页面。这是因为web.xml里面配置的访问路径为'/'也就是所有访问路径都被认为是请求url -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>




以上是这个文件的配置,基本的功能我都写到注释中了,如果有不明白的大家可以在回复中提出来。

都搞定了之后我们来看看Controller类是怎么实现的。



package com.ice.personnel.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.WebUtils;
import com.ice.personnel.bean.User;
import com.ice.personnel.service.IUserService;
@Controller
@RequestMapping(value = "/user")
public class UserController {
    /**
     * 添加用户(该方法用来测试ajax正常调用)
     *
     * @return
     */
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> addUser(HttpServletRequest request,
            HttpServletResponse response) {
        User user = new User();
        user.setUsername("ice");
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            userService.saveOrUpdateUser(user);
            map.put("flag", true);
        } catch (Exception e) {
            map.put("flag", false);
        }
        return map;
    }
    /**
     * 获取用户列表()
     *
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/getUserList", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getUserList(HttpServletRequest request,
            HttpServletResponse response) {
        String sPage = WebUtils.findParameterValue(request, "page");
        String sPageSize = request.getParameter("pageSize");
        int page = Integer.parseInt(sPage);
        int pageSize = Integer.parseInt(sPageSize);
        Map<String, Object> map = new HashMap<String, Object>();
        List<User> userList = userService.getUserList(page, pageSize);
        map.put("userList", userList);
        return map;
    }
    /**
     * 获取用户列表
     *
     * @return
     */
    @RequestMapping(value = "/userList", method = RequestMethod.GET)
    @ResponseBody
    public List<User> getUserList(HttpServletRequest request) {
        String sPage = WebUtils.findParameterValue(request, "page");
        String sPageSize = request.getParameter("pageSize");
        int page = Integer.parseInt(sPage);
        int pageSize = Integer.parseInt(sPageSize);
        List<User> userList = userService.getUserList(page, pageSize);
        return userList;
    }
    /**
     * 添加用户
     *
     * @return
     */
    @RequestMapping(value = "/add", method = RequestMethod.PUT)
    @ResponseBody
    public List<User> addUser(@RequestBody User user, HttpServletRequest request) {
        String sPage = WebUtils.findParameterValue(request, "page");
        String sPageSize = request.getParameter("pageSize");
        int page = Integer.parseInt(sPage);
        int pageSize = Integer.parseInt(sPageSize);
        userService.saveOrUpdateUser(user);
        List<User> userList = userService.getUserList(page, pageSize);
        return userList;
    }
    /**
     * 更新用户
     *
     * @param user
     *            前台获取用户对象
     * @param request
     *            请求对象
     * @return
     */
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @ResponseBody
    public List<User> updateUser(@RequestBody User user,
            HttpServletRequest request) {
        String sPage = WebUtils.findParameterValue(request, "page");
        String sPageSize = request.getParameter("pageSize");
        int page = Integer.parseInt(sPage);
        int pageSize = Integer.parseInt(sPageSize);
        userService.saveOrUpdateUser(user);
        List<User> list = userService.getUserList(page, pageSize);
        return list;
    }
    /**
     * 删除用户
     *
     * @param request
     *            请求对象
     * @return
     */
    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
    @ResponseBody
    public List<User> deleteUser(HttpServletRequest request) {
        String userId = request.getParameter("id");
        String sPage = WebUtils.findParameterValue(request, "page");
        String sPageSize = request.getParameter("pageSize");
        int page = Integer.parseInt(sPage);
        int pageSize = Integer.parseInt(sPageSize);
        User user = new User(userId);
        userService.deleteUser(user);
        List<User> list = userService.getUserList(page, pageSize);
        return list;
    }
    /**
     * 用户业务接口
     */
    @Autowired
    private IUserService userService;
}



我这里写的类比较乱,因为我把所有的异常都拿到Controller这里处理了。大家可能注意到了@ResponseBody这个可以保证该方法的返回值为json格式,因为我是为了做单页面程序才这样做的,只做数据的交换不做页面的跳转,springmvc的页面跳转网上的教程有很多我就不介绍了。

还有一点需要说明的是@RequestBody这个标注是为了将前台传递进来js的Object自动封装成相应的对象。前提是属性要一致。后台的基本配置已经基本准备好了。

还有restful我个人理解是一种思想,具体了解该方面的知识可以参考百度、google等搜索引擎

我把User这个类也贴一下:


package com.ice.personnel.bean;
/**
 * @author ice
 *
 */
public class User {
    public User() {
    }
    public User(String id) {
        this.id = id;
    }
    /**
     * @return the id
     */
    public String getId() {
        return id;
    }
    /**
     * @param id
     *            the id to set
     */
    public void setId(String id) {
        this.id = id;
    }
    /**
     * @return the username
     */
    public String getUsername() {
        return username;
    }
    /**
     * @param username
     *            the username to set
     */
    public void setUsername(String username) {
        this.username = username;
    }
    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }
    /**
     * @param password
     *            the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }
    /**
     * @return the realname
     */
    public String getRealname() {
        return realname;
    }
    /**
     * @param realname
     *            the realname to set
     */
    public void setRealname(String realname) {
        this.realname = realname;
    }
    /**
     * @return the email
     */
    public String getEmail() {
        return email;
    }
    /**
     * @param email
     *            the email to set
     */
    public void setEmail(String email) {
        this.email = email;
    }
    /**
     * @return the address
     */
    public String getAddress() {
        return address;
    }
    /**
     * @param address
     *            the address to set
     */
    public void setAddress(String address) {
        this.address = address;
    }
    /**
     * @return the zip
     */
    public int getZip() {
        return zip;
    }
    /**
     * @param zip
     *            the zip to set
     */
    public void setZip(int zip) {
        this.zip = zip;
    }
    /**
     * @return the identityCard
     */
    public String getIdentityCard() {
        return identityCard;
    }
    /**
     * @param identityCard
     *            the identityCard to set
     */
    public void setIdentityCard(String identityCard) {
        this.identityCard = identityCard;
    }
    /**
     * id
     */
    private String id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 真实姓名
     */
    private String realname;
    /**
     * 电子邮箱
     */
    private String email;
    /**
     * 地址
     */
    private String address;
    /**
     * 邮编
     */
    private int zip;
    /**
     * ×××
     */
    private String identityCard;
}


这样就可以准备我们的前台程序了。

前台程序也很简单,只需要两个东东。一个是angular.js,一个是angular-resource.js。因为我前台请求使用了angularjs中的resource模块。具体内容请看这里:http://docs.angularjs.org/api/ngResource.$resource




然后我们来关注一下去前台吧!废话不多说,先直接上代码


<%@ 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 ng-app="userService">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-1.10.2.js"></script>
<script type="text/javascript" src="js/angular.js"></script>
<script type="text/javascript" src="js/angular-resource.js"></script>
<script type="text/javascript" src="js/angular-my.js"></script>
<style type="text/css">
</style>
</script>
</head>
<body ng-controller="userController">
 <div id="save"
  style="display: block; margin-left: auto; margin-right: auto;">
  <table>
   <tr style="display: none">
    <td>用户id</td>
    <td><input type="text" name="user.id" ng-model="saveUser.id" /></td>
   </tr>
   <tr>
    <td>用户名</td>
    <td><input type="text" name="user.username"
     ng-model="saveUser.username" /></td>
   </tr>
   <tr>
    <td>密码</td>
    <td><input type="password" name="user.password"
     ng-model="saveUser.password" /></td>
   </tr>
   <tr>
    <td>用户姓名</td>
    <td><input type="text" name="user.cs"
     ng-model="saveUser.realname" /></td>
   </tr>
   <tr>
    <td colspan="2"><input type="button" value="添加"
     ng-click="addUserClick()" /></td>
   </tr>
  </table>
 </div>
 <div id="userList" style="margin-left: auto; margin-right: auto;">
  <table border="1" style="margin-left: auto; margin-right: auto;">
   <tr>
    <th>序号</th>
    <th>用户id</th>
    <th>用户名称</th>
    <th>用户密码</th>
    <th>用户姓名</th>
    <th>用户操作</th>
   </tr>
   <tr ng-repeat="user in mydata" ng-class-even="'even'"
    ng-class-odd="'odd'">
    <td>{{$index + 1}}</td>
    <td>`user`.`id`</td>
    <td>`user`.`username`</td>
    <td>`user`.`password`</td>
    <td>`user`.`realname`</td>
    <td><a href="" ng-click="updateUser(user)">修改</a> &nbsp; <a
     href="" ng-click="deleteUser(user)">删除</a></td>
   </tr>
  </table>
 </div>
 <div id="update"
  style="display: block; margin-left: auto; margin-right: auto;">
  <table>
   <tr style="display: none">
    <td>用户id</td>
    <td><input type="text" id="id" name="user.id"
     ng-model="modifyUser.id" /></td>
   </tr>
   <tr>
    <td>用户名</td>
    <td><input type="text" id="username" name="user.username"
     ng-model="modifyUser.username" /></td>
   </tr>
   <tr>
    <td>密码</td>
    <td><input type="password" id="password" name="user.password"
     ng-model="modifyUser.password" /></td>
   </tr>
   <tr>
    <td>用户姓名</td>
    <td><input type="text" id="cs" name="user.cs"
     ng-model="modifyUser.realname" /></td>
   </tr>
   <tr>
    <td colspan="2"><input type="button" value="更新"
     ng-click="updateUserClick()" /></td>
   </tr>
  </table>
 </div>
</body>
</html>


var projectName = '/' + window.location.pathname.split('/')[1];
var userUrl = {
    'addUrl' : projectName + '/user/add',
    'deleteUrl' : projectName + '/user/delete',
    'updateUrl' : projectName + '/user/update',
    'queryUrl' : projectName + '/user/userList'
};
var user = angular.module('userService', [ 'ngResource' ], angular.noop);
user.controller('userController', function($scope, $resource) {
    var actions = {
        'add' : {
            method : 'PUT',
            isArray : true,
            headers : {
                'Content-Type' : 'application/json'
            }
        },
        'delete' : {
            method : 'DELETE',
            isArray : true
        },
        'query' : {
            method : 'GET',
            isArray : true
        },
        'update' : {
            method : 'POST',
            isArray : true,
            headers : {
                'Content-Type' : 'application/json'
            }
        }
    };
    var getUserList = $resource(userUrl.queryUrl, {
        page : 1,
        pageSize : 20
    }, actions);
    getUserList.query({}, function(data) {
        subobj = data;
        $scope.mydata = data;
    });
    var userAdd = $resource(userUrl.addUrl, {
        page : 1,
        pageSize : 20
    }, actions);
    $scope.addUserClick = function() {
        userAdd.add($scope.saveUser, function(data) {
            subobj = data;
            $scope.mydata = data;
        });
    };
    var userUpdate = $resource(userUrl.updateUrl, {
        page : 1,
        pageSize : 20
    }, actions);
    $scope.updateUserClick = function() {
        userUpdate.update($scope.modifyUser, function(data) {
            subobj = data;
            $scope.mydata = data;
        });
    };
    var userDelete = $resource(userUrl.deleteUrl, {
        page : 1,
        pageSize : 20,
        id : ':id'
    }, actions);
    $scope.deleteUser = function(user) {
        userDelete['delete']({
            id : user.id
        }, {}, function(data) {
            subobj = data;
            $scope.mydata = data;
        });
    };
    $scope.updateUser = function(user) {
        $scope.modifyUser = user;
    };
});




现在这里已经把代码基本都已经贴出来了,可以根据这个代码写一个自己的单页面程序了。前台后台交互都用json来完成,值得注意一点我们如果获取的返回值为list或者数组形式的数组,那么我们应该在定义resource模块的时候,需要指定isArray: true(否则会浏览器报has no method 'push'的异常)。大致的流程是这样的,由于第一次写这么长的博客,写的不是很好。如果大家有什么问题可以给我留言。

我是通过这几个教程学习的,大家有兴趣可以参考一下他们的博文,对大家会很有帮助。

springmvc restful:http://badqiu.iteye.com/blog/473301

angularjs:http://zouyesheng.com/angular.html (推荐)   、   http://www.angularjs.cn/

可能大家有疑问,搭建这样一个项目需要哪些jar包呢?我是由maven来管理jar包的,pom的简单配置如下:



<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>springmvc</groupId>
    <artifactId>springmvc</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <spring.version>4.0.0.RELEASE</spring.version>
    </properties>
    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <warSourceDirectory>web</warSourceDirectory>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <!--spring framework start -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--spring framework end -->
        <!--commons start -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.1</version>
        </dependency>
        <!--commons end -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
            <scope>test</scope>
        </dependency>
        <!--jstl start -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--jstl end -->
        <!-- hibernate start -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.0.Final</version>
        </dependency>
        <!-- hibernate end -->
        <!-- jackson start -->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>1.9.13</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-lgpl</artifactId>
            <version>1.9.13</version>
        </dependency>
        <!-- jackson end -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.28</version>
        </dependency>
    </dependencies>
</project>



有些是不是必须的jar包,所以可以根据自己的需求来导入。如果不是使用maven来管理的话,可以根据artifactId来到maven资料库上面手动下载一下就可以了。

好了就说到这吧!

有问题留言探讨!


我把代码共享到51CTO的下载区了。稍后给出链接  共享链接:http://pan.baidu.com/s/1sjFC22x