Springboot整合RestTemplate发送企业微信消息通知

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

以下是整合了restTemplate的get、post、put、delete请求方法,方便系统调用其他系统的接口,统一封装,减少了冗余代码。


提示:以下是本篇文章正文内容,下面案例可供参考

一、基础配置

1. 先导入pom.xml依赖

 <dependencies>
 <!-- RestTemplate需要的依赖 -->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <!-- Lombok依赖 -->
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <optional>true</optional>
 </dependency>
 <!-- 单元测试依赖 -->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 </dependencies>

2、创建RestTemplateConfig配置类

@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

3. 基础类

@Data
public class TokenBO {
    /**
     * token
     */
    private String token;
    /**
     * 失效时间 (默认 3600 秒)
     */
    private long expiresIn = 3600;
}

二、封装Http请求

1.封装Http抽象类

代码如下(示例):

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
public abstract class AbstractHttpRequest implements InitializingBean {

    @Autowired
    protected RestTemplate restTemplate;

    @Autowired
    protected RedisService redisService;

    protected final HttpHeaders header = new HttpHeaders();

    /**
     * 获取token
     */
    protected abstract TokenBO getAccessToken();

    /**
     * @param tokenParamMap    带参数的map对象
     * @param tokenUrl         token请求url
     * @return {@link String}
     * 请求方式为json请求
     */
    protected String getAccessTokenByJson(Map<String, Object> tokenParamMap, String tokenUrl) {
        HttpEntity<String> request = getJsonHttpEntity(tokenParamMap);
        ResponseEntity<String> responseEntity;
        try {
            responseEntity = restTemplate.postForEntity(genUrl(tokenUrl), request, String.class);
        } catch (RestClientException e) {
            throw new BusinessException("获取token失败,msg" + e.getMessage());
        }
        log.debug("access_token:::{}", responseEntity.getBody());
        return responseEntity.getBody();
    }
    
    /**
     * @param tokenParamMap    带参数的map对象
     * @param tokenUrl         token请求url
     * @return {@link String}
     * 请求方式为form请求 不带header
     */
    protected String getAccessTokenByForm(Map<String, Object> tokenParamMap, String tokenUrl) {
        HttpEntity<MultiValueMap<String, Object>> httpEntity = getFormHttpEntityWithHeaders(tokenParamMap);
        ResponseEntity<String> responseEntity;
        try {
            responseEntity = restTemplate.postForEntity(genUrl(tokenUrl), httpEntity, String.class);
        } catch (RestClientException e) {
            throw new BusinessException("获取token失败,msg" + e.getMessage());
        }
        return responseEntity.getBody();
    }
    
    /**
     * @param tokenParamMap    带参数的map对象
     * @param tokenUrl         token请求url
     * @return {@link String}
     * 请求方式为form请求 带header
     */
    protected String getAccessTokenByForm(Map<String, Object> tokenParamMap, HttpHeaders header, String tokenUrl) {
        HttpEntity<MultiValueMap<String, Object>> httpEntity = getFormHttpEntityWithHeaders(tokenParamMap, header);
        ResponseEntity<String> responseEntity;
        try {
            responseEntity = restTemplate.postForEntity(genUrl(tokenUrl), httpEntity, String.class);
        } catch (RestClientException e) {
            throw new BusinessException("获取token失败,msg" + e.getMessage());
        }
        return responseEntity.getBody();
    }

     /**
     * @param url    拼接前缀url和请求url
     * @return {@link String}
     */
    protected String genUrl(String url) {
        if (StringUtils.isBlank(getIp())) {
            throw new BusinessException("接口请求的ip未配置");
        }
        return getIp() + url;
    }

    protected abstract String getIp();

    @Override
    public void afterPropertiesSet() throws Exception {

    }

    /**
     * 生成完整的get请求url
     */
    protected String beforeGet(String url) {
        return url;
    }

    /**
     * 生成完整的post请求url
     */
    protected String beforePost(String url) {
        return beforeGet(url);
    }

    /**
     * 生成完整的delete请求url
     */
    protected String beforeDelete(String url) {
        return url;
    }

    public String get(String url) {
        return dealResponseData(this.doGet(url, null), null);
    }

    public String get(String url, Map<String, Object> param) {
        return dealResponseData(this.doGet(url, param), param);
    }

    public void delete(String url, Map<String, Object> param) {
        this.doDelete(url, param);
    }

    /**
     * json格式的post请求
     */
    public String jsonPost(String url, Map<String, Object> param) {
        return dealResponseData(this.doPost(url, getJsonHttpEntity(param)), param);
    }

