鍍金池/ 教程/ Java/ Spring4 MVC RESTFul WebServices CRUD實例+RestTemplate
Spring MVC表單處理
Spring MVC多項單選按鈕
Spring MVC Bean名稱Url處理程序映射
Spring MVC下拉選項(Select)
Spring MVC多動作控制器
Spring4 MVC RESTFul Web Services CRUD實例+RestTemplate
Spring MVC頁面重定向
Spring MVC資源綁定視圖解析器
Spring4 MVC+Hibernate4 Many-to-many連接表+MySQL+Maven實例
Spring4 MVC REST服務(wù)示例使用@RestController
Spring MVC文本域
Spring4 MVC + AngularJS使用$http異步服務(wù)交互
Spring4 MVC文件下載實例
Spring4 MVC表單驗證
Spring4 MVC RESTFul WebServices CRUD實例+RestTemplate
Spring MVC教程
Spring MVC參數(shù)方法名稱解析器
Spring MVC生成JSON數(shù)據(jù)
Spring MVC生成XML
Spring4 MVC 表單驗證和資源處理 (使用注解)
Spring MVC單選按鈕
Spring MVC Xml視圖解析器
Spring MVC復(fù)選框
Spring4 MVC ContentNegotiatingViewResolver多種輸出格式實例
Spring MVC錯誤處理
Spring MVC復(fù)選框(多項)
Spring MVC Hibernate驗證器
Spring4 MVC Hello World注解 (Java Config)實例
Spring MVC靜態(tài)頁面
Spring4 MVC ContentNegotiatingViewResolver實例
Spring MVC列表多選框
Spring MVC生成Excel格式數(shù)據(jù)
Spring MVC文本框
Spring MVC內(nèi)部資源視圖解析器
Spring4 MVC HelloWorld 注解和JavaConfig實例
Spring4 MVC REST服務(wù)使用@RestController實例
Spring MVC簡單URL處理程序映射
Spring MVC4使用Servlet3 MultiPartConfigElement文件上傳實例
Spring MVC概述
Spring4 MVC使用Servlet 3 MultiPartConfigElement文件上傳實例
Spring4 MVC Hello WorldXML實例
Spring MVC屬性方法名稱解析器
Spring4 MVC + Hibernate4 + MySQL + Maven使用注解集成實例
Spring4 MVC + Hibernate4多對多連接表+MySQL+Maven實例
Spring4 MVC+Hibernate4+MySQL+Maven使用注解集成實例
Spring MVC配置靜態(tài)資源和資源包教程
Spring MVC可參數(shù)化的視圖控制器
Spring MVC生成RSS源
Spring4 MVC文件下載實例
Spring MVC密碼處理
Spring MVC隱藏字段域
Spring MVC文件上傳教程
Spring MVC多解析器映射
Spring MVC文件上傳處理
Spring4 MVC HelloWord實例
Spring MVC集成Log4j
Spring4 MVC+ AngularJS CRUD使用$http實例
Spring MVC - Hello World示例

Spring4 MVC RESTFul WebServices CRUD實例+RestTemplate


在這篇文章中,我們將使用Spring4 MVC編寫一個CRUD RESTful Web服務(wù),寫一個REST客戶端RestTemplate來使用這些服務(wù)。我們也將利用外部客戶端測試的服務(wù)。

簡單介紹REST

REST 表示狀態(tài)傳輸。這是一個體系結(jié)構(gòu)樣式,可用于設(shè)計網(wǎng)絡(luò)服務(wù),可以被各種客戶端消耗。核心思想是,不使用如CORBA,RPC或SOAP復(fù)雜的機制在機器之間進行連接,簡單的 HTTP 用于使它們之間調(diào)用。

在基于 REST 的設(shè)計中,資源被一套通用動詞操作使用。
  • 創(chuàng)建資源:應(yīng)該使用 HTTP POST
  • 要獲取資源:應(yīng)該使用HTTP GET
  • 更新資源:應(yīng)使用HTTP PUT
  • 要刪除資源:應(yīng)使用HTTP DELETE
這意味著,作為一個 REST 服務(wù)開發(fā)人員或客戶端,應(yīng)符合上述標(biāo)準(zhǔn),以便 REST 操作。

通常Rest 是基于Web服務(wù)返回JSON或XML數(shù)據(jù)格式作為響應(yīng),雖然它并不僅僅限于這些類型。客戶端可以指定(使用 HTTP Accept 報頭),他們所感興趣的資源類型,并且服務(wù)器可以返回資源,指定它所服務(wù)的內(nèi)容類型資源。 

基于REST的控制器

下面是一個可能基于 REST 的控制器,實現(xiàn)REST API。這里所說的“可能”,這意味著可以以另一種方式實現(xiàn)它,還是(或者更純粹的方式)符合REST風(fēng)格。

