简短 & 快速介绍REST

REST表示 Representational State Transfer(表示性状态转换).

 

它是可以用来设计web services的框架,可以被不同的客户端调用。

核心思想是:使用简单的HTTP协议来实现调用,而不是CORBA, RPC 或者 SOAP等负责的机制。

 

在Rest 基础设计中,资源使用以下动词进行操作。

 

  • 创建资源 : 使用 HTTP POST
  • 获取资源 : 使用 HTTP GET
  • 更新资源 : 使用 HTTP PUT 
  • 删除资源 : 使用 HTTP DELETE 

也意味着,你作为Rest 服务开发者或者客户,应该遵循以上的标准。

 

 

尽管没有限制必须返回的类型,但是一般基于Web services的Rest返回JSON或者XML作为响应。

 

客户端可以指定(使用HTTP Accept header)他们想要的资源类型吗,服务器返回需要的资源。

指明资源的Content-Type。如果想详细的理解 restful可以参考这里:StackOverflow link 

 

 

基于Rest的Controller(控制器)



我们的 REST API :

  • GET
  • GET
  • POST
  • PUT
  • DELETE
  • DELETE 方式请求/api/user/删除所有user

[java]  view plain  copy

 



1. package com.websystique.springmvc.controller;  
2.    
3. import java.util.List;  
4.    
5. import org.springframework.beans.factory.annotation.Autowired;  
6. import org.springframework.http.HttpHeaders;  
7. import org.springframework.http.HttpStatus;  
8. import org.springframework.http.MediaType;  
9. import org.springframework.http.ResponseEntity;  
10. import org.springframework.web.bind.annotation.PathVariable;  
11. import org.springframework.web.bind.annotation.RequestBody;  
12. import org.springframework.web.bind.annotation.RequestMapping;  
13. import org.springframework.web.bind.annotation.RequestMethod;  
14. import org.springframework.web.bind.annotation.RestController;  
15. import org.springframework.web.util.UriComponentsBuilder;  
16.    
17. import com.websystique.springmvc.model.User;  
18. import com.websystique.springmvc.service.UserService;  
19.    
20. @RestController  
21. public class HelloWorldRestController {  
22.    
23. @Autowired  
24. //Service which will do all data retrieval/manipulation work  
25.    
26.        
27. //-------------------Retrieve All Users--------------------------------------------------------  
28.        
29. @RequestMapping(value = "/user/", method = RequestMethod.GET)  
30. public ResponseEntity<List<User>> listAllUsers() {  
31.         List<User> users = userService.findAllUsers();  
32. if(users.isEmpty()){  
33. return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND  
34.         }  
35. return new ResponseEntity<List<User>>(users, HttpStatus.OK);  
36.     }  
37.    
38.    
39. //-------------------Retrieve Single User--------------------------------------------------------  
40.        
41. @RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)  
42. public ResponseEntity<User> getUser(@PathVariable("id") long id) {  
43. "Fetching User with id " + id);  
44.         User user = userService.findById(id);  
45. if (user == null) {  
46. "User with id " + id + " not found");  
47. return new ResponseEntity<User>(HttpStatus.NOT_FOUND);  
48.         }  
49. return new ResponseEntity<User>(user, HttpStatus.OK);  
50.     }  
51.    
52.        
53.        
54. //-------------------Create a User--------------------------------------------------------  
55.        
56. @RequestMapping(value = "/user/", method = RequestMethod.POST)  
57. public ResponseEntity<Void> createUser(@RequestBody User user,    UriComponentsBuilder ucBuilder) {  
58. "Creating User " + user.getName());  
59.    
60. if (userService.isUserExist(user)) {  
61. "A User with name " + user.getName() + " already exist");  
62. return new ResponseEntity<Void>(HttpStatus.CONFLICT);  
63.         }  
64.    
65.         userService.saveUser(user);  
66.    
67. new HttpHeaders();  
68. "/user/{id}").buildAndExpand(user.getId()).toUri());  
69. return new ResponseEntity<Void>(headers, HttpStatus.CREATED);  
70.     }  
71.    
72.        
73. //------------------- Update a User --------------------------------------------------------  
74.        
75. @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)  
76. public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user) {  
77. "Updating User " + id);  
78.            
79.         User currentUser = userService.findById(id);  
80.            
81. if (currentUser==null) {  
82. "User with id " + id + " not found");  
83. return new ResponseEntity<User>(HttpStatus.NOT_FOUND);  
84.         }  
85.    
86.         currentUser.setName(user.getName());  
87.         currentUser.setAge(user.getAge());  
88.         currentUser.setSalary(user.getSalary());  
89.            
90.         userService.updateUser(currentUser);  
91. return new ResponseEntity<User>(currentUser, HttpStatus.OK);  
92.     }  
93.    
94. //------------------- Delete a User --------------------------------------------------------  
95.        
96. @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)  
97. public ResponseEntity<User> deleteUser(@PathVariable("id") long id) {  
98. "Fetching & Deleting User with id " + id);  
99.    
100.         User user = userService.findById(id);  
101. if (user == null) {  
102. "Unable to delete. User with id " + id + " not found");  
103. return new ResponseEntity<User>(HttpStatus.NOT_FOUND);  
104.         }  
105.    
106.         userService.deleteUserById(id);  
107. return new ResponseEntity<User>(HttpStatus.NO_CONTENT);  
108.     }  
109.    
110.        
111. //------------------- Delete All Users --------------------------------------------------------  
112.        
113. @RequestMapping(value = "/user/", method = RequestMethod.DELETE)  
114. public ResponseEntity<User> deleteAllUsers() {  
115. "Deleting All Users");  
116.    
117.         userService.deleteAllUsers();  
118. return new ResponseEntity<User>(HttpStatus.NO_CONTENT);  
119.     }  
120.    
121. }


