import com.alibaba.fastjson.JSONObject;
import com.bhudy.entity.BhudyPlugin;
import com.bhudy.service.BhudyPluginService;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.util.*;

/**
* Created by Administrator on 2019/8/23/023.
*/
@Component
public final class WeChatUtils {

@Autowired
private WeChatUtils(BhudyPluginService bhudyPluginService) {
WeChatUtils.bhudyPluginService = bhudyPluginService;
}

private static BhudyPluginService bhudyPluginService; // 获取微信appid的接口

private static Map<String, String> tokenMap = null;

public static String wxGzhWorkOrder = "xxxxx"; // 工单状态通知Key
public static String weGzhReport = "xxxxxx"; // 报告生成通知Key

private static String authorizationCode = "authorization_code"; // 微信调用接口使用参数authorization_code
private static String clientCredential = "client_credential"; // 微信调用接口使用参数client_credential

/**
* 发送报告生成通知
* 报告生成通知Id: P9U-LYY4qtcKKqSoDb7sfqK4GlFQvDu8G5JxWOTkUQk
* <p>
* {{first.DATA}}
* 报告类型:{{keyword1.DATA}}
* 生成时间:{{keyword2.DATA}}
* {{remark.DATA}}
*
* @return 是否发送成功
*/
public static boolean sendWeGzhReport(String openId, String first, String remark, Map<String, Object> keywordMap) {
return sendWxGzh(openId, WeChatUtils.weGzhReport, first, remark, keywordMap);
}

/**
* 发送微信公众号工单消息提醒
* 工单模板信息id: i5JtheQBLYM9VyByYR2EqrGlbdZiiFZVyA7rndbOAuM
* <p>
* {{first.DATA}}
* 工单编号:{{keyword1.DATA}}
* 工单标题:{{keyword2.DATA}}
* 时间:{{keyword3.DATA}}
* {{remark.DATA}}
*
* @return 是否发送成功
*/
public static boolean sendWxGzhWorkOrder(String openId, String first, String remark, Map<String, Object> keywordMap) {
return sendWxGzh(openId, WeChatUtils.wxGzhWorkOrder, first, remark, keywordMap);
}

/**
* 发送微信公众号信息
* <p>
* 参数 是否必填 说明
* touser 是 接收者openid
* template_id 是 模板ID
* url 否 模板跳转链接(海外帐号没有跳转能力)
* miniprogram 否 跳小程序所需数据,不需跳小程序可不用传该数据
* appid 是 所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)
* pagepath 否 所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏
* data 是 模板数据
* color 否 模板内容字体颜色,不填默认为黑色
* <p>
* json数据模板
* {"touser":"OPENID","template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY","url":"http://weixin.qq.com/download",
* "miniprogram":{"appid":"xiaochengxuappid12345","pagepath":"index?foo=bar"},"data":{"first":{"value":"恭喜你购买成功!","color":"#173177"},
* "keyword1":{"value":"巧克力","color":"#173177"},"keyword2":{"value":"39.8元","color":"#173177"},"keyword3":{"value":"2014年9月22日","color":"#173177"},
* "remark":{"value":"欢迎再次购买!","color":"#173177"}}}
*
* @param openId 接收消息的用户openid
* @param templateId 消息模板id
* @param first 标题
* @param remark 结尾
* @param keywordMap 内容map
* @return 是否发送成功
*/
public static boolean sendWxGzh(String openId, String templateId, String first, String remark, Map<String, Object> keywordMap) {
if (openId == null || openId.equals("")) return false;

String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + WeChatUtils.getToken(BhudyPlugin.TENCENT_TAS);
Map<String, Object> map = new HashMap<>();
map.put("touser", openId);
map.put("template_id", templateId);
map.put("url", null);

Map<String, Object> miniprogramMap = new HashMap<>();

miniprogramMap.put("appid", bhudyPluginService.getBhudyPluginDataByType(BhudyPlugin.TENCENT_TAS).get(BhudyPlugin.appId));
//miniprogramMap.put("pagepath", "index");
map.put("miniprogram", miniprogramMap);

Map<String, Object> dataMap = new HashMap<>();

Map firstMap = new HashMap<>();
firstMap.put("value", first);
dataMap.put("first", firstMap);

for (Map.Entry entrySet : keywordMap.entrySet()) {
Map keyword1Map = new HashMap<>();
keyword1Map.put("value", entrySet.getValue());
dataMap.put(entrySet.getKey().toString(), keyword1Map);
}

Map remarkMap = new HashMap<>();
remarkMap.put("value", remark);
dataMap.put("remark", remarkMap);

map.put("data", dataMap);

Map<String, Object> resultMap = WeChatUtils.wxReqDataPost(url, JSONObject.toJSONString(map));
return resultMap != null;
}

/**
* 获取用户基本信息(UnionID机制)
* 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。
* 请注意,如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。
* <p>
* 参数 是否必须 说明
* access_token 是 调用接口凭证
* openid 是 普通用户的标识,对当前公众号唯一
* lang 否 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语
* ***********************************
*
* @return <br>
* 参数 说明
* subscribe 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
* openid 用户的标识,对当前公众号唯一
* nickname 用户的昵称
* sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
* city 用户所在城市
* country 用户所在国家
* province 用户所在省份
* language 用户的语言,简体中文为zh_CN
* headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
* subscribe_time 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
* unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
* remark 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
* groupid 用户所在的分组ID(兼容旧的用户分组接口)
* tagid_list 用户被打上的标签ID列表
* subscribe_scene 返回用户关注的渠道来源,ADD_SCENE_SEARCH 公众号搜索,ADD_SCENE_ACCOUNT_MIGRATION 公众号迁移,ADD_SCENE_PROFILE_CARD 名片分享,ADD_SCENE_QR_CODE 扫描二维码,ADD_SCENEPROFILE LINK 图文页内名称点击,ADD_SCENE_PROFILE_ITEM 图文页右上角菜单,ADD_SCENE_PAID 支付后关注,ADD_SCENE_OTHERS 其他
* qr_scene 二维码扫码场景(开发者自定义)
* qr_scene_str 二维码扫码场景描述(开发者自定义)
* UnionID
*/
public static Map<String, Object> getUserInfo(String openId, Integer type) {
String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + WeChatUtils.getToken(type) + "&openid=" + openId + "&lang=zh_CN";
Map resultMap = WeChatUtils.wxReqDataGet(url);
return resultMap;
}

/**
* 获取公众号用户列表
* 公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的)组成。一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
* <p>
* 参数 是否必须 说明
* access_token 是 调用接口凭证
* next_openid 是 第一个拉取的OPENID,不填默认从头开始拉取
*
* @param nextOpenid 第一个拉取的OPENID,不填默认从头开始拉取
* @return <br>
* 参数 说明
* total 关注该公众账号的总用户数
* count 拉取的OPENID个数,最大值为10000
* data 列表数据,OPENID的列表
* next_openid 拉取列表的最后一个用户的OPENID
*/
public static Map<String, Object> getOpenIdListMap(String nextOpenid) {
String url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + getToken(BhudyPlugin.TENCENT_TAS);
if (nextOpenid != null && nextOpenid.equals("")) {
url += "&next_openid=" + nextOpenid;
}

Map resultMap = WeChatUtils.wxReqDataGet(url);
return resultMap;
}

/**
* @param type 1是公众号请求
* @return * * *
* 属性 类型 说明
* access_token string 获取到的凭证
* expires_in number 凭证有效时间,单位:秒。目前是7200秒之内的值。
* errcode number 错误码
* errmsg string 错误信息
* <p>
* =====================================
* <p>
* errcode 的合法值
* 值 说明 最低版本
* -1 系统繁忙,此时请开发者稍候再试
* 0 请求成功
* 40001 AppSecret 错误或者 AppSecret 不属于这个小程序,请开发者确认 AppSecret 的正确性
* 40002 请确保 grant_type 字段值为 client_credential
* 40013 不合法的 AppID,请开发者检查 AppID 的正确性,避免异常字符,注意大小写
*/
public static String getToken(Integer type) {
Map<String, String> tokenMap = WeChatUtils.tokenMap;
// 微信的access_token有效期是7200秒,所以我们的过期时间要比微信的快token
if (tokenMap != null && Utils.formatLong(tokenMap.get("date")) >= (new Date().getTime() + (7200 * 1000))) {
return tokenMap.get("access_token");
}

Map<String, String> weChatMap = bhudyPluginService.getBhudyPluginDataByType(type);
String url = "https://api.weixin.qq.com/cgi-bin/token?appid=" + weChatMap.get(BhudyPlugin.appId) + "&secret=" + weChatMap.get(BhudyPlugin.appSecret) + "&grant_type=" + clientCredential;

Map<String, Object> resultMap = WeChatUtils.wxReqDataGet(url);
if (resultMap == null) throw new BhudyException(BhudyExceptionCode.CODE_29);

String token = (String) resultMap.get("access_token");
WeChatUtils.tokenMap = new HashMap<>();
WeChatUtils.tokenMap.put("date", String.valueOf(new Date().getTime()));
WeChatUtils.tokenMap.put("access_token", token);

return token;
}

/**
* @param code string 是 登录时获取的 code
* @return * * *
* 属性 类型 说明
* openid string 用户唯一标识
* session_key string 会话密钥
* unionid string 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见 UnionID 机制说明。
* errcode number 错误码
* errmsg string 错误信息
* <p>
* ===================================
* <p>
* errcode 的合法值
* 值 说明 最低版本
* -1 系统繁忙,此时请开发者稍候再试
* 0 请求成功
* 40029 code 无效
* 45011 频率限制,每个用户每分钟100次
*/
public static Map<String, Object> getOpenIdAndSessionKey(String code, Integer type) {
Map<String, String> weChatMap = bhudyPluginService.getBhudyPluginDataByType(type);
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + weChatMap.get(BhudyPlugin.appId) + "&secret=" + weChatMap.get(BhudyPlugin.appSecret) + "&grant_type=" + authorizationCode + "&js_code=" + code;
return WeChatUtils.wxReqDataGet(url);
}

/**
* 微信Post请求
* 如果微信端返回错误码或者没有返回数据,这个方法直接返回null
* 该方法没有使用线程,可能会卡死
*
* @param url 请求的url
* @param params
* @return
*/
public static Map<String, Object> wxReqDataPost(String url, String params) {
try {
Map<String, Object> reulstMap = Utils.reqPost(url, params);
if (reulstMap == null || (reulstMap.containsKey("errcode") && (Integer) reulstMap.get("errcode") != 0)) {
return null;
}
return reulstMap;
} catch (Exception e) {
return null;
}
}

/**
* 微信Get请求
* 如果微信端返回错误码或者没有返回数据,这个方法直接返回null
* 该方法没有使用线程,可能会卡死
*
* @param url 请求的url
* @return
*/
public static Map<String, Object> wxReqDataGet(String url) {
try {
Map<String, Object> reulstMap = Utils.reqGetMap(url);
if (reulstMap == null || (reulstMap.containsKey("errcode") && (Integer) reulstMap.get("errcode") != 0)) {
return null;
}
return reulstMap;
} catch (Exception e) {
return null;
}
}

/**
* 接收事件推送
* 用法@RequestMapping(value = "/wx/api/v1/receiveEventPush.do", method = RequestMethod.POST, consumes = {"application/xml", "text/xml"}, produces = {"application/xml;charset=utf-8", "text/xml;charset=utf-8"})
* public Object receiveEventPush(@RequestBody DOMSource domSource) {
* return WxUtils.receiveEventPush(domSource);
* }
*
* @param domSource
* @return * * *
* <p>
* 目录 MsgType Event
* 1 关注/取消关注事件
* 2 扫描带参数二维码事件
* 3 上报地理位置事件
* 4 自定义菜单事件
* 5 点击菜单拉取消息时的事件推送
* 6 点击菜单跳转链接时的事件推送
* <p>
* <p>
* 》》》1.关注/取消关注事件《《《
* 参数 描述
* ToUserName 开发者微信号
* FromUserName 发送方帐号(一个OpenID)
* CreateTime 消息创建时间 (整型)
* MsgType 消息类型,event
* Event 事件类型,subscribe(订阅)、unsubscribe(取消订阅)
* <p>
* <p>
* 》》》2.扫描带参数二维码事件《《《
* 参数 描述
* ToUserName 开发者微信号
* FromUserName 发送方帐号(一个OpenID)
* CreateTime 消息创建时间 (整型)
* MsgType 消息类型,event
* Event 事件类型,subscribe
* EventKey 事件KEY值,qrscene_为前缀,后面为二维码的参数值
* Ticket 二维码的ticket,可用来换取二维码图片
* <p>
* <p>
* 》》》3.上报地理位置事件《《《
* 参数 描述
* ToUserName 开发者微信号
* FromUserName 发送方帐号(一个OpenID)
* CreateTime 消息创建时间 (整型)
* MsgType 消息类型,event
* Event 事件类型,LOCATION
* Latitude 地理位置纬度
* Longitude 地理位置经度
* Precision 地理位置精度
* <p>
* <p>
* 》》》5.点击菜单拉取消息时的事件推送《《《
* 参数 描述
* ToUserName 开发者微信号
* FromUserName 发送方帐号(一个OpenID)
* CreateTime 消息创建时间 (整型)
* MsgType 消息类型,event
* Event 事件类型,CLICK
* EventKey 事件KEY值,与自定义菜单接口中KEY值对应
* <p>
* <p>
* 》》》6.点击菜单跳转链接时的事件推送《《《
* 参数 描述
* ToUserName 开发者微信号
* FromUserName 发送方帐号(一个OpenID)
* CreateTime 消息创建时间 (整型)
* MsgType 消息类型,event
* Event 事件类型,VIEW
* EventKey 事件KEY值,设置的跳转URL
* <p>
* <p>
* MsgType
* 消息类型,接收事件推送为event
* 消息类型,文本为text
* 消息类型,图片为image
* 消息类型,语音为voice
* 消息类型,视频为video
* 消息类型,音乐为music
* 消息类型,图文为news
*/
public static String receiveEventPush(DOMSource domSource) {
Map<String, Object> xmlMap = domSourceToMap(domSource);

if (xmlMap == null) return "";

String msgType = (String) xmlMap.get("MsgType");
String fromUserName = (String) xmlMap.get("FromUserName");
String toUserName = (String) xmlMap.get("ToUserName");
String event = (String) xmlMap.get("Event");
String text;
if (msgType.equals("event")) {
if (event.equals("subscribe")) {
// 关注事件
text = "关注事件";
} else if (event.equals("unsubscribe")) {
// 取消关注事件
text = "取消关注事件";
} else {
text = "对不起,无法识别消息类型";
}
} else if (msgType.equals("text")) {
// 消息类型,为text
text = "消息类型,文本为text";
} else if (msgType.equals("image")) {
// 消息类型,图片为image
text = "消息类型,图片为image";
} else if (msgType.equals("voice")) {
// 消息类型,语音为voice
text = "消息类型,语音为voice";
} else if (msgType.equals("video")) {
// 消息类型,视频为video
text = "消息类型,视频为video";
} else if (msgType.equals("music")) {
// 消息类型,音乐为music
text = "消息类型,音乐为music";
} else if (msgType.equals("news")) {
// 消息类型,图文为news
text = "消息类型,图文为news";
} else {
text = "对不起,无法识别消息类型";
}

String returnData = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" +
" <xml>" +
" <Content>" + text + "</Content>" +
" <ToUserName>" + fromUserName + "</ToUserName>" +
" <FromUserName>" + toUserName + "</FromUserName>" +
" <CreateTime>" + new Date().getTime() / 1000 + "</CreateTime>" +
" <MsgType>text</MsgType>" +
" </xml>";

//输出格式化后的json
return returnData;
}

private static Map<String, Object> domSourceToMap(DOMSource domSource) {
try {
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);

SAXBuilder sb = new SAXBuilder();
Document doc = sb.build(new StringReader(writer.toString()));
Element root = doc.getRootElement();

JSONObject json = new JSONObject();
json.put(root.getName(), iterateElement(root));

Map<String, Object> dataMap = JSONObject.parseObject(json.toJSONString(), Map.class);
Map<String, Object> xmlMap = (Map<String, Object>) dataMap.get("xml");
return xmlMap;
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
}

return null;
}

