您的位置:首页 > 编程语言 > Java开发

SpringBoot(六):SpringBoot使用CROS解决跨域问题

2017-07-10 22:07 811 查看
跨域问题其实之前就有说过,不明白的可以参考我之前的文章,这章主要讲解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;
}
}


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息