详解:



@RestController首先我们使用的是Spring 4的新注解 @RestController注解. 

此注解避免了每个方法都要加上@ResponseBody注解。也就是说@RestController 自己戴上了 @ResponseBody注解,看以看作是

 @Controller 和 @ResponseBody的结合体。

@RequestBody如果方法参数被 @RequestBody注解,Spring将绑定HTTP请求体到那个参数上。如果那样做,Spring将根据请求中的ACCEPT或者 Content-Type header(私下)使用 HTTP Message converters 来将http请求体转化为domain对象。

 

@ResponseBody如果方法加上了@ResponseBody注解,Spring返回值到响应体。如果这样做的话,Spring将根据请求中的 Content-Type header(私下)使用 HTTP Message converters 来将domain对象转换为响应体。

 

ResponseEntity是一个真实数据.它代表了整个 HTTP 响应(response). 它的好处是你可以控制任何对象放到它内部。

你可以指定状态码、头信息和响应体。它包含你想要构建HTTP Response 的信息。

@PathVariable此注解意味着一个方法参数应该绑定到一个url模板变量[在'{}'里的一个]中

一般来说你,要实现REST API in Spring 4 需要了解@RestController , @RequestBody, ResponseEntity 和 @PathVariable 这些注解 .另外, spring 也提供了一些支持类帮助你实现一些可定制化的东西。

MediaType : 带着 @RequestMapping 注解,通过特殊的控制器方法你可以额外指定,MediaType来生产或者消耗。



发布和测试此API



 http://localhost:8080/Spring4MVCCRUDRestService.



 



想要测试此API,我将使用POSTMAN这个外部客户端,接下来我们也将写我们自己的客户端。



1. 获取所有用户



 



打开 POSTMAN工具,选择请求类型为GET,指明uri



restController将控制类注入到哪里去_User



 



注意:我们没有指明任何HTTP头。点击 发送,将接收到所有用户的列表



 



restController将控制类注入到哪里去_java_02



 



也要注意HTTP 200 响应。



restController将控制类注入到哪里去_测试_03



 



你也许好奇为什么此响应通过JSON字符串发送的,在响应里的Content-Type 头说明了这个。



因为我们添加了JACKSON



[html]  view plain  copy

 


1. <dependency>  
2. <groupId>com.fasterxml.jackson.core</groupId>  
3. <artifactId>jackson-databind</artifactId>  
4. <version>2.5.3</version>  
5. </dependency


因为Spring在类路径发现了这个库,它调用了内置的

MappingJackson2HttpMessageConverter

 转换器将响应(对象集合)转换为JSON格式。


 Spring内置转换器的好处是,大部分情况下只要把库放到类路径,即可完成转换。当然了有时候我们也需要



采用我们的API。比如,如果我们像也提供XML格式的话,我们需要对User类加上JAXB注解。



 



2. 获取单个用户



 



GET方式 指定/user/1 



 



restController将控制类注入到哪里去_User_04



现在试着发送一个带有错误识别码的GET请求,将收到一个HTTP 404



restController将控制类注入到哪里去_java_05



 



3.创建一个 User



