1. 概述

本教程将演示如何使用 AngularJS 作为前端,Spring Data REST 作为后端,构建一个简单的 CRUD 应用程序。我们将通过实际代码展示前后端交互的核心逻辑,适合有经验的开发者快速上手。

2. 创建 REST 数据服务

2.1. 数据持久化配置

使用 Spring Data REST 实现数据持久化支持,配置基于 H2 内存数据库。核心数据模型 WebsiteUser 包含以下属性:

  • id:主键
  • name:用户名
  • email:邮箱

通过定义 UserRepository 接口,Spring 会自动创建 REST 资源端点:

@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends CrudRepository<WebsiteUser, Long> {}

2.2. 集合资源接口

访问 GET /users 接口可获取所有用户列表,返回 JSON 格式如下:

{
  "_embedded" : {
    "users" : [ {
      "name" : "Bryan",
      "email" : "bryan@example.com",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users/1"
        },
        "User" : {
          "href" : "http://localhost:8080/users/1"
        }
      }
    } ]
  }
}

2.3. 单项资源接口

针对单个用户的操作接口:

操作 方法 URL 请求体 响应状态
查询 GET /users/{id} 200 OK
新增 POST /users {name: "Bryan", email: "bryan@example.com"} 201 Created
更新 PATCH /users/{id} {name: "Bryan", email: "new@example.com"} 200 OK
删除 DELETE /users/{id} 204 No Content

⚠️ 踩坑提醒:更新操作必须使用 PATCH 而非 PUT,否则可能导致未提交字段被置空!

2.4. MVC 配置

添加基础 MVC 配置以支持 HTML 页面访问:

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
    
    @Override
    public void configureDefaultServletHandling(
      DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

   @Bean
   WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> enableDefaultServlet() {
     return (factory) -> factory.setRegisterDefaultServlet(true);
   }
}

2.5. 跨域支持

为前后端分离部署启用跨域请求,在 Repository 接口添加注解:

@CrossOrigin
@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends CrudRepository<WebsiteUser, Long> {}

3. 构建 AngularJS 客户端

3.1. 前端依赖引入

users.html 中引入 AngularJS 核心库:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="view/app.js"></script>

3.2. Angular 服务封装

创建 UserCRUDService 服务封装 REST 调用逻辑:

app.service('UserCRUDService', ['$http', function($http) {
    // 获取单个用户
    this.getUser = function(userId) {
        return $http({
            method: 'GET',
            url: 'users/' + userId
        });
    }
    
    // 新增用户
    this.addUser = function(name, email) {
        return $http({
            method: 'POST',
            url: 'users',
            data: { name: name, email: email }
        });
    }
    
    // 更新用户
    this.updateUser = function(id, name, email) {
        return $http({
            method: 'PATCH',
            url: 'users/' + id,
            data: { name: name, email: email }
        });
    }
    
    // 删除用户
    this.deleteUser = function(id) {
        return $http({
            method: 'DELETE',
            url: 'users/' + id
        });
    }
    
    // 获取所有用户
    this.getAllUsers = function() {
        return $http({
            method: 'GET',
            url: 'users'
        });
    }
}]);

3.3. 控制器实现

创建 UserCRUDCtrl 控制器处理业务逻辑:

app.controller('UserCRUDCtrl', ['$scope', 'UserCRUDService', 
  function($scope, UserCRUDService) {
      // 查询单个用户
      $scope.getUser = function() {
          UserCRUDService.getUser($scope.user.id)
            .then(function success(response) {
                $scope.user = response.data;
                $scope.message = '';
                $scope.errorMessage = '';
            }, function error(response) {
                $scope.errorMessage = response.status === 404 ? 
                    'User not found!' : 'Error getting user!';
            });
      };
      
      // 新增用户
      $scope.addUser = function() {
          if (!$scope.user?.name) {
              $scope.errorMessage = 'Please enter a name!';
              return;
          }
          UserCRUDService.addUser($scope.user.name, $scope.user.email)
            .then(function success() {
                $scope.message = 'User added!';
                $scope.errorMessage = '';
            }, function error() {
                $scope.errorMessage = 'Error adding user!';
            });
      };
      
      // 更新用户
      $scope.updateUser = function() {
          UserCRUDService.updateUser($scope.user.id, 
            $scope.user.name, $scope.user.email)
            .then(function success() {
                $scope.message = 'User data updated!';
            }, function error() {
                $scope.errorMessage = 'Error updating user!';
            });
      };
      
      // 删除用户
      $scope.deleteUser = function() {
          UserCRUDService.deleteUser($scope.user.id)
            .then(function success() {
                $scope.message = 'User deleted!';
                $scope.user = null;
            }, function error() {
                $scope.errorMessage = 'Error deleting user!';
            });
      };
      
      // 获取所有用户
      $scope.getAllUsers = function() {
          UserCRUDService.getAllUsers()
            .then(function success(response) {
                $scope.users = response.data._embedded.users;
            }, function error() {
                $scope.errorMessage = 'Error getting users!';
            });
      };
}]);

3.4. HTML 页面实现

users.html 中构建用户界面:

<html ng-app="app">
<body>
    <div ng-controller="UserCRUDCtrl">
        <!-- 用户信息表单 -->
        <table>
            <tr>
                <td>ID:</td>
                <td><input type="text" ng-model="user.id" /></td>
            </tr>
            <tr>
                <td>Name:</td>
                <td><input type="text" ng-model="user.name" /></td>
            </tr>
            <tr>
                <td>Email:</td>
                <td><input type="text" ng-model="user.email" /></td>
            </tr>
        </table>

        <!-- 操作按钮 -->
        <div>
            <a ng-click="getUser(user.id)">Get User</a>
            <a ng-click="updateUser()">Update User</a>
            <a ng-click="addUser()">Add User</a>
            <a ng-click="deleteUser()">Delete User</a>
        </div>

        <!-- 用户列表 -->
        <div>
            <a ng-click="getAllUsers()">Get all Users</a>
            <div ng-repeat="usr in users">
                {{usr.name}} ({{usr.email}})
            </div>
        </div>

        <!-- 消息提示 -->
        <div ng-show="message" style="color: green;">{{message}}</div>
        <div ng-show="errorMessage" style="color: red;">{{errorMessage}}</div>
    </div>
</body>
</html>

4. 总结

核心要点回顾

  1. 使用 Spring Data REST 自动生成 CRUD 接口
  2. AngularJS 通过 $http 服务与后端交互
  3. 跨域配置通过 @CrossOrigin 注解实现
  4. 前后端数据双向绑定提升开发效率

简单粗暴的运行方式

mvn spring-boot:run

访问 http://localhost:8080/users.html 即可体验完整功能。

完整代码示例可在 GitHub 项目 中获取。


原始标题:AngularJS CRUD Application with Spring Data REST