private static JSONObject iterateElement(Element element) {
List<Element> node = element.getChildren();
JSONObject obj = new JSONObject();
List list = null;
for (Element child : node) {
list = new LinkedList();
String text = child.getTextTrim();
if (text == null || text.equals("")) {
if (child.getChildren().size() == 0) {
continue;
}
if (obj.containsKey(child.getName())) {
list = (List) obj.get(child.getName());
}
list.add(iterateElement(child)); //遍历child的子节点
obj.put(child.getName(), list);
} else {
if (obj.containsKey(child.getName())) {
Object value = obj.get(child.getName());
try {
list = (List) value;
} catch (ClassCastException e) {
list.add(value);
}
}
if (child.getChildren().size() == 0) { //child无子节点时直接设置text
obj.put(child.getName(), text);
} else {
list.add(text);
obj.put(child.getName(), list);
}
}
}
return obj;
}

/**
* 验证微信绑定服务器的方法
*
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
//1.定义数组存放tooken,timestamp,nonce
String[] arr = {"7i6L5SEu4NPuYiGVAXMy0ZnFxd6", timestamp, nonce};

//2.对数组进行排序
Arrays.sort(arr);

//3.生成字符串
StringBuffer sb = new StringBuffer();
for (String s : arr) {
sb.append(s);
}

//4.sha1加密,网上均有现成代码
String temp = getSha(sb.toString());

//5.将加密后的字符串,与微信传来的加密签名比较,返回结果
return temp.equals(signature);
}

public static String getSha(String str) {
if (str == null || str.length() == 0) {
return null;
}
char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {

MessageDigest mdTemp = MessageDigest.getInstance("SHA1");

mdTemp.update(str.getBytes("UTF-8"));

byte[] md = mdTemp.digest();

int j = md.length;

char buf[] = new char[j * 2];

int k = 0;

for (int i = 0; i < j; i++) {

byte byte0 = md[i];

buf[k++] = hexDigits[byte0 >>> 4 & 0xf];

buf[k++] = hexDigits[byte0 & 0xf];

}

return new String(buf);

} catch (Exception e) {

// TODO: handle exception

return null;

}

}

}

微信工具类需要的其他方法

/**
* 发送HttpPost请求
*
* @param strURL 服务地址
* @param params json字符串,例如: "{ \"id\":\"12345\" }" ;其中属性名必须带双引号<br/>
* @return 成功:返回json字符串<br/>
*/
public static Map<String, Object> reqPost(String strURL, String params) {
BufferedReader reader;
try {
URL url = new URL(strURL);// 创建连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("POST"); // 设置请求方式
connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式
connection.connect();
//一定要用BufferedReader 来接收响应, 使用字节来接收响应的方法是接收不到内容的
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); // utf-8编码
out.append(params);
out.flush();
out.close();
// 读取响应
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
String res = "";
while ((line = reader.readLine()) != null) {
res += line;
}
reader.close();

return JSON.parseObject(res, Map.class);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}

