如何在SpringBoot应用中实现跨域访问资源和消息通信?

允许跨域访问

CORS ( Cross Origin Resource Sharing,跨域资源共享)机制允许Web应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在API容器中(如XMLHttpRequest或Fetch )使用CORS,以降低跨域HTTP请求所带来的风险。

本节将介绍如何在Spring Boot应用中,实现跨域访问资源。

什么是跨域访问

当一个资源从与该资源本身所在的服务器不同的域或端口请求一一个资源时, 资源会发起- - 个跨域HTTP请求。

比如,站点ht://example-a.com 的某HTML页面通过<img>的src请求

htp://example-b.com/image.jpg。网络上的许多页面都会加载来自不同域的CSS样式表、图像和脚本等资源。

W3C制定了CORS的相关规范,见hts://ww.w3.org/TR/cors/。出于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求。例如,XMLHttpRequest 和Fetch遵循同源策略。因此,使用XMLHtpRequest或Fetch的Web应用程序只能将HTTP请求发送到其自己的域。为了改进Web应用程序,开发人员要求浏览器厂商允许跨域请求。

如何识别是跨域行为

识别是否具有跨域行为,是由同源政策决定的。同源政策由Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。所谓“同源”, 指的是“三个相同”。

协议相同。

●域名相同。

● 端口相同。

举例来说,

htp://naquan.com/page.html 这个网址,协议是htp://, 域名是www.naquan.com,端口是80 (默认端口可以省略)。它的同源情况如下。

http://example.com/other.html:同源。

ht://www.naquan.com/other.html: 不同源,域名不同。

htp://v2.naquan.com/other.html: 不同源,域名不同。

htp://naquan.com:81/other.html: 不同源,端口不同。

在Spring Boot应用中允许跨域访问

在微服务的架构里面,由于每个服务都在其自身的源中运行,因此,很容易就会遇到来自多个来源的客户端Web应用程序来访问服务的问题(即跨域访问)。例如,- -个浏览器客户端从“客户”

微服务器访问“客户”,并从“订单”微服务器访问订单历史记录,这种做法在微服务领域非常普遍。

Spring MVC支持CORS的开箱即用的功能。主要有两种实现跨域访问的方式。

1.方法级别的跨域访问

Spring Boot提供了一种简单的声明式方法来实现跨域请求。以下示例显示如何使用@CrossOr-igin注解,来启用允许跨域访问某些接口。

import org. springf ramework. web. bind. annotation. CrossOrigin;

@CrossOrigin(origins = "*", maxAge = 3600) // 允许所有域名访问

@Controller

public class FileController {

//..

}

其中,origins ="**意味着允许所有域名访问(当然,你也可以限定某个域名来访问)。maxAge =3600是指有效期为3600秒。

2.全局跨域访问

可以通过使用自定义的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean来定义全局CORS配置。用法如下。

@Configuration