    public String jsonPost(String url, List<Map<String, Object>> param) {
        return dealResponseDataList(this.doPost(url, getJsonHttpEntity(param)), param);
    }

    public String jsonPostWithHeaders(String url, Map<String, Object> param, HttpHeaders headers) {
        return dealResponseData(this.doPost(url, getJsonHttpEntityWithHeaders(param, headers)), param);
    }

    public String jsonPut(String url, Map<String, Object> param) {
        return dealResponseData(this.doPut(url, getJsonHttpEntity(param)), param);
    }

    /**
     * form格式的post请求
     */
    public String formPost(String url, Map<String, Object> map) {
        return dealResponseData(this.doPost(url, getFormHttpEntityWithHeaders(map)), map);
    }

    public String formPostWithHeaders(String url, Map<String, Object> map, HttpHeaders headers) {
        return dealResponseData(this.doPost(url, getFormHttpEntityWithHeaders(map, headers)), map);
    }

    /**
     * 解密请求返回的数据,返回解密后的json格式数据
     */
    protected String dealResponseData(String responseStr, Map<String, Object> param) {
        return responseStr;
    }

    protected String dealResponseDataList(String responseStr, List<Map<String, Object>> param) {
        return responseStr;
    }

    protected HttpEntity<String> getJsonHttpEntity(Map<String, Object> param) {
        header.clear();
        header.setContentType(MediaType.APPLICATION_JSON);
        header.add("Accept", MediaType.APPLICATION_JSON.toString());
        return new HttpEntity<>(GsonUtils.getGson().toJson(param), header);
    }

    public HttpEntity<String> getJsonHttpEntity(List<Map<String, Object>> param) {
        header.clear();
        header.setContentType(MediaType.APPLICATION_JSON);
        header.add("Accept", MediaType.APPLICATION_JSON.toString());
        return new HttpEntity<>(GsonUtils.getGson().toJson(param), header);
    }

    protected HttpEntity<String> getJsonHttpEntityWithHeaders(Map<String, Object> param, HttpHeaders headers) {
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        return new HttpEntity<>(GsonUtils.getGson().toJson(param), headers);
    }

    protected HttpEntity<MultiValueMap<String, Object>> getFormHttpEntityWithHeaders(Map<String, Object> param) {
        header.clear();
        header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        LinkedMultiValueMap<String, Object> valueMap = new LinkedMultiValueMap<>();
        for (Map.Entry<String, Object> entry : param.entrySet()) {
            valueMap.add(entry.getKey(), entry.getValue());
        }
        return new HttpEntity<>(valueMap, header);
    }

    protected HttpEntity<MultiValueMap<String, Object>> getFormHttpEntityWithHeaders(Map<String, Object> param,
                                                                                     HttpHeaders headers) {
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        LinkedMultiValueMap<String, Object> valueMap = new LinkedMultiValueMap<>();
        for (Map.Entry<String, Object> entry : param.entrySet()) {
            valueMap.add(entry.getKey(), entry.getValue());
        }
        return new HttpEntity<>(valueMap, headers);
    }

    protected String doPost(String url, HttpEntity httpEntity) {
        // 解决提交中文乱码问题
        setRestTemplateEncode(restTemplate);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(beforePost(genUrl(url)), httpEntity, String.class);
        return responseEntity.getBody();
    }

    /**
     * 解决提交中文乱码问题
     *
     * @param restTemplate
     */
    public static void setRestTemplateEncode(RestTemplate restTemplate) {
        if (null == restTemplate || ObjectUtils.isEmpty(restTemplate.getMessageConverters())) {
            return;
        }

        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        for (int i = 0; i < messageConverters.size(); i++) {
            HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
            if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
                messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            }
        }
    }

    protected String doPut(String url, HttpEntity httpEntity) {
        String u = beforePost(genUrl(url));
        header.clear();
        header.add("StaffID", "jingwen.zong");
        header.setContentType(MediaType.APPLICATION_JSON);
        header.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        ResponseEntity<String> responseEntity = restTemplate.exchange(u, HttpMethod.PUT, httpEntity, String.class);
        return responseEntity.getBody();
    }

    protected String doGet(String url, Map<String, Object> param) {

        StringBuilder paramStr = new StringBuilder();
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                paramStr.append("&").append(entry.getKey()).append("=").append(entry.getValue());
            }
        }
        ResponseEntity<String> responseEntity =
                restTemplate.getForEntity(beforeGet(genUrl(url)) + paramStr.toString(), String.class);
        return responseEntity.getBody();
    }

    protected String doGetWithHeaders(String url, Map<String, Object> param, HttpHeaders header) {
        StringBuilder paramStr = new StringBuilder();
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                paramStr.append("&").append(entry.getKey()).append("=").append(entry.getValue());
            }
        }
        HttpEntity<String> httpEntity = new HttpEntity<>("parameters", header);

        ResponseEntity<String> responseEntity = restTemplate.exchange(beforeGet(genUrl(url)) + paramStr.toString(),
                HttpMethod.GET, httpEntity, String.class);
        return responseEntity.getBody();
    }

    protected String getToken(String redisKey) {
        Map<Object, Object> map = redisService.hmget(redisKey);
        return String.valueOf(MapUtils.isNotEmpty(map) ? redisService.hmget(redisKey).get("access_token")
                : getCache(redisKey).get("access_token"));
    }

    protected Map<Object, Object> getCache(String redisKey) {
        Map<Object, Object> cache = new HashMap<>();
        TokenBO token = this.getAccessToken();
        cache.put("access_token", token.getToken());
        redisService.hmset(redisKey, cache, token.getExpiresIn());
        return cache;
    }

    protected void doDelete(String url, Map<String, Object> param) {

        StringBuilder paramStr = new StringBuilder();
        if (MapUtils.isNotEmpty(param)) {
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                paramStr.append("&").append(entry.getKey()).append("=").append(entry.getValue());
            }
        }

        restTemplate.delete(beforeDelete(genUrl(url)) + paramStr.toString(), String.class);
    }
}

