在制定HTML规则时,为了安全的考虑,一个源的脚本(网页、网站)不能与另一个源的资源进行交互,所有引发了同源策略。
同源:即指在同一个域,就是两个页面具有相同的协议、主机和端口号。
同源策略:它是一种约定,它是浏览器最核心的也是最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能会受到影响。发起请求时,必须满足 协议://域名:端口都相同(和当前页面对比)时.满足同源策略要求.浏览器可以正确的发起请求,并且解析结果。
当浏览器解析ajax时,ajax发起请求的地址如果与当前页面所在的地址违反同源策略时,则称之为跨域(请求)。
1).利用javascript中的src属性实现跨域
<script type="text/javascript" src="http://manage.com/test.json"></script>
2).自定义回调函数 function callback(){}
function hello(data){
alert(data.name);
}
3).将返回值结果 进行特殊的格式封装 callback(JSON数据)
hello({"id":"1","name":"tomcat猫"})
<script type="text/javascript" src="http://manage.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
alert("测试访问开始!!!!!")
//网页位置: www.jt.com/JSONP.html
$.ajax({
url:"http://manage.com/web/testJSONP",
type:"get", //jsonp只能支持get请求 不支持post,因为src支持get
dataType:"jsonp", //dataType表示返回值类型 如果是跨域访问,则必须添加jsonp
//jsonp: "callback", //指定参数名称
//jsonpCallback: "hello", //指定回调函数名称
success:function (data){ //data经过jQuery封装返回就是json串
alert(data.id);
alert(data.name);
//转化为字符串使用
//var obj = eval("("+data+")");
//alert(obj.name);
}
});
})
</script>
@RestController
public class JSONPController {
/**
* url:http://manage.jt.com/web/testJSONP?callback=jQuery111107990405330439474_1595323762313&_=1595323762314
* @return JSONPObject 专门负责封装JSONP的返回值结果的.
* 注意事项: 返回值结果必须通过特殊的格式封装 callback(JSON数据)
*/
@RequestMapping("/web/testJSONP")
public JSONPObject jsonp(String callback) {
//准备返回数据
User user = new User();
user.setId(100L).setPassword("我是密码");
return new JSONPObject(callback, user);
}
}
说明:当下的主流的浏览器天生都支持跨域,通过添加请求头信息,将源地址进行标识,之后发往后端服务器。
关键点: 跨域请求由浏览器和服务器共同完成,要求双方都必须同意跨域才行。但是默认的条件下服务器端是不允许跨域的,所以必须经过配置才行。
//类似于web项目中使用的web.xml配置文件 @Configuration public class CorsConfig implements WebMvcConfigurer{
/** * 配置后端服务器可以跨域的清单 * 参数说明: addMapping:什么样的请求可以进行跨域 /web/** /aaa/b/c/e/d/d/d * /* 匹配一级目录 * /** 匹配多级目录 使用最多 */ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") //配置源 通配 .allowedMethods("GET","POST","PUT","DELETE","HEAD") //允许的请求方式 .allowCredentials(true) //是否允许携带cookie .maxAge(1800); //允许跨域的持续时间 }
}
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
$(function(){ //正常
alert("我要进行cors的跨域了!!!!"); //正常
//利用jQuery发起AJAX请求
$.get("http://manage.jt.com/web/testCors",function(data){
alert(data.id);
alert(data.password);
})
})
</script>
@RestController
public class CorsController {
@RequestMapping("/web/testCors")
public User testUser() {
System.out.println("我执行了业务操作!!!");
return new User().setId(100L).setPassword("我是cors的返回值!!!!");
}
}
RPC(Remote Procedure Call Protocol)是远程调用过程的简写,是一个协议,处于网络通信协议的第五层:会话层,其下就是TCP/IP协议,在建立在其基础上的通信会话协议。简言之,RPC使得程序能够像访问本地系统资源一样,去访问远端系统资源。
一个基本的RPC架构里面应该至少包含以下4个组件:
1、客户端(Client):服务调用方(服务消费者)
2、客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端
3、服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理
4、服务端(Server):服务的真正提供者
具体调用过程:
1、服务消费者(client客户端)通过调用本地服务的方式调用需要消费的服务;
2、客户端存根(client stub)接收到调用请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体;
3、客户端存根(client stub)找到远程的服务地址,并且将消息通过网络发送给服务端;
4、服务端存根(server stub)收到消息后进行解码(反序列化操作);
5、服务端存根(server stub)根据解码结果调用本地的服务进行相关处理;
6、本地服务执行具体业务逻辑并将处理结果返回给服务端存根(server stub);
7、服务端存根(server stub)将返回结果重新打包成消息(序列化)并通过网络发送至消费方;
8、客户端存根(client stub)接收到消息,并进行解码(反序列化);
9、服务消费方得到最终结果;
而RPC框架的实现目标则是将上面的第2-10步完好地封装起来,也就是把调用、编码/解码的过程给封装起来,让用户感觉上像调用本地服务一样的调用远程服务。
1、动态代理
生成Client Stub(客户端存根)和Server Stub(服务端存根)的时候需要用到Java动态代理技术,可以使用JDK提供的原生的动态代理机制,也可以使用开源的:CGLib代理,Javassist字节码生成技术。
2、序列化和反序列化
在网络中,所有的数据都将会被转化为字节进行传送,所以为了能够使参数对象在网络中进行传输,需要对这些参数进行序列化和反序列化操作。
序列化:把对象转换为字节序列的过程称为对象的序列化,也就是编码的过程。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化,也就是解码的过程。
目前比较高效的开源序列化框架:如Kryo、FastJson和Protobuf等。
3、NIO通信
出于并发性能的考虑,传统的阻塞式 IO 显然不太合适,因此我们需要异步的 IO,即 NIO。Java 提供了 NIO 的解决方案,Java 7 也提供了更优秀的 NIO.2 支持。可以选择Netty或者MINA来解决NIO数据传输的问题。
4、服务注册中心
可选:Redis、Zookeeper、Consul 、Etcd。一般使用ZooKeeper提供服务注册与发现功能,解决单点故障以及分布式部署的问题(注册中心)
1、需要有非常高效的网络通信,比如一般选择Netty作为网络通信框架;
2、需要有比较高效的序列化框架,比如谷歌的Protobuf序列化框架;
3、可靠的寻址方式(主要是提供服务的发现),比如可以使用Zookeeper来注册服务等等;
4、如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能。
1、如何确定客户端和服务端之间的通信协议?
2、如何更高效地进行网络通信?
3、服务端提供的服务如何暴露给客户端?
4、客户端如何发现这些暴露的服务?
5、如何更高效地对请求对象和响应结果进行序列化和反序列化操作?
参考下篇博客,Dubbo基础及原理。
SOA(Service-Oriented Architecture),即面向服务的架构。它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构件在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
所有的服务是自包含的,合乎逻辑。他们就像黑盒子。总之,我们并不需要了解业务服务的内部工作细节。对于外部世界,它只是一个能够使用消息交互的黑盒子。例如在“支付网关”业务服务获得消息“检查信贷”后会给出输出:这个客户的信贷有或没有。对于“订单系统”,“支付网关”的服务是一个黑盒子。
A) SOA组件是松耦合的。当我们说松耦合,这意味着每一个服务是自包含单独存在的逻辑。举例来说,我们采取了“支付网关”的服务,并将它附加到不同的系统。
B) SOA服务是黑匣子。在SOA中,服务隐藏有内在的复杂性。他们只使用交互消息,服务接受和发送消息。通过虚拟化一个服务为黑盒子,服务变得更松散的耦合。
C) SOA服务应该是自定义: SOA服务应该能够自己定义。
D) SOA服务维持在一个列表中: SOA服务保持在一个中央存储库。应用程序可以在中央存储库中搜索服务,并调用相应服务。
E) SOA服务可以编排和链接实现一个特定功能: SOA服务可以使用了即插即用的方式。例如,“业务流程”中有两个服务“安全服务”和“订单处理服务” 。从它的业务流程可以实现两种类型:一,您可以先检查用户,然后处理订单,或反之亦然。是的,你猜对了,使用SOA可以松散耦合的方式管理服务之间的工作流。
SOA有助于建立IT和业务线之间的无缝对接,通过产生更多的 IT灵活性,以支持更大的业务灵活性。您的业务流程变化越来越快以及全球剧烈竞争需要SOA能够提供高的灵活性。 SOA能够帮助您更好地重用现有的IT投资和服务。 SOA通过定义服务之间良好接口更易于集成。 SOA还提供了业务伙伴,客户和供应商的服务集成到一个企业的业务流程体系结构模型中。这降低了成本,提高了客户满意度。
服务是一个自主的,可重复使用的,可发现的,无状态的,有一定粒度的功能,并且是一个复合应用程序或一个组合服务的一部分。
可重复使用的服务通过业务活动标识,这个业务活动是使用服务规范(设计时合同)描述的。
一个服务约束是,包括安全性,QoS,SLA,使用策略,可以由多个运行时的合同 多个接口(WSDL中的Web服务)以及多个实现(代码)定义的。
可重复使用的服务应在被管制在其从设计到运行整个企业级生命周期。其重用应通过规范流程来推动,重用应该是可测量的。