选择POST方法,指明uri /user/ 指明POSTMAN Body选项卡,选择application/json类型



restController将控制类注入到哪里去_测试_06



Content-Type 头信息



restController将控制类注入到哪里去_HTTP_07



 



记住: Accept header包含client能给识别的类型。  Content-Type header表示数据的实际类型。



 



点击发送以后 将收到 HTTP 200 没有响应体(api里面没有在响应体发送任何东西)



restController将控制类注入到哪里去_测试_08



 



你可以查询新创建的用户



restController将控制类注入到哪里去_json_09



 



这是实现REST的普通实现方式。但是也没人阻止你为POST或者PUT方式响应体里发送内容。但是这还是REST 的API?值得怀疑。



不管怎样,我们试着创建同一个用户时,你将获得HTTP冲突的响应。



restController将控制类注入到哪里去_HTTP_10



 



4.更新用户



发送一个HTTP PUT 请求来更新用户。



restController将控制类注入到哪里去_测试_11



注意:这次我们接收到了响应体。这是因为在控制器的方法实现里我们发送了数据。再次强调,有的人也许不在响应体里面发送更新的详情,只发送位置头(和创建用户一样)。



5.删除用户



restController将控制类注入到哪里去_java_12



6 删除所有用户



restController将控制类注入到哪里去_User_13



7.删除用户后验证



restController将控制类注入到哪里去_java_14



根据RestTemplate 写REST Client  



 



Postman是测试Rest Api的超好用的工具,但是如果你想完整的消化REST,可以尝试自己写一个。


HttpClient(  
   Apache HttpComponents )。



但是用它来访问REST service则相对少见。


Spring的 

RestTemplate随之出现。RestTemplate 提供了高级方法,来响应者6种主要的HTTP方法。

 

HTTP 方法和对应的 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, ClassresponseType, String… uriVariables)
• HTTP HEAD : headForHeaders(String url, String… urlVariables)
• HTTP OPTIONS : optionsForAllow(String url, String… urlVariables)
• HTTP PATCH and others : exchange execute

定义 Rest client , 定义REST services 


[java]  view plain  copy

 


1. package com.websystique.springmvc;  
2.    
3. import java.net.URI;  
4. import java.util.LinkedHashMap;  
5. import java.util.List;  
6.    
7. import org.springframework.web.client.RestTemplate;  
8.    
9. import com.websystique.springmvc.model.User;  
10.    
11. public class SpringRestTestClient {  
12.    
13. public static final String REST_SERVICE_URI = "http://localhost:8080/Spring4MVCCRUDRestService";  
14.        
15. /* GET */  
16. @SuppressWarnings("unchecked")  
17. private static void listAllUsers(){  
18. "Testing listAllUsers API-----------");  
19.            
20. new RestTemplate();  
21. "/user/", List.class);  
22.            
23. if(usersMap!=null){  
24. for(LinkedHashMap<String, Object> map : usersMap){  
25. "User : id="+map.get("id")+", Name="+map.get("name")+", Age="+map.get("age")+", Salary="+map.get("salary"));;  
26.             }  
27. else{  
28. "No user exist----------");  
29.         }  
30.     }  
31.        
32. /* GET */  
33. private static void getUser(){  
34. "Testing getUser API----------");  
35. new RestTemplate();  
36. "/user/1", User.class);  
37.         System.out.println(user);  
38.     }  
39.        
40. /* POST */  
41. private static void createUser() {  
42. "Testing create User API----------");  
43. new RestTemplate();  
44. new User(0,"Sarah",51,134);  
45. "/user/", user, User.class);  
46. "Location : "+uri.toASCIIString());  
47.     }  
48.    
49. /* PUT */  
50. private static void updateUser() {  
51. "Testing update User API----------");  
52. new RestTemplate();  
53. new User(1,"Tomy",33, 70000);  
54. "/user/1", user);  
55.         System.out.println(user);  
56.     }  
57.    
58. /* DELETE */  
59. private static void deleteUser() {  
60. "Testing delete User API----------");  
61. new RestTemplate();  
62. "/user/3");  
63.     }  
64.    
65.    
66. /* DELETE */  
67. private static void deleteAllUsers() {  
68. "Testing all delete Users API----------");  
69. new RestTemplate();  
70. "/user/");  
71.     }  
72.    
73. public static void main(String args[]){  
74.         listAllUsers();  
75.         getUser();  
76.         createUser();  
77.         listAllUsers();  
78.         updateUser();  
79.         listAllUsers();  
80.         deleteUser();  
81.         listAllUsers();  
82.         deleteAllUsers();  
83.         listAllUsers();  
84.     }  
85. }


