SpringBoot3解決跨域請(qǐng)求的方案小結(jié)
在Spring Boot 3中,解決跨域請(qǐng)求(CORS,Cross-Origin Resource Sharing)的問題主要有以下幾種方式:
1. 使用@CrossOrigin注解
你可以直接在Controller類或者具體的請(qǐng)求處理方法上使用@CrossOrigin注解來允許跨域請(qǐng)求。
@RestController
@RequestMapping("/user")
@CrossOrigin(origins = "*") // 允許所有來源的請(qǐng)求跨域
public class UserController {
// ...
}在這個(gè)例子中,@CrossOrigin注解被添加到了控制器類上,表示這個(gè)控制器下的所有方法都允許來自http://example.com的GET和POST請(qǐng)求。你也可以將注解添加到特定的方法上,以對(duì)該方法應(yīng)用CORS配置。
2. 全局配置CORS
如果你希望全局配置CORS,而不是在每個(gè)Controller或方法上單獨(dú)配置,你可以創(chuàng)建一個(gè)配置類來實(shí)現(xiàn)WebMvcConfigurer接口,并重寫addCorsMappings方法。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 添加映射路徑
registry.addMapping("/**")
.allowedOrigins("*") // 允許哪些域的請(qǐng)求,星號(hào)代表允許所有
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 允許的方法
.allowedHeaders("*") // 允許的頭部設(shè)置
.allowCredentials(true) // 是否發(fā)送cookie
.maxAge(168000); // 預(yù)檢間隔時(shí)間
}
}在這個(gè)配置中,addMapping("/**")表示對(duì)所有的路徑都應(yīng)用CORS配置。allowedOrigins("*")表示允許所有來源的訪問,這在生產(chǎn)環(huán)境中可能不是最佳實(shí)踐,通常你會(huì)指定具體的域名。allowedMethods定義了允許的HTTP方法,allowedHeaders定義了允許的HTTP頭部,allowCredentials(true)表示是否允許攜帶憑證(cookies, HTTP認(rèn)證及客戶端SSL證明等),maxAge則用于設(shè)置預(yù)檢請(qǐng)求的有效期。
3. 使用Filter實(shí)現(xiàn)CORS
你也可以通過實(shí)現(xiàn)Filter接口來自定義CORS處理邏輯。
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SimpleCorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}
}然后需要在配置類中注冊(cè)這個(gè)Filter。
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<SimpleCorsFilter> corsFilter() {
FilterRegistrationBean<SimpleCorsFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new SimpleCorsFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}4. 使用攔截器(Interceptor)
如果需要更復(fù)雜的CORS邏輯,你可以創(chuàng)建一個(gè)攔截器來處理CORS請(qǐng)求。攔截器允許你在請(qǐng)求處理之前或之后添加邏輯。
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CorsInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Headers", "*");
// 其他CORS相關(guān)的響應(yīng)頭設(shè)置
return true;
}
}然后,你需要在配置類中注冊(cè)這個(gè)攔截器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private CorsInterceptor corsInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(corsInterceptor).addPathPatterns("/**");
}
}- 當(dāng)設(shè)置
allowedHeaders("*")時(shí),實(shí)際上瀏覽器會(huì)發(fā)送實(shí)際請(qǐng)求頭而不是*。出于安全考慮,最好明確指定允許的頭部。 - 在生產(chǎn)環(huán)境中,確保不要過于寬松地配置CORS,只允許必要的源和方法。
- 如果你的應(yīng)用部署在代理服務(wù)器后面(如Nginx或Apache),可能還需要在代理服務(wù)器上配置CORS。
5. 響應(yīng)體(Response Body)來設(shè)置CORS
雖然這種方式不如前面提到的幾種方法直接和常用,但在某些特殊場(chǎng)景下,你可能需要手動(dòng)控制響應(yīng)頭來實(shí)現(xiàn)跨域。
具體實(shí)現(xiàn)時(shí),你可以在Controller的方法中,通過HttpServletResponse對(duì)象來設(shè)置Access-Control-Allow-Origin等CORS相關(guān)的HTTP頭。
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/data")
public String getData(HttpServletResponse response) {
// 設(shè)置允許跨域的來源
response.setHeader("Access-Control-Allow-Origin", "http://example.com");
// 設(shè)置允許的方法(GET, POST, PUT, DELETE等)
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
// 設(shè)置允許的頭信息
response.setHeader("Access-Control-Allow-Headers", "*");
// 設(shè)置預(yù)檢請(qǐng)求的有效期
response.setHeader("Access-Control-Max-Age", "3600");
// 返回?cái)?shù)據(jù)
return "Data";
}
}需要注意的是,手動(dòng)設(shè)置響應(yīng)頭的方式相對(duì)繁瑣,且容易遺漏某些必要的頭信息,導(dǎo)致CORS配置不完整。因此,在實(shí)際開發(fā)中,推薦使用前面提到的方法,它們更為直接且易于管理。
此外,如果你正在使用Spring Security,還需要確保Spring Security的配置不會(huì)阻止跨域請(qǐng)求的處理。在某些情況下,你可能需要在Spring Security的配置中允許特定的CORS請(qǐng)求。
6. 通過自定義ResponseBodyAdvice
ResponseBodyAdvice是Spring MVC提供的一個(gè)接口,允許你在Controller方法返回響應(yīng)體之前對(duì)其進(jìn)行修改。雖然它本身不是專為CORS設(shè)計(jì)的,但你可以利用它在返回響應(yīng)之前添加CORS相關(guān)的HTTP頭。
下面是一個(gè)簡(jiǎn)單的示例,展示了如何通過實(shí)現(xiàn)ResponseBodyAdvice接口來添加CORS頭:
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.lang.reflect.Type;
public class CorsResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
// 支持所有返回類型
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
// 設(shè)置CORS相關(guān)的HTTP頭
response.getHeaders().set("Access-Control-Allow-Origin", "http://example.com");
response.getHeaders().set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.getHeaders().set("Access-Control-Allow-Headers", "*");
// 如果有需要,還可以設(shè)置其他CORS相關(guān)的頭,比如預(yù)檢請(qǐng)求的有效期等
// 返回原始的body,不做修改
return body;
}
}然后,你需要在Spring Boot的配置中注冊(cè)這個(gè)ResponseBodyAdvice:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 注冊(cè)你的ResponseBodyAdvice
converters.forEach(converter -> {
if (converter instanceof MappingJackson2HttpMessageConverter) {
((MappingJackson2HttpMessageConverter) converter).setResponseBodyAdvice(new CorsResponseBodyAdvice());
}
});
}
}這種方法的優(yōu)點(diǎn)在于它可以全局地應(yīng)用于所有Controller的響應(yīng),而無需在每個(gè)Controller或方法上單獨(dú)設(shè)置。然而,它同樣也有一些局限性,比如你可能需要手動(dòng)處理一些CORS的細(xì)節(jié),并且這種方式不如使用Spring提供的CORS支持那么直接和靈活。
在選擇解決方案時(shí),應(yīng)該根據(jù)項(xiàng)目的具體需求和團(tuán)隊(duì)的偏好來權(quán)衡各種方法的優(yōu)缺點(diǎn)。如果項(xiàng)目中有大量的Controller需要處理跨域請(qǐng)求,并且希望有一個(gè)統(tǒng)一且全局的解決方案,那么使用WebMvcConfigurer或CorsFilter可能是更好的選擇。如果只需要在特定的Controller或方法上處理跨域請(qǐng)求,那么使用@CrossOrigin注解可能更為簡(jiǎn)單直接。
以上就是SpringBoot3解決跨域請(qǐng)求的方案小結(jié)的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot3跨域請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java基于swing實(shí)現(xiàn)的五子棋游戲代碼
這篇文章主要介紹了java基于swing實(shí)現(xiàn)的五子棋游戲代碼,主要涉及圖形界面與數(shù)組的用法,有不錯(cuò)的參考借鑒價(jià)值,需要的朋友可以參考下2014-11-11
Java并發(fā)系列之AbstractQueuedSynchronizer源碼分析(概要分析)
這篇文章主要為大家詳細(xì)介紹了Java并發(fā)系列之AbstractQueuedSynchronizer源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
MyBatis Plus整合Redis實(shí)現(xiàn)分布式二級(jí)緩存的問題
Mybatis內(nèi)置的二級(jí)緩存在分布式環(huán)境下存在分布式問題,無法使用,但是我們可以整合Redis來實(shí)現(xiàn)分布式的二級(jí)緩存,這篇文章給大家介紹MyBatis Plus整合Redis實(shí)現(xiàn)分布式二級(jí)緩存,感興趣的朋友跟隨小編一起看看吧2023-11-11
Java中ShardingSphere 數(shù)據(jù)分片的實(shí)現(xiàn)
其實(shí)很多人對(duì)分庫分表多少都有點(diǎn)恐懼,我們今天用ShardingSphere 給大家演示數(shù)據(jù)分片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
JAVA發(fā)送HTTP請(qǐng)求的四種方式總結(jié)
這篇文章主要給大家介紹了關(guān)于JAVA發(fā)送HTTP請(qǐng)求的多種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03

