【springboot进阶】RestTemplate进阶封装常用请求方式

目录

一、封装思路

二、GET方式

三、POST方式

form-data

x-www-form-urlencoded

json

四、Header处理

五、完整代码


虽然spring已经帮我们简化了http的请求,但是在实际应用中,我们还是需要写很多重复的代码,显得不够优雅,所以我们还需要对RestTemplate再做一层封装,使外层的调用能够更加的规范和简单。

一、封装思路

我们需要构建一个基类,这个基类封装全部底层基础的请求方法,如GET/POST。

/**
 * 封装一些常用的远程调用方法
 *
 */
public class BackendHttpRequest {

    //伪代码
    get请求方法

    post的json格式请求方法

    post的x-www-form-urlencoded格式请求方法

    ....

}

将需要远程调用的方法封装在一个service服务类,同时继承上面的基类,这个服务类内部即可调用基类的请求方法。

@Service
class AServiceImpl extends BackendHttpRequest implements AService {
    
    //获取天气数据api
    public String getWeatherData(WeatherDataRequestBean params){
        //伪代码
        //调用基类的getData方法,传入请求api接口地址,并带上参数params
        //params内有city城市字段,根据城市名称查询当地天气
        String resBody = this.getData(apiUrl, params);
        return resBody;
    }
    
}

这样,我们就大概构建了一套请求的规范模型,并使用fastjson序列化传入的bean,下面会具体详细说明实战中如何应用。

二、GET方式

以下具体说明如何调用微信的"公众号的全局唯一接口调用凭据"接口,接口文档

    /**
     * get请求
     *
     * @param api 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String getData(String api, Object reqObj) {

        return this.getData(api, reqObj, null);
    }

    /**
     * get请求
     *
     * @param api 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String getData(String api, Object reqObj, Map<String, String> addHeaders) {

        JSONObject params = null;

        if (reqObj instanceof JSONObject) {
            params = (JSONObject) reqObj;
        } else {
            params = JSONObject.parseObject(JSON.toJSONString(reqObj));
        }

        //将map转换为query参数
        String queryParams = HttpUtil.toParams(params, Charset.forName("UTF-8"));

        String requestUrl = api + "?" + queryParams;

        HttpEntity<String> entity = this.getMethodHttpEntity(addHeaders);

        ResponseEntity<String> responseEntity = restTemplate.exchange(URI.create(requestUrl), HttpMethod.GET, entity, String.class);

        return responseEntity.getBody();
    }

同时构建一些公共的方法。 

    /**
     * 获取get方法的HttpEntity
     *
     * @param addHeaders 添加的头部
     * @return
     */
    public HttpEntity<String> getMethodHttpEntity(Map<String, String> addHeaders) {

        HttpHeaders headers = this.getJsonDataHttpHeaders();

        this.addHeaders(headers, addHeaders);

        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        return requestEntity;
    }


    /**
     * 获取json请求头
     *
     * @return
     */
    public HttpHeaders getJsonDataHttpHeaders() {
        HttpHeaders headers = this.getHttpHeaders(MediaType.APPLICATION_JSON);

        return headers;
    }

    /**
     * 获取指定mediaType请求头
     *
     * @param mediaType
     * @return
     */
    public HttpHeaders getHttpHeaders(MediaType mediaType) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(mediaType);

        return headers;
    }

GET方式的封装,重载了两个方法,其中一个方法可以传入自定义的头部参数。

对于请求的参数,统一转变成JSON对象,再使用hutool的工具类HttpUtil,将其转变为query参数形式,即key=value&key=value,最后拼接在url上。

最后,我们使用的是restTemplate.exchange方法,而没有使用getForEntity,是因为之前这里有踩过坑。

@Service
public class TokenServiceImpl extends BackendHttpRequest implements TokenService {

	@Override
    public AccessTokenResponse accessToken(AccessTokenRequest accessTokenRequest) {

        String apiUrl = "https://api.weixin.qq.com/cgi-bin/token";

        String resText = this.getData(apiUrl, accessTokenRequest);
        if (StrUtil.isNotBlank(resText)) {
            AccessTokenResponse response = JSON.parseObject(resText, AccessTokenResponse.class);
            return response;
        }

        return null;
    }

}

请求实体

@Data
public class AccessTokenRequest {

    @JSONField(name = "appid")
    private String appId;
    @JSONField(name = "secret")
    private String appSecret;
    @JSONField(name = "grant_type")
    private String grantType;
}

响应实体

