java實現(xiàn)網(wǎng)站微信掃碼支付
一、網(wǎng)站微信掃碼支付開發(fā)并沒有現(xiàn)成的java示例,總結(jié)一下自己微信掃碼支付心得
二、首先去微信公眾平臺申請賬戶
三、賬戶開通、開發(fā)者認證之后就可以進行微信支付開發(fā)了
1、微信統(tǒng)一下單接口調(diào)用獲取預(yù)支付id,以及生成二維碼所需的codeUrl
/**
* 保存訂單,并生成二維碼所需的codeUrl
*
* @param request
* @param response
* @param notifyURLBuf
* @param order
* @return
* @throws Exception
*/
@Override
public Map<String, String> getWechatOrderInfo(String ip, Cuser user, String notifyUrl, Order order) throws Exception {
Map<String, String> resultMap = new HashMap<String, String>();
// 生成并保存訂單
order.setUserId(user.getId());
// 支付方式 0:銀聯(lián) 1:支付寶 2:網(wǎng)上銀行 3:微信 4:其他
order.setPayType("3");
// 生成訂單號
order.setOrderNo(OrderNoGenerator.getOrderNo());
// 訂單類型 1:消費 2:退款
order.setOrderType("1");
// 訂單創(chuàng)建時間
order.setCreateTime(new Date());
// 訂單更新時間
order.setUpdateTime(new Date());
// 訂單狀態(tài) 0: 交易中 1:完成 2:已取消
order.setOrderStatus("0");
// 付款狀態(tài) 0:失敗 1:成功 2、待付款
order.setPayStatus("2");
// 設(shè)置訂單失效時間
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR, 2);
order.setExpireTime(calendar.getTime());
Integer orderId = this.balanceDao.saveOrder(order);
Map<String, String> payPreIdMap = new HashMap<>();
payPreIdMap = WechatUtil.getPayPreId(String.valueOf(orderId), "體檢報告", notifyUrl, ip,
String.valueOf((order.getMoney().multiply(new BigDecimal(100)).intValue())), orderId.toString());
String prePayId = payPreIdMap.get("prepay_id");
// 更新
order.setId(orderId);
order.setPrepayId(prePayId);
order.setCodeUrl(payPreIdMap.get("code_url"));
this.balanceDao.updateOrder(order);
// return WechatUtil.QRfromGoogle(order.getCodeUrl(), 300, 0);
resultMap.put("codeUrl", order.getCodeUrl());
resultMap.put("orderId", String.valueOf(order.getId()));
return resultMap;
}
此方法返回的數(shù)據(jù)如下
<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> <appid><![CDATA[wxaf0b*****8afbf]]></appid> <mch_id><![CDATA[1408****02]]></mch_id> <nonce_str><![CDATA[zf0vGvdtVycBliwB]]></nonce_str> <sign><![CDATA[A2910F16086211153D747058063B3368]]></sign> <result_code><![CDATA[SUCCESS]]></result_code> <prepay_id><![CDATA[wx201701191109388037e9a12310276591827]]></prepay_id> <trade_type><![CDATA[NATIVE]]></trade_type> <code_url><![CDATA[weixin://wxpay/bizpayurl?pr=1UjorNX]]></code_url> </xml>
2、服務(wù)器端接受微信支付結(jié)果通知
/**
* 保存微信通知結(jié)果
*
* @param request
* @param response
* @return
* @throws Exception
*/
@Override
public String saveWechatNotify(String notifyInfoXml) throws Exception {
Map<String, String> noticeMap = XMLUtil.doXMLParse(notifyInfoXml);
// 這個其實是訂單 的id
String outTradeNo = noticeMap.get("out_trade_no");
Order order = this.balanceDao.getOrderById(Integer.valueOf(outTradeNo));
// 如果支付通知信息不為,說明請求已經(jīng)處理過,直接返回
if (StringUtil.isNotEmpty(order.getNotifyInfo())) {
return "SUCCESS";
}
String sign = noticeMap.get("sign");
noticeMap.remove("sign");
// 驗簽通過
if (WechatUtil.getSignVeryfy(noticeMap, sign)) {
// 通信成功此字段是通信標識,非交易標識,交易是否成功需要查看result_code來判斷
if ("SUCCESS".equals(noticeMap.get("return_code"))) {
// 交易成功
if ("SUCCESS".equals(noticeMap.get("result_code"))) {
// 商戶訂單號
// 訂單更新時間
order.setUpdateTime(new Date());
// ------------------------------
// 處理業(yè)務(wù)開始
// ------------------------------
// 是否交易成功,1:成功0:失敗
// 微信支付成功
order.setPayStatus("1");
// 訂單狀態(tài) 0: 交易中 1:完成 2:已取消
order.setOrderStatus("1");
// 保存通知信息
order.setNotifyInfo(notifyInfoXml);
this.balanceDao.updateOrder(order);
// 處理業(yè)務(wù)完畢
} else {
// 錯誤時,返回結(jié)果未簽名,記錄retcode、retmsg看失敗詳情。
logger.info("查詢驗證簽名失敗或業(yè)務(wù)錯誤");
logger.info("retcode:" + noticeMap.get("retcode") + " retmsg:" + noticeMap.get("retmsg"));
}
return "SUCCESS";
} else {
logger.info("后臺調(diào)用通信失敗");
}
return "SUCCESS";
} else {
logger.info("通知簽名驗證失敗");
}
return null;
}
3、上面代碼用到的工具方法都在WechatUtil.java工具類中
package com.caifu.tencent.common;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.jdom2.JDOMException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.caifu.login.utils.XMLUtil;
public class WechatUtil {
private static Logger logger = LoggerFactory.getLogger(WechatUtil.class);
public static final String TAG = "Wechat.Util";
private static final int timeout = 5000;
public static byte[] httpPost(String url, String entity) throws URISyntaxException, IOException {
if (url == null || url.length() == 0) {
logger.info(TAG, "httpPost, url is null");
return null;
}
CloseableHttpClient httpClient = HttpClients.createDefault();
URIBuilder uriBuilder = new URIBuilder(url);
HttpPost httpPost = new HttpPost(uriBuilder.build());
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectionRequestTimeout(timeout).setConnectTimeout(timeout).build();
httpPost.setConfig(requestConfig);
// 避免漢字亂碼導致請求失敗,
httpPost.setEntity(new StringEntity(entity, "UTF-8"));
CloseableHttpResponse resp = null;
try {
resp = httpClient.execute(httpPost);
if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
logger.info(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
return null;
}
return EntityUtils.toByteArray(resp.getEntity());
} catch (Exception e) {
logger.info(TAG, "httpPost exception, e = " + e.getMessage());
e.printStackTrace();
return null;
} finally {
if (httpClient != null) {
httpClient.close();
}
if (resp != null) {
resp.close();
}
}
}
/**
* 把數(shù)組所有元素排序,并按照“參數(shù)=參數(shù)值”的模式用“&”字符拼接成字符串
*
* @param params
* 需要排序并參與字符拼接的參數(shù)組
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {// 拼接時,不包括最后一個&字符
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
/**
* 根據(jù)反饋回來的信息,生成簽名結(jié)果
*
* @param Params
* 通知返回來的參數(shù)數(shù)組
* @param sign
* 比對的簽名結(jié)果
* @return 生成的簽名結(jié)果
*/
public static boolean getSignVeryfy(Map<String, String> Params, String sign) {
// 過濾空值、sign與sign_type參數(shù)
// Map<String, String> sParaNew = AlipayCore.paraFilter(Params);
// 獲取待簽名字符串
String preSignStr = createLinkString(Params);
preSignStr += "&key=" + Configure.getKey();
// 獲得簽名驗證結(jié)果
String resultSign = MD5.MD5Encode(preSignStr).toUpperCase();
// String resultSign = MD5Util.MD5Encode(preSignStr.toString(),
// "UTF-8").toLowerCase();
if (sign.equals(resultSign)) {
return true;
} else {
return false;
}
}
/**
* 裝配xml,生成請求prePayId所需參數(shù)
*
* @param params
* @return
*/
public static String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (int i = 0; i < params.size(); i++) {
sb.append("<" + params.get(i).getName() + ">");
sb.append(params.get(i).getValue());
sb.append("</" + params.get(i).getName() + ">");
}
sb.append("</xml>");
return sb.toString();
}
/**
* 生成簽名
*/
public static String genPackageSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(Configure.getKey());
String packageSign = MD5.MD5Encode(sb.toString());
return packageSign;
}
/**
*
* @param goodOrderNo
* @param body
* @param noticeUrl
* @param ip
* @param totalFee
* @return
*/
public static String genProductArgs(String goodOrderNo, String body, String noticeUrl, String ip, String totalFee, String productId) {
StringBuffer xml = new StringBuffer();
try {
String nonceStr = getNonceStr();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid", Configure.getAppid()));
packageParams.add(new BasicNameValuePair("body", body));
packageParams.add(new BasicNameValuePair("mch_id", Configure.getMchid()));
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
packageParams.add(new BasicNameValuePair("notify_url", noticeUrl));
packageParams.add(new BasicNameValuePair("out_trade_no", goodOrderNo));
packageParams.add(new BasicNameValuePair("product_id", productId));
packageParams.add(new BasicNameValuePair("spbill_create_ip", ip));
packageParams.add(new BasicNameValuePair("total_fee", totalFee));
packageParams.add(new BasicNameValuePair("trade_type", "NATIVE"));
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring = toXml(packageParams);
return xmlstring;
} catch (Exception e) {
logger.info("genProductArgs fail, ex = " + e.getMessage());
return null;
}
}
/**
* 生成支付簽名
*
* @param params
* @return
*/
public static String genAppSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(Configure.getKey());
String appSign = MD5.MD5Encode(sb.toString()).toUpperCase();
logger.info("orion", appSign);
return appSign;
}
/**
* 生成調(diào)用微信支付所需參數(shù)
*
* @param prepayId
* @return
*/
public static Map<String, String> genPayReq(String prepayId) {
Map<String, String> resultMap = new HashMap<String, String>();
String timeStamp = getTimeStamp();
String nonceStr = getNonceStr();
List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", Configure.getAppid()));
signParams.add(new BasicNameValuePair("noncestr", nonceStr));
signParams.add(new BasicNameValuePair("package", "Sign=WXPay"));
signParams.add(new BasicNameValuePair("partnerid", Configure.getMchid()));
signParams.add(new BasicNameValuePair("prepayid", prepayId));
signParams.add(new BasicNameValuePair("timestamp", timeStamp));
String sign = genAppSign(signParams);
resultMap.put("appid", Configure.getAppid());
resultMap.put("noncestr", nonceStr);
resultMap.put("packageValue", "Sign=WXPay");
resultMap.put("partnerid", Configure.getMchid());
resultMap.put("prepayid", prepayId);
resultMap.put("timestamp", timeStamp);
resultMap.put("sign", sign);
return resultMap;
}
/**
* 微信支付生成預(yù)支付訂單
*
* @throws IOException
* @throws JDOMException
*/
public static Map<String, String> getPayPreId(String goodOrderNo, String body, String noticeUrl, String ip, String totalFee, String productId) throws Exception {
String paramsXml = genProductArgs(goodOrderNo, body, noticeUrl, ip, totalFee, productId);
logger.info("orion", paramsXml);
byte[] buf = WechatUtil.httpPost(Configure.UNIFIEDORDER_API, paramsXml);
String contentXml = new String(buf);
Map<String, String> resultMap = XMLUtil.doXMLParse(contentXml);
return resultMap;
}
public static String getNonceStr() {
Random random = new Random();
return MD5.MD5Encode(String.valueOf(random.nextInt(10000)));
}
public static String getTimeStamp() {
return String.valueOf(System.currentTimeMillis() / 1000);
}
/**
* 生成支付二維碼
* @param request
* @param response
* @param width
* @param height
* @param text 微信生成預(yù)定id時,返回的codeUrl
*/
public static void getQRcode(HttpServletRequest request, HttpServletResponse response, Integer width, Integer height, String text) {
if (width == null) {
width = 300;
}
if (height == null) {
height = 300;
}
String format = "jpg";
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
BitMatrix bitMatrix;
try {
bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
MatrixToImageWriter.writeToStream(bitMatrix, format, response.getOutputStream());
} catch (WriterException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
生成二維碼需要兩jar
<!-- google zxing 二維碼jar begin --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.0</version> </dependency> <!-- google zxing 二維碼jar begin -->
4、下面是用到的配置類
package com.caifu.tencent.common;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 14:40
* 這里放置各種配置數(shù)據(jù)
*/
public class Configure {
//這個就是自己要保管好的私有Key了(切記只能放在自己的后臺代碼里,不能放在任何可能被看到源代碼的客戶端程序中)
// 每次自己Post數(shù)據(jù)給API的時候都要用這個key來對所有字段進行簽名,生成的簽名會放在Sign這個字段,API收到Post數(shù)據(jù)的時候也會用同樣的簽名算法對Post過來的數(shù)據(jù)進行簽名和驗證
// 收到API的返回的時候也要用這個key來對返回的數(shù)據(jù)算下簽名,跟API的Sign數(shù)據(jù)進行比較,如果值不一致,有可能數(shù)據(jù)被第三方給篡改
private static String key = "A6gB0Dy4dsfdssuPCPsdfdshkSCDQcr3eXS";
private static String appSecret="7584sdfdsfe4f26fadsfsdfs56f10728a";
//微信分配的公眾號ID(開通公眾號之后可以獲取到)
private static String appID = "wxaf0b86sdfsdf8afbf";
//微信支付分配的商戶號ID(開通公眾號的微信支付功能之后可以獲取到)
private static String mchID = "14012313702";
//受理模式下給子商戶分配的子商戶號
private static String subMchID = "";
//HTTPS證書的本地路徑
private static String certLocalPath = "";
//HTTPS證書密碼,默認密碼等于商戶號MCHID
private static String certPassword = "";
//是否使用異步線程的方式來上報API測速,默認為異步模式
private static boolean useThreadToDoReport = true;
//機器IP
private static String ip = "";
//以下是幾個API的路徑:
//1)被掃支付API
public static String UNIFIEDORDER_API = "https://api.mch.weixin.qq.com/pay/unifiedorder";
public static String PAY_API = "https://api.mch.weixin.qq.com/pay/micropay";
//2)被掃支付查詢API
public static String PAY_QUERY_API = "https://api.mch.weixin.qq.d/pay/orderquery";
//3)退款A(yù)PI
public static String REFUND_API = "https://api.mch.weixin.qq.com/secapi/pay/refund";
//4)退款查詢API
public static String REFUND_QUERY_API = "https://api.mch.weixin.qq.com/pay/refundquery";
//5)撤銷API
public static String REVERSE_API = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
//6)下載對賬單API
public static String DOWNLOAD_BILL_API = "https://api.mch.weixin.qq.com/pay/downloadbill";
//7) 統(tǒng)計上報API
public static String REPORT_API = "https://api.mch.weixin.qq.com/payitil/report";
public static boolean isUseThreadToDoReport() {
return useThreadToDoReport;
}
public static void setUseThreadToDoReport(boolean useThreadToDoReport) {
Configure.useThreadToDoReport = useThreadToDoReport;
}
public static String HttpsRequestClassName = "com.tencent.common.HttpsRequest";
public static void setKey(String key) {
Configure.key = key;
}
public static void setAppID(String appID) {
Configure.appID = appID;
}
public static void setMchID(String mchID) {
Configure.mchID = mchID;
}
public static void setSubMchID(String subMchID) {
Configure.subMchID = subMchID;
}
public static void setCertLocalPath(String certLocalPath) {
Configure.certLocalPath = certLocalPath;
}
public static void setCertPassword(String certPassword) {
Configure.certPassword = certPassword;
}
public static void setIp(String ip) {
Configure.ip = ip;
}
public static String getKey(){
return key;
}
public static String getAppid(){
return appID;
}
public static String getMchid(){
return mchID;
}
public static String getSubMchid(){
return subMchID;
}
public static String getCertLocalPath(){
return certLocalPath;
}
public static String getCertPassword(){
return certPassword;
}
public static String getIP(){
return ip;
}
public static void setHttpsRequestClassName(String name){
HttpsRequestClassName = name;
}
}
在這里需要注意的配置
private static String key = “A6gB0Dy4dsfdssuPCPsdfdshkSCDQcr3eXS”;
這里的key 是登陸https://pay.weixin.qq.com/index.php/core/info (微信商戶平臺)設(shè)置的api_key
5、xml 解析工具類
package com.caifu.login.utils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.io.SAXReader;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
/**
* xml工具類
*
* @author miklchen
*
*/
public class XMLUtil {
/**
* 解析xml,返回第一級元素鍵值對。如果第一級元素有子節(jié)點,則此節(jié)點的值是子節(jié)點的xml數(shù)據(jù)。
*
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
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);
}
// 關(guān)閉流
in.close();
return m;
}
/**
* 獲取子結(jié)點的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();
}
/**
* 將requestxml通知結(jié)果轉(zhuǎn)出啊成map
* @param request
* @return
* @throws Exception
*/
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
// 解析結(jié)果存儲在HashMap
Map<String, String> map = new HashMap<String, String>();
InputStream inputStream = request.getInputStream();
// 讀取輸入流
SAXReader reader = new SAXReader();
org.dom4j.Document document = reader.read(inputStream);
// 得到xml根元素
org.dom4j.Element root = document.getRootElement();
// 得到根元素的所有子節(jié)點
List<org.dom4j.Element> elementList = root.elements();
// 遍歷所有子節(jié)點
for (org.dom4j.Element e : elementList)
map.put(e.getName(), e.getText());
// 釋放資源
inputStream.close();
inputStream = null;
return map;
}
}
6、整個后臺服務(wù)已經(jīng)完成,最后關(guān)閉頁面微信支付二維碼,告知用戶支付已經(jīng)完成了
var f;
/* 定時任務(wù)方法,異步請求去查詢訂單是否支付*/
function GetOrder() {
var orderId = $('#orderId').val();
if (orderId != '') {
$.ajax({
url : "${base}/balance/auth/isPay?orderId=" + orderId,
type : "GET",
async : false,
success : function(d) {
if (d == "1") {
//當獲取到微信支付結(jié)果時,關(guān)閉二維碼div
$(".weixinpay").css("display", "none");
$("#zhichutankuang").css("display", "block");
////當獲取到微信支付結(jié)果時,關(guān)閉定時任務(wù)
clearInterval(f);
// layer.alert('付款成功', {
// skin : 'layui-layer-molv', // 樣式類名
// closeBtn : 0
// }, function() {
// location.href = "${base}/balance/auth/presentation?tjNo=" + $("#tjNo").val();
// });
}
}
});
}
}
//異步請求獲取生成二維碼的url
$(".paylast").click(function() {
var $payType = $('input:radio:checked').val();
var $money = $("#money").val();
var $tjReportType = $("#tjReportType").val();
var $tjNo = $("#tjNo").val();
$.ajax({
url : "${base}/balance/auth/wechatInfo",
type : "POST",
async : false,
data : {
payType : $payType,
money : $money,
tjNo : $tjNo,
tjReportType : $tjReportType
},
success : function(d) {
if (d.resultCode == "1000") {
//當請求成功時,設(shè)置二維碼圖片地址
$("#codeImg").attr('src', d.obj);
$("#orderId").val(d.attributes.orderId);
////當請求成功時,啟動定時任務(wù),每隔3秒去后臺查詢一次訂單是否成功
f = setInterval(GetOrder, 3000);
// GetOrder(true);
}
}
});
$(".selpaycon").css("display", "none");
$(".weixinpay").css("display", "block");
});
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
聊聊springmvc中controller的方法的參數(shù)注解方式
本篇文章主要介紹了聊聊springmvc中controller的方法的參數(shù)注解方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
spring cloud hystrix 超時時間使用方式詳解
這篇文章主要介紹了spring cloud hystrix 超時時間使用方式,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
Mybatis Order by動態(tài)參數(shù)防注入方式
這篇文章主要介紹了Mybatis Order by動態(tài)參數(shù)防注入方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
java實現(xiàn)追加內(nèi)容到文件末尾的常用方法分析
這篇文章主要介紹了java實現(xiàn)追加內(nèi)容到文件末尾的常用方法,結(jié)合具體實例分析了java文件流及寫入指針等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
第一次使用Android Studio時你應(yīng)該知道的一切配置(推薦)
這篇文章主要介紹了第一次使用Android Studio時你應(yīng)該知道的一切配置(推薦) ,需要的朋友可以參考下2017-09-09