這就是我們的 REST API 功能/作用:
  • GET 請求 /api/user/ 返回用戶的列表
  • GET 請求  /api/user/1 返回ID為1的用戶
  • POST 請求 /api/user/ 以用戶對象的JSON格式創(chuàng)建新的用戶
  • PUT 請求 /api/user/3 以用戶對象作為JSON更新ID為3的用戶
  • DELETE 請求 /api/user/4 刪除ID為4的用戶
  • DELETE 請求 /api/user/ 刪除所有的用戶
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.getName());

		if (userService.isUserExist(user)) {
			System.out.println("A User with name " + user.getName() + " 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.setName(user.getName());
		currentUser.setAge(user.getAge());
		currentUser.setSalary(user.getSalary());
		
		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);
	}

}
詳細說明:

@RestController : 首先,我們使用 Spring4 的新 @RestController 注釋。 它的注解消除了注釋每個以@ResponseBody的方法。@RestController本身注解為@ResponseBody,并且可以被視為@Controller和@ResponseBody的組合。

@RequestBody : 如果一個方法的參數(shù)都注解有@RequestBody,Spring將綁定傳入的 HTTP 請求體(在@RequestMapping提到該法的URL)到這個參數(shù)。這樣做 Spring 將[在后臺]使用HTTP消息轉(zhuǎn)換為HTTP請求主體轉(zhuǎn)換成域?qū)ο骩反序列化要求主體域?qū)ο骫的基礎(chǔ)上,接受或Content-Type頭請求。

@ResponseBody :如果一個方法被注解為@ResponseBody,Spring將綁定返回值傳出的 HTTP 響應(yīng)體。這樣做Spring將[在后臺]使用HTTP消息轉(zhuǎn)換器的返回值轉(zhuǎn)換為HTTP響應(yīng)體[序列化對象響應(yīng)正文],根據(jù)內(nèi)容類型出現(xiàn)在請求的HTTP頭。 前面已經(jīng)提到,在 Spring4 可能會停止使用此注釋。

ResponseEntity是一個真正處理。 它代表了整個HTTP響應(yīng)。一件好事是你可以控制任何進入它東西??梢灾付顟B(tài)碼,頭和主體。它自帶幾個構(gòu)造函數(shù)執(zhí)行你想要的 HTTP 響應(yīng)發(fā)送的信息。

@PathVariable 這種表示法表示方法參數(shù)應(yīng)綁定到一個 URI 模板變量[“{}”]。

基本上,@RestController,@RequestBody,ResponseEntity&@PathVariable 都是用 Spring 4 實現(xiàn) REST API 需要知道的。此外,Spring提供了一些支持類來幫助你實現(xiàn)一些定制。

MediaType : 通過@RequestMapping注解,你還可以,指定要生產(chǎn)或消費的 MediaType(使用生產(chǎn)或消費屬性),通過特定的控制器的方法,以進一步縮小映射。


部署并測試API,讓我們深入研究這個東西是如何工作的