/**
* 请求url
*
* @param url
* @return
*/
public static Map<String, Object> reqGetMap(String url) {
try {
URL reqURL = new URL(url);
HttpsURLConnection openConnection = (HttpsURLConnection) reqURL.openConnection();
openConnection.setConnectTimeout(10000);
//这里我感觉获取openid的时间比较长,不过也可能是我网络的问题,
//所以设置的响应时间比较长
openConnection.connect();
InputStream in = openConnection.getInputStream();

StringBuilder builder = new StringBuilder();
BufferedReader bufreader = new BufferedReader(new InputStreamReader(in));
for (String temp = bufreader.readLine(); temp != null; temp = bufreader
.readLine()) {
builder.append(temp);
}

String result = builder.toString();
in.close();
openConnection.disconnect();

Map<String, Object> resultMap = JSON.parseObject(result, Map.class);

return resultMap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

java 微信开发的工具类WeChatUtils的更多相关文章

  1. java 微信开发 常用工具类(xml传输和解析 json转换对象)

    与微信通信常用工具(xml传输和解析) package com.lownsun.wechatOauth.utl; import java.io.IOException; import java.io. ...

  2. 用Java开发一个工具类,提供似于js中eval函数功能的eval方法

    今天在看到<Java疯狂讲义>中一个章节习题: 开发一个工具类,该工具类提供一个eval()方法,实现JavaScript中eval()函数的功能--可以动态运行一行或多行程序代码.例如: ...

  3. 微信https请求工具类

    工作中用到的微信https请求工具类. package com.gxgrh.wechat.tools; import com.gxgrh.wechat.wechatapi.service.System ...

  4. DbUtils是Apache出品一款简化JDBC开发的工具类

    DbUtils     - DbUtils是Apache出品一款简化JDBC开发的工具类     - 使用DbUtils可以让我们JDBC的开发更加简单     - DbUtils的使用:       ...

  5. java中常用的工具类(一)

    我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...

  6. Java学习-041-颜色工具类(RGB,HEX)

    在日常的网页开发中,经常需要进行颜色数值获取.转换,例如获取红色,获取蓝色,获取绿色,RGB转十六进制颜色,十六进制颜色转RGB等,因而在学习过程中,写了一个小工具类,仅供各位小主参考! 多不闲言,直 ...

  7. java微信开发API解析(二)-获取消息和回复消息

    java微信开发API解析(二)-获取消息和回复消息 说明 * 本演示样例依据微信开发文档:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/20 ...

  8. Java 后台验证的工具类

    Java 后台验证的工具类 public class ValidationUtil {         //手机号     public static String mobile = "^( ...

  9. Redis 工具类 java 实现的redis 工具类

    最近了解了一下非关系型数据库 redis 会使用简单的命令 在自己本地电脑 使用时必须先启动服务器端 在启动客户端 redis 简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内 ...

随机推荐

  1. DBUtils的最基本的使用

    背景 学习了如何连接数据库之后,发现里面进行查询的过程有点麻烦,因此使用DBUtils包来简化操作 配置环境 win10 jdk11 idea mysql8.0.13 jar包 连接数据库的包 c3p ...

  2. Java基础系列 - try...catch...finally

    package com.test6; import java.io.FileReader; import java.io.IOException; /** * try...catch...finall ...

  3. 1.linux 基本操作和命令

    整理复习之前的linux学习笔记,正好贴出来了.   1.[root@chen ~]#    [当前登录用户@主机名  当前所在目录]# 当前用户身份     #号表示管理员root     $号表示 ...

  4. oracle 编译无效对象

    在数据库中,会存在一些无效的对象,导致这种现象的发生原因很多,其中最常见的就是数据库升级(例如修改了表的结构),迁移而引起. 编译无效对象的方式: 1 使用alter **** compile 语句进 ...

  5. Matlab图像处理——中值滤波medfilt2问题解决

    本文链接:https://blog.csdn.net/Pxzly1117/article/details/79201772程序: I=imread('13.jpg');%读入图像imshow(I);h ...

  6. P5658 括号树

    P5658 括号树 题解 太菜了啥都不会写只能水5分数据 啥都不会写只能翻题解  题解大大我错了 我们手动找一下规律 我们设 w[ i ] 为从根节点到结点 i 对答案的贡献,也就是走到结点 i ,合 ...

  7. ISO/IEC 9899:2011 条款6.4.9——注释

    6.4.9 注释 1.除了在一个字符常量.一个字符串字面量.或一个注释内,字符 /* 引入一个注释.这么一个注释的内容被检查仅用于标识多字节字符,并且要找到 */ 来终结.[注:从而,/* ... * ...

  8. Tracker 服务器地址大全 Tracker List

    https://dns.icoa.cn/tracker/ udp://tracker.tiny-vps.com:6969/announce https://1337.abcvg.info/announ ...

  9. Build Telemetry for Distributed Services之OpenCensus:Tracing2(待续)

    part 1:Tracing1 Sampling Sampling Samplers Global sampler Per span sampler Rules References

  10. 阶段5 3.微服务项目【学成在线】_day09 课程预览 Eureka Feign_12-课程预览功能开发-需求分析

    5 课程预览功能开发 5.1 需求分析 课程预览功能将使用cms系统提供的页面预览功能,业务流程如下: 1.用户进入课程管理页面,点击课程预览,请求到课程管理服务 2.课程管理服务远程调用cms添加页 ...