第五届北大青鸟杯全国IT精英挑战赛中南&西南区域一等奖项目——日杂百货分销系统_关键代码说明书

第五届北大青鸟杯全国IT精英挑战赛中南&西南区域一等奖项目——日杂百货分销系统

                                                 关键代码说明书

                                                                                                                作者:武汉宏鹏田超凡

版权所有,转载请注明原作者,仿冒侵权必究法律责任

 

日杂百货分销商城关键代码说明 1

1.短信验证码功能的代码: 1

2.银联支付(接口api参考 银联api.txt 8

3.支付宝 20

4.QQ登录 32

    5.物流接口.............................................................................................................................37

    6.省市区下拉框联动..............................................................................................................38

    7.富文本编辑器UEditor.........................................................................................................41

    8.FastDFS+nginx图片服务器..................................................................................................26

    9.Redis+Jedis缓存..................................................................................................................27

    10.solr搜索引擎....................................................................................................................28

 

1.短信验证码功能的代码:

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 requestData = new HashMap();

 

/***银联全渠道系统,产品参数,除了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 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);

}

交易成功的响应报文:

uploading.4e448015.gif转存失败重新上传取消

交易失败会自动回调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 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 getAllRequestParam(

final HttpServletRequest request) {

Map res = new HashMap();

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 getAllRequestParamStream(

   final HttpServletRequest request) {

  Map res = new HashMap();

  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>CharsetEncodingFilterfilter-name>

    <filter-class>web.CharsetEncodingFilterfilter-class>

  filter>

  <filter-mapping>

    <filter-name>CharsetEncodingFilterfilter-name>

    <url-pattern>*.jspurl-pattern>

    <url-pattern>*url-pattern>

  filter-mapping>

  <servlet>

    <servlet-name>autoLoadServletservlet-name>

    <servlet-class>web.AutoLoadServletservlet-class>

    <load-on-startup>0load-on-startup>

  servlet>

  <servlet-mapping>

    <servlet-name>autoLoadServletservlet-name>

    <url-pattern>/autoLoadServleturl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>frontRcvResponseservlet-name>

    <servlet-class>com.unionpay.acp.demo.FrontRcvResponseservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>frontRcvResponseservlet-name>

    <url-pattern>/frontRcvResponseurl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>backRcvResponseservlet-name>

    <servlet-class>com.unionpay.acp.demo.BackRcvResponseservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>backRcvResponseservlet-name>

    <url-pattern>/backRcvResponseurl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_2_FrontConsumeservlet-name>

    <servlet-class>com.unionpay.acp.demo.consume.Form_6_2_FrontConsumeservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_2_FrontConsumeservlet-name>

    <url-pattern>/form_6_2_FrontConsumeurl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_5_Queryservlet-name>

    <servlet-class>com.unionpay.acp.demo.Form_6_5_Queryservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_5_Queryservlet-name>

    <url-pattern>/form_6_5_Queryurl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_3_ConsumeUndoservlet-name>

    <servlet-class>com.unionpay.acp.demo.consume.Form_6_3_ConsumeUndoservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_3_ConsumeUndoservlet-name>

    <url-pattern>/form_6_3_ConsumeUndourl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_4_Refundservlet-name>

    <servlet-class>com.unionpay.acp.demo.Form_6_4_Refundservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_4_Refundservlet-name>

    <url-pattern>/form_6_4_Refundurl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_6_FileTransferservlet-name>

    <servlet-class>com.unionpay.acp.demo.Form_6_6_FileTransferservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_6_FileTransferservlet-name>

    <url-pattern>/form_6_6_FileTransferurl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_7_1_AuthDeal_Frontservlet-name>

    <servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_1_AuthDeal_Frontservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_7_1_AuthDeal_Frontservlet-name>

    <url-pattern>/form_6_7_1_AuthDeal_Fronturl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_7_2_AuthUndoservlet-name>

    <servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_2_AuthUndoservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_7_2_AuthUndoservlet-name>

    <url-pattern>/form_6_7_2_AuthUndourl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_7_3_AuthFinishservlet-name>

    <servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_3_AuthFinishservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_7_3_AuthFinishservlet-name>

    <url-pattern>/form_6_7_3_AuthFinishurl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_7_4_AuthFinishUndoservlet-name>

    <servlet-class>com.unionpay.acp.demo.preauth.Form_6_7_4_AuthFinishUndoservlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_7_4_AuthFinishUndoservlet-name>

    <url-pattern>/form_6_7_4_AuthFinishUndourl-pattern>

  servlet-mapping>

  <servlet>

    <servlet-name>form_6_2_FrontConsume2servlet-name>

    <servlet-class>com.unionpay.acp.demo.consume.Form_6_2_FrontConsume2servlet-class>

  servlet>

  <servlet-mapping>

    <servlet-name>form_6_2_FrontConsume2servlet-name>

    <url-pattern>/form_6_2_FrontConsume2url-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 params = new HashMap();

Map requestParams = request.getParameterMap();

for (Iterator 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

uploading.4e448015.gif转存失败重新上传取消 uploading.4e448015.gif转存失败重新上传取消 uploading.4e448015.gif转存失败重新上传取消

 

 

 

 

uploading.4e448015.gif转存失败重新上传取消 uploading.4e448015.gif转存失败重新上传取消 uploading.4e448015.gif转存失败重新上传取消

页面回调

uploading.4e448015.gif转存失败重新上传取消

提交订单的请求参数

uploading.4e448015.gif转存失败重新上传取消

uploading.4e448015.gif转存失败重新上传取消

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(" + "/shuoshuoDemo.html" +  " target=\"_blank\">去看看发表说说的demo吧");

                // 利用获取到的accessToken 去获取当前用户的openid --------- end

 

 

                out.println("

start -----------------------------------利用获取到的accessToken,openid 去获取用户在Qzone的昵称等信息 ---------------------------- start

");

                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

    <servlet>

        <servlet-name>loginservlet-name>

        <servlet-class>com.qq.connect.demo.IndexServletservlet-class>

    servlet>

    <servlet-mapping>

        <servlet-name>loginservlet-name>

        

        <url-pattern>/login.dourl-pattern>

    servlet-mapping>

    <servlet>

        <servlet-name>afterloginservlet-name>

        <servlet-class>com.qq.connect.demo.AfterLoginRedirectServletservlet-class>

    servlet>

    <servlet-mapping>

        <servlet-name>afterloginservlet-name>

        

        <url-pattern>/afterlogin.dourl-pattern>

    servlet-mapping>

    <servlet>

        <servlet-name>shuoshuoservlet-name>

        <servlet-class>com.qq.connect.demo.ShuoShuoServletservlet-class>

    servlet>

    <servlet-mapping>

        <servlet-name>shuoshuoservlet-name>

        <url-pattern>/shuoshuo.dourl-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";

}

}

 

  1. 省市区下拉框联动

$(document).ready(function(){

      //联动加载二级市区

      $("[name='province']").change(function(){

         var province=$(this).val();

         

         $(this).next().empty();

         $(this).next().append("");

         $(this).next().next().empty();

         $(this).next().next().append("");

         for(var i=0;i

         {

            if(provinceList[i].name==province)

            {

               for(var j=0;j

               {

                  var city=provinceList[i].cityList[j];

                  $(this).next().append("+city.name+"");

               }

            }

         }

      });

      

      //联动加载三级县区域

      $("[name='city']").change(function(){

         var province=$(this).prev().val();

         var city=$(this).val();

 

         $(this).next().empty();

         $(this).next().append("");

         for(var i=0;i

         {

            if(provinceList[i].name==province)

            {

               for(var j=0;j

               {

                   if(provinceList[i].cityList[j].name==city)

                   {

                      for(var k=0;k

                      {

                         var area=provinceList[i].cityList[j].areaList[k];

                         $(this).next().append("+area+"");

                      }

                   }

               }

            }

         }

      });

   });

   

//页面加载立即执行,加载省市区三级联动

//加载一级省份

function loadProvider()

{

   $("[name='province']").empty();

   $("[name='province']").append("");

   for(var i=0;i

   {

      var province=provinceList[i];

      $("[name='province']").append("+province.name+"");

   }

}

 

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:['江津市','合川市','永川市','南川市']}

]},

 

  1. 富文本编辑器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>

    

    

<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>

 

  1. 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文件夹下

uploading.4e448015.gif转存失败重新上传取消

 

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下。

要拷贝的文件如下:

uploading.4e448015.gif转存失败重新上传取消

 

tracker编译安装

将FastDFS_v5.05.tar.gz拷贝至/usr/local/下

tar -zxvf FastDFS_v5.05.tar.gz

 

cd FastDFS

 

./make.sh

./make.sh install

uploading.4e448015.gif转存失败重新上传取消

安装成功将安装目录下的conf下的文件拷贝到/etc/fdfs/下。

uploading.4e448015.gif转存失败重新上传取消

uploading.4e448015.gif转存失败重新上传取消

 

配置

安装成功后进入/etc/fdfs目录:

uploading.4e448015.gif转存失败重新上传取消

 

拷贝一份新的tracker配置文件:

cp tracker.conf.sample tracker.conf

uploading.4e448015.gif转存失败重新上传取消

回车.

 

修改tracker.conf

vi tracker.conf

base_path=/home/yuqing/FastDFS   

改为:

base_path=/home/FastDFS

去home文件夹创建文件

uploading.4e448015.gif转存失败重新上传取消

[root@localhost home]# mkdir FastDFS

启动

/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart

第一次启动是以下画面

uploading.4e448015.gif转存失败重新上传取消

第二次启动

(实际环境不是5619)再启动,如下图:

uploading.4e448015.gif转存失败重新上传取消

uploading.4e448015.gif转存失败重新上传取消

注意:如果没有显示上图要注意是否正常停止原有进程。

 

  1. 设置开机自动启动。

[root@localhost fdfs]# vim /etc/rc.d/rc.local

 

 

 

 

 

将运行命令行添加进文件:/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart

uploading.4e448015.gif转存失败重新上传取消

配置

安装成功后进入 cd  /etc/fdfs目录:

uploading.4e448015.gif转存失败重新上传取消

拷贝一份新的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

创建目录

uploading.4e448015.gif转存失败重新上传取消

 

启动

/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

uploading.4e448015.gif转存失败重新上传取消

注意:如果没有显示上图要注意是否正常停止原有进程。

  1. 设置开机自动启动。

 

[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

 

uploading.4e448015.gif转存失败重新上传取消

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下载。

uploading.4e448015.gif转存失败重新上传取消

通过java Client API

Client.conf

uploading.4e448015.gif转存失败重新上传取消

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

uploading.4e448015.gif转存失败重新上传取消

进入到src目录

 

修改config文件将/usr/local/路径改为/usr/

uploading.4e448015.gif转存失败重新上传取消

复制文件

将FastDFS-nginx-module/src下的mod_FastDFS.conf拷贝至/etc/fdfs/下

 

[root@localhost src]# cp mod_fastdfs.conf /etc/fdfs/

uploading.4e448015.gif转存失败重新上传取消

修改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的解压目录执行以下代码.

uploading.4e448015.gif转存失败重新上传取消

 

./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

uploading.4e448015.gif转存失败重新上传取消

server {

        listen   80;

        server_name  192.168.177.139;

        location  /group1/M00/  {

                root /home/FastDFS/fdfs_storage/data;

                ngx_fastdfs_module;

        }

}

修改nginx的nginx.conf文件

uploading.4e448015.gif转存失败重新上传取消

 

 

说明:

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/

修改配置文件:

uploading.4e448015.gif转存失败重新上传取消

[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:

uploading.4e448015.gif转存失败重新上传取消

Aof的配置:

uploading.4e448015.gif转存失败重新上传取消

两种持久化方案同时开启使用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();

}

 

  1. Solr搜索引擎
  1. 上传solr安装包到服务器
  2. 解压缩

uploading.4e448015.gif转存失败重新上传取消

目录结构说明

bin :solr命令

uploading.4e448015.gif转存失败重新上传取消

Contrib:文件扩展包

dist:相关jar包及war包

examples:例子

uploading.4e448015.gif转存失败重新上传取消

 

  1. 安装tomcat到对应目录

uploading.4e448015.gif转存失败重新上传取消

  1. 将solr解压缩目录下的dist目录的solr工程部署到tomcat下面,并重命名为solr.war

uploading.4e448015.gif转存失败重新上传取消

  1. 进入到tomcat目录启动tomcat,solr war包自动解压缩

uploading.4e448015.gif转存失败重新上传取消

查看控制台命令

uploading.4e448015.gif转存失败重新上传取消

删除solr.war 需要注意:在tomcat启动时删除解压缩的solr目录也会被删除,在停止tomcat的时候删除solr.war,solr目录不会被删除

  1. 从solr解压缩目录的example目录下复制相关jar包到tomcat solr工程的lib包下

uploading.4e448015.gif转存失败重新上传取消

  1. 配置solrhome:从example目录下复制solr目录到/usr/local/solr下

uploading.4e448015.gif转存失败重新上传取消

  1. Solr和solrhome建立联系:修改solr工程下的web.xml配置文件

uploading.4e448015.gif转存失败重新上传取消

  1. 修改solrhome地址

uploading.4e448015.gif转存失败重新上传取消

  1. 启动tomcat

uploading.4e448015.gif转存失败重新上传取消

  1. 浏览器访问solr

uploading.4e448015.gif转存失败重新上传取消

  1. 访问成功出现如下界面

uploading.4e448015.gif转存失败重新上传取消

二.添加数据到索引库

1.添加业务域到schema文件

uploading.4e448015.gif转存失败重新上传取消

2.添加中文分词器

1. 上传IK Analyzer 2012FF_hf1文件夹到服务器

2. 将IKAnalyzer2012FF_u1.jar添加到solr工程

uploading.4e448015.gif转存失败重新上传取消

3. 将ext_stopword.dic(停用词典)、mydict.dic(扩展词典)、IKAnalyzer.cfg.xml添加到类路径下面

Solr工程下没有classes目录,需创建

uploading.4e448015.gif转存失败重新上传取消

复制文件到classes目录下

uploading.4e448015.gif转存失败重新上传取消

3.定义业务域

uploading.4e448015.gif转存失败重新上传取消

uploading.4e448015.gif转存失败重新上传取消

uploading.4e448015.gif转存失败重新上传取消

Solrconfig.xml:solr服务的相关配置

Schema.xml定义solr所有使用的业务域

4.修改schema.xml配置文件

uploading.4e448015.gif转存失败重新上传取消

5.添加如下类容

uploading.4e448015.gif转存失败重新上传取消

6.测试配置的业务域是否生效

uploading.4e448015.gif转存失败重新上传取消

7.编写sql语句从数据库取出数据

uploading.4e448015.gif转存失败重新上传取消

8.搭建搜索服务工程

A.Taotao-search-interface

B.Taotao-search-service

需要在taotao-commom中创建SearchItem对象,

9.测试solrJ

uploading.4e448015.gif转存失败重新上传取消

uploading.4e448015.gif转存失败重新上传取消

uploading.4e448015.gif转存失败重新上传取消

10.在applicationContext-solr中配置SolrServer

uploading.4e448015.gif转存失败重新上传取消

11.完成接口及实现类

uploading.4e448015.gif转存失败重新上传取消

12.发布服务

13. 后台系统首页添加索引库管理

uploading.4e448015.gif转存失败重新上传取消

Import-index.jsp

uploading.4e448015.gif转存失败重新上传取消

 

 

 

你可能感兴趣的:(JavaWeb项目)