SpringMVC + Angularjs

来源:互联网 发布:android水印相机源码 编辑:程序博客网 时间:2024/05/02 18:43

    本博客将展示使用AngularJS和Spring MVC4,我们将创建一个增删查改的应用。前端使用AngularJS,后端使用Spring REST API。AngularJS使用$http服务和后端进行异步通信,同时使用AngularJS进行表单验证。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    在本应用中,客户端是基于AngularJS,服务器端基于Spring REST API。最终本应用界面如下:

功能展示:
   只是为了展示后台使用模拟数据,你也可以进一步扩展程序使所有的数据都保存到数据库中。

让我们开始本应用开发。

所涉及到的技术点为:

  • Spring 4.3.1.RELEASE
  • AngularJS 1.4.4
  • Maven 3
  • JDK 1.7
  • Eclipse JUNO Service Release 2
  • M2Eclipse plugin (Optional)
项目目录结构如下:

maven依赖库如下:

<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/maven-v4_0_0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.websystique.springmvc</groupId>    <artifactId>Spring4MVCAngularJSExample</artifactId>    <packaging>war</packaging>    <version>1.0.0</version>    <name>Spring4MVCAngularJSExample Maven Webapp</name>     <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <springframework.version>4.3.1.RELEASE</springframework.version>        <jackson.version>2.7.5</jackson.version>    </properties>     <dependencies>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>${springframework.version}</version>        </dependency>        <dependency>            <groupId>com.fasterxml.jackson.core</groupId>            <artifactId>jackson-databind</artifactId>            <version>${jackson.version}</version>        </dependency>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>javax.servlet-api</artifactId>            <version>3.1.0</version>        </dependency>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>jstl</artifactId>            <version>1.2</version>        </dependency>    </dependencies>      <build>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.2</version>                <configuration>                    <source>1.7</source>                    <target>1.7</target>                </configuration>            </plugin>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-war-plugin</artifactId>                <version>2.4</version>                <configuration>                    <warSourceDirectory>src/main/webapp</warSourceDirectory>                    <warName>Spring4MVCAngularJSExample</warName>                    <failOnMissingWebXml>false</failOnMissingWebXml>                </configuration>            </plugin>        </plugins>        <finalName>Spring4MVCAngularJSExample</finalName>    </build></project>

1,前端部分
本应用前端是基于angularjs框架的。如果你想增加angularJS的开发水平建议把angularJS官方文档学习一遍,AngularJS是比较流行的前端框架。


创建AngularJS模块
模块是AngularJS应用中最重要的一部分,一个模块可被认为是java中的一个包。模块中可以包含应用的各个部分,控制器,服务,过滤器,指令等。

模块可以被用于AngularJS作为整个程序启动程序。通过增加ng-model这个指令我们能告诉AngularJS从哪里开始作为应用的入口程序。如下是我们定义的模块。想要了解AngularJS模块相关的概念,请阅读官方文档。

app.js

'use strict'; var App = angular.module('myApp',[]);

创建AngularJS服务与服务器进行通信
在我们的应用中,我们将和Spring REST API后台进行通信,前端部分我们将使用AngularJS内建的$http服务。AngularJS 的$http服务封装了XHR对象方便我们
与服务器进行数据交互。$http是基于promise对象传递异步消息。本应用的service如下:

user_service.js

'use strict'; angular.module('myApp').factory('UserService', ['$http', '$q', function($http, $q){     var REST_SERVICE_URI = 'http://localhost:8080/Spring4MVCAngularJSExample/user/';     var factory = {        fetchAllUsers: fetchAllUsers,        createUser: createUser,        updateUser:updateUser,        deleteUser:deleteUser    };     return factory;     function fetchAllUsers() {        var deferred = $q.defer();        $http.get(REST_SERVICE_URI)            .then(            function (response) {                deferred.resolve(response.data);            },            function(errResponse){                console.error('Error while fetching Users');                deferred.reject(errResponse);            }        );        return deferred.promise;    }     function createUser(user) {        var deferred = $q.defer();        $http.post(REST_SERVICE_URI, user)            .then(            function (response) {                deferred.resolve(response.data);            },            function(errResponse){                console.error('Error while creating User');                deferred.reject(errResponse);            }        );        return deferred.promise;    }      function updateUser(user, id) {        var deferred = $q.defer();        $http.put(REST_SERVICE_URI+id, user)            .then(            function (response) {                deferred.resolve(response.data);            },            function(errResponse){                console.error('Error while updating User');                deferred.reject(errResponse);            }        );        return deferred.promise;    }     function deleteUser(id) {        var deferred = $q.defer();        $http.delete(REST_SERVICE_URI+id)            .then(            function (response) {                deferred.resolve(response.data);            },            function(errResponse){                console.error('Error while deleting User');                deferred.reject(errResponse);            }        );        return deferred.promise;    } }]);

