第五屆北大青鳥杯全國IT精英挑戰賽中南&西南區域一等獎項目——日雜百貨分銷系統
關鍵代碼說明書
作者:武漢宏鵬田超凡
版權所有,轉載請註明原作者,仿冒侵權必究法律責任
5.物流接口.............................................................................................................................37
6.省市區下拉框聯動..............................................................................................................38
7.富文本編輯器UEditor.........................................................................................................41
8.FastDFS+nginx圖片服務器..................................................................................................26
9.Redis+Jedis緩存..................................................................................................................27
10.solr搜索引擎....................................................................................................................28
public class GetMessageCode {
private static final String QUERY_PATH="https://api.miaodiyun.com/20150822/industrySMS/sendSMS";
private static final String ACCOUNT_SID="a9c07995abc648c98edb12d5f15bd651";
private static final String AUTH_TOKEN="94da4ab341c94ebd9f0c213677510e0b";
//根據相應的手機號發送驗證碼
public static String getCode(String phone){
String rod=smsCode();
String timestamp=getTimestamp();
String sig=getMD5(ACCOUNT_SID,AUTH_TOKEN,timestamp);
String tamp="【EasyBuy科技】您的短信驗證碼爲"+rod+",請在5分鐘內使用。";
OutputStreamWriter out=null;
BufferedReader br=null;
StringBuilder result=new StringBuilder();
try {
URL url=new URL(QUERY_PATH);
HttpURLConnection connection=(HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);//設置是否允許數據寫入
connection.setDoOutput(true);//設置是否允許參數數據輸出
connection.setConnectTimeout(5000);//設置鏈接響應時間
connection.setReadTimeout(10000);//設置參數讀取時間
connection.setRequestProperty("Content-type","application/x-www-form-urlencoded");
//提交請求
out=new OutputStreamWriter(connection.getOutputStream(),"UTF-8");
String args=getQueryArgs(ACCOUNT_SID, tamp, phone, timestamp, sig, "JSON");
out.write(args);
out.flush();
//讀取返回參數
br=new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
String temp="";
while((temp=br.readLine())!=null){
result.append(temp);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject json=new JSONObject(result.toString());
String respCode=json.getString("respCode");
String defaultRespCode="00000";
if(defaultRespCode.equals(respCode)){
return rod;
}else{
return defaultRespCode;
}
}
//定義一個請求參數拼接方法
public static String getQueryArgs(String accountSid,String smsContent,String to,String timestamp,String sig,String respDataType){
return "accountSid="+accountSid+"&smsContent="+smsContent+"&to="+to+"×tamp="+timestamp+"&sig="+sig+"&respDataType="+respDataType;
}
//獲取時間戳
public static String getTimestamp(){
return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
}
//sing簽名
public static String getMD5(String sid,String token,String timestamp){
StringBuilder result=new StringBuilder();
String source=sid+token+timestamp;
//獲取某個類的實例
try {
MessageDigest digest=MessageDigest.getInstance("MD5");
//要進行加密的東西
byte[] bytes=digest.digest(source.getBytes());
for(byte b:bytes){
String hex=Integer.toHexString(b&0xff);
if(hex.length()==1){
result.append("0"+hex);
}else{
result.append(hex);
}
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result.toString();
}
//創建驗證碼
public static String smsCode(){
String random=(int)((Math.random()*9+1)*100000)+"";
return random;
}
}
//響應狀態值說明
代碼 |
說明 |
||
00001 |
未知錯誤,請聯繫技術客服。 |
||
00002 |
未知的方法名 |
||
00003 |
請求方式錯誤 |
||
00004 |
參數非法,如request parameter (key) is missing |
||
00005 |
timestamp已過期 |
||
00006 |
sign錯誤 |
||
00007 |
重複提交 |
||
00008 |
操作頻繁 |
||
00011 |
請求的xml格式不對 |
||
00012 |
不支持get請求,請使用post |
||
00013 |
請求url格式不正確 |
||
00015 |
時間戳超出有效時間範圍 |
||
00016 |
請求json格式不對 |
||
00017 |
數據庫操作失敗 |
||
00018 |
參數爲空 |
||
00019 |
訂單已存在 |
||
00020 |
用戶不存在 |
||
00021 |
子賬號餘額不足 |
||
00022 |
操作頻繁 |
||
00023 |
開發者餘額不足 |
||
00025 |
手機格式不對 |
||
00026 |
手機號存在 |
||
00027 |
子賬號名稱已存在 |
||
00028 |
子賬號名稱過長 |
||
00029 |
回調開發者服務器異常 |
||
00030 |
回調地址爲空 |
||
00031 |
appId爲空或者沒有傳值 |
||
00032 |
主叫號碼爲空或者沒有傳值 |
||
00033 |
被叫號碼爲空或者沒有傳值 |
||
00034 |
子賬號爲空或者沒有傳值 |
||
00035 |
主叫號碼和被叫號碼相同 |
||
00036 |
驗證碼格式不對(4-8位數字) |
||
00037 |
limit格式不對 |
||
00038 |
start格式不對 |
||
00039 |
驗證碼爲空或者缺少此參數 |
||
00040 |
用戶名或者密碼錯誤 |
||
00050 |
短信或者語音驗證碼錯誤 |
||
00051 |
顯示號碼與被叫號碼一樣,不允許呼叫 |
||
00052 |
回撥主叫號碼格式錯誤 |
||
00053 |
被叫號碼格式錯誤 |
||
00054 |
顯號格式錯誤 |
||
00055 |
應用不包含此子賬號 |
||
00056 |
開發者不包含此應用 |
||
00060 |
請求數據不存在 |
||
00061 |
app不存在 |
||
00062 |
developerId 請求錯誤 |
||
00063 |
app未上線 |
||
00064 |
請求Content-Type錯誤 |
||
00065 |
請求Accept錯誤 |
||
00066 |
開發者餘額已被凍結 |
||
00070 |
手機號未綁定 |
||
00071 |
通知類型已停用或者未創建 |
||
00072 |
balance格式不對(必須爲大於等於0的double) |
||
00073 |
charge格式不對(必須爲大於等於0的double) |
||
00074 |
主叫和子賬戶綁定的手機號不相同 |
||
00075 |
子賬戶沒有綁定手機號 |
||
00076 |
時間格式不對 |
||
00077 |
開始時間小於結束時間 |
||
00078 |
開始時間和結束時間必須是同一天 |
||
00079 |
服務器內部異常 |
||
00080 |
子賬號不存在 |
||
00081 |
通知計費系統失敗 |
||
00082 |
參數校驗失敗 |
||
00083 |
充值失敗 |
||
00084 |
子賬號沒有託管 不能進行充值 |
||
00085 |
開發者不包含子帳號 |
||
00086 |
DEMO不能進行充值 |
||
00087 |
IQ類型錯誤 |
||
00090 |
回調地址爲空 |
||
00091 |
沒有語音 |
||
00093 |
沒有這個語音文件或者審覈沒通過 |
||
00094 |
每批發送的手機號數量不得超過100個 |
||
00098 |
同一手機號每天只能發送n條相同的內容 |
||
00099 |
相同的應用每天只能給同一手機號發送n條不同的內容 |
||
00100 |
短信內容不能含有關鍵字或者審覈不通過 |
//發送短信驗證碼
public JSON sendMessage(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException
{
try
{
//設置字符編碼
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//獲取參數,發送短信的手機號
String mobile=request.getParameter("mobile");
if(mobile==null || mobile.equals(""))
{
mobile="17364251109";
}
//發送短信驗證碼並獲取發送的驗證碼
String flag=GetMessageCode.getCode(mobile);
//返回json響應到客戶端
Return JSONObject.parseObject("{\"flag\":\""+flag+"\"}");
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
js代碼:
var InterValObj; //timer變量,控制時間
var count = 30; //間隔函數,1秒執行
var curCount;//當前剩餘秒數
var code=null;
function sendMessage()
{
//註冊手機號,發送短信的手機號
var mobile=$("[name='mobile']").val();
if(mobile==null || mobile=="")
{
alert("請先輸入註冊的手機號!");
return;
}
else
{
//ajax異步校驗手機號是否已存在
$.getJSON("/EasyBuy/AddUserServlet","action=checkMobile&mobile="+mobile,function(data){
if(data.status=="1")
{
//手機號可用
curCount = count;
$("#btn").attr("disabled", "true");
$("#btn").val(curCount+"秒後可重新發送");
InterValObj = window.setInterval(SetRemainTime, 1000); //啓動計時器,1秒執行一次請求後臺發送驗證碼 TODO
//發送驗證碼
//ajax異步發送短信驗證碼
$.ajax({
url:"/EasyBuy/AddUserServlet",
type:"POST",
data:"action=sendMessage&mobile="+mobile,
dataType:"json",
success:function(data){
code=data.flag;
},
error:function(){
alert("發送短信失敗!");
}
});
}
else
{
alert(data.message);
}
});
}
}
//timer處理函數
function SetRemainTime() {
if (curCount == 0) {
window.clearInterval(InterValObj);//停止計時器
$("#btn").removeAttr("disabled");//啓用按鈕
$("#btn").val("重新發送驗證碼");
}
else {
curCount--;
$("#btn").val(curCount + "秒後可重新發送");
}
}
//校驗驗證碼
function checkCode()
{
//獲取輸入的驗證碼
var inputValue=$("[name='random']").val();
if(inputValue==null || inputValue=="")
{
alert("請輸入驗證碼!");
return false;
}
else if(code!=inputValue)
{
alert("驗證碼輸入錯誤!");
return false;
}
else
{
return true;
}
}
2.銀聯支付(接口api參考 銀聯api.txt)
基於Servlet的接口,接受用戶傳入參數生成自動跳轉的Html表單,返回響應報文到回調地址;
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
/**
* 請求銀聯接入地址,獲取證書文件,證書路徑等相關參數初始化到SDKConfig類中
* 在java main 方式運行時必須每次都執行加載
* 如果是在web應用開發裏,這個方法可使用監聽的方式寫入緩存,無須在這出現
*/
//這裏已經將加載屬性文件的方法挪到了web/AutoLoadServlet.java中
//SDKConfig.getConfig().loadPropertiesFromSrc(); //從classpath加載acp_sdk.properties文件
//前臺頁面傳過來的
String merId = req.getParameter("merId");
String txnAmt = req.getParameter("txnAmt");
String userid=req.getParameter("userid");
String addid=req.getParameter("addid");
Map<String, String> requestData = new HashMap<String, String>();
/***銀聯全渠道系統,產品參數,除了encoding自行選擇外其他不需修改***/
requestData.put("version", DemoBase.version); //版本號,全渠道默認值
requestData.put("encoding", DemoBase.encoding_UTF8); //字符集編碼,可以使用UTF-8,GBK兩種方式
requestData.put("signMethod", "01"); //簽名方法,只支持 01:RSA方式證書加密
requestData.put("txnType", "02"); //交易類型 ,02:預授權
requestData.put("txnSubType", "01"); //交易子類型, 01:預授權
requestData.put("bizType", "000201"); //業務類型,B2C網關支付,手機wap支付
requestData.put("channelType", "07"); //渠道類型,這個字段區分B2C網關支付和手機wap支付;07:PC,平板 08:手機
/***商戶接入參數***/
requestData.put("merId", merId); //商戶號碼,請改成自己申請的正式商戶號或者open上註冊得來的777測試商戶號
requestData.put("accessType", "0"); //接入類型,0:直連商戶
requestData.put("orderId",DemoBase.getOrderId()); //商戶訂單號,8-40位數字字母,不能含“-”或“_”,可以自行定製規則
requestData.put("txnTime", DemoBase.getCurrentTime()); //訂單發送時間,取系統時間,格式爲YYYYMMDDhhmmss,必須取當前時間,否則會報txnTime無效
requestData.put("currencyCode", "156"); //交易幣種(境內商戶一般是156 人民幣)
requestData.put("txnAmt", txnAmt); //交易金額,單位分,不要帶小數點
requestData.put("reqReserved", userid+","+addid); //請求方保留域,如需使用請啓用即可;透傳字段(可以實現商戶自定義參數的追蹤)本交易的後臺通知,對本交易的交易狀態查詢交易、對賬文件中均會原樣返回,商戶可以按需上傳,長度爲1-1024個字節
//前臺通知地址 (需設置爲外網能訪問 http https均可),支付成功後的頁面 點擊“返回商戶”按鈕的時候將異步通知報文post到該地址
//如果想要實現過幾秒中自動跳轉回商戶頁面權限,需聯繫銀聯業務(發郵件到operation@unionpay.com)申請開通自動返回商戶權限
//異步通知參數詳見open.unionpay.com幫助中心 下載 產品接口規範 網關支付產品接口規範 消費交易 商戶通知
requestData.put("frontUrl", DemoBase.frontUrl);
//後臺通知地址(需設置爲【外網】能訪問 http https均可),支付成功後銀聯會自動將異步通知報文post到商戶上送的該地址,失敗的交易銀聯不會發送後臺通知
//後臺通知參數詳見open.unionpay.com幫助中心 下載 產品接口規範 網關支付產品接口規範 消費交易 商戶通知
//注意:1.需設置爲外網能訪問,否則收不到通知 2.http https均可 3.收單後臺通知後需要10秒內返回http200或302狀態碼
// 4.如果銀聯通知服務器發送通知後10秒內未收到返回狀態碼或者應答碼非http200,那麼銀聯會間隔一段時間再次發送。總共發送5次,每次的間隔時間爲0,1,2,4分鐘。
// 5.後臺通知地址如果上送了帶有?的參數,例如:http://abc/web?a=b&c=d 在後臺通知處理程序驗證簽名之前需要編寫邏輯將這些字段去掉再驗籤,否則將會驗籤失敗
requestData.put("backUrl", DemoBase.backUrl);
//////////////////////////////////////////////////
//
// 報文中特殊用法請查看 PC wap網關跳轉預授權特殊用法.txt
//
//////////////////////////////////////////////////
/**請求參數設置完畢,以下對請求參數進行簽名並生成html表單,將表單寫入瀏覽器跳轉打開銀聯頁面**/
Map<String, String> submitFromData = AcpService.sign(requestData,DemoBase.encoding_UTF8); //報文中certId,signature的值是在signData方法中獲取並自動賦值的,只要證書配置正確即可。
String requestFrontUrl = SDKConfig.getConfig().getFrontRequestUrl(); //獲取請求銀聯的前臺地址:對應屬性文件acp_sdk.properties文件中的acpsdk.frontTransUrl
String html = AcpService.createAutoFormHtml(requestFrontUrl, submitFromData,DemoBase.encoding_UTF8); //生成自動跳轉的Html表單
LogUtil.writeLog("打印請求HTML,此爲請求報文,爲聯調排查問題的依據:"+html);
//將生成的html寫到瀏覽器中完成自動跳轉打開銀聯支付頁面;這裏調用signData之後,將html寫到瀏覽器跳轉到銀聯頁面之前均不能對html中的表單項的名稱和值進行修改,如果修改會導致驗籤不通過
resp.getWriter().write(html);
}
交易成功的響應報文:
交易失敗會自動回調error;
public class BackRcvResponse extends HttpServlet{
@Override
public void init() throws ServletException {
/**
* 請求銀聯接入地址,獲取證書文件,證書路徑等相關參數初始化到SDKConfig類中
* 在java main 方式運行時必須每次都執行加載
* 如果是在web應用開發裏,這個方法可使用監聽的方式寫入緩存,無須在這出現
*/
//這裏已經將加載屬性文件的方法挪到了web/AutoLoadServlet.java中
//SDKConfig.getConfig().loadPropertiesFromSrc(); //從classpath加載acp_sdk.properties文件
super.init();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
LogUtil.writeLog("BackRcvResponse接收後臺通知開始");
String encoding = req.getParameter(SDKConstants.param_encoding);
// 獲取銀聯通知服務器發送的後臺通知參數
Map<String, String> reqParam = getAllRequestParam(req);
LogUtil.printRequestLog(reqParam);
//重要!驗證簽名前不要修改reqParam中的鍵值對的內容,否則會驗籤不過
if (!AcpService.validate(reqParam, encoding)) {
LogUtil.writeLog("驗證簽名結果[失敗].");
//驗籤失敗,需解決驗籤問題
} else {
LogUtil.writeLog("驗證簽名結果[成功].");
//【注:爲了安全驗籤成功才應該寫商戶的成功處理邏輯】交易成功,更新商戶訂單狀態
String orderId =reqParam.get("orderId"); //獲取後臺通知的數據,其他字段也可用類似方式獲取
String respCode = reqParam.get("respCode");
//判斷respCode=00、A6後,對涉及資金類的交易,請再發起查詢接口查詢,確定交易成功後更新數據庫。
}
LogUtil.writeLog("BackRcvResponse接收後臺通知結束");
//返回給銀聯服務器http 200 狀態碼
resp.getWriter().print("ok");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
this.doPost(req, resp);
}
處理銀聯支付請求的Servlet代碼
//銀聯支付
public String toUnionPay(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException
{
try
{
//設置字符編碼
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//獲取參數
String totalMoney=request.getParameter("totalMoney");
//獲取訂單號
String serialNumber=request.getParameter("serialNumber");
//獲取訂單id
int id=Integer.parseInt(request.getParameter("id"));
request.setAttribute("totalMoney",totalMoney);
request.setAttribute("serialNumber",serialNumber);
request.setAttribute("id",id);
return "ACPSample_B2C/pages/consume";
}
catch(Exception e)
{
e.printStackTrace();
return "500";
}
}
acp_sdk.properties配置文件:
##############SDK配置文件(證書方式簽名)################
# 說明:
# 1. 使用時請將此文件複製到src文件夾下替換原來的acp_sdk.properties。
# 2. 具體配置項請根據註釋修改。
#
################################################
##########################入網測試環境交易發送地址(線上測試需要使用生產環境交易請求地址)#############################
##交易請求地址
acpsdk.frontTransUrl=https://gateway.test.95516.com/gateway/api/frontTransReq.do
acpsdk.backTransUrl=https://gateway.test.95516.com/gateway/api/backTransReq.do
acpsdk.singleQueryUrl=https://gateway.test.95516.com/gateway/api/queryTrans.do
acpsdk.batchTransUrl=https://gateway.test.95516.com/gateway/api/batchTrans.do
acpsdk.fileTransUrl=https://filedownload.test.95516.com/
acpsdk.appTransUrl=https://gateway.test.95516.com/gateway/api/appTransReq.do
acpsdk.cardTransUrl=https://gateway.test.95516.com/gateway/api/cardTransReq.do
#以下繳費產品使用,其餘產品用不到
acpsdk.jfFrontTransUrl=https://gateway.test.95516.com/jiaofei/api/frontTransReq.do
acpsdk.jfBackTransUrl=https://gateway.test.95516.com/jiaofei/api/backTransReq.do
acpsdk.jfSingleQueryUrl=https://gateway.test.95516.com/jiaofei/api/queryTrans.do
acpsdk.jfCardTransUrl=https://gateway.test.95516.com/jiaofei/api/cardTransReq.do
acpsdk.jfAppTransUrl=https://gateway.test.95516.com/jiaofei/api/appTransReq.do
########################################################################
# 報文版本號,固定5.1.0,請勿改動
acpsdk.version=5.1.0
# 簽名方式,證書方式固定01,請勿改動
acpsdk.signMethod=01
# 是否驗證驗簽證書的CN,測試環境請設置false,生產環境請設置true。非false的值默認都當true處理。
acpsdk.ifValidateCNName=false
# 是否驗證https證書,測試環境請設置false,生產環境建議優先嚐試true,不行再false。非true的值默認都當false處理。
acpsdk.ifValidateRemoteCert=false
#*****後臺通知地址,填寫接收銀聯後臺通知的地址,必須外網能訪問*****
acpsdk.backUrl=http://222.222.222.222:8080/ACPSample_B2C/backRcvResponse
#*****前臺通知地址,填寫銀聯前臺通知的地址,必須外網能訪問*****
acpsdk.frontUrl=http://localhost:8080/EasyBuy/AfterPayServlet
/**
* 獲取請求參數中所有的信息
* 當商戶上送frontUrl或backUrl地址中帶有參數信息的時候,
* 這種方式會將url地址中的參數讀到map中,會導多出來這些信息從而致驗籤失敗,這個時候可以自行修改過濾掉url中的參數或者使用getAllRequestParamStream方法。
* @param request
* @return
*/
public static Map<String, String> getAllRequestParam(
final HttpServletRequest request) {
Map<String, String> res = new HashMap<String, String>();
Enumeration<?> temp = request.getParameterNames();
if (null != temp) {
while (temp.hasMoreElements()) {
String en = (String) temp.nextElement();
String value = request.getParameter(en);
res.put(en, value);
// 在報文上送時,如果字段的值爲空,則不上送<下面的處理爲在獲取所有參數數據時,判斷若值爲空,則刪除這個字段>
if (res.get(en) == null || "".equals(res.get(en))) {
// System.out.println("======爲空的字段名===="+en);
res.remove(en);
}
}
}
return res;
}
/**
* 獲取請求參數中所有的信息。
* 非struts可以改用此方法獲取,好處是可以過濾掉request.getParameter方法過濾不掉的url中的參數。
* struts可能對某些content-type會提前讀取參數導致從inputstream讀不到信息,所以可能用不了這個方法。理論應該可以調整struts配置使不影響,但請自己去研究。
* 調用本方法之前不能調用req.getParameter("key");這種方法,否則會導致request取不到輸入流。
* @param request
* @return
*/
public static Map<String, String> getAllRequestParamStream(
final HttpServletRequest request) {
Map<String, String> res = new HashMap<String, String>();
try {
String notifyStr = new String(IOUtils.toByteArray(request.getInputStream()),DemoBase.encoding);
LogUtil.writeLog("收到通知報文:" + notifyStr);
String[] kvs= notifyStr.split("&");
for(String kv : kvs){
String[] tmp = kv.split("=");
if(tmp.length >= 2){
String key = tmp[0];
String value = URLDecoder.decode(tmp[1],DemoBase.encoding);
res.put(key, value);
}
}
} catch (UnsupportedEncodingException e) {
LogUtil.writeLog("getAllRequestParamStream.UnsupportedEncodingException error: " + e.getClass() + ":" + e.getMessage());
} catch (IOException e) {
LogUtil.writeLog("getAllRequestParamStream.IOException error: " + e.getClass() + ":" + e.getMessage());
}
return res;
}
}
Web.xml:
<!-- 銀聯支付 -->
<filter>
<filter-name>CharsetEncodingFilter</filter-name>
<filter-class>web.CharsetEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharsetEncodingFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>autoLoadServlet</servlet-name>
<servlet-class>web.AutoLoadServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>autoLoadServlet</servlet-name>
<url-pattern>/autoLoadServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>frontRcvResponse</servlet-name>
<servlet-class>com.unionpay.acp.demo.FrontRcvResponse</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>frontRcvResponse</servlet-name>
<url-pattern>/frontRcvResponse</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>backRcvResponse</servlet-name>
<servlet-class>com.unionpay.acp.demo.BackRcvResponse</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>backRcvResponse</servlet-name>
<url-pattern>/backRcvResponse</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_2_FrontConsume</servlet-name>
<servlet-class>com.unionpay.acp.demo.consume.Form_6_2_FrontConsume</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_2_FrontConsume</servlet-name>
<url-pattern>/form_6_2_FrontConsume</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_5_Query</servlet-name>
<servlet-class>com.unionpay.acp.demo.Form_6_5_Query</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_5_Query</servlet-name>
<url-pattern>/form_6_5_Query</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_3_ConsumeUndo</servlet-name>
<servlet-class>com.unionpay.acp.demo.consume.Form_6_3_ConsumeUndo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_3_ConsumeUndo</servlet-name>
<url-pattern>/form_6_3_ConsumeUndo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_4_Refund</servlet-name>
<servlet-class>com.unionpay.acp.demo.Form_6_4_Refund</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_4_Refund</servlet-name>
<url-pattern>/form_6_4_Refund</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_6_FileTransfer</servlet-name>
<servlet-class>com.unionpay.acp.demo.Form_6_6_FileTransfer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_6_FileTransfer</servlet-name>
<url-pattern>/form_6_6_FileTransfer</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_7_1_AuthDeal_Front</servlet-name>
<servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_1_AuthDeal_Front</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_7_1_AuthDeal_Front</servlet-name>
<url-pattern>/form_6_7_1_AuthDeal_Front</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_7_2_AuthUndo</servlet-name>
<servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_2_AuthUndo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_7_2_AuthUndo</servlet-name>
<url-pattern>/form_6_7_2_AuthUndo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_7_3_AuthFinish</servlet-name>
<servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_3_AuthFinish</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_7_3_AuthFinish</servlet-name>
<url-pattern>/form_6_7_3_AuthFinish</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_7_4_AuthFinishUndo</servlet-name>
<servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_4_AuthFinishUndo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_7_4_AuthFinishUndo</servlet-name>
<url-pattern>/form_6_7_4_AuthFinishUndo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>form_6_2_FrontConsume2</servlet-name>
<servlet-class>com.unionpay.acp.demo.consume.Form_6_2_FrontConsume2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>form_6_2_FrontConsume2</servlet-name>
<url-pattern>/form_6_2_FrontConsume2</url-pattern>
</servlet-mapping>
3.支付寶
配置支付寶的系統參數:
* *
*類名:AlipayConfig
*功能:基礎配置類
*詳細:設置帳戶有關信息及返回路徑
*修改日期:2017-04-05
*說明:
*以下代碼只是爲了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。
*該代碼僅供學習和研究支付寶接口使用,只是提供一個參考。
*/
public class AlipayConfig {
//↓↓↓↓↓↓↓↓↓↓請在這裏配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 應用ID,您的APPID,收款賬號既是您的APPID對應支付寶賬號
public static String app_id = "2016091500513317";
// 商戶私鑰,您的PKCS8格式RSA2私鑰
public static String merchant_private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDrgo+hXY13m/CfF7IbUolh5jJKNpFSLt8eq/nc/FvHGWURnIWySnYe2rzrn9csHY5Y+Xv9hUu0SJZD/NOUN0yIN/AFNCz90HoT5un8GZmZYh6hmr3C3WeHHEgKqml6A/aFLnZeajM8dJ0jE/og2/5cOjG2J7yGrI9xt3lKTfm+ZxE8zQnspwZBUQLYPKL39M8DTGqpCS2lKqL3xVpWEE49OPY8vYP/M2/1w/a10UhSye3F6kKmD9dRmTqCjlvb+gaAKrSfrO0ix2oOFlQ18v+p8KQiiQ5Ka93wC5knBXxqV/HLs02nFXffN1wVfvQEcnguwhK7Vs2ph6QUgCH0okItAgMBAAECggEAYxLvvWCPzMuLNEJRqPDV3ptqeJHwHHSfZFXQrUh0i5OBUyFXlSOCAYTfiPgbGvHsGj4KDSLwMA2BOWS41VdWGM//ZxEGBFiZopm3wVg7p60BWdaxEbL2hH4/SE1cRfo40No07Y8bsskT+dfDl+M0ZDQPCaQ5ySX6ykn2+m1HLPN8QnEpeOvNdivXba4bx4yAhkKN0hzbTmo/LHKKg4DUcN1D7ySsZjjejgxOZA/YZiWNRzkManb0R2rncn3YhTWu/+fLV32NMAVeR02ZfTDi7c5yeXuHgZz6dOKRnwXRNqDXc9UV6zuU6FHc0sHuoeEDES7eSgvi9ty5iopVP8QyQQKBgQD74IfwqucvNCoXCD+wI57v0Sz1vP1wdQePj2BCyo+E8IEGy53OCMuB6yqF8Vs/xhsZdyGZODzpN4qWXmXOtz9dXb+GxJWNrQ47/qSrNufRKmi1F07oGPGilQhoHIcp2Nzs5JW1Q8SP11jp0KbpdEEWmwPd0nojlUKEpyl7dGzfhQKBgQDvXXH8P5CS0nSzKDRGvGnafYLBL8SGZFzRDCfkU3GPBunFsNEC8v7ndXLKVN3EJyf9xPdQuGRaG1PdkW+rJO54uVGKKO6ovqCp3clYOVpUad1R+MSDCYblhaRKHZIsMldcvKhSgK5o26m7Q/IL0+yfdB4JmACp+rglsTwiEhtUiQKBgBGm9b//Kj6bqEt+73+3r17dSQpb2WM1QHdmM/faXF6TwGcqg/+5jBGp2owSkzOP/bw2JiunzlUF6HeLXBU1sIIpnM+kHVsVgsbfnMjHC04Ua8wtOwF3JhAf47vwK+TZ5vnPN1LB0hfGntucHOaFmD4uVQIJyzeNMWE8meKmES9FAoGBAJGJKG/tmhKbIVd432gO0PGGlISvbXck+IYmNO8PiSEkW+jWHA8F/dRvRa8dsIS+JgOWyaRrqKBcsz4pWlMdrlz6mEg/oPQ6i2ccsXoRzQk8INPhRGJD3aAaBI0Hs8NpjFKXZmRbVy/sNyPkKPvmC53btROyNt0i0uof++bfSXy5AoGAfbu72+EAgvrSV/Wbex3bNen0N+5I4FxxG26DzquQ2XsKAZxnk4dYhPPVJ4+hGV+jqYjOCqb6nD5u73P0zfyop8s3EtiQqn2bZnYvaVj+U8av6SMjWlXdJEn9SZgM9YB5BfDye9U8p0KzhzVkS57JHGzRcVN7lj94j3LMTftu8mo=";
// 支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。
public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqyAPfcaoUhPTny0NsThFRaM249Ur7jk/PUFOrv6cQkj9Kr/qD9/Ch2jktx5tlSjkztoiRZgUnBT/zN6UCeyq/rZ/sdZHXkWFmZL7ovWqLzsy2HiKwfncJeWDsNkFT6KKmd4uXoKu1BLCEU6e8oG3dLS980NVMwPHn11SxkpHSAqm/A0N1/O5NmlN+UYIAmEaGLe4IPTxsnWMTuov6l2yKiUvaIQ+nCOPU5wLsCh3hKZzfYQCdiFjNgXqnKRQpK23gWnh+vfF0WMyf53nwPfLF91K4I9quKmTo62B8FW5k9FAkoc9DG6uy0Eqa1udEWUYUsr5YZXKAi2wT8+mj/TzgwIDAQAB";
// 服務器異步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
public static String notify_url = "http://localhost:8080/EasyBuy/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp";
// 頁面跳轉同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
public static String return_url = "http://localhost:8080/EasyBuy/AfterPayServlet";
// 簽名方式
public static String sign_type = "RSA2";
// 字符編碼格式
public static String charset = "utf-8";
// 支付寶網關
public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
// 支付寶網關
public static String log_path = "C:\\";
//↑↑↑↑↑↑↑↑↑↑請在這裏配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
/**
* 寫日誌,方便測試(看網站需求,也可以改成把記錄存入數據庫)
* @param sWord 要寫入日誌裏的文本內容
*/
public static void logResult(String sWord) {
FileWriter writer = null;
try {
writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis()+".txt");
writer.write(sWord);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
//獲得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
//設置請求參數
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(AlipayConfig.return_url);
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
//商戶訂單號,商戶網站訂單系統中唯一訂單號,必填
String out_trade_no = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//付款金額,必填
String total_amount = new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"),"UTF-8");
//訂單名稱,必填
String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8");
//商品描述,可空
String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"),"UTF-8");
alipayRequest.setBizContent("{\"out_trade_no\":\""+out_trade_no+"\","
+ "\"total_amount\":\""+ total_amount +"\","
+ "\"subject\":\""+ subject +"\","
+ "\"body\":\""+ body +"\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//若想給BizContent增加其他可選請求參數,以增加自定義超時時間參數timeout_express來舉例說明
//alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
// + "\"total_amount\":\""+ total_amount +"\","
// + "\"subject\":\""+ subject +"\","
// + "\"body\":\""+ body +"\","
// + "\"timeout_express\":\"10m\","
// + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//請求參數可查閱【電腦網站支付的API文檔-alipay.trade.page.pay-請求參數】章節
//請求
String result = alipayClient.pageExecute(alipayRequest).getBody();
//輸出
out.println(result);
/* *
* 功能:支付寶服務器異步通知頁面
* 日期:2017-03-30
* 說明:
* 以下代碼只是爲了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。
* 該代碼僅供學習和研究支付寶接口使用,只是提供一個參考。
*************************頁面功能說明*************************
* 創建該頁面文件時,請留心該頁面文件中無任何HTML代碼及空格。
* 該頁面不能在本機電腦測試,請到服務器上做測試。請確保外部可以訪問該頁面。
* 如果沒有收到該頁面返回的 success
* 建議該頁面只做支付成功的業務邏輯處理,退款的處理請以調用退款查詢接口的結果爲準。
*/
//獲取支付寶POST過來反饋信息
Map<String,String> params = new HashMap<String,String>();
Map<String,String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//亂碼解決,這段代碼在出現亂碼時使用
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //調用SDK驗證簽名
//——請在這裏編寫您的程序(以下代碼僅作參考)——
/* 實際驗證過程建議商戶務必添加以下校驗:
1、需要驗證該通知數據中的out_trade_no是否爲商戶系統中創建的訂單號,
2、判斷total_amount是否確實爲該訂單的實際金額(即商戶訂單創建時的金額),
3、校驗通知中的seller_id(或者seller_email) 是否爲out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email)
4、驗證app_id是否爲該商戶本身。
*/
if(signVerified) {//驗證成功
//商戶訂單號
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//支付寶交易號
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
//交易狀態
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
if(trade_status.equals("TRADE_FINISHED")){
//判斷該筆訂單是否在商戶網站中已經做過處理
//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
//如果有做過處理,不執行商戶的業務程序
//注意:
//退款日期超過可退款期限後(如三個月可退款),支付寶系統發送該交易狀態通知
}else if (trade_status.equals("TRADE_SUCCESS")){
//判斷該筆訂單是否在商戶網站中已經做過處理
//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程序
//如果有做過處理,不執行商戶的業務程序
//注意:
//付款完成後,支付寶系統發送該交易狀態通知
}
out.println("success");
}else {//驗證失敗
out.println("fail");
//調試用,寫文本函數記錄程序運行情況是否正常
//String sWord = AlipaySignature.getSignCheckContentV1(params);
//AlipayConfig.logResult(sWord);
}
//支付寶支付
public String toAlipay(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException
{
try
{
//設置字符編碼
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//獲取參數
//付款金額
String totalAmount=request.getParameter("totalAmount");
//訂單號
String number=request.getParameter("serializeNumber");
//存入請求作用域
request.setAttribute("totalAmount",totalAmount);
request.setAttribute("serializeNumber",number);
return "alipay.trade.page.pay-JAVA-UTF-8/index";
}
catch(Exception e)
{
e.printStackTrace();
return "500";
}
}
對應api參考
https://doc.open.alipay.com/doc2/detail.htm?treeId=270&articleId=105901&docType=1
轉存失敗重新上傳取消 轉存失敗重新上傳取消 轉存失敗重新上傳取消
轉存失敗重新上傳取消 轉存失敗重新上傳取消 轉存失敗重新上傳取消
頁面回調
提交訂單的請求參數
4.QQ登錄
首先到QQ開發平臺註冊應用等信息,獲取appid
JS:
<script type="text/javascript"
src="http://qzonestyle.gtimg.cn/qzone/openapi/qc_loader.js" data-appid="101394710" data-redirecturi="http://localhost:8080/AmpleShop/qq.jsp" charset="utf-8"></script>
//通過QQjs,將指定的節點變成QQ登錄按鈕
QC.Login({
btnId:"qqLoginBtn" //插入按鈕的節點id
});
//使用自定義的QQ登錄按鈕,綁定登錄的功能
function qq(){
$("#qqLoginBtn a").trigger('click');
QQreg();
}
//實時獲取登錄狀態
function QQreg(){
var image= $(".figure img").attr("src");
var name=$(".nickname").text();
if(image==undefined){
setTimeout(QQreg,1000);
}else{
jQuery.ajax({
url : 'As_user_login1.action',
data : {"image":image,"username":name},
type : "POST",
beforeSend : function() {
},
success : function(data) {
var js=$.parseJSON(data);
if(js.user_id!=0){
callback();
}else{
$(".userpwd").val("");
$(".userlogin").val("");
}
}
});
}
}
//註銷登錄
QC.Login.signOut();
qqconnectconfig.properties配置文件:
app_ID = 101472093
app_KEY = 28c74e2d5e2bce253c10474a33cb3e6d
redirect_URI = http://localhost:8080/EasyBuy
scope = get_user_info,add_topic,add_one_blog,add_album,upload_pic,list_album,add_share,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idollist,add_idol,del_ido,get_tenpay_addr
baseURL = https://graph.qq.com/
getUserInfoURL = https://graph.qq.com/user/get_user_info
accessTokenURL = https://graph.qq.com/oauth2.0/token
authorizeURL = https://graph.qq.com/oauth2.0/authorize
getOpenIDURL = https://graph.qq.com/oauth2.0/me
addTopicURL = https://graph.qq.com/shuoshuo/add_topic
addBlogURL = https://graph.qq.com/blog/add_one_blog
addAlbumURL = https://graph.qq.com/photo/add_album
uploadPicURL = https://graph.qq.com/photo/upload_pic
listAlbumURL = https://graph.qq.com/photo/list_album
addShareURL = https://graph.qq.com/share/add_share
checkPageFansURL = https://graph.qq.com/user/check_page_fans
addTURL = https://graph.qq.com/t/add_t
addPicTURL = https://graph.qq.com/t/add_pic_t
delTURL = https://graph.qq.com/t/del_t
getWeiboUserInfoURL = https://graph.qq.com/user/get_info
getWeiboOtherUserInfoURL = https://graph.qq.com/user/get_other_info
getFansListURL = https://graph.qq.com/relation/get_fanslist
getIdolsListURL = https://graph.qq.com/relation/get_idollist
addIdolURL = https://graph.qq.com/relation/add_idol
delIdolURL = https://graph.qq.com/relation/del_idol
getTenpayAddrURL = https://graph.qq.com/cft_info/get_tenpay_addr
getRepostListURL = https://graph.qq.com/t/get_repost_list
version =2.0.0.0
public class IndexServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
try {
response.sendRedirect(new Oauth().getAuthorizeURL(request));
} catch (QQConnectException e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
doGet(request, response);
}
}
/**提交登錄後處理
* Date: 12-12-4
* Time: 下午4:36
*/
public class AfterLoginRedirectServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
try {
AccessToken accessTokenObj = (new Oauth()).getAccessTokenByRequest(request);
String accessToken = null,
openID = null;
long tokenExpireIn = 0L;
if (accessTokenObj.getAccessToken().equals("")) {
// 我們的網站被CSRF攻擊了或者用戶取消了授權
// 做一些數據統計工作
System.out.print("沒有獲取到響應參數");
} else {
accessToken = accessTokenObj.getAccessToken();
tokenExpireIn = accessTokenObj.getExpireIn();
request.getSession().setAttribute("demo_access_token", accessToken);
request.getSession().setAttribute("demo_token_expirein", String.valueOf(tokenExpireIn));
// 利用獲取到的accessToken 去獲取當前用的openid -------- start
OpenID openIDObj = new OpenID(accessToken);
openID = openIDObj.getUserOpenID();
out.println("歡迎你,代號爲 " + openID + " 的用戶!");
request.getSession().setAttribute("demo_openid", openID);
out.println("<a href=" + "/shuoshuoDemo.html" + " target=\"_blank\">去看看發表說說的demo吧</a>");
// 利用獲取到的accessToken 去獲取當前用戶的openid --------- end
out.println("<p> start -----------------------------------利用獲取到的accessToken,openid 去獲取用戶在Qzone的暱稱等信息 ---------------------------- start </p>");
UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);
UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
//根據qq基本信息生成用戶,存入請求作用域
User user=new User();
user.setUserName(userInfoBean.getNickname());
request.getSession().setAttribute("loginWay","qq");
request.getSession().setAttribute("user",user);
response.sendRedirect("InitialServlet");
return;
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Web.xml
<!-- QQ登錄 -->
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.qq.connect.demo.IndexServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<!-- 業界標準 用.do後綴來表示 controler -->
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>afterlogin</servlet-name>
<servlet-class>com.qq.connect.demo.AfterLoginRedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>afterlogin</servlet-name>
<!-- 業界標準 用.do後綴來表示 controler -->
<url-pattern>/afterlogin.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>shuoshuo</servlet-name>
<servlet-class>com.qq.connect.demo.ShuoShuoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>shuoshuo</servlet-name>
<url-pattern>/shuoshuo.do</url-pattern>
</servlet-mapping>
5.物流接口(快遞鳥api)
<script src="http://www.kdniao.com/OutDemo/KDNWidget/KDNWidget.js"></script>
<script type="text/javascript" src="js/jquery-1.8.3.js"></script>
<script type="text/javascript">
var number = $("[name='number']").val();
var company = $("[name='company']").val();
$(document).ready(function() {
KDNWidget.run({
serviceType : "B",
expCode : company,
expNo : number,
showType : "normal",
container : "demoID"
})
});
</script>
//查看物流信息
public String showExpressInfo(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException
{
try
{
//設置字符編碼
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//獲取參數
int orderId=Integer.parseInt(request.getParameter("orderId"));
//根據訂單id獲取物流信息
OrderService service=new OrderServiceImpl();
Express express=service.getExpressInfo(orderId);
//存入請求作用域
request.setAttribute("express",express);
return "pre/showExpressResult";
}
catch(Exception e)
{
e.printStackTrace();
return "500";
}
}
- 省市區下拉框聯動
$(document).ready(function(){
//聯動加載二級市區
$("[name='province']").change(function(){
var province=$(this).val();
$(this).next().empty();
$(this).next().append("<option value='0'>請選擇</option>");
$(this).next().next().empty();
$(this).next().next().append("<option value='0'>請選擇</option>");
for(var i=0;i<provinceList.length;i++)
{
if(provinceList[i].name==province)
{
for(var j=0;j<provinceList[i].cityList.length;j++)
{
var city=provinceList[i].cityList[j];
$(this).next().append("<option value='"+city.name+"'>"+city.name+"</option>");
}
}
}
});
//聯動加載三級縣區域
$("[name='city']").change(function(){
var province=$(this).prev().val();
var city=$(this).val();
$(this).next().empty();
$(this).next().append("<option value='0'>請選擇</option>");
for(var i=0;i<provinceList.length;i++)
{
if(provinceList[i].name==province)
{
for(var j=0;j<provinceList[i].cityList.length;j++)
{
if(provinceList[i].cityList[j].name==city)
{
for(var k=0;k<provinceList[i].cityList[j].areaList.length;k++)
{
var area=provinceList[i].cityList[j].areaList[k];
$(this).next().append("<option value='"+area+"'>"+area+"</option>");
}
}
}
}
}
});
});
//頁面加載立即執行,加載省市區三級聯動
//加載一級省份
function loadProvider()
{
$("[name='province']").empty();
$("[name='province']").append("<option value='0'>請選擇</option>");
for(var i=0;i<provinceList.length;i++)
{
var province=provinceList[i];
$("[name='province']").append("<option value='"+province.name+"'>"+province.name+"</option>");
}
}
Province.js(詳見文件:province.js):
var provinceList = [
{name:'北京', cityList:[
{name:'市轄區', areaList:['東城區','西城區','崇文區','宣武區','朝陽區','豐臺區','石景山區','海淀區','門頭溝區','房山區','通州區','順義區','昌平區','大興區','懷柔區','平谷區']},
{name:'縣', areaList:['密雲縣','延慶縣']}
]},
{name:'上海', cityList:[
{name:'市轄區', areaList:['黃浦區','盧灣區','徐彙區','長寧區','靜安區','普陀區','閘北區','虹口區','楊浦區','閔行區','寶山區','嘉定區','浦東新區','金山區','松江區','青浦區','南匯區','奉賢區']},
{name:'縣', areaList:['崇明縣']}
]},
{name:'天津', cityList:[
{name:'市轄區', areaList:['和平區','河東區','河西區','南開區','河北區','紅橋區','塘沽區','漢沽區','大港區','東麗區','西青區','津南區','北辰區','武清區','寶坻區']},
{name:'縣', areaList:['寧河縣','靜海縣','薊 縣']}
]},
{name:'重慶', cityList:[
{name:'市轄區', areaList:['萬州區','涪陵區','渝中區','大渡口區','江北區','沙坪壩區','九龍坡區','南岸區','北碚區','萬盛區','雙橋區','渝北區','巴南區','黔江區','長壽區']},
{name:'縣', areaList:['綦江縣','潼南縣','銅梁縣','大足縣','榮昌縣','璧山縣','梁平縣','城口縣','豐都縣','墊江縣','武隆縣','忠 縣','開 縣','雲陽縣','奉節縣','巫山縣','巫溪縣','石柱土家族自治縣','秀山土家族苗族自治縣','酉陽土家族苗族自治縣','彭水苗族土家族自治縣']},
{name:'市', areaList:['江津市','合川市','永川市','南川市']}
]},
- 富文本編輯器UEditor
Config.json配置文件:
/* 前後端通信相關的配置,註釋只允許使用多行方式 */
{
/* 上傳圖片配置項 */
"imageActionName": "uploadimage", /* 執行上傳圖片的action名稱 */
"imageFieldName": "upfile", /* 提交的圖片表單名稱 */
"imageMaxSize": 2048000, /* 上傳大小限制,單位B */
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上傳圖片格式顯示 */
"imageCompressEnable": true, /* 是否壓縮圖片,默認是true */
"imageCompressBorder": 1600, /* 圖片壓縮最長邊限制 */
"imageInsertAlign": "none", /* 插入的圖片浮動方式 */
"imageUrlPrefix": "/EasyBuy", /* 圖片訪問路徑前綴 */
"imagePathFormat": "/statics/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
/* {filename} 會替換成原文件名,配置這項需要注意中文亂碼問題 */
/* {rand:6} 會替換成隨機數,後面的數字是隨機數的位數 */
/* {time} 會替換成時間戳 */
/* {yyyy} 會替換成四位年份 */
/* {yy} 會替換成兩位年份 */
/* {mm} 會替換成兩位月份 */
/* {dd} 會替換成兩位日期 */
/* {hh} 會替換成兩位小時 */
/* {ii} 會替換成兩位分鐘 */
/* {ss} 會替換成兩位秒 */
/* 非法字符 \ : * ? " < > | */
/* 具請體看線上文檔: fex.baidu.com/ueditor/#use-format_upload_filename */
/* 塗鴉圖片上傳配置項 */
"scrawlActionName": "uploadscrawl", /* 執行上傳塗鴉的action名稱 */
"scrawlFieldName": "upfile", /* 提交的圖片表單名稱 */
"scrawlPathFormat": "/ueditor1_4_3_2/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"scrawlMaxSize": 2048000, /* 上傳大小限制,單位B */
"scrawlUrlPrefix": "", /* 圖片訪問路徑前綴 */
"scrawlInsertAlign": "none",
/* 截圖工具上傳 */
"snapscreenActionName": "uploadimage", /* 執行上傳截圖的action名稱 */
"snapscreenPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"snapscreenUrlPrefix": "", /* 圖片訪問路徑前綴 */
"snapscreenInsertAlign": "none", /* 插入的圖片浮動方式 */
/* 抓取遠程圖片配置 */
"catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
"catcherActionName": "catchimage", /* 執行抓取遠程圖片的action名稱 */
"catcherFieldName": "source", /* 提交的圖片列表表單名稱 */
"catcherPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"catcherUrlPrefix": "", /* 圖片訪問路徑前綴 */
"catcherMaxSize": 2048000, /* 上傳大小限制,單位B */
"catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取圖片格式顯示 */
/* 上傳視頻配置 */
"videoActionName": "uploadvideo", /* 執行上傳視頻的action名稱 */
"videoFieldName": "upfile", /* 提交的視頻表單名稱 */
"videoPathFormat": "/ueditor/jsp/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"videoUrlPrefix": "", /* 視頻訪問路徑前綴 */
"videoMaxSize": 102400000, /* 上傳大小限制,單位B,默認100MB */
"videoAllowFiles": [
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上傳視頻格式顯示 */
/* 上傳文件配置 */
"fileActionName": "uploadfile", /* controller裏,執行上傳視頻的action名稱 */
"fileFieldName": "upfile", /* 提交的文件表單名稱 */
"filePathFormat": "/ueditor/jsp/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上傳保存路徑,可以自定義保存路徑和文件名格式 */
"fileUrlPrefix": "", /* 文件訪問路徑前綴 */
"fileMaxSize": 51200000, /* 上傳大小限制,單位B,默認50MB */
"fileAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
], /* 上傳文件格式顯示 */
/* 列出指定目錄下的圖片 */
"imageManagerActionName": "listimage", /* 執行圖片管理的action名稱 */
"imageManagerListPath": "/ueditor/jsp/upload/image/", /* 指定要列出圖片的目錄 */
"imageManagerListSize": 20, /* 每次列出文件數量 */
"imageManagerUrlPrefix": "", /* 圖片訪問路徑前綴 */
"imageManagerInsertAlign": "none", /* 插入的圖片浮動方式 */
"imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件類型 */
/* 列出指定目錄下的文件 */
"fileManagerActionName": "listfile", /* 執行文件管理的action名稱 */
"fileManagerListPath": "/ueditor/jsp/upload/file/", /* 指定要列出文件的目錄 */
"fileManagerUrlPrefix": "", /* 文件訪問路徑前綴 */
"fileManagerListSize": 20, /* 每次列出文件數量 */
"fileManagerAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
] /* 列出的文件類型 */
}
* ueditor完整配置項
* 可以在這裏配置整個編輯器的特性
*/
/**************************提示********************************
* 所有被註釋的配置項均爲UEditor默認值。
* 修改默認配置請首先確保已經完全明確該參數的真實用途。
* 主要有兩種修改方案,一種是取消此處註釋,然後修改成對應參數;另一種是在實例化編輯器時傳入對應參數。
* 當升級編輯器時,可直接使用舊版配置文件替換新版配置文件,不用擔心舊版配置文件中因缺少新功能所需的參數而導致腳本報錯。
**************************提示********************************/
<%
request.setCharacterEncoding( "utf-8" );
response.setHeader("Content-Type" , "text/html");
String rootPath = application.getRealPath( "/" );
out.write( new ActionEnter( request, rootPath ).exec() );
%>
(function () {
/**
* 編輯器資源文件根路徑。它所表示的含義是:以編輯器實例化頁面爲當前路徑,指向編輯器資源文件(即dialog等文件夾)的路徑。
* 鑑於很多同學在使用編輯器的時候出現的種種路徑問題,此處強烈建議大家使用"相對於網站根目錄的相對路徑"進行配置。
* "相對於網站根目錄的相對路徑"也就是以斜槓開頭的形如"/myProject/ueditor/"這樣的路徑。
* 如果站點中有多個不在同一層級的頁面需要實例化編輯器,且引用了同一UEditor的時候,此處的URL可能不適用於每個頁面的編輯器。
* 因此,UEditor提供了針對不同頁面的編輯器可單獨配置的根路徑,具體來說,在需要實例化編輯器的頁面最頂部寫上如下代碼即可。當然,需要令此處的URL等於對應的配置。
* window.UEDITOR_HOME_URL = "/xxxx/xxxx/";
*/
window.UEDITOR_HOME_URL="/EasyBuy/ueditor1_4_3_2/";
var URL = window.UEDITOR_HOME_URL || getUEBasePath();
/**
* 配置項主體。注意,此處所有涉及到路徑的配置別遺漏URL變量。
*/
window.UEDITOR_CONFIG = {
//爲編輯器實例添加一個路徑,這個不能被註釋
UEDITOR_HOME_URL: URL
// 服務器統一請求接口路徑
, serverUrl: URL + "jsp/controller.jsp"
//工具欄上的所有的功能按鈕和下拉框,可以在new編輯器的實例時選擇自己需要的重新定義
, toolbars: [[
'fullscreen', 'source', '|', 'undo', 'redo', '|',
'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|',
'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
'directionalityltr', 'directionalityrtl', 'indent', '|',
'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',
'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',
'simpleupload', 'insertimage', 'emotion', 'scrawl', 'insertvideo', 'music', 'attachment', 'map', 'gmap', 'insertframe', 'insertcode', 'webapp', 'pagebreak', 'template', 'background', '|',
'horizontal', 'date', 'time', 'spechars', 'snapscreen', 'wordimage', '|',
'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|',
'print', 'preview', 'searchreplace', 'drafts', 'help'
]]
<script type="text/javascript" charset="utf-8" src="${pageContext.request.contextPath}/ueditor1_4_3_2/ueditor.config.js"></script>
<script type="text/javascript" charset="utf-8" src="${pageContext.request.contextPath}/ueditor1_4_3_2/ueditor.all.min.js"> </script>
<!--建議手動加在語言,避免在ie下有時因爲加載語言失敗導致編輯器加載失敗-->
<!--這裏加載的語言文件會覆蓋你在配置項目裏添加的語言類型,比如你在配置項目裏配置的是英文,這裏加載的中文,那最後就是中文-->
<script type="text/javascript" charset="utf-8" src="${pageContext.request.contextPath}/ueditor1_4_3_2/lang/zh-cn/zh-cn.js"></script>
<script type="text/javascript">
//實例化編輯器
//建議使用工廠方法getEditor創建和引用編輯器實例,如果在某個閉包下引用該編輯器,直接調用UE.getEditor('editor')就能拿到相關的實例
var ue = UE.getEditor('editor');
function getContent() {
var arr = [];
arr.push("使用editor.getContent()方法可以獲得編輯器的內容");
arr.push("內容爲:");
arr.push(UE.getEditor('editor').getContent());
alert(arr.join("\n"));
}
</script>
- FastDFS+nginx文件服務器
FastDFS安裝環境
FastDFS是C語言開發,建議在linux上運行,本項目使用Centos6.4作爲安裝環境。
安裝FastDFS需要先將官網下載的源碼進行編譯,編譯依賴gcc環境,如果沒有gcc環境,需要安裝gcc:yum install gcc-c++
安裝libevent
FastDFS依賴libevent庫,需要安裝:
yum -y install libevent
安裝libfastcommon
把五個文件都上傳到/usr/local文件夾下
libfastcommon是FastDFS官方提供的,libfastcommon包含了FastDFS運行所需要的一些基礎庫。
將libfastcommonV1.0.7.tar.gz拷貝至/usr/local/下
cd /usr/local
tar -zxvf libfastcommonV1.0.7.tar.gz
cd libfastcommon-1.0.7
./make.sh
./make.sh install
注意:libfastcommon安裝好後會自動將庫文件拷貝至/usr/lib64下,由於FastDFS程序引用usr/lib目錄所以需要將/usr/lib64下的庫文件拷貝至/usr/lib下。
要拷貝的文件如下:
tracker編譯安裝
將FastDFS_v5.05.tar.gz拷貝至/usr/local/下
tar -zxvf FastDFS_v5.05.tar.gz
cd FastDFS
./make.sh
./make.sh install
安裝成功將安裝目錄下的conf下的文件拷貝到/etc/fdfs/下。
配置
安裝成功後進入/etc/fdfs目錄:
拷貝一份新的tracker配置文件:
cp tracker.conf.sample tracker.conf
回車.
修改tracker.conf
vi tracker.conf
base_path=/home/yuqing/FastDFS
改爲:
base_path=/home/FastDFS
去home文件夾創建文件
[root@localhost home]# mkdir FastDFS
啓動
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
第一次啓動是以下畫面
第二次啓動
(實際環境不是5619)再啓動,如下圖:
注意:如果沒有顯示上圖要注意是否正常停止原有進程。
- 設置開機自動啓動。
[root@localhost fdfs]# vim /etc/rc.d/rc.local
|
|
|
將運行命令行添加進文件:/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
配置
安裝成功後進入 cd /etc/fdfs目錄:
拷貝一份新的storage配置文件:
cp storage.conf.sample storage.conf
修改storage.conf
vi storage.conf
group_name=group1
base_path=/home/yuqing/FastDFS改爲:base_path=/home/FastDFS
store_path0=/home/yuqing/FastDFS改爲:store_path0=/home/FastDFS/fdfs_storage
#如果有多個掛載磁盤則定義多個store_path,如下
#store_path1=.....
#store_path2=......
tracker_server=192.168.101.3:22122 #配置tracker服務器:IP
#如果有多個則配置多個tracker
tracker_server=192.168.101.4:22122
創建目錄
啓動
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
注意:如果沒有顯示上圖要注意是否正常停止原有進程。
- 設置開機自動啓動。
[root@storage1 FastDFS]# vim /etc/rc.d/rc.local |
將運行命令行添加進文件:/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
上傳圖片測試
通過fdfs_test程序
FastDFS安裝成功可通過/usr/bin/fdfs_test測試上傳、下載等操作。
修改/etc/fdfs/client.conf
[root@localhost ~]# vim /etc/fdfs/client.conf
base_path=/home/FastDFS
tracker_server=192.168.177.139:22122
使用格式:
/usr/bin/fdfs_test 客戶端配置文件地址 upload 上傳文件
比如將/home下的圖片上傳到FastDFS中:
/usr/bin/fdfs_test /etc/fdfs/client.conf upload /home/1.jpg
http://192.168.101.3/group1/M00/00/00/wKhlBVVY2M-AM_9DAAAT7-0xdqM485_big.png就是文件的下載路徑。
對應storage服務器上的
/home/fastdfs/fdfs_storage/data/00/00/wKhlBVVY2M-AM_9DAAAT7-0xdqM485_big.png文件。
由於現在還沒有和nginx整合無法使用http下載。
通過java Client API
Client.conf
tracker_server=192.168.177.139:22122
-A INPUT -p tcp -m tcp --dport 8090 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 9080 -j ACCEPT
完整的測試方法參考測試源代碼。
public class FastClientTest { public static void main(String[] args) throws Exception { // 1、加載配置文件,配置文件中的內容就是tracker服務的地址。 ClientGlobal.init("D:/client.conf"); // 2、創建一個TrackerClient對象。直接new一個。 TrackerClient trackerClient = new TrackerClient(); // 3、使用TrackerClient對象創建連接,獲得一個TrackerServer對象。 TrackerServer trackerServer = trackerClient.getConnection(); // 4、創建一個StorageServer的引用,值爲null StorageServer storageServer = null; // 5、創建一個StorageClient對象,需要兩個參數TrackerServer對象、StorageServer的引用 StorageClient storageClient = new StorageClient(trackerServer, storageServer); // 6、使用StorageClient對象上傳圖片。 // 擴展名不帶“.” String[] strings = storageClient.upload_file("D:/1.jpg", "jpg", null); // 7、返回數組。包含組名和圖片的路徑。 for (String string : strings) { System.out.println(string); } } } |
FastDFS 和nginx整合
在tracker上安裝nginx
nginx的安裝細節參考nginx文檔。
在每個tracker上安裝nginx,的主要目的是做負載均衡及實現高可用。如果只有一臺tracker服務器可以不配置nginx。
在Storage上安裝nginx
FastDFS-nginx-module
將FastDFS-nginx-module_v1.16.tar.gz傳至/usr/local/下
cd /usr/local
tar -zvxf fastdfs-nginx-module_v1.16.tar.gz
[root@localhost local]# cd fastdfs-nginx-module
進入到src目錄
修改config文件將/usr/local/路徑改爲/usr/
複製文件
將FastDFS-nginx-module/src下的mod_FastDFS.conf拷貝至/etc/fdfs/下
[root@localhost src]# cp mod_fastdfs.conf /etc/fdfs/
修改mod_FastDFS.conf的內容
[root@localhost src]# vi /etc/fdfs/mod_fastdfs.conf
base_path=/home/FastDFS
tracker_server=192.168.101.3:22122
#tracker_server=192.168.101.4:22122(多個tracker配置多行)
url_have_group_name=true #url中包含group名稱
store_path0=/home/FastDFS/fdfs_storage #指定文件存儲路徑
複製文件
將libfdfsclient.so拷貝至/usr/lib下
cp /usr/lib64/libfdfsclient.so /usr/lib/
創建nginx/client目錄
mkdir -p /var/temp/nginx/client
nginx安裝
添加FastDFS-nginx-module模塊
去nginx的解壓目錄執行以下代碼.
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/usr/local/fastdfs-nginx-module/src
執行以下命令
make
make install
nginx配置文件
在/usr/local/nginx/conf/新建一個nginx配置文件nginx-fdfs.conf.
添加server:
vim nginx-fdfs.conf
server {
listen 80;
server_name 192.168.177.139;
location /group1/M00/ {
root /home/FastDFS/fdfs_storage/data;
ngx_fastdfs_module;
}
}
修改nginx的nginx.conf文件
說明:
server_name指定本機ip
location /group1/M00/:group1爲nginx 服務FastDFS的分組名稱,M00是FastDFS自動生成編號,對應store_path0=/home/FastDFS/fdfs_storage,如果FastDFS定義store_path1,這裏就是M01
啓動nginx服務:cd /usr/local/nginx/sbin
./nginx
測試
通過java客戶端上傳文件,使用瀏覽器訪問,比如訪問上傳圖片測試的文件:
例如:訪問storage:
http://192.168.101.3/group1/M00/00/00/wKhlBVVY2M-AM_9DAAAT7-0xdqM485_big.png
9.Redis+Jedis緩存
Redis的安裝
Redis是c語言開發的。
安裝redis需要c語言的編譯環境。如果沒有gcc需要在線安裝。yum install gcc-c++
安裝步驟:
第一步:redis的源碼包上傳到linux系統。
第二步:解壓縮redis。
第三步:編譯。進入redis源碼目錄。make
第四步:安裝。make install PREFIX=/usr/local/redis
PREFIX參數指定redis的安裝目錄。一般軟件安裝到/usr目錄下
連接redis
redis的啓動:
前端啓動:在redis的安裝目錄下直接啓動redis-server
[root@localhost bin]# ./redis-server
後臺啓動:
把/root/redis-3.0.0/redis.conf複製到/usr/local/redis/bin目錄下
[root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/
修改配置文件:
[root@localhost bin]# ./redis-server redis.conf
查看redis進程:
[root@localhost bin]# ps aux|grep redis
root 5190 0.1 0.3 33936 1712 ? Ssl 18:23 0:00 ./redis-server *:6379
root 5196 0.0 0.1 4356 728 pts/0 S+ 18:24 0:00 grep redis
殺死所有 redis進程: killall -9 redis-server
[root@localhost bin]#
Redis-cli
[root@localhost bin]# ./redis-cli
默認連接localhost運行在6379端口的redis服務。
[root@localhost bin]# ./redis-cli -h 192.168.25.153 -p 6379
-h:連接的服務器的地址
-p:服務的端口號
關閉redis:[root@localhost bin]# ./redis-cli shutdown
Redis五種數據類型
String:key-value(做緩存)
Redis中所有的數據都是字符串。命令不區分大小寫,key是區分大小寫的。Redis是單線程的。Redis中不適合保存內容大的數據。
get、set、
incr:加一(生成id)
Decr:減一
Hash:key-fields-values(做緩存)
相當於一個key對於一個map,map中還有key-value
使用hash對key進行歸類。
Hset:向hash中添加內容
Hget:從hash中取內容
List:有順序可重複(-1)
192.168.25.153:6379> lpush list1 a b c d
(integer) 4
192.168.25.153:6379> lrange list1 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
192.168.25.153:6379> rpush list1 1 2 3 4
(integer) 8
192.168.25.153:6379> lrange list1 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
7) "3"
8) "4"
192.168.25.153:6379>
192.168.25.153:6379> lpop list1
"d"
192.168.25.153:6379> lrange list1 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
6) "3"
7) "4"
192.168.25.153:6379> rpop list1
"4"
192.168.25.153:6379> lrange list1 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
6) "3"
192.168.25.153:6379>
Set:元素無順序,不能重複
192.168.25.153:6379> sadd set1 a b c c c d
(integer) 4
192.168.25.153:6379> smembers set1
1) "b"
2) "c"
3) "d"
4) "a"
192.168.25.153:6379> srem set1 a
(integer) 1
192.168.25.153:6379> smembers set1
1) "b"
2) "c"
3) "d"
192.168.25.153:6379>
還有集合運算命令,自學。
SortedSet(zset):有順序,不能重複
192.168.25.153:6379> zadd zset1 2 a 5 b 1 c 6 d
(integer) 4
192.168.25.153:6379> zrange zset1 0 -1
1) "c"
2) "a"
3) "b"
4) "d"
192.168.25.153:6379> zrem zset1 a
(integer) 1
192.168.25.153:6379> zrange zset1 0 -1
1) "c"
2) "b"
3) "d"
192.168.25.153:6379> zrevrange zset1 0 -1
1) "d"
2) "b"
3) "c"
192.168.25.153:6379> zrange zset1 0 -1 withscores
1) "c"
2) "1"
3) "b"
4) "5"
5) "d"
6) "6"
192.168.25.153:6379> zrevrange zset1 0 -1 withscores
1) "d"
2) "6"
3) "b"
4) "5"
5) "c"
6) "1"
192.168.25.153:6379>
Key命令
設置key的過期時間。
Expire key second:設置key的過期時間
Ttl key:查看key的有效期
Persist key:清除key的過期時間。Key持久化。
192.168.25.153:6379> expire Hello 100
(integer) 1
192.168.25.153:6379> ttl Hello
(integer) 77
Redis的持久化方案
Redis的所有數據都是保存到內存中的。
Rdb:快照形式,定期把內存中當前時刻的數據保存到磁盤。Redis默認支持的持久化方案。
aof形式:append only file。把所有對redis數據庫操作的命令,增刪改操作的命令。保存到文件中。數據庫恢復時把所有的命令執行一遍即可。
在redis.conf配置文件中配置。
Rdb:
Aof的配置:
兩種持久化方案同時開啓使用aof文件來恢復數據庫。
Jedis
需要把jedis依賴的jar包添加到工程中。Maven工程中需要把jedis的座標添加到依賴。
推薦添加到服務層。qingniao-content-service工程中。
連接單機版
第一步:創建一個Jedis對象。需要指定服務端的ip及端口。
第二步:使用Jedis對象操作數據庫,每個redis命令對應一個方法。
第三步:打印結果。
第四步:關閉Jedis
@Test public void testJedis() throws Exception { // 第一步:創建一個Jedis對象。需要指定服務端的ip及端口。 Jedis jedis = new Jedis("192.168.25.153", 6379); // 第二步:使用Jedis對象操作數據庫,每個redis命令對應一個方法。 String result = jedis.get("hello"); // 第三步:打印結果。 System.out.println(result); // 第四步:關閉Jedis jedis.close(); } |
連接單機版使用連接池
第一步:創建一個JedisPool對象。需要指定服務端的ip及端口。
第二步:從JedisPool中獲得Jedis對象。
第三步:使用Jedis操作redis服務器。
第四步:操作完畢後關閉jedis對象,連接池回收資源。
第五步:關閉JedisPool對象。
@Test public void testJedisPool() throws Exception { // 第一步:創建一個JedisPool對象。需要指定服務端的ip及端口。 JedisPool jedisPool = new JedisPool("192.168.25.153", 6379); // 第二步:從JedisPool中獲得Jedis對象。 Jedis jedis = jedisPool.getResource(); // 第三步:使用Jedis操作redis服務器。 jedis.set("jedis", "test"); String result = jedis.get("jedis"); System.out.println(result); // 第四步:操作完畢後關閉jedis對象,連接池回收資源。 jedis.close(); // 第五步:關閉JedisPool對象。 jedisPool.close(); } |
- Solr搜索引擎
- 上傳solr安裝包到服務器
- 解壓縮
目錄結構說明
bin :solr命令
Contrib:文件擴展包
dist:相關jar包及war包
examples:例子
- 安裝tomcat到對應目錄
- 將solr解壓縮目錄下的dist目錄的solr工程部署到tomcat下面,並重命名爲solr.war
- 進入到tomcat目錄啓動tomcat,solr war包自動解壓縮
查看控制檯命令
刪除solr.war 需要注意:在tomcat啓動時刪除解壓縮的solr目錄也會被刪除,在停止tomcat的時候刪除solr.war,solr目錄不會被刪除
- 從solr解壓縮目錄的example目錄下複製相關jar包到tomcat solr工程的lib包下
- 配置solrhome:從example目錄下複製solr目錄到/usr/local/solr下
- Solr和solrhome建立聯繫:修改solr工程下的web.xml配置文件
- 修改solrhome地址
- 啓動tomcat
- 瀏覽器訪問solr
- 訪問成功出現如下界面
二.添加數據到索引庫
1.添加業務域到schema文件
2.添加中文分詞器
1. 上傳IK Analyzer 2012FF_hf1文件夾到服務器
2. 將IKAnalyzer2012FF_u1.jar添加到solr工程
3. 將ext_stopword.dic(停用詞典)、mydict.dic(擴展詞典)、IKAnalyzer.cfg.xml添加到類路徑下面
Solr工程下沒有classes目錄,需創建
複製文件到classes目錄下
3.定義業務域
Solrconfig.xml:solr服務的相關配置
Schema.xml定義solr所有使用的業務域
4.修改schema.xml配置文件
5.添加如下類容
6.測試配置的業務域是否生效
7.編寫sql語句從數據庫取出數據
8.搭建搜索服務工程
A.Taotao-search-interface
B.Taotao-search-service
需要在taotao-commom中創建SearchItem對象,
9.測試solrJ
10.在applicationContext-solr中配置SolrServer
11.完成接口及實現類
12.發佈服務
13. 後臺系統首頁添加索引庫管理
Import-index.jsp