2.Gson的帮助类,对接收的json格式的转换

import com.google.gson.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class GsonUtils {

    private static final Gson GSON;

    private static final Gson GSONIDENTITY;

    private static final JsonParser JSON_PARSER;

    static {
        // 下划线转驼峰
        // 需要特别的设置可以加上配置
        GSON = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
        // 返回本身的格式
        GSONIDENTITY = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).create();
        JSON_PARSER = new JsonParser();
    }

    public static Gson getGson() {
        return GSON;
    }

    public static Gson getGson(FieldNamingPolicy fieldNamingPolicy) {
        //反序列化
        JsonDeserializer<LocalDateTime> jsonDeserializerDateTime = (jsonElement, type, jsonDeserializationContext)
                -> LocalDateTime.parse(jsonElement.getAsJsonPrimitive().getAsString(),
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        Gson gson = new GsonBuilder().serializeNulls()
                .registerTypeAdapter(LocalDateTime.class, jsonDeserializerDateTime)
                .setFieldNamingPolicy(fieldNamingPolicy).create();
        return gson;
    }

    public static Gson getGsonIdentity() {
        return GSONIDENTITY;
    }

    public static JsonObject parse(String jsonStr) {
        JsonElement parse = parseToJsonElement(jsonStr);
        return parse == null ? null : parse.getAsJsonObject();
    }

    public static JsonElement parseToJsonElement(String jsonStr) {
        JsonElement parse = JSON_PARSER.parse(jsonStr);
        return parse.isJsonNull() ? null : parse;
    }

}

3. 将请求的接口URL变成常量类

public interface QyWeixinRequestConstants {

    /**
     * 获取token
     */
    String TOKEN_URL = "/gettoken";

    /**
     * 创建部门
     */
     String CREATE_DEPARTMENT = "/department/create";

     /**
     * 修改部门
     */
    String UPDATE_DEPARTMENT = "/department/update";

    /**
     * 删除部门
     * */
    String DELETE_DEPARTMENT = "department/delete";

    /**
     * 获取部门列表
     * */
    String DEPARTMENT_LIST = "/department/list";

    /**
     * 读取成员
     */
    String GET_USER = "/user/get";

    /**
     *获取部门成员详情
     */
    String GET_DEPARTMENT_USER = "/user/list";

    /**
     * 创建成员
     */
    String INSERT_USER = "/user/create";

    /**
     * 更新成员
     */
    String UPDATE_USER = "/user/update";

    /**
     * 删除成员
     */
    String DELETE_USER = "/user/delete";

    /**
     * 批量删除成员
     */
    String DELETE_USER_LIST = "/user/batchdelete";

    /**
     * 发送消息
     */
    String MESSAGE_SEND = "/message/send";
}

4.继承封装的请求抽象类,具象化企业微信的请求

@Slf4j
@Component
public class QyWeixinRequest extends AbstractHttpRequest {
    private Map<String, Object> tokenParamMap;
    
    @Value("${qyweixin.request.corpid}")
    String workId;

    @Value("${qyweixin.request.corpsecret}")
    String secret;

    @Value("${qyweixin.request.ip}")
    String ip;

    /**
     * 企业微信应用ID agentId
     */
    @Value("${qyweixin.request.agentId}")
    String agentId;

    public String getAgentId() {
        return agentId;
    }

