最近项目上需要用到企业微信应用进行消息的群发功能,用来将系统产生的告警消息通过企业微信群发的方式通知客户方,来达到及时处理故障的目的,使用了下还是较简单的,这里记录一下过程,备查。文章前面有一点术语的介绍,如果想快速直接看怎么使用,点击这里跳过基本术语介绍,直接开始。
一.基本术语介绍说明
1.corpid
2.userid
3.部门id
4.tagid
5.agentid
6.secret
secret是企业应用里面用于保障数据安全的“钥匙”,每一个应用都有一个独立的访问密钥,为了保证数据的安全,secret务必不能泄漏。
自建应用secret。在管理后台->“应用与小程序”->“应用”->“自建”,点进某个应用,即可看到。 基础应用secret。某些基础应用(如“审批”“打卡”应用),支持通过API进行操作。在管理后台->“应用与小程序”->“应用->”“基础”,点进某个应用,点开“API”小按钮,即可看到。 通讯录管理secret。在“管理工具”-“通讯录同步”里面查看(需开启“API接口同步”); 客户联系管理secret。在“客户联系”栏,点开“API”小按钮,即可看到。
7.access_token
access_token是企业后台去企业微信的后台获取信息时的重要票据,由corpid和secret产生。所有接口在通信时都需要携带此信息用于验证接口的访问权限
二.通过企业微信服务端API群发应用消息
1.Http接口调用工具类准备
因为需要用到Http调用,这里提前准备2个Http的调用工具,一个是J
ava的Jdk自带实现的,不依赖任何jar包,可用于测试,如果你的调用量不多,也可以用于生产。另一个是依赖apache的httpClient,具备连接池功能,建议可用于生产。因为代码占内容太多,因此代码位于文章最后,可直接跳转至代码部署查看,点击即会跳转
2.获取access_token
官方接口文档:
https://work.weixin..com/api/doc/90000/90135/91039
请求方式:GET(HTTPS)
请求URL:https://qyapi.weixin..com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
注:通常正式环境需要自己登陆后自行维护access_token,一般是2小时有效期,在快到期或已过期时需要重新登陆,可以用利用返回结果码为40014和42001分别表示为非法access_token和过期的access_token,可以利用此两个错误码进行判断与更新
public static void main(String[] args) throws Exception {
String url = "https://qyapi.weixin..com/cgi-bin/gettoken?corpid=ww160d&corpsecret=BAtr2B*"; HttpRestUtils util = new HttpRestUtils(); String result = util.doGet(url); System.out.println(result); }
或者使用apache的httpClient的工具类调试:
public static void main(String[] args) throws InterruptedException {
//这里把你的corpid和corpsecret替换成正确的 String url = "https://qyapi.weixin..com/cgi-bin/gettoken?corpid=ww160d&corpsecret=BAtr2B*"; System.out.println(HttpsKit.get(url)); //关闭连接池,正式环境中这个不要关闭 HttpsKit.closeConnectionPool(); }
响应接果:
{
"errcode":0,"errmsg":"ok","access_token":"vMpg1HNU8PHf0NSfVGMXw2Gg0HN16LnvMH3J4LXeoY5MMA25PiO2ZabcdHJ6bRi5PqUuyLf94aRBb3yTKs344h5eU35doprLeIKtuf9xfKOk8VQ6F_GeTuxmcV_qQH0CLOrc5y9cXT9SCEi7LpQCiS4F4ssdff0zu-jyGmlEtUBplqSF8xDQBJ3aj6-hfg","expires_in":7200}
3.调用群应用消息发送接口即可
群应用消息发送接口官方文档:
https://work.weixin..com/api/doc/90000/90135/90236
应用支持推送文本、图片、视频、文件、图文等类型。
请求方式:POST(HTTPS)
请求地址:https://qyapi.weixin..com/cgi-bin/message/send?access_token=ACCESS_TOKEN
public static void main(String[] args) throws Exception {
String url = "https://qyapi.weixin..com/cgi-bin/message/send?access_token=JhLKJB2cZssssssssssssssssssssssssssssssssssssU2HHQ"; HttpRestUtils util = new HttpRestUtils(); String paramStr = "{\"touser\":\"@all\",\"msgtype\":\"text\",\"agentid\":,\"text\":{\"content\":\"测试下应用群发告警消息,打扰了,请忽略。\"}}"; String result = util.doPost(url, paramStr); System.out.println(result); }
或者使用apache的httpClient的工具类调试:
public static void main(String[] args) throws InterruptedException {
String url = "https://qyapi.weixin..com/cgi-bin/message/send?access_token=JhLKJB2cZssssssssssssssssssssssssssssssssssssU2HHQ"; String data = "{\"touser\":\"@all\",\"msgtype\":\"text\",\"agentid\":,\"text\":{\"content\":\"测试下应用群发告警消息,打扰了,请忽略。\"}}"; System.out.println(HttpsKit.postJson(url, data)); //关闭连接池,正式环境中这个不要关闭 HttpsKit.closeConnectionPool(); }
4.Http接口调用工具类代码提供如下
工具类1:使用纯jdk自带的URLConnection实现的
package cn.gzsendi.system.utils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HttpRestUtils {
private final String GET = "GET"; private final String POST = "POST"; private final String CharacterSet = "UTF-8"; public String doGet(String url) throws Exception{
String method = this.GET; return load(url,null,method); } public String doPost(String url, String params) throws Exception{
String method = this.POST; return load(url,params,method); } / * @param url * @param params * @param method * @return * @throws Exception */ public String load(String url,String params,String method) throws Exception {
HttpURLConnection conn = null; try {
boolean isHttps = url.startsWith("https"); URL restURL = new URL(url); conn = (HttpURLConnection) restURL.openConnection(); //https请求需要格外处理下 if(isHttps) {
TrustManager[] tm = {
new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); SSLSocketFactory ssf = sslContext.getSocketFactory(); ((HttpsURLConnection)conn).setSSLSocketFactory(ssf); ((HttpsURLConnection)conn).setHostnameVerifier(new TrustAnyHostnameVerifier()); } conn.setDoOutput(true); conn.setAllowUserInteraction(false); conn.setUseCaches(false); conn.setRequestMethod(method); conn.connect(); OutputStreamWriter out = null; OutputStream outputStream = null; if(this.POST.equals(method) && params != null){
outputStream = conn.getOutputStream(); out = new OutputStreamWriter(outputStream, this.CharacterSet); out.write(params); out.close(); } InputStream inputStream = conn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, this.CharacterSet); BufferedReader bReader = new BufferedReader(inputStreamReader); String line = ""; StringBuffer resultStr = new StringBuffer(); while (null != (line = bReader.readLine())) {
resultStr.append(line); } // 释放资源 bReader.close(); inputStreamReader.close(); inputStream.close(); inputStream = null; if(out!=null) out.close(); if(outputStream!=null)outputStream.close(); return resultStr.toString(); } catch (Exception e) {
e.printStackTrace(); } finally {
if(conn != null) conn.disconnect(); } return null; } private class TrustAnyHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
// 直接返回true return true; } } private class MyX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
} public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
} public X509Certificate[] getAcceptedIssuers() {
return null; } } }
工具类2:使用apache的httpclient进行编写实现类
注:pom依赖,我的工具类里面用到了common-io,httpclient,和log4j,其中log4j如果你不想要,可以根据代码进行调整删除,common-io也是一样,也可以采用其他方法,修改点代码就可。
<!-- httpclient start --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.12</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.5.12</version> </dependency> <!-- httpclient end --> <!-- common-io start --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.7</version> </dependency> <!-- common-io end --> <!-- log start --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <!-- log end -->
package cn.gzsendi.system.utils; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; import org.apache.http.NameValuePair; import org.apache.http.NoHttpResponseException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; 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.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContextBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpsKit {
private static Logger logger = LoggerFactory.getLogger(HttpsKit.class); private static final int CONNECT_TIMEOUT = 10000;// 设置连接建立的超时时间为10000ms private static final int SOCKET_TIMEOUT = 30000; // 多少时间没有数据传输 private static final int HttpIdelTimeout = 30000;//空闲时间 private static final int HttpMonitorInterval = 10000;//多久检查一次 private static final int MAX_CONN = 200; // 最大连接数 private static final int Max_PRE_ROUTE = 200; //设置到路由的最大连接数, private static CloseableHttpClient httpClient; // 发送请求的客户端单例 private static PoolingHttpClientConnectionManager manager; // 连接池管理类 private static ScheduledExecutorService monitorExecutor; private static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded"; private static final String APPLICATION_JSON = "application/json"; private final static Object syncLock = new Object(); // 相当于线程锁,用于线程安全 private static RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(CONNECT_TIMEOUT) .setConnectTimeout(CONNECT_TIMEOUT) .setSocketTimeout(SOCKET_TIMEOUT).build(); private static CloseableHttpClient getHttpClient() {
if (httpClient == null) {
// 多线程下多个线程同时调用getHttpClient容易导致重复创建httpClient对象的问题,所以加上了同步锁 synchronized (syncLock) {
if (httpClient == null) {
try {
httpClient = createHttpClient(); } catch (KeyManagementException e) {
logger.error("error",e); } catch (NoSuchAlgorithmException e) {
logger.error("error",e); } catch (KeyStoreException e) {
logger.error("error",e); } // 开启监控线程,对异常和空闲线程进行关闭 monitorExecutor = Executors.newScheduledThreadPool(1); monitorExecutor.scheduleAtFixedRate(new TimerTask() {
@Override public void run() {
// 关闭异常连接 manager.closeExpiredConnections(); // 关闭5s空闲的连接 manager.closeIdleConnections(HttpIdelTimeout,TimeUnit.MILLISECONDS); logger.info(manager.getTotalStats().toString()); //logger.info("close expired and idle for over "+HttpIdelTimeout+"ms connection"); } }, HttpMonitorInterval, HttpMonitorInterval, TimeUnit.MILLISECONDS); } } } return httpClient; } / * 构建httpclient实例 * @return * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws KeyManagementException */ private static CloseableHttpClient createHttpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
SSLContextBuilder builder = new SSLContextBuilder(); // 全部信任 不做身份鉴定 builder.loadTrustMaterial(null, new TrustStrategy() {
@Override public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
return true; } }); ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory(); LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE); Registry<ConnectionSocketFactory> registry = RegistryBuilder .<ConnectionSocketFactory> create() .register("http", plainSocketFactory) .register("https", sslSocketFactory).build(); manager = new PoolingHttpClientConnectionManager(registry); // 设置连接参数 manager.setMaxTotal(MAX_CONN); // 最大连接数 manager.setDefaultMaxPerRoute(Max_PRE_ROUTE); // 路由最大连接数 // 请求失败时,进行请求重试 HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
@Override public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
if (i > 3) {
// 重试超过3次,放弃请求 logger.error("retry has more than 3 time, give up request"); return false; } if (e instanceof NoHttpResponseException) {
// 服务器没有响应,可能是服务器断开了连接,应该重试 logger.error("receive no response from server, retry"); return true; } if (e instanceof SSLHandshakeException) {
// SSL握手异常 logger.error("SSL hand shake exception"); return false; } if (e instanceof InterruptedIOException) {
// 超时 logger.error("InterruptedIOException"); return false; } if (e instanceof UnknownHostException) {
// 服务器不可达 logger.error("server host unknown"); return false; } if (e instanceof ConnectTimeoutException) {
// 连接超时 logger.error("Connection Time out"); return false; } if (e instanceof SSLException) {
logger.error("SSLException"); return false; } HttpClientContext context = HttpClientContext.adapt(httpContext); HttpRequest request = context.getRequest(); if (!(request instanceof HttpEntityEnclosingRequest)) {
// 如果请求不是关闭连接的请求 return true; } return false; } }; CloseableHttpClient client = HttpClients.custom().setConnectionManager(manager).setRetryHandler(handler).build(); return client; } public static String get(String url) {
HttpGet httpGet = new HttpGet(url); httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"); httpGet.setConfig(requestConfig); CloseableHttpResponse response = null; InputStream in = null; String result = null; try {
response = getHttpClient().execute(httpGet,HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (entity != null) {
in = entity.getContent(); result = IOUtils.toString(in, "utf-8"); } } catch (IOException e) {
logger.error("error",e); } finally {
try {
if (in != null) in.close(); } catch (IOException e) {
logger.error("error",e); } try {
if (response != null) response.close(); } catch (IOException e) {
logger.error("error",e); } } return result; } public static String postJson(String url,Map<String,Object> requestParams) {
return postJson(url, JsonUtil.toJSONString(requestParams)); } public static String postJson(String url,Map<String,Object> requestParams,Map<String,Object> headerParams) {
return postJson(url, JsonUtil.toJSONString(requestParams),headerParams); } public static String postJson(String url,String requestParamStr) {
return postJson(url, requestParamStr, null); } public static String postJson(String url,String requestParamStr,Map<String,Object> headerParams) {
HttpPost httppost = new HttpPost(url); httppost.setHeader("Content-Type", APPLICATION_JSON+";charset=" + CharEncoding.UTF_8); httppost.setHeader("Accept",APPLICATION_JSON+";charset=" +CharEncoding.UTF_8); httppost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"); if(headerParams != null && headerParams.size()>0){
for(String headerName : headerParams.keySet()) {
httppost.setHeader(headerName,headerParams.get(headerName)+""); } } StringEntity se = new StringEntity(requestParamStr,CharEncoding.UTF_8); se.setContentType(APPLICATION_JSON+";charset=" +CharEncoding.UTF_8); httppost.setEntity(se); httppost.setConfig(requestConfig); CloseableHttpResponse response = null; InputStream in = null; String result = null; try {
response = getHttpClient().execute(httppost,HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (entity != null) {
in = entity.getContent(); result = IOUtils.toString(in, "utf-8"); } } catch (IOException e) {
logger.error("error",e); } finally {
try {
if (in != null) in.close(); } catch (IOException e) {
logger.error("error",e); } try {
if (response != null) response.close(); } catch (IOException e) {
logger.error("error",e); } } return result; } //requestParamStr---------->>> name=test&age=12 public static String postFormUrlencoded(String url,String requestParamStr) {
return postFormUrlencoded(url, requestParamStr ,null); } public static String postFormUrlencoded(String url,String requestParamStr,Map<String,Object> headerParams) {
Map<String,String> requestParams = new HashMap<String,String>(); String[] strs = requestParamStr.split("&"); for(String str : strs) {
String[] keyValues = str.split("="); if(keyValues.length == 2) {
requestParams.put(keyValues[0], keyValues[1]); } } return postFormUrlencoded(url, requestParams,headerParams); } public static String postFormUrlencoded(String url,Map<String,String> requestParams) {
return postFormUrlencoded(url,requestParams,null); } public static String postFormUrlencoded(String url,Map<String,String> requestParams,Map<String,Object> headerParams) {
HttpPost httppost = new HttpPost(url); //application/json httppost.setHeader("Content-Type", APPLICATION_FORM_URLENCODED+";charset=" + CharEncoding.UTF_8); httppost.setHeader("Accept",APPLICATION_FORM_URLENCODED+";charset=" +CharEncoding.UTF_8); httppost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"); if(headerParams != null && headerParams.size()>0){
for(String headerName : headerParams.keySet()) {
httppost.setHeader(headerName,headerParams.get(headerName)+""); } } List<NameValuePair> formparams = new ArrayList<NameValuePair>(); for(String keyStr : requestParams.keySet()) {
formparams.add(new BasicNameValuePair(keyStr, requestParams.get(keyStr))); } UrlEncodedFormEntity uefe = new UrlEncodedFormEntity(formparams, Consts.UTF_8); httppost.setEntity(uefe); httppost.setConfig(requestConfig); CloseableHttpResponse response = null; InputStream in = null; String result = null; try {
response = getHttpClient().execute(httppost,HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (entity != null) {
in = entity.getContent(); result = IOUtils.toString(in, "utf-8"); } } catch (IOException e) {
logger.error("error",e); } finally {
try {
if (in != null) in.close(); if (response != null) response.close(); } catch (IOException e) {
logger.error("error",e); } } return result; } / * 关闭连接池 */ public static void closeConnectionPool() {
try {
if(httpClient != null) httpClient.close(); if(manager != null) manager.close(); if(monitorExecutor != null) monitorExecutor.shutdown(); } catch (IOException e) {
logger.error("error",e); } } }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/215734.html原文链接:https://javaforall.net