它只是一個普通的控制器類,可部署的應(yīng)用程序的一部分。[完整下載的應(yīng)用程序代碼顯示在本教程文章最后,你可以直接部署到容器。先部署它,才能有這些可用服務(wù),這里先詳細討論了每一個操作。部署的應(yīng)用程序并訪問:http://localhost:8080/Spring4MVCCRUDRestService.

為了測試這個API,這里使用一個外部客戶端POSTMAN(這是一個 Chrome 插件,下載安裝:http://www.getpostman.com/)。后面我們也將編寫我們自己的客戶端,也就幾分鐘的時間。

1. 檢索所有用戶

打開POSTMAN 工具中,選擇請求類型[GET這個用例],指定操作URI。訪問:http://localhost:8080/Spring4MVCCRUDRestService/user/
請注意,我們這里沒有指定任何HTTP標(biāo)頭。點擊發(fā)送(Send),您將收到的所有用戶的列表。

還要注意 HTTP 200 響應(yīng)。此外這里查看一下報頭。

你可能想知道的響應(yīng)是如何發(fā)送 JSON 字符串,并在響應(yīng)中確認(rèn)Content-Type頭。這已在我們的項目Jackson庫中實現(xiàn)。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
</dependency>
由于 Spring 找到這個庫在 classpath 中,它調(diào)用內(nèi)置MappingJackson2HttpMessageConverter 轉(zhuǎn)換器轉(zhuǎn)換成JSON響應(yīng)(對象的列表)。

關(guān)于Spring內(nèi)置轉(zhuǎn)換器,大部分的時間他們只需要某些庫在類路徑中以便進行轉(zhuǎn)換。當(dāng)然,有時我們也需要去適應(yīng)我們的 API/應(yīng)用程序也是如此。舉例來說,如果我們想為XML,我們應(yīng)標(biāo)注適當(dāng)JAXB標(biāo)注User類。

2. 檢索單用戶

指定 GET /user/1,點擊發(fā)送(Send)。

如果發(fā)送的是無效標(biāo)識符的GET,您會收到一個HTTP 404。

3. 創(chuàng)建一個用戶

選擇方法POST,指定的URI為/user/,在 POSTMAN 主體標(biāo)簽中指定主體,選擇類型[application/json]。

您可能已經(jīng)注意到,POSTMAN會自動添加一個頭 Content-Type 。

隨著POST和PUT請求,客戶端將數(shù)據(jù)發(fā)送到服務(wù)器,它們應(yīng)指定正在發(fā)送的數(shù)據(jù)的實際內(nèi)容類型。

發(fā)送。您應(yīng)該看到HTTP200響應(yīng),沒有主體(如API不發(fā)送主體任何東西)。但是,你應(yīng)該找一個Location頭指定位置新創(chuàng)建的用戶。

現(xiàn)在,您可以獲取新創(chuàng)建的用戶。

通過這種方式實現(xiàn)是常見的REST。但是,如果你想以 POST/ PUT請求的響應(yīng)主體發(fā)送內(nèi)容,也沒有人阻止你。

無論如何,讓我們再次嘗試創(chuàng)建相同的用戶。應(yīng)該得到的HTTP響應(yīng)顯示沖突。

4.更新用戶
發(fā)送一個HTTP PUT請求以更新的用戶。一并發(fā)送新的用戶的信息。

請注意,我們收到的響應(yīng)體的這個時候。這是在控制器中的方法的實現(xiàn)發(fā)送。同樣,可以決定不發(fā)送更新信息的響應(yīng)體,并只發(fā)送位置標(biāo)頭(如創(chuàng)建)。

5. 刪除一個用戶

6. 刪除所有用戶

7. 用戶刪除后,驗證所有用戶


使用REST模板編寫REST客戶端

我們上面使用 Postman 是一個很好的客戶端測試 REST API 工具。但是,如果想從應(yīng)用程序消耗基于REST的Web服務(wù),需要一個REST客戶端的應(yīng)用程序。其中最流行的 HTTP 客戶端就是 Apache HttpComponents HttpClient。 但在細節(jié)上使用這種訪問 REST 服務(wù)太低級。

Spring RestTemplate 可以來補救。 RestTemplate 提供對應(yīng)于六個主要的 HTTP 方法,使許多調(diào)用RESTful服務(wù)只需要一行代碼,就可執(zhí)行 REST最佳實踐的更高層次的方法。

下面顯示的是 HTTP 方法和相應(yīng) RestTemplate 方法來處理該類型的 HTTP 請求。
HTTP方法和相應(yīng)的 RestTemplate 方法:
  • HTTP GET : getForObject, getForEntity
  • HTTP PUT : put(String url, Object request, String…urlVariables)
  • HTTP DELETE : delete
  • HTTP POST : postForLocation(String url, Object request, String… urlVariables), postForObject(String url, Object request, Class responseType, String… uriVariables)
  • HTTP HEAD : headForHeaders(String url, String… urlVariables)
  • HTTP OPTIONS : optionsForAllow(String url, String… urlVariables)
  • HTTP PATCH and others : exchange execute
自定義REST客戶端,消費前面創(chuàng)建的 REST 服務(wù)。
package com.yiibai.springmvc;

import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;

import org.springframework.web.client.RestTemplate;

import com.yiibai.springmvc.model.User;

public class SpringRestTestClient {

	public static final String REST_SERVICE_URI = "http://localhost:8080/Spring4MVCCRUDRestService";
	
	/* GET */
	@SuppressWarnings("unchecked")
	private static void listAllUsers(){
		System.out.println("Testing listAllUsers API-----------");
		
		RestTemplate restTemplate = new RestTemplate();
		List<LinkedHashMap<String, Object>> usersMap = restTemplate.getForObject(REST_SERVICE_URI+"/user/", List.class);
		
		if(usersMap!=null){
			for(LinkedHashMap<String, Object> map : usersMap){
	            System.out.println("User : id="+map.get("id")+", Name="+map.get("name")+", Age="+map.get("age")+", Salary="+map.get("salary"));;
	        }
		}else{
			System.out.println("No user exist----------");
		}
	}
	
	/* GET */
	private static void getUser(){
		System.out.println("Testing getUser API----------");
		RestTemplate restTemplate = new RestTemplate();
        User user = restTemplate.getForObject(REST_SERVICE_URI+"/user/1", User.class);
        System.out.println(user);
	}
	
	/* POST */
    private static void createUser() {
		System.out.println("Testing create User API----------");
    	RestTemplate restTemplate = new RestTemplate();
        User user = new User(0,"Sarah",51,134);
        URI uri = restTemplate.postForLocation(REST_SERVICE_URI+"/user/", user, User.class);
        System.out.println("Location : "+uri.toASCIIString());
    }

    /* PUT */
    private static void updateUser() {
		System.out.println("Testing update User API----------");
        RestTemplate restTemplate = new RestTemplate();
        User user  = new User(1,"Tomy",33, 70000);
        restTemplate.put(REST_SERVICE_URI+"/user/1", user);
        System.out.println(user);
    }

    /* DELETE */
    private static void deleteUser() {
		System.out.println("Testing delete User API----------");
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.delete(REST_SERVICE_URI+"/user/3");
    }


    /* DELETE */
    private static void deleteAllUsers() {
		System.out.println("Testing all delete Users API----------");
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.delete(REST_SERVICE_URI+"/user/");
    }

    public static void main(String args[]){
		listAllUsers();
		getUser();
		createUser();
		listAllUsers();
		updateUser();
		listAllUsers();
		deleteUser();
		listAllUsers();
		deleteAllUsers();
		listAllUsers();
    }
}
重新啟動服務(wù)器(在我們的例子中,在服務(wù)器端的數(shù)據(jù)是固定的)。上面的程序運行。
從上面的客戶端程序輸出
Testing listAllUsers API-----------
User : id=1, Name=Sam, Age=30, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
Testing getUser API----------
User [id=1, name=Sam, age=30, salary=70000.0]
Testing create User API----------
Location : http://localhost:8080/Spring4MVCCRUDRestService/user/5
Testing listAllUsers API-----------
User : id=1, Name=Sam, Age=30, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
Testing update User API----------
User [id=1, name=Tomy, age=33, salary=70000.0]
Testing listAllUsers API-----------
User : id=1, Name=Tomy, Age=33, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
Testing delete User API----------
Testing listAllUsers API-----------
User : id=1, Name=Tomy, Age=33, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
Testing all delete Users API----------
Testing listAllUsers API-----------
No user exist----------

完整的實例

工程結(jié)構(gòu)

聲明項目的依賴關(guān)系

<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>Spring4MVCCRUDRestService</artifactId>
  <packaging>war</packaging>
  <version>1.0.0</version>
  <name>Spring4MVCCRUDRestService 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>
			
	</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>Spring4MVCCRUDRestService</warName>
						<failOnMissingWebXml>false</failOnMissingWebXml>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>

		<finalName>Spring4MVCCRUDRestService</finalName>
	</build>
</project>

User Service

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.getName().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.getName())!=null;
	}

	private static List<User> populateDummyUsers(){
		List<User> users = new ArrayList<User>();
		users.add(new User(counter.incrementAndGet(),"Sam",30, 70000));
		users.add(new User(counter.incrementAndGet(),"Tom",40, 50000));
		users.add(new User(counter.incrementAndGet(),"Jerome",45, 30000));
		users.add(new User(counter.incrementAndGet(),"Silvia",50, 40000));
		return users;
	}

	public void deleteAllUsers() {
		users.clear();
	}

}

