版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/saytime https://blog.csdn.net/saytime/article/details/74937204 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
<div class="htmledit_views" id="content_views">
跨域问题其实之前就有说过,不明白的可以参考我之前的文章,这章主要讲解SpringBoot CROS的支持。
这里主要按照官方文档方式讲述。
SpringBoot CROS 参考: http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-cors
Spring CROS 参考: http://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/#cors
一、代码准备
首先是支持Restful的controller,这里就不使用数据库了,简单一点。 UserController.class
-
package cn.saytime.web;
-
-
import cn.saytime.bean.JsonResult;
-
import cn.saytime.bean.User;
-
import org.springframework.http.ResponseEntity;
-
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;
-
-
import java.util.ArrayList;
-
import java.util.Collections;
-
import java.util.Date;
-
import java.util.HashMap;
-
import java.util.List;
-
import java.util.Map;
-
-
/**
-
*
@author
zh
-
*
@ClassName
cn.saytime.web.UserController
-
*
@Description
-
*/
-
@RestController
-
public
class UserController {
-
-
// 创建线程安全的Map
-
static Map<Integer, User> users = Collections.synchronizedMap(
new HashMap<Integer, User>());
-
-
/**
-
* 根据ID查询用户
-
*
@param
id
-
*
@return
-
*/
-
@RequestMapping
(value =
"user/{id}"
, method = RequestMethod.GET)
-
public ResponseEntity<JsonResult> getUserById (
@PathVariable
(value =
"id"
) Integer id){
-
JsonResult r =
new JsonResult();
-
try {
-
User user = users.
get(id);
-
r.setResult(user);
-
r.setStatus(
"ok");
-
}
catch (Exception e) {
-
r.setResult(e.getClass().getName() +
":" + e.getMessage());
-
r.setStatus(
"error");
-
e.printStackTrace();
-
}
-
return ResponseEntity.ok(r);
-
}
-
-
/**
-
* 查询用户列表
-
*
@return
-
*/
-
@CrossOrigin
-
@RequestMapping
(value =
"users"
, method = RequestMethod.GET)
-
public ResponseEntity<JsonResult> getUserList (){
-
JsonResult r =
new JsonResult();
-
try {
-
List<User> userList =
new ArrayList<User>(users.values());
-
r.setResult(userList);
-
r.setStatus(
"ok");
-
}
catch (Exception e) {
-
r.setResult(e.getClass().getName() +
":" + e.getMessage());
-
r.setStatus(
"error");
-
e.printStackTrace();
-
}
-
return ResponseEntity.ok(r);
-
}
-
-
/**
-
* 添加用户
-
*
@param
user
-
*
@return
-
*/
-
@RequestMapping
(value =
"user"
, method = RequestMethod.POST)
-
public ResponseEntity<JsonResult> add (
@RequestBody User user){
-
JsonResult r =
new JsonResult();
-
try {
-
users.put(user.getId(), user);
-
r.setResult(user.getId());
-
r.setStatus(
"ok");
-
}
catch (Exception e) {
-
r.setResult(e.getClass().getName() +
":" + e.getMessage());
-
r.setStatus(
"error");
-
-
e.printStackTrace();
-
}
-
return ResponseEntity.ok(r);
-
}
-
-
/**
-
* 根据id删除用户
-
*
@param
id
-
*
@return
-
*/
-
@RequestMapping
(value =
"user/{id}"
, method = RequestMethod.DELETE)
-
public ResponseEntity<JsonResult> delete (
@PathVariable
(value =
"id"
) Integer id){
-
JsonResult r =
new JsonResult();
-
try {
-
users.remove(id);
-
r.setResult(id);
-
r.setStatus(
"ok");
-
}
catch (Exception e) {
-
r.setResult(e.getClass().getName() +
":" + e.getMessage());
-
r.setStatus(
"error");
-
-
e.printStackTrace();
-
}
-
return ResponseEntity.ok(r);
-
}
-
-
/**
-
* 根据id修改用户信息
-
*
@param
user
-
*
@return
-
*/
-
@RequestMapping
(value =
"user/{id}"
, method = RequestMethod.PUT)
-
public ResponseEntity<JsonResult> update (
@PathVariable
(
"id"
) Integer id,
@RequestBody User user){
-
JsonResult r =
new JsonResult();
-
try {
-
User u = users.
get(id);
-
u.setUsername(user.getUsername());
-
u.setAge(user.getAge());
-
users.put(id, u);
-
r.setResult(u);
-
r.setStatus(
"ok");
-
}
catch (Exception e) {
-
r.setResult(e.getClass().getName() +
":" + e.getMessage());
-
r.setStatus(
"error");
-
-
e.printStackTrace();
-
}
-
return ResponseEntity.ok(r);
-
}
-
-
}
User.class
-
package cn.saytime.bean;
-
-
import java.util.Date;
-
-
/**
-
*
@author
zh
-
*
@ClassName
cn.saytime.bean.User
-
*
@Description
-
*/
-
public
class User {
-
-
private
int id;
-
private String username;
-
private
int age;
-
private Date ctm;
-
-
// Getter Setter
-
}
JsonResult.class
-
package cn.saytime.bean;
-
-
public
class
JsonResult
{
-
-
private
String status =
null;
-
-
private
Object
result =
null;
-
-
//
Getter
Setter
-
}
二、测试是否存在跨域问题
我们在static目录新建一个test.html
-
<!DOCTYPE html>
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8">
-
<title>Title
</title>
-
<script src="https://cdn.bootcss.com/jquery/2.1.0/jquery.min.js">
</script>
-
<script type="text/javascript">
-
function crosRequest()
{
-
$.ajax({
-
url:
'http://localhost:8080/users'
,
-
type:
'get'
,
-
dataType:
'json'
,
-
success:
function(data)
{
-
console
.log(data);
-
}
-
});
-
}
-
</script>
-
</head>
-
<body>
-
<button onclick="crosRequest()">请求跨域资源
</button>
-
</body>
-
</html>
- 我们使用IDEA的浏览器预览功能,点击谷歌小图标,可以看到打开网址为: http://localhost:63342/springboot-demo/springboot-cros/static/test.html?_ijt=ibtt432ffb9rh0vffqkkug3je8
- 启动SpringBoot工程,默认8080
不是使用IDEA的用户,自己找个tomcat启动test.html页面,修改端口为其他,然后启动springboot。
所以证明存在跨域问题。
一、@CrossOrigin注解方式 Controller method CORS configuration
这里我们在users映射的方法getUserList上面加上@CrossOrigin
-
@CrossOrigin
-
@RequestMapping
(value =
"users"
, method = RequestMethod.GET)
-
public ResponseEntity<JsonResult> getUserList ()
然后再次使用上面的方式访问。
表示跨域问题解决。 default @CrossOrigin allows all origins and the HTTP methods specified in the @RequestMapping annotation 上面的官方文档说明,也就是默认的@CrossOrigin允许所有跨域请求。
通过查看CrossOrigin源码可以看到, 默认配置为:
-
"Access-Control-Allow-Origin" :
"*"
-
"Access-Control-Allow-Methods" :
"GET,POST,PUT,OPTIONS"
-
"Access-Control-Allow-Credentials" :
"true"
-
@Target({ElementType.METHOD, ElementType.TYPE})
-
@Retention(RetentionPolicy.RUNTIME)
-
@Documented
-
public
@interface CrossOrigin {
-
/** @deprecated */
-
@Deprecated
-
String[] DEFAULT_ORIGINS =
new
String[]{
"*"};
-
/** @deprecated */
-
@Deprecated
-
String[] DEFAULT_ALLOWED_HEADERS =
new
String[]{
"*"};
-
/** @deprecated */
-
@Deprecated
-
boolean DEFAULT_ALLOW_CREDENTIALS =
true;
-
/** @deprecated */
-
@Deprecated
-
long DEFAULT_MAX_AGE =
1800
L;
-
-
@AliasFor(
"origins")
-
String[] value()
default {};
-
-
@AliasFor(
"value")
-
String[] origins()
default {};
-
-
String[] allowedHeaders()
default {};
-
-
String[] exposedHeaders()
default {};
-
-
RequestMethod[] methods()
default {};
-
-
String
allowCredentials()
default
"";
-
-
long maxAge()
default
-
1
L;
-
}
It is also possible to enable CORS for the whole controller 也可以用在整个Controller类上面。即该controller所有映射都支持跨域请求。
-
@CrossOrigin(
origins =
"http://domain2.com",
-
maxAge =
3600,
-
methods = {
RequestMethod
.GET,
RequestMethod
.POST})
-
@RestController
-
public class UserController
二、全局CORS配置
Global CORS configuration In addition to fine-grained, annotation-based configuration you’ll probably want to define some global CORS configuration as well. This is similar to using filters but can be declared withing Spring MVC and combined with fine-grained @CrossOrigin configuration. By default all origins and GET, HEAD and POST methods are allowed.
-
package cn.saytime.config;
-
-
import org.springframework.context.
annotation.Bean;
-
import org.springframework.context.
annotation.Configuration;
-
import org.springframework.web.servlet.config.
annotation.CorsRegistry;
-
import org.springframework.web.servlet.config.
annotation.WebMvcConfigurer;
-
import org.springframework.web.servlet.config.
annotation.WebMvcConfigurerAdapter;
-
-
/**
-
* @author zh
-
* @ClassName cn.saytime.config.CORSConfiguration
-
* @Description
-
*/
-
@Configuration
-
public
class CORSConfiguration {
-
-
@Bean
-
public WebMvcConfigurer corsConfigurer() {
-
return new WebMvcConfigurerAdapter() {
-
@Override
-
public void addCorsMappings(CorsRegistry registry) {
-
// registry.addMapping(
"/api/**"
);
-
registry.addMapping(
"/**")
-
.allowedOrigins(
"http://domain.com",
"http://domain2.com")
-
.allowedMethods(
"GET",
"POST",
"DELETE",
"PUT",
"OPTIONS")
-
.allowCredentials(
false).maxAge(
3600);
-
}
-
};
-
}
-
}
三、过滤器实现跨域 Filter based CORS support
-
@Configuration
-
public
class MyConfiguration {
-
-
@Bean
-
public FilterRegistrationBean corsFilter() {
-
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
-
CorsConfiguration config =
new CorsConfiguration();
-
config.setAllowCredentials(
false);
-
config.addAllowedOrigin(
"http://domain.com");
-
config.addAllowedHeader(
"*");
-
config.addAllowedMethod(
"*");
-
source.registerCorsConfiguration(
"/**", config);
-
FilterRegistrationBean bean =
new FilterRegistrationBean(
new CorsFilter(source));
-
bean.setOrder(
0);
-
return bean;
-
}
-
}