@Data
public class AccessTokenResponse {

    @JSONField(name = "errcode")
    private String errcode;
    @JSONField(name = "errmsg")
    private String errmsg;

    @JSONField(name = "access_token")
    private String accessToken;
    @JSONField(name = "expires_in")
    private Integer expiresIn;
}

三、POST方式

主要对form-data、x-www-form-urlencoded、json等格式分别进行处理。

form-data

    /**
     * form-data的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String postFormData(String requestUrl, Object reqObj) {

        return this.postFormData(requestUrl, reqObj, null);
    }

    /**
     * form-data的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String postFormData(String requestUrl, Object reqObj, Map<String, String> addHeaders) {

        HttpEntity<MultiValueMap<String, Object>> entity = this.getFormRequestHttpEntity(reqObj, MediaType.MULTIPART_FORM_DATA_VALUE, addHeaders);

        String resText = restTemplate.postForObject(requestUrl, entity, String.class);

        return resText;
    }

请求体需要使用MultiValueMap进行封装,构建公共方法将请求bean转换为MultiValueMap。 

    /**
     * 请求request实体转form-data的map
     *
     * @param reqObj 请求request实体
     * @return
     */
    public MultiValueMap<String, Object> requestBeanToFormParams(Object reqObj) {

        Map<String, Object> params = JSONObject.parseObject(JSON.toJSONString(reqObj), HashMap.class);

        MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        for (String key : params.keySet()) {
            multiValueMap.add(key, params.get(key));
        }

        return multiValueMap;
    }

x-www-form-urlencoded

    /**
     * x-www-form-urlencoded的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String postFormUrlencoded(String requestUrl, Object reqObj) {

        return this.postFormUrlencoded(requestUrl, reqObj, null);
    }

    /**
     * x-www-form-urlencoded的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String postFormUrlencoded(String requestUrl, Object reqObj, Map<String, String> addHeaders) {

        HttpEntity<MultiValueMap<String, Object>> entity = this.getFormRequestHttpEntity(reqObj, MediaType.APPLICATION_FORM_URLENCODED_VALUE, addHeaders);

        String resText = restTemplate.postForObject(requestUrl, entity, String.class);

        return resText;
    }

方式跟form-data相同,只是header的content-type不相同。

    /**
     * 获取x-www-form-urlencoded请求头
     *
     * @return
     */
    public HttpHeaders getFormUrlencodedHttpHeaders() {
        HttpHeaders headers = this.getHttpHeaders(MediaType.APPLICATION_FORM_URLENCODED);

        return headers;
    }

    /**
     * 获取form-data请求头
     *
     * @return
     */
    public HttpHeaders getFormDataHttpHeaders() {
        HttpHeaders headers = this.getHttpHeaders(MediaType.MULTIPART_FORM_DATA);

        return headers;
    }

json

    /**
     * json的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String postJsonData(String requestUrl, Object reqObj) {

        return this.postJsonData(requestUrl, reqObj, null);
    }

    /**
     * json的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String postJsonData(String requestUrl, Object reqObj, Map<String, String> addHeaders) {

        HttpEntity<String> entity = this.getJsonRequestHttpEntity(reqObj, addHeaders);

        String resText = restTemplate.postForObject(requestUrl, entity, String.class);

        return resText;
    }

json格式的请求只需要将请求体转化为json字符串即可。

    /**
     * 获取json请求的HttpEntity
     *
     * @param obj 请求request实体
     * @param addHeaders 添加的头部
     * @return
     */
    public HttpEntity<String> getJsonRequestHttpEntity(Object obj, Map<String, String> addHeaders) {

        HttpHeaders headers = this.getJsonDataHttpHeaders();

        this.addHeaders(headers, addHeaders);

        JSONObject params = null;

        if (obj instanceof JSONObject) {
            params = (JSONObject) obj;
        } else {
            params = JSONObject.parseObject(JSON.toJSONString(obj));
        }

        HttpEntity<String> entity = new HttpEntity<>(params.toString(), headers);

        return entity;
    }

四、Header处理

在请求头的处理中,可以针对jwt进行处理。

    /**
     * 添加自定义的头部
     *
     * @param headers
     * @param addHeaders
     */
    public void addHeaders(HttpHeaders headers, Map<String, String> addHeaders) {

        if (addHeaders != null) {

            for (String key : addHeaders.keySet()) {

                if ("Bearer-Auth".equals(key)) {//jwt授权
                    headers.setBearerAuth(addHeaders.get(key));
                    continue;
                }

                headers.set(key, addHeaders.get(key));
            }

        }
    }

