【063】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="",method=RequestMethod.POST)
	public User save(@RequestBody User user){
		user.id = UUID.randomUUID().toString();
		return user;
	}
	
	@RequestMapping(value="/{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="",method=RequestMethod.PUT)
	public User update(@RequestBody User user){
		return user;
	}
	
	@RequestMapping(value="/{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="",method=RequestMethod.POST)
	public User save(@RequestBody User user){
		user.id = UUID.randomUUID().toString();
		return user;
	}
	
	@RequestMapping(value="/{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="",method=RequestMethod.PUT)
	public User update(@RequestBody User user){
		return user;
	}
	
	@CrossOrigin(origins = "*", maxAge = 3600)
	@RequestMapping(value="/{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 的后端代码。打开浏览器的控制面板,点击按钮,查看相应的返回信息即可。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值