亲宝软件园·资讯

展开

SpringBoot CORS支持

一只小熊猫呀 人气:0

本章概要

CORS 支持

CORS (Cross-Origin Resource Sharing)是由 W3C 制定开发的一种跨域资源共享技术标准,其目的就是为了解决前端的跨域请求。在 Java EE 开发中,最常见的前端跨域请求解决方案是 JSONP ,但是 JSONP 只支持 GET 请求,而 CORS 则支持多种 HTTP 请求方法。

GET、POST、HEAD 请求流程:响应头中有一个 Access-Control-Orgin 字段,用来记录可以访问该资源的域。当浏览器收到这样的响应头信息后,提取 Access-Control-Orgin 字段中的值,发现该值包含当前页面所在的域,就知道这个跨域是被允许的。

DELETE、PUT 及 自定义请求等请求流程:以 DELETE 请求为例,当前端发起一个 DELETE 请求时,这个请求的处理会经过两个步骤。第一步,发送一个 OPTIONS 请求询问服务端是否具备该资源的 DELETE 权限,服务端给浏览器响应, Allow 头信息表示服务端支持的请求方法。第二步,发送 DELETE 请求,服务端再次给出一次响应。

无论是简单请求还是自定义请求,前端的写法都不变,额外的处理都是在服务端来完成的。在传统 Java EE 开发中,可以通过过滤器统一配置,而 Spring Boot 中对此则提供了更简洁的解决方案。

1. 创建SpringBoot工程

创建 Spring Boot 工程,添加 Web 依赖,如下

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. 创建控制器

@RestController
@RequestMapping("/book")
public class BookController {
    @PostMapping("/")
    public String addBook(String name){
        return "receive:"+name;
    }
    @DeleteMapping("/{id}")
    public String deleteBookById(@PathVariable long id){
        return String.valueOf(id);
    }
}

3. 配置跨域

跨域有两个地方可以配置,一个是直接在相应的请求方法上加注解:

@RestController
@RequestMapping("/book")
public class BookController {
    @PostMapping("/")
    @CrossOrigin(value = "http://localhost:8081",maxAge = 1800,allowedHeaders = "*")
    public String addBook(String name){
        return "receive:"+name;
    }
    @DeleteMapping("/{id}")
    @CrossOrigin(value = "http://localhost:8081",maxAge = 1800,allowedHeaders = "*")
    public String deleteBookById(@PathVariable long id){
        return String.valueOf(id);
    }
}

代码解释:

这种配置方式是一种细粒度的配置,可以控制到每一个方法上。也可以不再每个方法上加 @CrossOrigin 注解,而是采用全局配置,如下:

@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/book/**")
                .allowedHeaders("*")
                .allowedMethods("*")
                .maxAge(1800)
                .allowedOrigins("http://localhost:8081");
        System.out.println("进入跨域配置");
    }
}

代码解释:

上面两种配置方式,选择一种即可,然后启动项目。

4. 测试

新建一个Spring Boot 项目,添加Web依赖,然后在 resources/static 目录下加入jquery.js并创建一个index.html文件,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery3.3.1.js"></script>
</head>
<body>
<div id="contentDiv"></div>
<div id="deleteResult"></div>
<input type="button" value="提交数据" onclick="getData()"><br>
<input type="button" value="删除数据" onclick="deleteData()"><br>
<script>
    function getData() {
        $.ajax({
            url: 'http://localhost:8081/book/',
            type: 'get',
            success: function (msg) {
                $("#contentDiv").html(msg);
            }
        })
    }
    function deleteData() {
        $.ajax({
            url: 'http://localhost:8081/book/99',
            type: 'delete',
            success: function (msg) {
                $("#deleteResult").html(msg);
            }
        })
    }
</script>
</body>
</html>

运行项目,访问"http://localhost:8081/index.html",查看结果

配置类与 XML 配置

Spring Boot 推荐使用 Java 完成相关的配置工作。在项目中,不建议将所有的配置放在一个配置类中,可以根据不同的需求提供不同的配置类,例如专门处理Spring Security 的配置类、提供 Bean 的配置类、Spring MVC 相关的配置类。这些配置上都需要添加 @Configuration,@ComponentScan 注解会扫描所有的 Spring 组件,也包括 @Configuration 。@ComponentScan注解 在项目入口类的 @SpringBootApplication 注解中已经提供,因此在实际项目中只需要按需提供相关配置类即可。

Spring Boot 中并不推荐使用 XML配置。如果需要使用 XML 配置,只需要在 resources 目录下提供配置文件 然后通过 @ImportResource 加载配置文件即可,例如,有一个 Hello 类,如下:

public class Hello {
    public String sayHello(String name){
        return "hello" + name;
    }
}

在resources 目录下新建 beans.xml 文件配置该类:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="com.sang.chapter04.Hello" id="hello"/>
</beans>

然后创建 Bean 配置类,导入 XML 配置

@Configuration
@ImportResource("classpath:beans.xml")
public class Beans {
}

最后在 Controller 中就可以直接导入 Hello 类使用了:

@RestController
public class HelloController {
    @Autowired
    Hello hello;
    @GetMapping("/hello")
    public String hello(){
        return hello.sayHello("嗨喽!");
    }
}

注册拦截器

Spring Boot 中提供了 AOP 风格的拦截器,拥有更加精细的拦截处理能力。Spring Boot 中拦截器的注册更加方便。

步骤1:创建一个 Spring Boot 项目,添加 spring-boot-starter-web 依赖。

步骤2:创建拦截器实现 HandlerInterceptor 接口

public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("MyInterceptor1>>>preHandle");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("MyInterceptor1>>>postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("MyInterceptor1>>>afterCompletion");
    }
}

拦截器中的方法将按 preHandle --> Controller --> postHandle --> afterCompletion 的顺序执行。注意,只有 preHandle 方法返回 true 时后面的方法才会执行。当拦截器链内存在多个拦截拦截器时,postHandle 在拦截器链内的所有的拦截器返回成功时才会调用,而 afterCompletion 只有 preHandle 返回 true 才会调用,若拦截器链内的第一个拦截器的 preHandle 方法返回 false ,则后面的方法都不会执行。

步骤3:配置拦截器。定义配置类进行拦截器的配置,如下

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor1())
                .addPathPatterns("/**")
                .excludePathPatterns("/hello");
    }
}

自定义实现 WebMvcConfigurer 接口,实现接口中的 addInterceptors 方法。其中,addPathPatterns表示拦截路径,excludePathPatterns 表示排除的路径。

步骤4:测试。在浏览器中访问 /hello 和 /hello2 接口,当访问 /hello2 时,打印日志如下:

MyInterceptor1>>>preHandle
MyInterceptor1>>>postHandle
MyInterceptor1>>>afterCompletion

加载全部内容

相关教程
猜你喜欢
用户评论