我们还可以做一些公共的加密鉴权的方法在这里,这样就不需要每个请求方法都写一遍加密方式。

五、完整代码

public class BackendHttpRequest {

    @Resource
    RestTemplate restTemplate;

    /**
     * get请求
     *
     * @param api 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String getData(String api, Object reqObj) {

        return this.getData(api, reqObj, null);
    }

    /**
     * get请求
     *
     * @param api 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String getData(String api, Object reqObj, Map<String, String> addHeaders) {

        JSONObject params = null;

        if (reqObj instanceof JSONObject) {
            params = (JSONObject) reqObj;
        } else {
            params = JSONObject.parseObject(JSON.toJSONString(reqObj));
        }

        //将map转换为query参数
        String queryParams = HttpUtil.toParams(params, Charset.forName("UTF-8"));

        String requestUrl = api + "?" + queryParams;

        HttpEntity<String> entity = this.getMethodHttpEntity(addHeaders);

        ResponseEntity<String> responseEntity = restTemplate.exchange(URI.create(requestUrl), HttpMethod.GET, entity, String.class);

        return responseEntity.getBody();
    }

    /**
     * form-data的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String postFormData(String requestUrl, Object reqObj) {

        return this.postFormData(requestUrl, reqObj, null);
    }

    /**
     * form-data的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String postFormData(String requestUrl, Object reqObj, Map<String, String> addHeaders) {

        HttpEntity<MultiValueMap<String, Object>> entity = this.getFormRequestHttpEntity(reqObj, MediaType.MULTIPART_FORM_DATA_VALUE, addHeaders);

        String resText = restTemplate.postForObject(requestUrl, entity, String.class);

        return resText;
    }

    /**
     * x-www-form-urlencoded的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String postFormUrlencoded(String requestUrl, Object reqObj) {

        return this.postFormUrlencoded(requestUrl, reqObj, null);
    }

    /**
     * x-www-form-urlencoded的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String postFormUrlencoded(String requestUrl, Object reqObj, Map<String, String> addHeaders) {

        HttpEntity<MultiValueMap<String, Object>> entity = this.getFormRequestHttpEntity(reqObj, MediaType.APPLICATION_FORM_URLENCODED_VALUE, addHeaders);

        String resText = restTemplate.postForObject(requestUrl, entity, String.class);

        return resText;
    }

    /**
     * json的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @return
     */
    public String postJsonData(String requestUrl, Object reqObj) {

        return this.postJsonData(requestUrl, reqObj, null);
    }

    /**
     * json的post请求
     *
     * @param requestUrl 请求url
     * @param reqObj 请求request实体
     * @param addHeaders 添加的头部 如需要使用jwt,key名称需设为"Bearer-Auth"
     * @return
     */
    public String postJsonData(String requestUrl, Object reqObj, Map<String, String> addHeaders) {

        HttpEntity<String> entity = this.getJsonRequestHttpEntity(reqObj, addHeaders);

        String resText = restTemplate.postForObject(requestUrl, entity, String.class);

        return resText;
    }

    /**
     * 请求request实体转form-data的map
     *
     * @param reqObj 请求request实体
     * @return
     */
    public MultiValueMap<String, Object> requestBeanToFormParams(Object reqObj) {

        Map<String, Object> params = JSONObject.parseObject(JSON.toJSONString(reqObj), HashMap.class);

        MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        for (String key : params.keySet()) {
            multiValueMap.add(key, params.get(key));
        }

        return multiValueMap;
    }

    /**
     * 获取get方法的HttpEntity
     *
     * @param addHeaders 添加的头部
     * @return
     */
    public HttpEntity<String> getMethodHttpEntity(Map<String, String> addHeaders) {

        HttpHeaders headers = this.getJsonDataHttpHeaders();

        this.addHeaders(headers, addHeaders);

        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        return requestEntity;
    }

    /**
     * 获取form请求的HttpEntity
     *
     * @param reqObj 请求request实体
     * @param contentType form请求类型
     * @param addHeaders 添加的头部
     * @return
     */
    public HttpEntity<MultiValueMap<String, Object>> getFormRequestHttpEntity(Object reqObj, String contentType, Map<String, String> addHeaders) {

        HttpHeaders headers = null;
        if (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(contentType)) {
            headers = this.getFormUrlencodedHttpHeaders();
        } else if (MediaType.MULTIPART_FORM_DATA_VALUE.equals(contentType)) {
            headers = this.getFormDataHttpHeaders();
        }

        this.addHeaders(headers, addHeaders);

        MultiValueMap<String, Object> multiValueMap = this.requestBeanToFormParams(reqObj);

        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(multiValueMap, headers);

        return entity;
    }

