只是为了学习的话,你可以在这里本例中使用的模板。%uA0它是一个小型应用程序,这是不符合服务器交互。所以需要刷新页面重新加载数据。
现在让我们开始!
- Spring 4.2.0.RELEASE
- AngularJS 1.4.4
- Maven 3
- JDK 1.7
- Eclipse JUNO Service Release 2
- M2Eclipse plugin (Optional)
工程目录结构
提供相关依赖关系
<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.yiibai.springmvc</groupId> <artifactId>Spring4MVCAngularJSExample</artifactId> <packaging>war</packaging> <version>1.0.0</version> <name>Spring4MVCAngularJSExample Maven Webapp</name> <properties> <springframework.version>4.2.0.RELEASE</springframework.version> <jackson.version>2.5.3</jackson.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</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> <pluginManagement> <plugins> <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> </pluginManagement> <finalName>Spring4MVCAngularJSExample</finalName> </build> </project>
1.客户端(前端)
这里的应用程序的客户端是基于AngularJS。如果你想学习AngularJs,那么不访看看我们的%uA0AngularJS教程%uA0可让你在最流行的JavaScript框架有一个了解认识。
创建AngularJS模块
模块是AngularJS应用中最重要的部分。AngularJS模块你可以认为是在Java中的包。它应用程序的容器有不同部分%uA0-%uA0控制器,服务器,过滤器,指令等。AngularJS可以组合某些功能/Javascript在一起在单个模块之下。
模块可用于通过AngularJS来引导应用程序。%uA0通过传递模块名到%uA0ng-app%uA0指令,我们可以告诉AngularJS加载该模块的应用程序主入口点。
app.js
&aposuse strict&apos var App = angular.module(&aposmyApp&apos,[])
创建AngularJS服务和服务器进行通信
在我们的应用中,将与Spring%uA0REST%uA0API,例如基于后端服务器的方式进行通信。在基于AngularJS应用中,与服务器进行通信的首选方式是使用AngularJS内置的%uA0$http%uA0服务。%uA0AngularJS$%uA0http服务允许我们使用XHR[浏览器的XMLHttpRequest对象]%uA0API与服务器端点通信。
user_service.js
&aposuse strict&apos App.factory(&aposUserService&apos, [&apos$http&apos, &apos$q&apos, function($http, $q){ return { fetchAllUsers: function() { return $http.get(&aposhttp://localhost:8080/Spring4MVCAngularJSExample/user/&apos) .then( function(response){ return response.data }, function(errResponse){ console.error(&aposError while fetching users&apos) return $q.reject(errResponse) } ) }, createUser: function(user){ return $http.post(&aposhttp://localhost:8080/Spring4MVCAngularJSExample/user/&apos, user) .then( function(response){ return response.data }, function(errResponse){ console.error(&aposError while creating user&apos) return $q.reject(errResponse) } ) }, updateUser: function(user, id){ return $http.put(&aposhttp://localhost:8080/Spring4MVCAngularJSExample/user/&apos+id, user) .then( function(response){ return response.data }, function(errResponse){ console.error(&aposError while updating user&apos) return $q.reject(errResponse) } ) }, deleteUser: function(id){ return $http.delete(&aposhttp://localhost:8080/Spring4MVCAngularJSExample/user/&apos+id) .then( function(response){ return response.data }, function(errResponse){ console.error(&aposError while deleting user&apos) return $q.reject(errResponse) } ) } } }])
创建AngularJS控制器
控制器是一个AngularJS应用的最有用的部分。这些是执行JavaScript函数/对象大多数用户界面相关的工作。它们可以被看作是驱动程序模型和视图的变化。它们是模型(在我们的应用程序中的数据),和视图(无论用户看到在屏幕上以及与其交互)之间的网关。
user_controller.js
&aposuse strict&apos App.controller(&aposUserController&apos, [&apos$scope&apos, &aposUserService&apos, function($scope, UserService) { var self = this self.user={id:null,username:&apos&apos,address:&apos&apos,email:&apos&apos} self.users=[] self.fetchAllUsers = function(){ UserService.fetchAllUsers() .then( function(d) { self.users = d }, function(errResponse){ console.error(&aposError while fetching Currencies&apos) } ) } self.createUser = function(user){ UserService.createUser(user) .then( self.fetchAllUsers, function(errResponse){ console.error(&aposError while creating User.&apos) } ) } self.updateUser = function(user, id){ UserService.updateUser(user, id) .then( self.fetchAllUsers, function(errResponse){ console.error(&aposError while updating User.&apos) } ) } self.deleteUser = function(id){ UserService.deleteUser(id) .then( self.fetchAllUsers, function(errResponse){ console.error(&aposError while deleting User.&apos) } ) } self.fetchAllUsers() self.submit = function() { if(self.user.id===null){ console.log(&aposSaving New User&apos, self.user) self.createUser(self.user) }else{ self.updateUser(self.user, self.user.id) console.log(&aposUser updated with id &apos, self.user.id) } self.reset() } self.edit = function(id){ console.log(&aposid to be edited&apos, id) for(var i = 0 i < self.users.length i++){ if(self.users[i].id === id) { self.user = angular.copy(self.users[i]) break } } } self.remove = function(id){ console.log(&aposid to be deleted&apos, id) if(self.user.id === id) {//clean form if the user to be deleted is shown there. self.reset() } self.deleteUser(id) } self.reset = function(){ self.user={id:null,username:&apos&apos,address:&apos&apos,email:&apos&apos} $scope.myForm.$setPristine() //reset Form } }])
Spring%uA0MVC应用程序的创建视图
在这里,我们在操作上有些传统,并用纯JSP封装我们上面写的所有的AngularJS代码。请注意,您可以使用其他FE技术,而不是JSP(Velocity模板为例)。我们还增加了bootstrap%uA0以增强其外观和感觉。此外,我们也将进行必要的表单验证。
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=&apos/static/css/app.css&apos />" 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 ? &aposAdd&apos : &aposUpdate&apos}}" 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=&apos/static/js/app.js&apos />"></script> <script src="<c:url value=&apos/static/js/service/user_service.js&apos />"></script> <script src="<c:url value=&apos/static/js/controller/user_controller.js&apos />"></script> </body> </html>
2.%uA0服务器端
创建REST控制器的Spring%uA0MVC应用程序
下面显示的是一个基于REST控制器。这相同于%uA0Spring%uA0MVC中4%uA0RESTful%uA0Web服务的CRUD例子+RestTemplate中的控制器。唯一的区别在于用户[模型对象]具有不同的特性,这是根据在本实例的用户界面。
package com.yiibai.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.yiibai.springmvc.model.User import com.yiibai.springmvc.service.UserService @RestController public 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) } }
创建Spring%uA0MVC应用程序的主控制器
package com.yiibai.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事务来处理用户的相关操作
package com.yiibai.springmvc.service import java.util.List import com.yiibai.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.yiibai.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 org.springframework.transaction.annotation.Transactional import com.yiibai.springmvc.model.User @Service("userService") @Transactional 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 } }
创建模型 - Model
package com.yiibai.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.yiibai.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.yiibai.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初始化器类
package com.yiibai.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.yiibai.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(无论是在Eclipse中,如提到的前面的教程)或通过Maven的命令行(mvn%uA0clean%uA0install)。部署%uA0war%uA0到Servlet3.0容器。
打开浏览器,浏览:http://localhost:8080/Spring4MVCAngularJSExample/
由于AngularJS表单验证,如果试图不按要求提供输入,你会看到验证错误如下图所示。
就这样(包教不包会)!