重启服务器,运行上面的程序。



下面是输出:



[plain]  view plain  copy

 


1. Testing listAllUsers API-----------  
2. User : id=1, Name=Sam, Age=30, Salary=70000.0  
3. User : id=2, Name=Tom, Age=40, Salary=50000.0  
4. User : id=3, Name=Jerome, Age=45, Salary=30000.0  
5. User : id=4, Name=Silvia, Age=50, Salary=40000.0  
6. Testing getUser API----------  
7. User [id=1, name=Sam, age=30, salary=70000.0]  
8. Testing create User API----------  
9. Location : http://localhost:8080/Spring4MVCCRUDRestService/user/5  
10. Testing listAllUsers API-----------  
11. User : id=1, Name=Sam, Age=30, Salary=70000.0  
12. User : id=2, Name=Tom, Age=40, Salary=50000.0  
13. User : id=3, Name=Jerome, Age=45, Salary=30000.0  
14. User : id=4, Name=Silvia, Age=50, Salary=40000.0  
15. User : id=5, Name=Sarah, Age=51, Salary=134.0  
16. Testing update User API----------  
17. User [id=1, name=Tomy, age=33, salary=70000.0]  
18. Testing listAllUsers API-----------  
19. User : id=1, Name=Tomy, Age=33, Salary=70000.0  
20. User : id=2, Name=Tom, Age=40, Salary=50000.0  
21. User : id=3, Name=Jerome, Age=45, Salary=30000.0  
22. User : id=4, Name=Silvia, Age=50, Salary=40000.0  
23. User : id=5, Name=Sarah, Age=51, Salary=134.0  
24. Testing delete User API----------  
25. Testing listAllUsers API-----------  
26. User : id=1, Name=Tomy, Age=33, Salary=70000.0  
27. User : id=2, Name=Tom, Age=40, Salary=50000.0  
28. User : id=4, Name=Silvia, Age=50, Salary=40000.0  
29. User : id=5, Name=Sarah, Age=51, Salary=134.0  
30. Testing all delete Users API----------  
31. Testing listAllUsers API-----------  
32. No user exist----------


完整的例子



restController将控制类注入到哪里去_java_15



 



更新pom.xml添加项目依赖



[html]  view plain  copy

1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
3. <modelVersion>4.0.0</modelVersion>  
4. <groupId>com.websystique.springmvc</groupId>  
5. <artifactId>Spring4MVCCRUDRestService</artifactId>  
6. <packaging>war</packaging>  
7. <version>1.0.0</version>  
8. <name>Spring4MVCCRUDRestService Maven Webapp</name>  
9.    
10. <properties>  
11. <springframework.version>4.2.0.RELEASE</springframework.version>  
12. <jackson.version>2.5.3</jackson.version>  
13. </properties>  
14.    
15. <dependencies>  
16. <dependency>  
17. <groupId>org.springframework</groupId>  
18. <artifactId>spring-webmvc</artifactId>  
19. <version>${springframework.version}</version>  
20. </dependency>  
21. <dependency>  
22. <groupId>org.springframework</groupId>  
23. <artifactId>spring-tx</artifactId>  
24. <version>${springframework.version}</version>  
25. </dependency>  
26.    
27. <dependency>  
28. <groupId>com.fasterxml.jackson.core</groupId>  
29. <artifactId>jackson-databind</artifactId>  
30. <version>${jackson.version}</version>  
31. </dependency>  
32. <dependency>  
33. <groupId>javax.servlet</groupId>  
34. <artifactId>javax.servlet-api</artifactId>  
35. <version>3.1.0</version>  
36. </dependency>  
37.                
38. </dependencies>  
39.    
40.    
41. <build>  
42. <pluginManagement>  
43. <plugins>  
44. <plugin>  
45. <groupId>org.apache.maven.plugins</groupId>  
46. <artifactId>maven-compiler-plugin</artifactId>  
47. <version>3.2</version>  
48. <configuration>  
49. <source>1.7</source>  
50. <target>1.7</target>  
51. </configuration>  
52. </plugin>  
53. <plugin>  
54. <groupId>org.apache.maven.plugins</groupId>  
55. <artifactId>maven-war-plugin</artifactId>  
56. <version>2.4</version>  
57. <configuration>  
58. <warSourceDirectory>src/main/webapp</warSourceDirectory>  
59. <warName>Spring4MVCCRUDRestService</warName>  
60. <failOnMissingWebXml>false</failOnMissingWebXml>  
61. </configuration>  
62. </plugin>  
63. </plugins>  
64. </pluginManagement>  
65.    
66. <finalName>Spring4MVCCRUDRestService</finalName>  
67. </build>  
68. </project>


