提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
以下是整合了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网络请求的数据。
总结
以上请求封装就是方便调用多个系统的请求数据,做到一次封装,多次使用。