一.使用远程服务

    远程调用是客户端应用和服务端之间的会话。

    1.Spring通过多种远程调用技术支持RPC(remote procedure call,远程过程调用)

RPC模型 使用场景
RMI 不考虑网络限制时(例如防火墙),访问/发布基于Java的服务
Hessian 或 Burlap 考虑网络限制时,通过HTTP访问/发布基于Java的服务。Hessian是二进制协议,而Burlap是基于XML的
HTTP invoker 考虑网络限制,并希望使用基于XML或专有的序列化机制实现Java序列化时,访问/发布基于Spring的服务
JAX-RPC 和 JAX-WS 访问/发布平台独立的、基于SOAP的Web服务

    远程服务:

        -- RMI:基于Java的远程方法调用,使用了Java的序列化机制,服务端和客户端Java版本需要保持一致(http://blog.csdn.net/a19881029/article/details/9465663);

        -- Hessian:类似于RMI,都是使用二进制消息进行客户端和服务端的交互,但Hessian的二进制消息可以移植到其他非Java语言中(PHP、Python、C++、C#);

        -- Burlap:基于XML的远程调用技术,能够移植到能够解析XML的语言上,在调试过程中易读。

        Hessian和Burlap是基于HTTP的,解决了RMI的防火墙***问题。但是当传递过来的RPC消息包含序列化对象时应使用RMI。

        -- HTTP invoker:是Spring框架提供的远程调用解决方案。客户端和服务端必须是Spring应用,且必须是基于Java的(序列化机制)。

Spring实战笔记:Spring集成_第1张图片


            -- SOA:面向服务的架构,简单对象访问协议是在分散或分布式的环境中交换信息的简单的协议,是一个基于XML的协议。核心理念是应用程序可以并且应该被设计成依赖一组公共的核心服务,而不是为每个应用都重新实现相同功能。

            Spring为使用Java API for XML Web Service(JAX-WS)来发布和使用所支持的SOAP Web服务提供了大力支持。

            JAX-WS编程模型使用注解将类和类的方法声明为Web服务的操作。使用@WebService注解所标注的类被认为Web服务的端点,而使用@WebMethod注解所标注的方法被认为是操作。

            https://www.ibm.com/developerworks/cn/xml/x-sisoap/index.html


    2.REST

        RPC和REST的区别:

            -- RPC远程过程调用是面向服务的,关注于行为和动作;

            -- REST是面向资源的,强调描述应用程序的事物和名词。

        REST:

            -- 表述性(Representational):REST资源实际上可以用各种形式进行表述,包括XML、JSON、HTML(选择最适合资源使用者的任意形式);

            -- 状态(State):当使用REST时,我们更关注资源的状态而不是对资源采取的行为;

            -- 转移(Transfer):REST涉及到转移资源数据,它以某种表述性形式从一个应用转移到另一个应用。

            即:REST就是将资源的状态最适合客户端或服务端的形式从服务器端转移到客户端(或者反过来)。

                  资源在网络中以某种表现形式进行状态转移。

    

        用HTTP协议里的动词来实现资源的添加,修改,删除等操作:

        -- GET:用来获取资源,

        -- POST:用来新建资源(也可以用于更新资源),

        -- PUT:用来更新资源,

        -- DELETE:用来删除资源。

        Spring支持以下方式创建REST:

            -- 控制器可以处理所有的HTTP方法,包含四个主要的REST方法:GET、PUT、DELETE、POST,PATCH在Spring 3.2及以上版本中支持。

            -- 借助@PathVariable注解,控制器能够处理参数化的URL(将变量输入作为URL的一部分);

            -- 借助Spring的视图和视图解析器,资源能够以多种方式进行表述,包括将模型数据渲染为XML、JSON、Atom以及RSS的View实现;

            -- 可以使用ContentNegotiatingViewResolver来选择最合适客户端的表述;

            -- 借助@ResponseBody注解和各种HttpMethodConverter实现,能够替换基于视图的渲染方式;

            -- @RequestBody注解以及HttpMethodConverter实现可以讲传入的HTTP数据转化为传入控制器处理方法的Java对象;

            -- 借助RestTemplate,Spring应用能够方便地使用REST资源。

        Spring提供了两种方式将资源的Java转换为发送给客户端的表述形式:

            -- 内容协商:选择一个视图,它能够将模型渲染为呈现给客户端的表述形式;

                    视图解析器ContentNegotiatingViewResolver和ContentNegotiationManager共同作用。该方法得到的响应是渲染模型:key-value组成的Map,而不是资源,并不是客户端预期结果。

            -- 消息转换器(HTTP信息转换器):通过一个消息转换器将控制器所返回的对象转换为呈现给客户端的表述形式。

            

        在响应体返回资源状态:

            正常情况下,方处理方法返回Java对象(除String或View的实现以外)时,这个对象会放在模型中并在视图中渲染使用。而使用消息转换功能时,我们需要告诉Spring跳过正常的模型/视图流程,并使用消息转换器。最简单的方法就是为控制器方法添加@ResponseBody注解。

            @ResponseBody注解会告诉Spring,我们要将返回的对象作为资源发送给客户端,并将其转换为客户端可以接收的表述形式。

@RequestMapping(method=RequestMethod.GET, produces="application/json")
public @ResponseBody List spittles(
        @RequestParam(value="max", defaultValue=MAX_LONG_AS_STRING) long max,
        @RequestParam(value="count", defaultValue="20") int count) {
    return spittleRepository.findSpittles(max, count);
}

                该例中的@RequestMapping注解中使用了produces属性,表明这个方法只处理预期输出为JSON的请求。即该方法只处理Accept头部信息包含"application/json"的请求。其他任何类型的请求,即使他的URL匹配指定的路径并且是GET请求也不会被这个方法处理。这样的请求会被其他方法来进行处理(如果存在适当方法的话),或者返回客户端HTTP 406响应。

        在请求体中接收资源状态:

            @ResponseBody能够告诉Spring在把数据发送给客户端的时候,要使用一个消息器,类似的,@RequestBody能告诉Spring查找一个消息转换器。

@RequestMapping(method=RequestMethod.POST, consumes="application/json")         --consumes与produces类似,不过它会关注Content-Type请求的头部信息
public @ResponseBody List saveSpittle(@RequestBody Spittle spittle) {
    return spittleRepository.save(spittle);
}

        @ResponseBody和@RequestBody是启用消息转换器的一种简洁和强大的方式,Spring 4.0中引入@RestController注解,在控制器类上使用@RestController来代替@Controller的话,Spring将会为该控制器的所有处理方法应用消息转换功能。

    

        发送错误信息到客户端:

            Spring提供多种方式处理返回错误信息的场景:

                -- 使用@ResponseStatus注解可以指定状态码;

                -- 控制器方法可以返回ResponseEntity对象,该对象能够包含更多响应相关的元数据;

                -- 异常处理器能够应对错误场景,这样处理器方法就能关注于正常的状况。

@RequestMapping(value="/{id}", method=RequestMethod.GET)      
public @ResponseEntity spittleById(@PathVariable long id) {
    Spittle spittle = spittleRepository.findOne(id);
    if (spittle == null) {
        Error error = new Error(4, "Spittle [" + id + "] not found");
        return new ResponseEntity(error, HttpStatus.NOT_FOUND);
    }
    return new ResponseEntity(spittle, HttpStatus.OK);
}

        处理异常:

            当抛出指定异常时运行。

@ExceptionHandler(SpittleNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ResponseEntity spittleNotFound(SpittleNotFoundException e) {
    long spittleId = e.getSpittleId();
    return new Error(4, "Spittle [" + id + "] not found");
}


    3.Spring消息

        同步通信:客户端应用程序直接与远程服务相交互,并且一直等到远程过程完成后才就像执行。

        异步消息:一个应用程序向另一个应用程序间接发送消息的一种方式,无需等待对方的响应。

        在Spring中搭建消息代理:

            -- 创建连接工厂;

            -- 声明ActiveMQ;

            -- 使用Spring的JMS模板。