User Service



[java]  view plain  copy

 


1. package com.websystique.springmvc.service;  
2.    
3. import java.util.List;  
4.    
5. import com.websystique.springmvc.model.User;  
6.    
7.    
8.    
9. public interface UserService {  
10.        
11. long id);  
12.        
13.     User findByName(String name);  
14.        
15. void saveUser(User user);  
16.        
17. void updateUser(User user);  
18.        
19. void deleteUserById(long id);  
20.    
21.     List<User> findAllUsers();   
22.        
23. void deleteAllUsers();  
24.        
25. public boolean isUserExist(User user);  
26.        
27. }





[java]  view plain  copy

 


1. package com.websystique.springmvc.service;  
2.    
3. import java.util.ArrayList;  
4. import java.util.Iterator;  
5. import java.util.List;  
6. import java.util.concurrent.atomic.AtomicLong;  
7.    
8. import org.springframework.stereotype.Service;  
9. import org.springframework.transaction.annotation.Transactional;  
10.    
11. import com.websystique.springmvc.model.User;  
12.    
13. @Service("userService")  
14. @Transactional  
15. public class UserServiceImpl implements UserService{  
16.        
17. private static final AtomicLong counter = new AtomicLong();  
18.        
19. private static List<User> users;  
20.        
21. static{  
22.         users= populateDummyUsers();  
23.     }  
24.    
25. public List<User> findAllUsers() {  
26. return users;  
27.     }  
28.        
29. public User findById(long id) {  
30. for(User user : users){  
31. if(user.getId() == id){  
32. return user;  
33.             }  
34.         }  
35. return null;  
36.     }  
37.        
38. public User findByName(String name) {  
39. for(User user : users){  
40. if(user.getName().equalsIgnoreCase(name)){  
41. return user;  
42.             }  
43.         }  
44. return null;  
45.     }  
46.        
47. public void saveUser(User user) {  
48.         user.setId(counter.incrementAndGet());  
49.         users.add(user);  
50.     }  
51.    
52. public void updateUser(User user) {  
53. int index = users.indexOf(user);  
54.         users.set(index, user);  
55.     }  
56.    
57. public void deleteUserById(long id) {  
58.            
59. for (Iterator<User> iterator = users.iterator(); iterator.hasNext(); ) {  
60.             User user = iterator.next();  
61. if (user.getId() == id) {  
62.                 iterator.remove();  
63.             }  
64.         }  
65.     }  
66.    
67. public boolean isUserExist(User user) {  
68. return findByName(user.getName())!=null;  
69.     }  
70.    
71. private static List<User> populateDummyUsers(){  
72. new ArrayList<User>();  
73. new User(counter.incrementAndGet(),"Sam",30, 70000));  
74. new User(counter.incrementAndGet(),"Tom",40, 50000));  
75. new User(counter.incrementAndGet(),"Jerome",45, 30000));  
76. new User(counter.incrementAndGet(),"Silvia",50, 40000));  
77. return users;  
78.     }  
79.    
80. public void deleteAllUsers() {  
81.         users.clear();  
82.     }  
83.    
84. }


Model (模型)类



[java]  view plain  copy

 



1. package com.websystique.springmvc.model;  
2.    
3. public class User {  
4.    
5. private long id;  
6.        
7. private String name;  
8.        
9. private int age;  
10.        
11. private double salary;  
12.    
13. public User(){  
14. 0;  
15.     }  
16.        
17. public User(long id, String name, int age, double salary){  
18. this.id = id;  
19. this.name = name;  
20. this.age = age;  
21. this.salary = salary;  
22.     }  
23.        
24. public long getId() {  
25. return id;  
26.     }  
27.    
28. public void setId(long id) {  
29. this.id = id;  
30.     }  
31.    
32. public String getName() {  
33. return name;  
34.     }  
35.    
36. public void setName(String name) {  
37. this.name = name;  
38.     }  
39.    
40. public int getAge() {  
41. return age;  
42.     }  
43.    
44. public void setAge(int age) {  
45. this.age = age;  
46.     }  
47.    
48. public double getSalary() {  
49. return salary;  
50.     }  
51.    
52. public void setSalary(double salary) {  
53. this.salary = salary;  
54.     }  
55.    
56. @Override  
57. public int hashCode() {  
58. final int prime = 31;  
59. int result = 1;  
60. int) (id ^ (id >>> 32));  
61. return result;  
62.     }  
63.    
64. @Override  
65. public boolean equals(Object obj) {  
66. if (this == obj)  
67. return true;  
68. if (obj == null)  
69. return false;  
70. if (getClass() != obj.getClass())  
71. return false;  
72.         User other = (User) obj;  
73. if (id != other.id)  
74. return false;  
75. return true;  
76.     }  
77.    
78. @Override  
79. public String toString() {  
80. return "User [id=" + id + ", name=" + name + ", age=" + age  
81. ", salary=" + salary + "]";  
82.     }  
83.    
84.    
85. }