Model class

package com.yiibai.springmvc.model;

public class User {

	private long id;
	
	private String name;
	
	private int age;
	
	private double salary;

	public User(){
		id=0;
	}
	
	public User(long id, String name, int age, double salary){
		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}
	
	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	@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 (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (id != other.id)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age
				+ ", salary=" + salary + "]";
	}
}

Configuration class

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;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.yiibai.springmvc")
public class HelloWorldConfiguration {
	
}

Initialization Class

package com.yiibai.springmvc.configuration;

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[] { "/" };
    }
 
}

添加CORS支持REST API

當(dāng)訪問 REST API 時,可能會面臨關(guān)于同源策略的問題。
可能會出現(xiàn)這樣的錯誤:

” No ‘Access-Control-Allow-Origin’ 的頭存在于所請求的資源。 Origin ‘http://127.0.0.1:8080′ is therefore not allowed access.” OR” XMLHttpRequest cannot load http://abc.com/bla. Origin http://localhost:12345 is not allowed by Access-Control-Allow-Origin.” are common in such case.

解決辦法是跨域資源共享。基本上,在服務(wù)器端,我們可以返回更多的CORS系統(tǒng)的訪問控制頭在響應(yīng)中,這將最終允許進一步域間的通信。

借助于Spring,我們可以寫一個簡單的過濾器,并將這些 CORS 特定的頭文件添加到每一個響應(yīng)中。
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");
		chain.doFilter(req, res);
	}

	public void init(FilterConfig filterConfig) {}

	public void destroy() {}

}
然后我們可以簡單地將其配置在我們的 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;
    }
 
}
有了這兩個額外的步驟,客戶可以與您的 REST API進行通信而無需擔(dān)心跨域問題。
到些整個示例教程講解完成,包教不包會。有興趣的朋友可以下載代碼:http://pan.baidu.com/s/1dEjOnp3