首页 > 代码库 > Spring Boot如何让某个Controller支持跨源请求,以及如何让Controller类某个成员方法支持跨源请求
Spring Boot如何让某个Controller支持跨源请求,以及如何让Controller类某个成员方法支持跨源请求
在前面我们已经讨论了Spring Boot 如何全局支持跨源请求。如果你想了解可以查看这篇文章
下面我们讨论另一种场景。有些时候,你需要让你的应用在大部分的时候,仅仅支持当前域名下的请求。而仅仅在极其特殊的几个场合下,才支持跨源请求。这个时候,你需要把跨源请求仅仅缩小在几个Controller上,或者Controller类的几个成员方法上。这个时候你需要用到如下的注解:@CrossOrigin(origins = "*", maxAge = 3600)
。把这个注解放到 Controller 类上或者Controller类的成员方法上,就可以支持跨源请求了。
下面给出了一个例子。
这个项目名字是 blog3。由Maven管理。这个项目源代码组织结构如下:
blog3
src
main
java
zhangchao
blog3
Blog3Application.java
MethodController.java
User.java
UserController.java
resources
application.properties
pom.xml
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>zhangchao</groupId>
<artifactId>blog3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
#S Beautiful jsckson string
spring.jackson.serialization.indent_output=true
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
Blog3Application.java
package zhangchao.blog3;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Blog3Application {
public static void main(String[] args){
SpringApplication.run(Blog3Application.class, args);
}
}
实体类 User.java
package zhangchao.blog3;
import java.math.BigDecimal;
public class User {
public String id;
public String name;
public BigDecimal balance;
}
UserController.java 演示Controller范围,支持跨源请求
package zhangchao.blog3;
import java.math.BigDecimal;
import java.util.UUID;
import org.springframework.web.bind.annotation.CrossOrigin;
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;
//@CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping(value=http://www.mamicode.com/"",method=RequestMethod.POST)
public User save(@RequestBody User user){
user.id = UUID.randomUUID().toString();
return user;
}
@RequestMapping(value=http://www.mamicode.com/"/{id}",method=RequestMethod.GET)
public User get(@PathVariable String id){
User user = new User();
user.balance = new BigDecimal("3.2");
user.id = id;
user.name = "小明";
return user;
}
@RequestMapping(value=http://www.mamicode.com/"",method=RequestMethod.PUT)
public User update(@RequestBody User user){
return user;
}
@RequestMapping(value=http://www.mamicode.com/"/{id}",method=RequestMethod.DELETE)
public String delete(@PathVariable String id){
return "success";
}
}
MethodController.java 演示仅仅指定 Controller 类的成员方法支持跨源请求
package zhangchao.blog3;
import java.math.BigDecimal;
import java.util.UUID;
import org.springframework.web.bind.annotation.CrossOrigin;
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;
@RestController
@RequestMapping("/methodTest")
public class MethodController {
@RequestMapping(value=http://www.mamicode.com/"",method=RequestMethod.POST)
public User save(@RequestBody User user){
user.id = UUID.randomUUID().toString();
return user;
}
@RequestMapping(value=http://www.mamicode.com/"/{id}",method=RequestMethod.GET)
public User get(@PathVariable String id){
User user = new User();
user.balance = new BigDecimal("3.2");
user.id = id;
user.name = "小明";
return user;
}
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping(value=http://www.mamicode.com/"",method=RequestMethod.PUT)
public User update(@RequestBody User user){
return user;
}
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping(value=http://www.mamicode.com/"/{id}",method=RequestMethod.DELETE)
public String delete(@PathVariable String id){
return "success";
}
}
为了做测试,你需要前端程序来模拟跨源请求。对于浏览器来说,只要协议、域名、ip和端口有任意一个不同,就视作跨源请求。我在自己的电脑上使用了nodejs的serve工具作为前端的服务器。你可以查看这个项目的地址:https://github.com/zeit/serve。
我新建了一个文件夹,名字是blog3client。blog3client一共包含三个文件:index.html、vue.js 和 vue-resource.js。其中 vue 的版本是2。
index.html 文件内容如下:
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta content="text/html;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>测试</title>
</head>
<body>
<div id="app">
整个Controller设置成跨域
<table border="1" width="600">
<tbody>
<tr>
<td width="50%">
姓名:<input v-model="e1.name" type="text"/> <br/>
余额:<input v-model="e1.balance" type="text"/> <br/>
<button v-on:click="saveE1()" >保存</button>
</td>
<td>
<div v-if="e1success">
保存成功 <br/>
id: {{e1.id}} <br />
name: {{e1.name}} <br />
balance: {{e1.balance}} <br />
</div>
</td>
</tr>
<tr>
<td>
<button v-on:click="deleteE2()" >删除</button>
</td>
<td>
<div v-if="e2success">
删除成功
</div>
</td>
</tr>
</tbody>
</table>
<hr/>
Controller里面的部分方法跨域<br/>
<table border="1" width="600">
<tbody>
<tr>
<td width="50%">
姓名:<input v-model="e5.name" type="text"/> <br/>
余额:<input v-model="e5.balance" type="text"/> <br/>
<button v-on:click="updateE5()" >更新</button>
</td>
<td>
<div v-if="e5success">
更新成功 <br/>
id: {{e5.id}} <br />
name: {{e5.name}} <br />
balance: {{e5.balance}} <br />
</div>
</td>
</tr>
<tr>
<td>
<button v-on:click="getE6()" >详情</button>
</td>
<td>
<div v-if="e6success">
详情<br/>
id: {{e6.id}} <br />
name: {{e6.name}} <br />
balance: {{e6.balance}} <br />
</div>
</td>
</tr>
</tbody>
</table>
</div>
<script src="./vue.js" type="text/javascript"></script>
<script src="./vue-resource.js" type="text/javascript"></script>
<script type="text/javascript">
Vue.use(VueResource);
var app = new Vue({
el: ‘#app‘,
data: {
"e1":{
"name": "",
"balance": ""
},
"e1success": false,
"e2success": false,
"e5":{
"name": "",
"balance": ""
},
"e5success": false,
"e6success": false,
"e6":{
"id":"",
"name": "",
"balance": ""
}
},
methods: {
saveE1: function() {
var entity = this.e1;
var self = this;
const successCallback = function(res) {
console.log(res.data)
self.e1 = res.data;
self.e1success = true;
};
this.$http.post("http://localhost:8080/user/", entity, {
headers: {
‘Content-Type‘: ‘application/json‘
}
}).then(successCallback, function(e){
window.console.log("error");
});
},
deleteE2: function(){
var self = this;
this.$http.delete("http://localhost:8080/user/234", {}, {
headers: {
‘Content-Type‘: ‘application/json‘
}
}).then(function(res){
self.e2success = true;
},
function(e){
window.console.log("error");
});
},
updateE5:function(){
var self = this;
self.e5.id="123";
this.$http.put("http://localhost:8080/methodTest/", self.e5, {
headers: {
‘Content-Type‘: ‘application/json‘
}
}).then(function(res){
self.e5 = res.data;
self.e5success = true;
}, function(e){
window.console.log("error");
});
},
getE6: function(){
this.$http.get("http://localhost:8080/methodTest/123", {}, {
headers: {
‘Content-Type‘: ‘application/json‘
}
}).then(function(res){
self.e6 = res.data;
self.e5success = true;
}, function(e){
window.console.log("error");
});
}
} // end methods
});
</script>
</body>
</html>
安装好 serve 后,用cd命令进入blog3client文件夹。使用serve
启动前端服务器,默认端口是3000。浏览器访问 http://localhost:3000/ 。运行Spring Boot 的后端代码。打开浏览器的控制面板,点击按钮,查看相应的返回信息即可。
Spring Boot如何让某个Controller支持跨源请求,以及如何让Controller类某个成员方法支持跨源请求