    /**
     * 获取json请求的HttpEntity
     *
     * @param obj 请求request实体
     * @param addHeaders 添加的头部
     * @return
     */
    public HttpEntity<String> getJsonRequestHttpEntity(Object obj, Map<String, String> addHeaders) {

        HttpHeaders headers = this.getJsonDataHttpHeaders();

        this.addHeaders(headers, addHeaders);

        JSONObject params = null;

        if (obj instanceof JSONObject) {
            params = (JSONObject) obj;
        } else {
            params = JSONObject.parseObject(JSON.toJSONString(obj));
        }

        HttpEntity<String> entity = new HttpEntity<>(params.toString(), headers);

        return entity;
    }

    /**
     * 获取x-www-form-urlencoded请求头
     *
     * @return
     */
    public HttpHeaders getFormUrlencodedHttpHeaders() {
        HttpHeaders headers = this.getHttpHeaders(MediaType.APPLICATION_FORM_URLENCODED);

        return headers;
    }

    /**
     * 获取form-data请求头
     *
     * @return
     */
    public HttpHeaders getFormDataHttpHeaders() {
        HttpHeaders headers = this.getHttpHeaders(MediaType.MULTIPART_FORM_DATA);

        return headers;
    }

    /**
     * 获取json请求头
     *
     * @return
     */
    public HttpHeaders getJsonDataHttpHeaders() {
        HttpHeaders headers = this.getHttpHeaders(MediaType.APPLICATION_JSON);

        return headers;
    }

    /**
     * 获取指定mediaType请求头
     *
     * @param mediaType
     * @return
     */
    public HttpHeaders getHttpHeaders(MediaType mediaType) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(mediaType);

        return headers;
    }

    /**
     * 添加自定义的头部
     *
     * @param headers
     * @param addHeaders
     */
    public void addHeaders(HttpHeaders headers, Map<String, String> addHeaders) {

        if (addHeaders != null) {

            for (String key : addHeaders.keySet()) {

                if ("Bearer-Auth".equals(key)) {//jwt授权
                    headers.setBearerAuth(addHeaders.get(key));
                    continue;
                }

                headers.set(key, addHeaders.get(key));
            }

        }
    }

}

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当然,我可以分享一些关于Spring Boot进阶的笔记。请记住,以下笔记仅供参考,因为Spring Boot是一个非常广泛且不断发展的框架,有许多不同的用例和最佳实践。 1. 自定义Starter:Spring Boot提供了Starter的概念,它是一组必要的依赖项和配置的集合,可用于简化项目的配置。你可以通过创建自定义Starter来封装你的常用依赖项和配置,以便在多个项目中重复使用。 2. 运行时配置:Spring Boot提供了多种方式来配置应用程序。除了传统的application.properties或application.yml文件外,你还可以使用环境变量、命令行参数、系统属性等来配置应用程序。了解这些配置选项将帮助你更好地管理应用程序的行为。 3. 多环境支持:Spring Boot允许你为不同的环境(如开发、测试、生产)提供不同的配置。通过使用不同的配置文件或配置选项,你可以轻松地在不同的环境中管理应用程序的行为。 4. 自定义错误页面:Spring Boot提供了默认的错误页面,但你也可以自定义错误页面以提供更好的用户体验。通过创建一个自定义的错误处理器并将其注册到应用程序中,你可以捕获和处理特定类型的错误,并显示自定义的错误页面。 5. 安全性:Spring Boot集成了Spring Security框架,可以轻松地为应用程序添加身份验证和授权功能。你可以通过配置安全规则、自定义认证逻辑和使用各种身份验证提供者来保护你的应用程序。 6. 数据访问:Spring Boot简化了与各种数据源(如关系型数据库、NoSQL数据库、消息队列等)的集成。你可以使用Spring Data JPA、Spring Data MongoDB等模块来简化数据访问层的开发。 7. 缓存:Spring Boot提供了对各种缓存提供者(如Ehcache、Redis等)的集成支持。通过简单的配置,你可以启用缓存功能,并将其应用于适当的方法或查询。 这些只是Spring Boot进阶中的一些主题,还有许多其他方面可以深入研究。希望这些笔记能对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

reui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值