`

集成https方式的rest服务

    博客分类:
  • J2SE
阅读更多

虽然REST架构是Roy Fielding(他也是HTTP和URI规范的主要作者之一)在一篇论文中描述的,没有被官方指定相关的标准,但在REST服务大行其道的今天,其实已经成为事实的开发选型过程中的首选。

 

REST服务能够大行其道,有一定原因在里头。对系统层级关系的减负之类我们本次不表,单说对团队角色职责清晰化带来的影响,比如,交互采用JSON串,这样就可以很方便的通过js技术以最少的编码量来使用,这样一来,使原来前后端界限不明的前端页面从后端开发同学这里完全释放出来。UI端与API端已经从职业的角度划分开来。因此,REST服务的到来使前端开发同学与后端开发同学的精力能够更加聚焦,更加专注于处理自己擅长的工作。

 

为确保服务通信安全,通常会使用https服务。但问题也跟随来了,对于https方式的rest服务,如何集成到我们系统服务中来。如果直接还是使用默认的http方式集成进来,那https提供的证书怎么支持,下面我们将说明如何在访问https方式的rest服务时,将相关的证书信息一并处理,确保对接业务的正常执行。

 

spring提供了一个模板 org.springframework.web.client.RestTemplate 用来在服务端进行REST服务的对接工作。RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。


调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。


ClientHttpRequestFactory接口主要提供了两种实现方式

  • 一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接。
  • 一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。

有了这些常识的预热,接下来的做法就很好办了,为方便集成过程中的使用,我们把通过HttpComponentsClientHttpRequestFactory类构建RestTemplate过程整理为一个工具类:

/**
 * Danlley Wei (mailto://danlley@126.com)
 * Copyright (c) 2005-2017 All Rights Reserved.
 */
package com.myteay.restful.mapper;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.log4j.Logger;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * HttpClient证书处理工具类
 * 
 * @author danlley(danlley@126.com)
 * @version $Id: HttpClientUtils.java, v 0.1 2017年4月22日 下午8:40:55 danlley(danlley@126.com) Exp $
 */
public class HttpClientUtils {

    /** 日志 */
    private static final Logger          logger    = Logger.getLogger(HttpClientUtils.class);

    private static final HttpClientUtils _instance = new HttpClientUtils();

    public static HttpClientUtils getInstance() {
        return _instance;
    }

    /**
     * 初始化证书支持的CloseableHttpClient
     * 
     * @return                          CloseableHttpClient
     * @throws KeyStoreException        证书存储异常
     * @throws NoSuchAlgorithmException 算法异常
     * @throws KeyManagementException   证书管理异常
     */
    public static CloseableHttpClient acceptsUntrustedCertsHttpClient() throws KeyStoreException,
                                                                        NoSuchAlgorithmException,
                                                                        KeyManagementException {

        //不做任何处理,默认相信所有证书
        SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(null, new TrustStrategy() {
                public boolean isTrusted(X509Certificate[] arg0,
                                         String arg1) throws CertificateException {
                    return true;
                }
            }).build();

        //将对证书的认可配置加入上下文
        HttpClientBuilder b = HttpClientBuilder.create();
        b.setSSLContext(sslContext);

        //对HostName不做校验
        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;

        //注册请求方式
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
            hostnameVerifier);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
            .<ConnectionSocketFactory> create()
            .register("http", PlainConnectionSocketFactory.getSocketFactory())
            .register("https", sslSocketFactory).build();

        //将请求方式加入连接管理器(支持多线程)
        PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(
            socketFactoryRegistry);
        connMgr.setMaxTotal(200);
        connMgr.setDefaultMaxPerRoute(100);
        b.setConnectionManager(connMgr);

        return b.build();
    }

    /**
     * 构建RestTemplate实例
     * 
     * @return  RestTemplate
     */
    public static RestTemplate buildRestTemplate() {
        CloseableHttpClient httpClient = null;
        try {
            httpClient = acceptsUntrustedCertsHttpClient();
        } catch (KeyManagementException e) {
            logger.error("证书关键字异常:" + e.getMessage(), e);
        } catch (KeyStoreException e) {
            logger.error("证书存储异常:" + e.getMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            logger.error("算法执行异常:" + e.getMessage(), e);
        }
        return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
    }

    /**
     * 请求指定地址的restful服务
     * 
     * @param url
     * @param obj
     * @return
     */
    public Object postRestfulService(String url, Object obj) {

        if (obj == null) {
            logger.warn("入参对象不可用,不做请求。 obj is null!");
            return null;
        }

        RestTemplate template = buildRestTemplate();
        return template.postForObject(url, obj, obj.getClass());
    }

}

 

 

接下来编写使用代码:

    @RequestMapping(value = "/greet", method = { RequestMethod.POST })
    public ApplicationModel greeting(@RequestBody ApplicationModel model,
                                     HttpServletRequest request, HttpServletResponse response) {
        logger.warn("------------------->model=" + model);

        Object quote = HttpClientUtils.getInstance()
            .postRestfulService("https://192.168.56.102:8080/greet", model);
        logger.warn("++++++++++++++++  read from server quote: " + quote);

        return (ApplicationModel) quote;
    }

 

 

执行结果如下:

2017-04-22 21:59:56.195  WARN 27752 --- [nio-8080-exec-4] c.m.r.service.impl.RestfulController     : ------------------->model=ApplicationModel[keyModel=ObjectModel[id=test,content=danlley-55---],key=my,value=alipay]
2017-04-22 21:59:56.592  WARN 27752 --- [nio-8080-exec-4] c.m.r.service.impl.RestfulController     : ++++++++++++++++  read from server quote: ApplicationModel[keyModel=ObjectModel[id=test,content=danlley-55---],key=my,value=alipay]

 

 

 

 

0
3
分享到:
评论

相关推荐

    apache wink集成spring 开发rest服务

    1. **RESTful服务基础**:REST(Representational State Transfer)是一种网络应用程序的设计风格和开发方式,基于HTTP协议,强调资源的表示和状态转移。Wink提供了构建REST服务的工具,如Resource类用于定义服务...

    REST服务构建的web应用的优势和不足

    基于 REST 服务(RESTful Service)的 Web 应用系统设计任务主要包括:识别并设计 REST 风格的服务,采用面向服务的思想进行 REST 服务集成。采用这种方法设计的 Web 应用系统能够结合 REST 风格和面向服务思想的...

    ArcGis Server10 java版Rest服务部署方法

    2. **SDK集成** - Esri提供了各种语言的SDK,如JavaScript、Python、.NET等,方便开发者集成REST服务到他们的应用程序中。 总的来说,ArcGIS Server 10 Java版的REST服务部署是一个包含安装、配置、发布和使用服务...

    Rest服务搭建范例

    这种设计方式使得REST服务轻量级、高效且易于使用。 Jersey是Java语言中最流行的RESTful服务框架之一,由Sun Microsystems(现已被Oracle收购)开发。它实现了JAX-RS(Java API for RESTful Web Services)规范,为...

    蓝凌标准产品V15.0管理员手册-RestService服务管理

    蓝凌标准产品V15.0管理员手册-RestService服务管理 蓝凌标准产品V15.0管理员手册-RestService服务管理是蓝凌标准产品V15.0管理员手册中的一部分,主要介绍了RestService服务管理的相关知识点。 第一章 引言 本...

    Openlayer调用arcgis的REST服务的代码

    ### OpenLayers与ArcGIS Server REST API的集成及应用 #### OpenLayers简介 OpenLayers是一款开源的JavaScript库,用于显示地理图层和矢量数据。它无需服务器端支持即可运行,并且是免费软件,由开放源代码社区开发...

    REST地图与天地图叠加

    首先,REST(Representational State Transfer,表现层状态转移)是一种网络应用程序的设计风格和开发方式,常用于提供Web服务。在GIS领域,REST地图服务允许客户端通过HTTP协议请求地图资源,如地图图层、图元等,...

    dubbo提供 rest 服务接口

    在现代微服务架构中,REST(Representational State Transfer)接口已经成为一种常见的服务暴露方式,因为它具有良好的可扩展性和跨语言支持。本文将详细介绍如何利用 Dubbo 实现 REST 服务接口。 ### 1. RESTful ...

    postman REST服务测试

    **Postman:REST服务测试的首选工具** Postman是一款强大的API开发、测试和文档制作工具,尤其在处理REST(Representational State Transfer)服务时表现出色。它作为一个独立的应用程序,支持Windows、Mac和Linux...

    关于activiti rest服务

    `关于activiti rest服务`这一主题,我们将深入探讨Activiti如何通过REST API实现远程调用和集成。 首先,理解Activiti REST API的重要性:在分布式系统和微服务架构中,服务间的通信通常依赖于API。Activiti REST ...

    C++ REST SDK开发HTTP服务器

    同时,这个项目也为你提供了一个起点,可以在此基础上扩展功能,比如添加路由管理、数据库集成、身份验证等高级特性。 总之,C++ REST SDK为C++开发者提供了一个强大的工具集,用于构建高效、可扩展的HTTP服务器。...

    android4.0发布rest服务

    在Android 4.0(Ice Cream Sandwich)系统中,开发者可以利用后台Service组件来实现REST服务的发布。REST(Representational State Transfer)是一种网络应用程序的设计风格和开发方式,基于HTTP协议,强调简洁和标准...

    动态发布rest接口及服务调用

    在IT行业中,REST(Representational State Transfer)是一种广泛应用于网络应用程序设计的架构风格,它强调资源的表述...通过这种方式,开发者可以快速地开发和测试REST服务,为分布式系统提供灵活、高效的通信方式。

    Asp.net 实现 Rest服务接口

    可以使用Postman这样的工具来测试REST服务,也可以集成Swagger(Swashbuckle.AspNetCore)为API生成交互式文档,方便开发者使用。 8. **流(Stream)处理** 对于大文件或持续的数据流,可以直接返回`System.IO....

    Android+REST WebService服务方式手机开发

    总的来说,这篇博客应该涵盖了如何在Android项目中集成REST Web服务的全过程,包括配置、调用、响应处理以及异常管理。对于想要学习Android网络编程的开发者来说,这是一份非常有价值的学习资料。通过阅读和实践,你...

    使用CXF发布Rest服务

    4. **部署服务**:将这个配置集成到你的Web应用中,启动服务器,REST服务就在`http://yourserver:port/context/rest/hello`路径下对外提供服务了。 **CXF REST客户端调用** 1. **创建客户端代理**:CXF提供了JAX-RS...

    springboot集成mybatis+rest接口提供+文件访问自定义配置

    在本项目中,"springboot集成mybatis+rest接口提供+文件访问自定义配置"是一个典型的企业级开发示例,旨在帮助初学者理解和实践Spring Boot与MyBatis的整合,以及如何通过RESTful接口提供服务,并自定义文件访问配置...

    Rest Severs in Delphi XE Using DataSnap

    在Delphi XE中利用DataSnap构建REST服务器是一项强大的技术,可以帮助开发者创建高效、可扩展的Web服务。本文将深入探讨这一主题,介绍REST(Representational State Transfer)架构原理,以及如何在Delphi环境中...

    Android客户端-调用iServer发布的REST地图服务

    首先,理解REST(Representational State Transfer)是一种网络应用程序的设计风格和开发方式,基于HTTP协议,使得客户端和服务器之间的交互变得简单、直观。在GIS领域,REST服务可以提供地图数据、图层、查询等功能...

    activiti入门六(集成新版activitimodeler与rest服务).pdf

    Activiti集成新版Activiti Modeler与Rest服务详解 Activiti是一款开源的业务流程管理(BPM)系统,提供了强大的工作流引擎和模型设计器。Activiti Modeler是Activiti提供的一种模型设计器,能够帮助开发者快速设计...

Global site tag (gtag.js) - Google Analytics