配置类



[java]  view plain  copy

 

1. package com.websystique.springmvc.configuration;  
2.    
3. import org.springframework.context.annotation.ComponentScan;  
4. import org.springframework.context.annotation.Configuration;  
5. import org.springframework.web.servlet.config.annotation.EnableWebMvc;  
6.    
7. @Configuration  
8. @EnableWebMvc  
9. @ComponentScan(basePackages = "com.websystique.springmvc")  
10. public class HelloWorldConfiguration {  
11.        
12.    
13. }



[java]  view plain  copy

 



1. package com.websystique.springmvc.configuration;  
2.    
3. import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;  
4.    
5. public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {  
6.     
7. @Override  
8. protected Class<?>[] getRootConfigClasses() {  
9. return new Class[] { HelloWorldConfiguration.class };  
10.     }  
11.      
12. @Override  
13. protected Class<?>[] getServletConfigClasses() {  
14. return null;  
15.     }  
16.      
17. @Override  
18. protected String[] getServletMappings() {  
19. return new String[] { "/" };  
20.     }  
21.     
22. }




为你的REST API添加CORS支持



当访问REST API时,你可能需要面对“同源策略”问题。



错误如下:



” No ‘Access-Control-Allow-Origin’ header is present on the requested resource. 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.”



一般来说,在服务器端,我们在响应中返回额外的CORS访问控制头,实现跨域链接。



用 Spring的话,我么可以写一个简单的过滤器为每个响应添加CORS特征头。



[java]  view plain  copy

 


1. package com.websystique.springmvc.configuration;  
2.    
3. import java.io.IOException;  
4.    
5. import javax.servlet.Filter;  
6. import javax.servlet.FilterChain;  
7. import javax.servlet.FilterConfig;  
8. import javax.servlet.ServletException;  
9. import javax.servlet.ServletRequest;  
10. import javax.servlet.ServletResponse;  
11. import javax.servlet.http.HttpServletResponse;  
12.    
13.    
14. public class CORSFilter implements Filter {  
15.    
16. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {  
17. "Filtering on...........................................................");  
18.         HttpServletResponse response = (HttpServletResponse) res;  
19. "Access-Control-Allow-Origin", "*");  
20. "Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");  
21. "Access-Control-Max-Age", "3600");  
22. "Access-Control-Allow-Headers", "x-requested-with");  
23.         chain.doFilter(req, res);  
24.     }  
25.    
26. public void init(FilterConfig filterConfig) {}  
27.    
28. public void destroy() {}  
29.    
30. }

需要将其添加在Spring 配置中:



[java]  view plain  copy

 


1. package com.websystique.springmvc.configuration;  
2.    
3. import javax.servlet.Filter;  
4.    
5. import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;  
6.    
7. public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {  
8.     
9. @Override  
10. protected Class<?>[] getRootConfigClasses() {  
11. return new Class[] { HelloWorldConfiguration.class };  
12.     }  
13.      
14. @Override  
15. protected Class<?>[] getServletConfigClasses() {  
16. return null;  
17.     }  
18.      
19. @Override  
20. protected String[] getServletMappings() {  
21. return new String[] { "/" };  
22.     }  
23.        
24. @Override  
25. protected Filter[] getServletFilters() {  
26. new CORSFilter()};  
27. return singleton;  
28.     }  
29.     
30. }




源码下载:http://websystique.com/?smd_process_download=1&download_id=1689



源码(带SORS)下载: http://websystique.com/?smd_process_download=1&download_id=1890



 



特别说明:此系列教程有的童鞋下载下来运行 经常404 或者改成xml方式以后



缺少org.springframework.web.context.ContextLoaderServlet