SpringBoot使用CROS解决跨域问题
跨域问题其实之前就有说过,不明白的可以参考我之前的文章,这章主要讲解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 = 1800L;
-
-
@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 -1L;
-
}
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;
-
}
-
}