请注意如上url部分的硬编码 [http://localhost:8080/],在发布的时候要根据具体的主机/端口号进行调整。

创建AngularJS控制器
控制器是AngularJS应用中最有用的部分,UI中大多数的操作都需要在controller中进行逻辑控制,可被认为是模型和视图改变的驱动程序。是模型和视图之间的网关。控制器主要的职责是为UI提供数据,数据可以是静态的也可以是来自服务器端的,管理展示逻辑,例如什么元素该显示什么元素该隐藏,需要用什么主题等。处理用户输入,例如当用户点击某一控件是会发生什么,输入的数据是否是有效的,处理用户的数据并发给服务器。

user_controller.js

'use strict'; angular.module('myApp').controller('UserController', ['$scope', 'UserService', function($scope, UserService) {    var self = this;    self.user={id:null,username:'',address:'',email:''};    self.users=[];     self.submit = submit;    self.edit = edit;    self.remove = remove;    self.reset = reset;      fetchAllUsers();     function fetchAllUsers(){        UserService.fetchAllUsers()            .then(            function(d) {                self.users = d;            },            function(errResponse){                console.error('Error while fetching Users');            }        );    }     function createUser(user){        UserService.createUser(user)            .then(            fetchAllUsers,            function(errResponse){                console.error('Error while creating User');            }        );    }     function updateUser(user, id){        UserService.updateUser(user, id)            .then(            fetchAllUsers,            function(errResponse){                console.error('Error while updating User');            }        );    }     function deleteUser(id){        UserService.deleteUser(id)            .then(            fetchAllUsers,            function(errResponse){                console.error('Error while deleting User');            }        );    }     function submit() {        if(self.user.id===null){            console.log('Saving New User', self.user);            createUser(self.user);        }else{            updateUser(self.user, self.user.id);            console.log('User updated with id ', self.user.id);        }        reset();    }     function edit(id){        console.log('id to be edited', id);        for(var i = 0; i < self.users.length; i++){            if(self.users[i].id === id) {                self.user = angular.copy(self.users[i]);                break;            }        }    }     function remove(id){        console.log('id to be deleted', id);        if(self.user.id === id) {//clean form if the user to be deleted is shown there.            reset();        }        deleteUser(id);    }      function reset(){        self.user={id:null,username:'',address:'',email:''};        $scope.myForm.$setPristine(); //reset Form    } }]);

为Spring MVC应用创建视图
本应用我们展示传统的方式完成视图创建,使用JSP封装AngularJS的方式。你也可以创建纯html文件,为了界面美观我们添加了bootstrap,同时增加表单验证功能。

UserManagement.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html>  <head>      <title>AngularJS $http Example</title>      <style>      .username.ng-valid {          background-color: lightgreen;      }      .username.ng-dirty.ng-invalid-required {          background-color: red;      }      .username.ng-dirty.ng-invalid-minlength {          background-color: yellow;      }       .email.ng-valid {          background-color: lightgreen;      }      .email.ng-dirty.ng-invalid-required {          background-color: red;      }      .email.ng-dirty.ng-invalid-email {          background-color: yellow;      }     </style>     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">     <link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>  </head>  <body ng-app="myApp" class="ng-cloak">      <div class="generic-container" ng-controller="UserController as ctrl">          <div class="panel panel-default">              <div class="panel-heading"><span class="lead">User Registration Form </span></div>              <div class="formcontainer">                  <form ng-submit="ctrl.submit()" name="myForm" class="form-horizontal">                      <input type="hidden" ng-model="ctrl.user.id" />                      <div class="row">                          <div class="form-group col-md-12">                              <label class="col-md-2 control-lable" for="uname">Name</label>                              <div class="col-md-7">                                  <input type="text" ng-model="ctrl.user.username" id="uname" class="username form-control input-sm" placeholder="Enter your name" required ng-minlength="3"/>                                  <div class="has-error" ng-show="myForm.$dirty">                                      <span ng-show="myForm.uname.$error.required">This is a required field</span>                                      <span ng-show="myForm.uname.$error.minlength">Minimum length required is 3</span>                                      <span ng-show="myForm.uname.$invalid">This field is invalid </span>                                  </div>                              </div>                          </div>                      </div>                                                                      <div class="row">                          <div class="form-group col-md-12">                              <label class="col-md-2 control-lable" for="address">Address</label>                              <div class="col-md-7">                                  <input type="text" ng-model="ctrl.user.address" id="address" class="form-control input-sm" placeholder="Enter your Address. [This field is validation free]"/>                              </div>                          </div>                      </div>                       <div class="row">                          <div class="form-group col-md-12">                              <label class="col-md-2 control-lable" for="email">Email</label>                              <div class="col-md-7">                                  <input type="email" ng-model="ctrl.user.email" id="email" class="email form-control input-sm" placeholder="Enter your Email" required/>                                  <div class="has-error" ng-show="myForm.$dirty">                                      <span ng-show="myForm.email.$error.required">This is a required field</span>                                      <span ng-show="myForm.email.$invalid">This field is invalid </span>                                  </div>                              </div>                          </div>                      </div>                       <div class="row">                          <div class="form-actions floatRight">                              <input type="submit"  value="{{!ctrl.user.id ? 'Add' : 'Update'}}" class="btn btn-primary btn-sm" ng-disabled="myForm.$invalid">                              <button type="button" ng-click="ctrl.reset()" class="btn btn-warning btn-sm" ng-disabled="myForm.$pristine">Reset Form</button>                          </div>                      </div>                  </form>              </div>          </div>          <div class="panel panel-default">                <!-- Default panel contents -->              <div class="panel-heading"><span class="lead">List of Users </span></div>              <div class="tablecontainer">                  <table class="table table-hover">                      <thead>                          <tr>                              <th>ID.</th>                              <th>Name</th>                              <th>Address</th>                              <th>Email</th>                              <th width="20%"></th>                          </tr>                      </thead>                      <tbody>                          <tr ng-repeat="u in ctrl.users">                              <td><span ng-bind="u.id"></span></td>                              <td><span ng-bind="u.username"></span></td>                              <td><span ng-bind="u.address"></span></td>                              <td><span ng-bind="u.email"></span></td>                              <td>                              <button type="button" ng-click="ctrl.edit(u.id)" class="btn btn-success custom-width">Edit</button>  <button type="button" ng-click="ctrl.remove(u.id)" class="btn btn-danger custom-width">Remove</button>                              </td>                          </tr>                      </tbody>                  </table>              </div>          </div>      </div>             <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.js"></script>      <script src="<c:url value='/static/js/app.js' />"></script>      <script src="<c:url value='/static/js/service/user_service.js' />"></script>      <script src="<c:url value='/static/js/controller/user_controller.js' />"></script>  </body></html>

2,服务器端
使用Spring MVC创建REST应用,代码如下:

package com.websystique.springmvc.controller;  import java.util.List; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.MediaType;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.PathVariable;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.RestController;import org.springframework.web.util.UriComponentsBuilder; import com.websystique.springmvc.model.User;import com.websystique.springmvc.service.UserService;  @RestControllerpublic class HelloWorldRestController {      @Autowired    UserService userService;  //Service which will do all data retrieval/manipulation work           //-------------------Retrieve All Users--------------------------------------------------------          @RequestMapping(value = "/user/", method = RequestMethod.GET)    public ResponseEntity<List<User>> listAllUsers() {        List<User> users = userService.findAllUsers();        if(users.isEmpty()){            return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND        }        return new ResponseEntity<List<User>>(users, HttpStatus.OK);    }             //-------------------Retrieve Single User--------------------------------------------------------          @RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)    public ResponseEntity<User> getUser(@PathVariable("id") long id) {        System.out.println("Fetching User with id " + id);        User user = userService.findById(id);        if (user == null) {            System.out.println("User with id " + id + " not found");            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);        }        return new ResponseEntity<User>(user, HttpStatus.OK);    }                  //-------------------Create a User--------------------------------------------------------          @RequestMapping(value = "/user/", method = RequestMethod.POST)    public ResponseEntity<Void> createUser(@RequestBody User user,    UriComponentsBuilder ucBuilder) {        System.out.println("Creating User " + user.getUsername());          if (userService.isUserExist(user)) {            System.out.println("A User with name " + user.getUsername() + " already exist");            return new ResponseEntity<Void>(HttpStatus.CONFLICT);        }          userService.saveUser(user);          HttpHeaders headers = new HttpHeaders();        headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());        return new ResponseEntity<Void>(headers, HttpStatus.CREATED);    }                 //------------------- Update a User --------------------------------------------------------          @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)    public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user) {        System.out.println("Updating User " + id);                  User currentUser = userService.findById(id);                  if (currentUser==null) {            System.out.println("User with id " + id + " not found");            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);        }          currentUser.setUsername(user.getUsername());        currentUser.setAddress(user.getAddress());        currentUser.setEmail(user.getEmail());                  userService.updateUser(currentUser);        return new ResponseEntity<User>(currentUser, HttpStatus.OK);    }                //------------------- Delete a User --------------------------------------------------------          @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)    public ResponseEntity<User> deleteUser(@PathVariable("id") long id) {        System.out.println("Fetching & Deleting User with id " + id);          User user = userService.findById(id);        if (user == null) {            System.out.println("Unable to delete. User with id " + id + " not found");            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);        }          userService.deleteUserById(id);        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);    }                 //------------------- Delete All Users --------------------------------------------------------          @RequestMapping(value = "/user/", method = RequestMethod.DELETE)    public ResponseEntity<User> deleteAllUsers() {        System.out.println("Deleting All Users");          userService.deleteAllUsers();        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);    }  }

创建程序的根controller
如下为程序的根目录对应的controller

package com.websystique.springmvc.controller; import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod; @Controller@RequestMapping("/")public class IndexController {       @RequestMapping(method = RequestMethod.GET)        public String getIndexPage() {            return "UserManagement";        } }

创建Spring Service处理用户提交的数据。

package com.websystique.springmvc.service; import java.util.List; import com.websystique.springmvc.model.User;   public interface UserService {         User findById(long id);         User findByName(String name);         void saveUser(User user);         void updateUser(User user);         void deleteUserById(long id);     List<User> findAllUsers();          void deleteAllUsers();         public boolean isUserExist(User user);     }

package com.websystique.springmvc.service; import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.concurrent.atomic.AtomicLong; import org.springframework.stereotype.Service; import com.websystique.springmvc.model.User; @Service("userService")public class UserServiceImpl implements UserService{         private static final AtomicLong counter = new AtomicLong();         private static List<User> users;         static{        users= populateDummyUsers();    }     public List<User> findAllUsers() {        return users;    }         public User findById(long id) {        for(User user : users){            if(user.getId() == id){                return user;            }        }        return null;    }         public User findByName(String name) {        for(User user : users){            if(user.getUsername().equalsIgnoreCase(name)){                return user;            }        }        return null;    }         public void saveUser(User user) {        user.setId(counter.incrementAndGet());        users.add(user);    }     public void updateUser(User user) {        int index = users.indexOf(user);        users.set(index, user);    }     public void deleteUserById(long id) {                 for (Iterator<User> iterator = users.iterator(); iterator.hasNext(); ) {            User user = iterator.next();            if (user.getId() == id) {                iterator.remove();            }        }    }     public boolean isUserExist(User user) {        return findByName(user.getUsername())!=null;    }         public void deleteAllUsers(){        users.clear();    }     private static List<User> populateDummyUsers(){        List<User> users = new ArrayList<User>();        users.add(new User(counter.incrementAndGet(),"Sam", "NY", "sam@abc.com"));        users.add(new User(counter.incrementAndGet(),"Tomy", "ALBAMA", "tomy@abc.com"));        users.add(new User(counter.incrementAndGet(),"Kelly", "NEBRASKA", "kelly@abc.com"));        return users;    } }

创建模型

package com.websystique.springmvc.model; public class User {     private long id;         private String username;         private String address;         private String email;         public User(){        id=0;    }         public User(long id, String username, String address, String email){        this.id = id;        this.username = username;        this.address = address;        this.email = email;    }     public long getId() {        return id;    }     public void setId(long id) {        this.id = id;    }     public String getUsername() {        return username;    }     public void setUsername(String username) {        this.username = username;    }     public String getAddress() {        return address;    }     public void setAddress(String address) {        this.address = address;    }     public String getEmail() {        return email;    }     public void setEmail(String email) {        this.email = email;    }     @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + (int) (id ^ (id >>> 32));        return result;    }     @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (!(obj instanceof User))            return false;        User other = (User) obj;        if (id != other.id)            return false;        return true;    }     @Override    public String toString() {        return "User [id=" + id + ", username=" + username + ", address=" + address                + ", email=" + email + "]";    }           }

创建Spring配置文件
package com.websystique.springmvc.configuration; import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import org.springframework.web.servlet.view.InternalResourceViewResolver;import org.springframework.web.servlet.view.JstlView; @Configuration@EnableWebMvc@ComponentScan(basePackages = "com.websystique.springmvc")public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{         @Override    public void configureViewResolvers(ViewResolverRegistry registry) {        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();        viewResolver.setViewClass(JstlView.class);        viewResolver.setPrefix("/WEB-INF/views/");        viewResolver.setSuffix(".jsp");        registry.viewResolver(viewResolver);    }     @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        registry.addResourceHandler("/static/**").addResourceLocations("/static/");    } }

创建Spring初始化类
看如下代码是如何配置CORS过滤的,帮助我们处理同源策略问题。
package com.websystique.springmvc.configuration; import javax.servlet.Filter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {      @Override    protected Class<?>[] getRootConfigClasses() {        return new Class[] { HelloWorldConfiguration.class };    }       @Override    protected Class<?>[] getServletConfigClasses() {        return null;    }       @Override    protected String[] getServletMappings() {        return new String[] { "/" };    }         @Override    protected Filter[] getServletFilters() {        Filter [] singleton = { new CORSFilter() };        return singleton;    }  }

创建过滤器处理同源策略问题
package com.websystique.springmvc.configuration; import java.io.IOException; import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletResponse;  public class CORSFilter implements Filter {     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {        System.out.println("Filtering on...........................................................");        HttpServletResponse response = (HttpServletResponse) res;        response.setHeader("Access-Control-Allow-Origin", "*");        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");        response.setHeader("Access-Control-Max-Age", "3600");        response.setHeader("Access-Control-Allow-Headers", "X-requested-with, Content-Type");        chain.doFilter(req, res);    }     public void init(FilterConfig filterConfig) {}     public void destroy() {} }

部署和运行
现在可以创建一个war包或者通过maven命令打包程序,发布war到Servlet3.0容器中,本次开发使用的Tomcat,仅仅需要将war包放到tomcat的webapps目录
下,点击startup.bat即可启动服务器。
打开浏览器并输入http://localhost:8080/Spring4MVCAngularJSExample/将能看到如下界面:


新增用户:


点击新增后,用户信息将会异步发送到服务器并新增一条记录


点击删除后,用户信息将被删除


点击编辑后用户信息将会显示到表单中方便更新。还有部分功能就不演示了。
项目代码: https://github.com/yuanlunchuan/spring4Angular
csdn下载地址:http://download.csdn.net/detail/u010381707/9677924



0 0
原创粉丝点击