JAVA微信支付代码(WeChatPay.java 才是调用类)
微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html MD5Util.java
package weixin; import java.security.MessageDigest; public class MD5Util { private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i])); return resultSb.toString();
} private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
} public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
} private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; }
RandomUtil.java
package weixin; import java.util.Random; public class RandomUtil {
private static char ch[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '0', '1' };//最后又重复两个0和1,因为需要凑足数组长度为64 private static Random random = new Random(); //生成指定长度的随机字符串
public static synchronized String createRandomString(int length) {
if (length > 0) {
int index = 0;
char[] temp = new char[length];
int num = random.nextInt();
for (int i = 0; i < length % 5; i++) {
temp[index++] = ch[num & 63];//取后面六位,记得对应的二进制是以补码形式存在的。
num >>= 6;//63的二进制为:111111
// 为什么要右移6位?因为数组里面一共有64个有效字符。为什么要除5取余?因为一个int型要用4个字节表示,也就是32位。
}
for (int i = 0; i < length / 5; i++) {
num = random.nextInt();
for (int j = 0; j < 5; j++) {
temp[index++] = ch[num & 63];
num >>= 6;
}
}
return new String(temp, 0, length);
}
else if (length == 0) {
return "";
}
else {
throw new IllegalArgumentException();
}
} }
SignUtil.java
package weixin; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*; public class SignUtil {
/**
* 微信支付签名算法sign
* @param parameters
* @return
*/
@SuppressWarnings("unchecked")
public static String createSign(SortedMap<Object,Object> parameters,String key){
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + key);
String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
return sign;
}
/**
* 与接口配置信息中的 token 要一致,这里赋予什么值,在接口配置信息中的Token就要填写什么值,
* 两边保持一致即可,建议用项目名称、公司名称缩写等,我在这里用的是项目名称weixinface
*/
private static String token = "HR9QhjKMCoUQlwd"; /**
* 验证签名
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce){
String[] arr = new String[]{token, timestamp, nonce};
// 将 token, timestamp, nonce 三个参数进行字典排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for(int i = 0; i < arr.length; i++){
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null; try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行 shal 加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
content = null;
// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()): false;
} /**
* 将字节数组转换为十六进制字符串
* @param digest
* @return
*/
private static String byteToStr(byte[] digest) {
// TODO Auto-generated method stub
String strDigest = "";
for(int i = 0; i < digest.length; i++){
strDigest += byteToHexStr(digest[i]);
}
return strDigest;
} /**
* 将字节转换为十六进制字符串
* @param b
* @return
*/
private static String byteToHexStr(byte b) {
// TODO Auto-generated method stub
char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] tempArr = new char[2];
tempArr[0] = Digit[(b >>> 4) & 0X0F];
tempArr[1] = Digit[b & 0X0F]; String s = new String(tempArr);
return s;
}
}
XmlPostUtil.java
package weixin; import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; public class XmlPostUtil {
public static byte[] sendXmlRequest(String path, String params) throws Exception {
URL url = new URL(path);
System.out.println("发送xml:" + params);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");// 提交模式
conn.setDoOutput(true);// 是否输入参数
conn.setRequestProperty("Pragma:", "no-cache");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setRequestProperty("Content-Type", "text/xml");
byte[] bypes = params.toString().getBytes("UTF-8");
conn.getOutputStream().write(bypes);// 输入参数
InputStream inStream = conn.getInputStream();
return readInputStream(inStream);
} public static byte[] readInputStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
byte[] data = outStream.toByteArray();//网页的二进制数据
outStream.close();
inStream.close();
System.out.println(new String(data, "utf-8"));
return data;
} }
XMLUtil.java
package weixin; import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*; /**
*xml工具类
*
*/
public class XMLUtil { /**
* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
if(null == strxml || "".equals(strxml)) {
return null;
} Map m = new HashMap();
InputStream in = String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
/**********************修复部分内容*********************/ String FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
builder.setFeature(FEATURE, true); FEATURE = "http://xml.org/sax/features/external-general-entities";
builder.setFeature(FEATURE, false); FEATURE = "http://xml.org/sax/features/external-parameter-entities";
builder.setFeature(FEATURE, false); FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
builder.setFeature(FEATURE, false); Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = XMLUtil.getChildrenText(children);
} m.put(k, v);
} in.close(); return m;
} /**
* 获取子结点的xml
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(XMLUtil.getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
} return sb.toString();
} public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
} public static String mapToXml(SortedMap<Object, Object> sortedMap){
StringBuffer sb = new StringBuffer("<xml>");
Iterator iterator = sortedMap.keySet().iterator();
while (iterator.hasNext()) {
Object key = (String) iterator.next();
Object value = sortedMap.get(key);
sb.append("<"+key+">");
sb.append("<![CDATA["+value+"]]>");
sb.append("</"+key+">");
}
sb.append("</xml>");
return sb.toString();
} }
PaymentConfig.java
package weixin; public class PaymentConfig {
/*******微信支付参数*********/
//公众账号ID
public static final String appid="";
//密钥
public static final String appKey="";
//商户号
public static final String mch_id="";
//接口地址
public static final String pay_url="https://api.mch.weixin.qq.com/pay/unifiedorder";
//支付返回地址
public static final String wxRetrun="";
//交易场景信息 具体参照微信官方文档不同支付类型的写法
public static final String scene_info = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"https://pay.qq.com\",\"wap_name\": \"微信支付\"}} "; public static final int ENROLL_PRICE = 200; }
WeChatPay.java
package weixin; import org.jdom.JDOMException; import java.io.IOException;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap; public class WeChatPay { /**
* 二维码支付
* @param orderNo
* @param money
* @param body
* @param ip
* @return
*/
public Map getPaymentMapCode(String orderNo,int money,String body,String ip,String wxReturn){
//一次签名
SortedMap<Object, Object> paramMap = new TreeMap<Object, Object>();
paramMap.put("appid",PaymentConfig.appid);//公众号ID
paramMap.put("mch_id",PaymentConfig.mch_id);//商户号
paramMap.put("nonce_str",RandomUtil.createRandomString(32));//32位随机字符串
paramMap.put("body",body);//商品描述
paramMap.put("out_trade_no",orderNo);//商户订单号
paramMap.put("total_fee",String.valueOf(money));//设置交易金额 金额为分
//paramMap.put("total_fee",1);//设置交易金额 金额为分
paramMap.put("spbill_create_ip",ip);//客户机IP
paramMap.put("notify_url",wxRetrun);//通知地址
paramMap.put("trade_type","NATIVE");//支付方式 原生扫码
paramMap.put("product_id", "shangpingid"); //自行定义
paramMap.put("sign",SignUtil.createSign(paramMap, PaymentConfig.appKey));
String rXml = "";
String prepayid="";
try {
rXml = new String(XmlPostUtil.sendXmlRequest(PaymentConfig.pay_url, XMLUtil.mapToXml(paramMap)));
prepayid = (String) XMLUtil.doXMLParse(rXml).get("prepay_id");//得到预支付id
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//二次签名
SortedMap<Object, Object> paramMap1 = new TreeMap<Object, Object>();
paramMap1.put("appId", PaymentConfig.appid);
paramMap1.put("timeStamp", System.currentTimeMillis());
paramMap1.put("package", "prepay_id="+prepayid);
paramMap1.put("signType", "MD5");
paramMap1.put("nonceStr", RandomUtil.createRandomString(32));
paramMap1.put("paySign", SignUtil.createSign(paramMap1, PaymentConfig.appKey)); try {
Map map = XMLUtil.doXMLParse(rXml);
System.out.println("return_code:"+map.get("return_code"));
System.out.println("code_url:"+map.get("code_url"));
return map;
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return paramMap1; } }
调用类方法,需要自行完善逻辑代码
public void weixinPay(HttpServletRequest request){
//请求IP地址
String ip = request.getRemoteAddr();
//发起支付
WeChatPay weChatPay = new WeChatPay();
//wxReturn 为微信异步回调地址,这里可以根据自己的方式获取
String wxReturn = PropertyUtils.getPropertyValue(new File(realPathResolver.get(CONFIG)), WEIXIN_NOTICE_URL); /**
* 调用微信支付
* order.getOrderNo() 订单号
* order.getPrice() 订单价格,因为微信是分为单位 所以这里要乘以100
*/
Map map = weChatPay.getPaymentMapCode(order.getOrderNo(), (int) (order.getPrice() * 100), "微信支付", ip, wxReturn);
String return_code = String.valueOf(map.get("return_code"));
if (return_code.equals("SUCCESS")) {
//微信调用成功
//code_url是支付的链接
request.getSession().setAttribute("code_url", map.get("code_url") + "");
//跳转到支付页面
} else {
//微信支付调取失败!
}
}
QRCodeUtil.java
package weixin; import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Hashtable; public class QRCodeUtil { private static final String CHARSET = "utf-8";
private static final String FORMAT_NAME = "JPG";
// 二维码尺寸
private static final int QRCODE_SIZE = 300;
// LOGO宽度
private static final int WIDTH = 60;
// LOGO高度
private static final int HEIGHT = 60; private static BufferedImage createImage(String content, String imgPath,
boolean needCompress) throws Exception {
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000
: 0xFFFFFFFF);
}
}
if (imgPath == null || "".equals(imgPath)) {
return image;
}
// 插入图片
QRCodeUtil.insertImage(image, imgPath, needCompress);
return image;
} private static void insertImage(BufferedImage source, String imgPath,
boolean needCompress) throws Exception {
File file = new File(imgPath);
if (!file.exists()) {
System.err.println(""+imgPath+" 该文件不存在!");
return;
}
Image src = ImageIO.read(new File(imgPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress) { // 压缩LOGO
if (width > WIDTH) {
width = WIDTH;
}
if (height > HEIGHT) {
height = HEIGHT;
}
Image image = src.getScaledInstance(width, height,
Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
src = image;
}
// 插入LOGO
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
} //获取生成二维码的图片流
public static ByteArrayOutputStream encodeIO(String content,String imgPath,Boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath,
needCompress);
//创建储存图片二进制流的输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//将二进制数据写入ByteArrayOutputStream
ImageIO.write(image, "jpg", baos);
return baos;
}
}
生成二维码请求
@RequestMapping(value = "/get_qr_code")
public void getQrCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
//从session中获取前面放在code_url地址
String content = request.getSession().getAttribute("code_url") + "";
System.out.printf(content);
//二维码图片中间logo
String imgPath = "";
Boolean needCompress = true;
//通过调用我们的写的工具类,拿到图片流
ByteArrayOutputStream out = QRCodeUtil.encodeIO(content, imgPath, needCompress);
//定义返回参数
response.setCharacterEncoding("UTF-8");
response.setContentType("image/jpeg;charset=UTF-8");
response.setContentLength(out.size());
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(out.toByteArray());
outputStream.flush();
outputStream.close();
}
支付页面代码、显示二维码,由于微信支付没有同步支付通知,所以需要在这个页面上写轮询方法,查询自己数据库订单,判断是否已经支付
<img src="/get_qr_code"><br/>
微信异步回调类,需要自行完善逻辑代码
/**
* 微信支付通知
*
* @return
*/
@ResponseBody
@RequestMapping(value = "/wechart_notice")
public String wechartNotice(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
String result = "";
try {
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
result = new String(outSteam.toByteArray(), "utf-8");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//判断返回报文是否为空
if (StringUtils.isNotBlank(result)) {
try {
Map<String, String> map = XMLUtil.doXMLParse(result);
//获取商家订单编号 对应orderNo
String orderNo = map.get("out_trade_no");
//获取微信支付订单号
String transaction_id = map.get("transaction_id"); Order order = orderMng.findByOrderNo(orderNo);
//判断支付是否成功
if ("SUCCESS".equals(map.get("result_code"))) {
//支付成功,这里之所以加了一个判断,是因为这个回调可能会有多次,所以我们只有当订单状态时未支付的情况下,才执行下面操作
if (!Constants.ORDER_SUCCESS.equals(order.getStatus())) {
//当微信支付成功后,把订单支付状态改为已支付
order.setStatus(Constants.ORDER_SUCCESS);
}
//处理业务逻辑
} else {
//支付失败
order.setStatus(Constants.ORDER_FAIL);
}
//更新数据库订单状态
orderMng.update(order);
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
WeChatPay weChatPay = new WeChatPay();
return weChatPay.getSuccessXml();
}
JAVA微信支付代码(WeChatPay.java 才是调用类)的更多相关文章
- JAVA微信支付~
1,简单说明 现在好多项目上都需要用到微信支付接口,官方文档上也是简单的描述了下,技术不高深的真的难以理解(我自己看官方文档就看不懂),还是需要自己收集,总结, 网上看了好多 有些照着弄最后还是没法成 ...
- 微信支付 V3 的 Java 实现 Payment Spring Boot-1.0.7.RELEASE 发布
Payment Spring Boot 是微信支付V3的Java实现,仅仅依赖Spring内置的一些类库.配置简单方便,可以让开发者快速为Spring Boot应用接入微信支付. 功能特性 实现微信支 ...
- 分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要)
原文:分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要) Java InputStream读取数据问题 ======== ...
- asp微信支付代码证书文件post_url.aspx和post_url.aspx.cs源码下载
很多朋友在网上找的asp支付代码中都没有这两个证书文件,只能是用别人的,但是如果别人把他的网站这个文件删了,你的支付也就不能用了,今天我就把大家需要的这两个asp微信支付代码证书文件post_url. ...
- DELPHI微信支付代码
DELPHI微信支付代码 不管是微信支付还是支付宝支付, 3个最棘手的问题是:1,如何生成签名2,支付请求如何提交3, 如何验证签名 下面就围绕这二个问题来讲. 我使用的是XE3. 先看微信支付: ...
- JAVA微信支付——微信公众号内支付 代码
官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 微信PC二维码支付方式参考:https://www.cnblogs. ...
- JAVA 微信支付 native方式
最近做了一个微信native方式支付的demo,整理一下. 首先到微信公众号官网阅读开发文档,虽然文档对于java没有例子,但是也可以作参考.https://pay.weixin.qq.com/wik ...
- JAVA微信支付接口开发——支付
微信支付接口开发--支付 这几天在做支付服务,系统接入了支付宝.微信.银联三方支付接口.个人感觉支付宝的接口开发较为简单,并且易于测试. 关于数据传输,微信是用xml,所以需要对xml进行解析. 1. ...
- 170327、Java微信支付中的扫码支付
微信支付现在已经变得越来越流行了,随之也出现了很多以可以快速接入微信支付为噱头的产品,不过方便之余也使得我们做东西慢慢依赖第三方,丧失了独立思考的能力,这次打算分享下我之前开发过的微信支付. 一 H5 ...
随机推荐
- Android Studio打包程序时出现transformClassesWithDexForRelease错误
百度半天.没找到直接原因..国外网站上有写这个错误的..国内的真心没找到..英语水平有太低..实在没看懂怎么搞.. 后来发现clean项目的时候是提示如下错误: Information:Gradle ...
- Jet.com
Jet.com是一家电商startup,总部在最爱的小城市Hoboken.目前是类似Amazon的一个网站,后台用F#来做Micro Services,服务器都在Azure和AWS上.人员配置年轻聪明 ...
- halcon 特征测量
Features 1. line_orientation 功能:计算线的方位. 2. line_position 功能:计算一条线的重心.长度和方位. 3. partition_lines ...
- ubuntu下同时安装anaconda2与anaconda3,并分别安装与之对应的软件
1.安装anaconda2 参考网址:https://www.cnblogs.com/chamie/p/8876271.html 2.安装anaconda3 转载:https://blog.csdn. ...
- HAWQ配置之HDFS HA
一.在ambari管理界面启用HDFS HA 在ambari中这步很简单,在所有安装的服务都正常之后,在HDFS的服务界面中,点击下拉菜单“Actions”,选择启用HDFS HA项 “Enable ...
- CreateWindowEx failed (当前程序已使用了 Window 管理器对象的系统允许的所有句柄。)
我在QT图形场景视图中通过QGraphicsProxyWidget添加代理Widget(实现添加基本的QT Widget,如按钮.复选框.日期时间控件等),当数量超过3500左右的时候,QT应用程序直 ...
- TIJ -- 吐司BlockingQueue
1. 吐司BlockingQueue 考虑下面这个使用BlockingQueue的示例.有一台机器具有三个任务:一个制作吐司,一个给吐司抹黄油,另一个在抹过黄油的吐司上吐果酱.我们可以通过各个处理过程 ...
- git使用git-credential-winstore保存https访问密码
使用 https 方式 clone 一个 git 仓库,每次pull 或者 push 的时候都需要输入用户名和密码. 访问远程Git仓库可以用 SSH 方式和 https 方式,https 每次访问时 ...
- C++对windows控制面板的操作
经常碰到程序无法卸载, 就老是骂微软搞的什么安装方式,安装好了不能卸载. 后来就打算研究一下windows是如何卸载程序的,一个程序安装完后留下了什么信息用于后面的卸载. 研究对象win7 64位, ...
- Codeforces Round 504
(交互题真神奇,,,我自己瞎写了一发目测样例都没过去就AC了...) (只出了两题的竟然没掉下蓝名真是可怕) A:我的代码太不美观了,放个同学的(因为我是c++63分的蒟蒻所以根本不知道那些函数怎么用 ...