public class MyConfiguration {

@Bean

public WebMvcConfigurer corsConfigurer() {

return new WebMvcConfigurer () {

@Override

public void addCorsMappings (CorsRegistry registry){

registry. addMapping ("/api/**");

};

}}

消息通信

消息通信是企业信息集成中非常重要的一种方式。

消息的通信一般是由消息队列系统( MessageQueuing System, MQ )或面向消息中间件( Message Oriented Middleware, MOM )来提供高效可靠的消息传递机制进行平台无关的数据交流,并可基于数据通信进行分布式系统的集成。通过提供消息传递和消息排队模型,可在分布环境下扩展进程间的通信,并支持多种通信协议、语言、应用程序、硬件和软件平台。

消息通信的好处

通过使用MQ或MOM,通信双方的程序(称其为消息客户程序)可以在不同的时间运行,程序不在网络.上直接通话,而是间接地将消息放入MQ或MOM服务器的消息队列中。因为程序间没有直接的联系,所以它们不必同时运行:消息放入适当的队列时,目标程序不需要正在运行;即使目标程序在运行,也不意味着要立即处理该消息。

消息客户程序之间通过将消息放入消息队列或从消息队列中取出消息来进行通信。客户程序不直接与其他程序通信,避免了网络通信的复杂性。消息队列和网络通信的维护工作由MQ或MOM完成。

常见的MQ或MOM产品有Java Message Service、 Apache ActiveMQ、Apache RocketMQ、RabbitMQ、Apache Kafka等。

对于Spring应用而言,Spring Boot针对Java Message Service、RabbitMQ、 Apache Kafka等提供了开箱即用的支持。

使用Java Message Service

Java Message Service ( JMS ) API是- -个 Java面向消息中间件的API,用于两个或多个客户端之间发送消息。

JMS的目标包括:

●包含实现复杂企业应用所需要的功能特性;

●定义了企业消息概念和功能的一组通用集合;

●最小化企业消息产品的概念,以降低学习成本。

最大化消息应用的可移植性。

JMS支持企业消息产品提供以下两种主要的消息风格。

●点对点 (Point-to-Point, PTP )消息风格:允许一个客户端通过-一个叫“队列( queue)”的中间抽象发送一个消息给另- 一个客户端。发送消息的客户端将-一个消息发送 到指定的队列中,接收消息的客户端从这个队列中抽取消息。

●发布订阅( Publish/Subscribe, Pub/Sub )消息风格:允许-一个客户端通过-一个叫“主题( topic )”的中间抽象发送一个消息给多个客 户端。发送消息的客户端将一个消 息发布到指定的主题中,然后这个消息将被投递到所有订阅了这个主题的客户端。

在Spring Boot应用中使用JMS,通常需要以下几个步骤。

1.使用JNDI ConnectionFactory

在应用程序中,Spring Boot将尝试使用JNDI找到JMS ConnectionFactory。 默认情况下,将检查位置java:/JmsXA和java:/XAConnectionFactory。如果需要指定其他位置,可以使用spring.jms.jndi-name属性。

spring.jms.jndi-name=java:/MyConnectionFactory

2.发送消息

Spring的JmsTemplate是自动配置的,可以将其直接自动装配到自己的bean中。

import org. springf ramework. beans. factory . annotation. Autowired;

import org. spr ingframework. jms . core . JmsTemplate;

import org. spr ingframework. stereotype . Component;

@Component

public class MyBean

private final JmsTemplate jmsTemplate;

@Autowi red

public MyBean (JmsTemplate jmsTemplate) {

this. jmsTemplate = jmsTemplate;

3.接收消息

在JMS架构中,可以使用@JmsListener来注解任何bean,以创建侦听器端点。如果没有定义

JmsListenerContainerFactory,则会自动配置默认值。如果定义了DestinationResolver 或Message-Converter bean,则它们将自动关联到默认工厂。

默认工厂是事务性的。如果在JtaTransactionManager 存在的基础架构中运行,则默认情况下将

与侦听器容器相关联。如果没有,sessionTransacted 标志将被启用。在后一种情况下, 可以通过在

侦听器方法(或其代理)上添加@Transactional来将本地数据存储事务关联到传入消息的处理。这

将确保在本地事务完成后确认传入的消息。这还包括发送在同-一个JMS会话上执行的响应消息。

以下案例在someQueue目标上创建一个 侦听器端点。

@Component

public class MyBean {

@JmsListener (destination = "someQueue")

public void processMessage (String content) {

}

}

使用RabbitMQ

RabbitMQ是更高级别的消息中间件,实现了Advanced Message Queuing Protocol( AMQP )协议。

Spring AMQP项目将核心Spring 概念应用于基于AMQP的消息传递解决方案的开发。Spring Boot提供了几种通过RabbitMQ与AMQP协同工作的开箱即用的方式,包括spring-boot- sarter-amqp等各种Starter。

1.配置RabbitMQ

RabbitMQ的配置由外部配置属性spring.rabbitmq.*来控制。例如,可以在application.properties中声明以下部分。

spring. rabbi tmq. host=localhost

spring. rabbi tmq.port=5672

spring. rabbi tmq . username=admin

spring. rabbi tmq. password=secret

2.发送消息

Spring 的AmqpTemplate和AmqpAdmin是自动配置的,可以将它们直接自动装配到自己的bean中。

import org.spr ingframework. amgp . core . AmqpAdmin;

import org. spr ingf ramework. amqp. core . AmqpTemplate;

import org. springframework.beans. factory . annotation. Autowired;

import org. springframework. stereotype. Component;

@Component

public class MyBean

private final AmqpAdmin amqpAdmin;

private final AmqpTemplate amqpTemplate;

@Autowired

public MyBean (AmqpAdmin amqpAdmin, AmqpTemplate amqpTemplate) {

this . amqpAdmin = amqpAdmin;

this . amqpTemplate = amqpTemplate;

}

}

3.接收消息

当Rabbit 的基础架构存在时,可以使用@RabbitListener来注解bean,以创建侦听器端点。如果没有定义

RabbitListenerContainerFactory,则会自动配置默认的SimpleRabitListenerContainerFactory。可以使用spring.rabbitmq.listener.type属性切换到直接容器。如果MessageConverter或MessageRecoverer bean被定义,它们将自动关联到默认工厂。

以下示例是在someQueue队列上创建-一个侦听器端点。

@Component

public class MyBean

@RabbitListener (queues = " someQueue")

public void processMessage (String content) {

//...

}

}

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值