    @Override
    public void afterPropertiesSet() {
        tokenParamMap = new HashMap<>();
        tokenParamMap.put("corpid", workId);
        tokenParamMap.put("corpsecret", secret);
        tokenParamMap.put("access_token", "");
    }

    @Override
    protected TokenBO getAccessToken() {
        TokenBO token = new TokenBO();
        String responseStr = getAccessTokenByJson(tokenParamMap, QyWeixinRequestConstants.TOKEN_URL);
        JsonObject asJsonObject = GsonUtils.parse(Objects.requireNonNull(responseStr));
        String accessToken = asJsonObject.get("access_token").getAsString();
        token.setToken(accessToken);
        token.setExpiresIn(asJsonObject.get("expires_in").getAsLong());
        tokenParamMap.put("access_token", accessToken);
        return token;
    }

    @Override
    protected String beforeGet(String url) {
        tokenParamMap.put("corpsecret", secret);
        return url + "?access_token=" + getToken("QYWX-Token");
    }

    @Override
    protected String getIp() {
        return this.ip;
    }
}

5. 企业微信的配置

qyweixin:
  request:
    corpid: 
    corpsecret: 
    agentId: 
    ip: https://qyapi.weixin.qq.com/cgi-bin

3. 实例调用封装的http请求,获取企业微信接口信息,并发送消息通知

1. 消息通知的实体类

@Data
public class WxBaseMessage implements Serializable {
    /**
     * 否	成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向该企业应用的全部成员发送
     */
    private String touser;

    /**
     * 是	消息类型,文本:text,图片:image,语音:voice,视频:video,文件:file,文本卡片:textcard,图文消息展现此:mpnews,markdown消息:markdown,小程序通知:miniprogram_notice
     */
    private String msgtype;

    /**
     * 是	企业应用的id,整型。企业内部开发,可在应用的设置页面查看;第三方服务商,可通过接口 获取企业授权信息 获取该参数值
     */
    private String agentid;

    /**
     * 否	表示是否是保密消息,0表示否,1表示是,默认0
     */
    private String safe;

    private ListDTO text;

    @Data
    public static class ListDTO implements Serializable {

        private String content;
    }
}

2. 调用企微的接口获取人员并发送短信通知

@Component
public class QyWeixinJob {
    @Autowired
    private QyWeixinRequest request;

    public void getQyDeptList() {
        String departmentStr = request.get(QyWeixinRequestConstants.DEPARTMENT_LIST);
        if (StringUtils.isBlank(departmentStr)) {
            return;
        }

        QyWeixinDepartmentDTO list = GsonUtils.getGson().fromJson(departmentStr, new TypeToken<QyWeixinDepartmentDTO>() {
        }.getType());
        List<QyWeixinDepartmentDTO.ListDTO> qyDeptList = list.getDepartment();

        List<QyWeixinUserDTO.ListDTO> allUserList = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(qyDeptList)) {
            qyDeptList.forEach(item -> {
                HashMap<String, Object> map = new HashMap<>();
                map.put("department_id", item.getId());

                String employeeStr = request.get(QyWeixinRequestConstants.GET_DEPARTMENT_USER, map);
                QyWeixinUserDTO qyWeixinUserDto = GsonUtils.getGson().fromJson(employeeStr, new TypeToken<QyWeixinUserDTO>() {
                }.getType());

                List<QyWeixinUserDTO.ListDTO> userList = qyWeixinUserDto.getUserlist();
                if (CollectionUtils.isNotEmpty(userList)) {
                    allUserList.addAll(userList);
                }
            });

            String userIds = allUserList.stream().map(QyWeixinUserDTO.ListDTO::getUserid).collect(Collectors.joining("|"));
            String content = "1111";
            if (StringUtils.isNotBlank(userIds)) {
                sendMessage(userIds, content);
            }
        }
    }

    /**
     * 发送应用消息
     */
    private void sendMessage(String userIds, String content) {
        WxBaseMessage wxMessage = new WxBaseMessage();
        wxMessage.setAgentid(request.getAgentId());
        wxMessage.setTouser(userIds);
        wxMessage.setMsgtype("text");
        WxBaseMessage.ListDTO text = new WxBaseMessage.ListDTO();
        text.setContent(content);
        wxMessage.setText(text);
        wxMessage.setSafe("1");
        Map<String, Object> param = BeanUtil.beanToMap(wxMessage);
        String result = request.jsonPost(QyWeixinRequestConstants.MESSAGE_SEND, param);
    }
}

该处使用的url网络请求的数据。


总结

以上请求封装就是方便调用多个系统的请求数据,做到一次封装,多次使用。

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值