版权所有,转载请注明原作者,仿冒侵权必究法律责任
日杂百货分销商城关键代码说明 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;
}
}
基于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
/***银联全渠道系统,产品参数,除了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 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
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
final HttpServletRequest request) {
Map
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
final HttpServletRequest request) {
Map
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>
配置支付宝的系统参数:
* *
*类名: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
Map
for (Iterator
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
转存失败重新上传取消 转存失败重新上传取消 转存失败重新上传取消
转存失败重新上传取消 转存失败重新上传取消 转存失败重新上传取消
页面回调
转存失败重新上传取消
提交订单的请求参数
转存失败重新上传取消
转存失败重新上传取消
首先到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>
<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("");
$(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:['江津市','合川市','永川市','南川市']}
]},
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>
FastDFS是C语言开发,建议在linux上运行,本项目使用Centos6.4作为安装环境。
安装FastDFS需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc:yum install gcc-c++
FastDFS依赖libevent库,需要安装:
yum -y install libevent
把五个文件都上传到/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下。
要拷贝的文件如下:
转存失败重新上传取消
将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
转存失败重新上传取消
[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
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下载。
转存失败重新上传取消
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); } } } |
nginx的安装细节参考nginx文档。
在每个tracker上安装nginx,的主要目的是做负载均衡及实现高可用。如果只有一台tracker服务器可以不配置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/
转存失败重新上传取消
[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/
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;
}
}
转存失败重新上传取消
说明:
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是c语言开发的。
安装redis需要c语言的编译环境。如果没有gcc需要在线安装。yum install gcc-c++
安装步骤:
第一步:redis的源码包上传到linux系统。
第二步:解压缩redis。
第三步:编译。进入redis源码目录。make
第四步:安装。make install PREFIX=/usr/local/redis
PREFIX参数指定redis的安装目录。一般软件安装到/usr目录下
前端启动:在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]#
[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
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的过期时间。
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的所有数据都是保存到内存中的。
Rdb:快照形式,定期把内存中当前时刻的数据保存到磁盘。Redis默认支持的持久化方案。
aof形式:append only file。把所有对redis数据库操作的命令,增删改操作的命令。保存到文件中。数据库恢复时把所有的命令执行一遍即可。
在redis.conf配置文件中配置。
Rdb:
转存失败重新上传取消
Aof的配置:
转存失败重新上传取消
两种持久化方案同时开启使用aof文件来恢复数据库。
需要把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(); } |
转存失败重新上传取消
目录结构说明
bin :solr命令
转存失败重新上传取消
Contrib:文件扩展包
dist:相关jar包及war包
examples:例子
转存失败重新上传取消
转存失败重新上传取消
转存失败重新上传取消
转存失败重新上传取消
查看控制台命令
转存失败重新上传取消
删除solr.war 需要注意:在tomcat启动时删除解压缩的solr目录也会被删除,在停止tomcat的时候删除solr.war,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
转存失败重新上传取消