标签:des style blog http color io os 使用 java
秒杀思路:后台根据商品加入秒杀发布秒杀详细信息,生成静态页面,发布信息添加到库,前台查看秒杀信息,
(我前台的概念是买家使用的系统为前台,公司内部使用的管理系统为后台),秒杀中库存和事件通过ajax
取服务器时间(客户端的时间不准),秒杀库存的统计已下单为主,库存数量的更改以下单为准,秒杀结束和下面《》里内容
就直接抛秒杀结束的静态页面.
《阻止秒杀请求,比如有一个商品,已经有100人在秒杀,前100人至少有一个人来买
正在秒杀的信息可以放入缓存(可以用开源的memcached等)【key:商品id,value:action请求统计数】
(只允许让产品数量的N倍以内的人请求秒杀可以通过配置文件判断)》
要参与秒杀的商品都放入缓存中,价格,库存,id,数量,加上一个字段 加上sell_num 卖出数量,缓存中存储是否
已经达到卖出数量,达到的话就直接抛出秒杀结束静态页面。支付的时候根据是否已卖出判断,商品的秒杀数量已经达到的话操作秒杀用户信息的操作事务回滚。先下单成功的去库中减1,保存用户支付信息
( action请求统计数可以单独弄服务器来做 这个action只做一件事情就是统计请求数量,用servlet就可以了,一台不行,弄多台)
秒杀:准点开抢,先抢先得。
页面上的操作流程大致是这样的:登录->填写用户资料->等待倒计时->弹出随机问题->填写答案->提交。
前两步人工完成,程序完成从等待倒计时到提交结束的步骤。主要使用httpclient模拟http请求。前期工作主要研究下原站的相关js代码,获得各步骤必要的URL和相关参数。其中还用到了坛子里的fastjson感谢一下 。
主要代码如下,就不做什么解释了。
一、题目
这是一个秒杀系统,即大量用户抢有限的商品,先到先得
用户并发访问流量非常大,需要分布式的机器集群处理请求
系统实现使用Java
二、模块设计
1、用户请求分发模块:使用Nginx或Apache将用户的请求分发到不同的机器上。
2、用户请求预处理模块:判断商品是不是还有剩余来决定是不是要处理该请求。
3、用户请求处理模块:把通过预处理的请求封装成事务提交给数据库,并返回是否成功。
4、数据库接口模块:该模块是数据库的唯一接口,负责与数据库交互,提供RPC接口供查询是否秒杀结束、剩余数量等信息。
第一部分就不多说了,配置HTTP服务器即可,这里主要谈谈后面的模块。
用户请求预处理模块:
经过HTTP服务器的分发后,单个服务器的负载相对低了一些,但总量依然可能很大,如果后台商品已经被秒杀完毕,那么直接给后来的请求返回秒杀失败即可,不必再进一步发送事务了,示例代码可以如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package seckill; import org.apache.http.HttpRequest; /** * 预处理阶段,把不必要的请求直接驳回,必要的请求添加到队列中进入下一阶段. */ public class PreProcessor { // 商品是否还有剩余 private static boolean reminds = true; private static void forbidden() { // Do something. } public static boolean checkReminds() { if (reminds) { // 远程检测是否还有剩余,该RPC接口应由数据库服务器提供,不必完全严格检查. if (!RPC.checkReminds()) { reminds = false; } } return reminds; } /** * 每一个HTTP请求都要经过该预处理. */ public static void preProcess(HttpRequest request) { if (checkReminds()) { // 一个并发的队列 RequestQueue.queue.add(request); } else { // 如果已经没有商品了,则直接驳回请求即可. forbidden(); } } } |
并发队列的选择
Java的并发包提供了三个常用的并发队列实现,分别是:ConcurrentLinkedQueue 、 LinkedBlockingQueue 和 ArrayBlockingQueue。
ArrayBlockingQueue是初始容量固定的阻塞队列,我们可以用来作为数据库模块成功竞拍的队列,比如有10个商品,那么我们就设定一个10大小的数组队列。
ConcurrentLinkedQueue使用的是CAS原语无锁队列实现,是一个异步队列,入队的速度很快,出队进行了加锁,性能稍慢。
LinkedBlockingQueue也是阻塞的队列,入队和出队都用了加锁,当队空的时候线程会暂时阻塞。
由于我们的系统入队需求要远大于出队需求,一般不会出现队空的情况,所以我们可以选择ConcurrentLinkedQueue来作为我们的请求队列实现:
1 2 3 4 5 6 7 8 9 10 11 |
package seckill; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.http.HttpRequest; public class RequestQueue { public static ConcurrentLinkedQueue<HttpRequest> queue = new ConcurrentLinkedQueue<HttpRequest>(); } |
用户请求模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package seckill; import org.apache.http.HttpRequest; public class Processor { /** * 发送秒杀事务到数据库队列. */ public static void kill(BidInfo info) { DB.bids.add(info); } public static void process() { BidInfo info = new BidInfo(RequestQueue.queue.poll()); if (info != null) { kill(info); } } } class BidInfo { BidInfo(HttpRequest request) { // Do something. } } |
数据库模块:
数据库主要是使用一个ArrayBlockingQueue来暂存有可能成功的用户请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package seckill; import java.util.concurrent.ArrayBlockingQueue; /** * DB应该是数据库的唯一接口. */ public class DB { public static int count = 10; public static ArrayBlockingQueue<BidInfo> bids = new ArrayBlockingQueue<BidInfo>(10); public static boolean checkReminds() { // TODO return true; } // 单线程操作 public static void bid() { BidInfo info = bids.poll(); while (count-- > 0) { // insert into table Bids values(item_id, user_id, bid_date, other) // select count(id) from Bids where item_id = ? // 如果数据库商品数量大约总数,则标志秒杀已完成,设置标志位reminds = false. info = bids.poll(); } } } |
三、结语
看起来大体这样应该就可以了,当然还有细节可以优化,比如数据库请求可以都做成异步的等等。
昨天晚上睡觉的时候还在想这个秒杀,还是发现了一些问题,一个在秒杀商品共享一个action,
1:每个商品的秒杀用户都可能不同,都会变化,一起秒杀过来,怎么让秒杀同一个商品的共享同一个action
2:什么时候开始对USER_NUM开始递增,根据客户端时间显然不行,调度?还是每次请求都判断下时间?
解释下为什么要同一个商品要共享一个action:用户数不是确定的 秒杀这个商品的人肯定得共享这个商品的action,为了知道USER_NUM是否已经超过允许的,不允许的话直接抛出秒杀结束静态页面。有多少的秒杀商品就应该有多少的action实例,请求的这个商品的秒杀就是请求这个商品对应的action,但是参与秒杀的商品数不是固定的。该如何设计action,这样的需求怎么配置???秒杀这玩意儿还真的很麻烦,你妹的,看来这样的action无法配置,那就所有用户共同用一个action,放一个map, key:商品ID,value:请求数。这个商品有请求的话就放入map,重新put(商品id,请求+1)每次请求判断下该商品的时间,到了时间就对该商品的请求数进行+1操作
网络误差:请求action的到操作库的时间 可能会导致超过了秒杀结束时
主要的问题
1共同问题:宽带问题
2 服务器端的问题:1:web服务器所在的PC硬件配置 2 web服务器的处理能力 3 数据库服务器的处理能力
用户的问题:1 用户PC配置问题 2 用户所使用的浏览器(用IE就是等死) 3 用户对秒杀点击的及不及时问题
前台对于秒杀时间问题显示问题:加载静态页面用ajax 请求服务器,获取服务器时间当前时间和开始时间,结束时间,
然后页面秒杀的时间就根据第一次请求的时间用js处理
一个文章不错,贴上来:javascript实现秒杀倒计时
被秒杀过的商品数据直接转入历史库,原表不存该数据,减少查询时间,秒杀关注的是未来或者正在秒杀的商品,历史已成为过去,只是查看。
秒杀这东西我感觉都是虚头,刚好那一秒 0 微妙 如此精确的时间,这个时间点可能真的没人在0微妙 秒杀到,那肯定还有要让一个人秒杀到的,估计很多是选这一秒内的随机数,或者这一秒的第一个人。如果以提交订单为主那就谁先提交谁先得到。
所有问题都已解决,网络延迟,这个问题我们这个真心没办法
秒杀seckill大致接口:
前台就是请求静态页面查看,ajax查询动态信息,比如库存,秒杀时间
1:查询秒杀分类信息接口(包括全部秒杀,aa秒杀,bb秒杀,价格段秒杀)
2:搜索秒杀接口
3:秒杀详细内页接口
4: 秒杀剩余时间接口
5: 跳转秒杀结束静态页面接口
6:查询秒杀开始结束和当前服务器时间接口
7:查询已卖出数接口
8: 查询秒杀缓存接口
9: 修改秒杀缓存接口
10:删除秒杀缓存接口
后台:
1:商品加入秒杀接口(同时添加到缓存中)
2:秒杀分类管理接口
3:修改详细秒杀信息接口
4:删除详细秒杀信息接口(转入历史库)
5:静态页面生成接口
6:历史秒杀管理接口
7:秒杀搜索接口
8:请求配置(配置商品的N倍才可请求秒杀)
9:审核接口
欢迎讨论秒杀合理性,缺点等,谢谢
高并发,cache,锁机制函数用synchronized修饰,数据库先插入在判断是否到达秒杀最大人数,cache记录本次秒杀是否完成.
没深入研究过,不过参与过淘宝的双11活动。很明显的一点是商品没有提供一个非常即时的锁,即便商品实际没有了也是可以下单成功的。但是在支付的时候会提示你商品没有了。猜测只是在支付的时候才有即时的锁。如果都使用锁的话,效率可能会有问题。秒杀的PV一般都会相当高
简单介绍下功能
1.每隔一段时间(比如1分钟)在京东手机每日一秒杀页面提取产品(手机)链接。
http://sale.360buy.com/act/8VTHFGr10CjMDyZ.html#01
2.根据提取到得产品链接给后台发送数据,以便获取产品价格,描述,折扣,库存(是否有货)等信息。
3.根据得到的信息,进行判断。
若符合条件自动调用浏览器(前提是chrome加入环境变量,或者改代码将浏览器.exe路径加入代码,修改程序)打开产品订购页面。
4.其实也就解决了一个问题:不用自己频繁的刷新网页了,不用自己查看;
登陆,提交订单还得浏览器解决(貌似这几个功能点比较复杂,没做处理)
程序做的不太完善:
运行前需要修改几个地方:
1.环境变量:chrome 加入浏览器变量,以便调用。。或者自己修改源代码用其它方式打开。
2.活动中每个产品的价格信息需要设置。这个比较不好,必须修改源代码。
修改的地方在filter()这个函数里。
3.另外一个需要修改的地方是
hasStore(String skuidkey)
address="http://price.360buy.com/stocksoa/StockHandler.ashx?callback=getProvinceStockCallback&type=pcastock&skuid="+skuidkey+"&provinceid=1&cityid=2800&areaid=2850";
这个地方的cityid=2800&areaid=...地里位置信息。这个没做处理。需要从手机产品页自己搞出来。
其实也比较简单。chrome+F12 ,修改“城市”,区域等信息后,会看到一个get请求发送到后台,这个链接里面包含了需要的信息。(http://price.360buy.com/stocksoa/StockHandler.ashx?callback=getProvinceStockCallback&type=pcastock&skuid=64EBD0F20F593D95C72C6EED59B64658&provinceid=1&cityid=2805&areaid=2854)适当修改。
Util.java
import java.util.ArrayList;
public class Util {
public static void print(Object o){
System.out.print(o);
}
public static void println(Object o){
if(null==o)
System.out.println();
else
System.out.println(o);
}
public static ArrayList<Integer> toArrayList(int[] ints){
if(ints.length==0)
return null;
ArrayList<Integer> al=new ArrayList<Integer>();
for(int i=0;i<ints.length;i++){
al.add(ints[i]);
}
return al;
}
}
Miaosha360buy.java
public class Miaosha360buy {
java.util.concurrent.CountDownLatch t= new java.util.concurrent.CountDownLatch(1);
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName() + "开始");
Miaosha360buy ms360=new Miaosha360buy();
new ThreadOne360buy(ms360.t).start();
while(true){
try {
ms360.t.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Thread.sleep(1000*60);//间隔1分钟调用一次?
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ms360.t=new java.util.concurrent.CountDownLatch(1);
new ThreadOne360buy(ms360.t).start();
System.out.println("New Tread in while..");
}
}
}
Miaosha360buy.java
public class Miaosha360buy {
java.util.concurrent.CountDownLatch t= new java.util.concurrent.CountDownLatch(1);
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName() + "开始");
Miaosha360buy ms360=new Miaosha360buy();
new ThreadOne360buy(ms360.t).start();
while(true){
try {
ms360.t.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Thread.sleep(1000*60);//间隔1分钟调用一次?
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ms360.t=new java.util.concurrent.CountDownLatch(1);
new ThreadOne360buy(ms360.t).start();
System.out.println("New Tread in while..");
}
}
}
ThreadOne360buy.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import view.Util.Util;
public class ThreadOne360buy extends Thread{
java.util.concurrent.CountDownLatch c;
ArrayList al;//记录秒杀产品页面
float price=0.0f;//商品价格
float discount=0.0f;//商品折扣
//用于保存线程信息,在这个项目里用处不大
private static List<Thread> runningThreads = new ArrayList<Thread>();
//这个是一个计数器(不太会用,线程这方面一直感觉是比较复杂的)
public ThreadOne360buy(java.util.concurrent.CountDownLatch c) {
this.c=c;
}
@Override
public void run() {
regist(this);// 线程开始时注册
// 打印开始标记
System.out.println(Thread.currentThread().getName() + "开始...");
try {
//抓取京东手机秒杀页面
this.getMessage("http://sale.360buy.com/act/8VTHFGr10CjMDyZ.html#01");
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
c.countDown();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
c.countDown();
}
c.countDown();
unRegist(this);// 线程结束时取消注册
// 打印结束标记
System.out.println(Thread.currentThread().getName() + "结束.");
}
public void regist(Thread t) {
synchronized (runningThreads) {
runningThreads.add(t);
}
}
public void unRegist(Thread t) {
synchronized (runningThreads) {
runningThreads.remove(t);
}
}
public static boolean hasThreadRunning() {
// 通过判断runningThreads是否为空就能知道是否还有线程未执行完
return (runningThreads.size() > 0);
}
/**
* 从手机秒杀页面获取 prodcut链接,product skuid,skuidkey,price,store信息
* @param url:手机秒杀页面
* @throws ClientProtocolException
* @throws IOException
*/
public void getMessage(String url) throws ClientProtocolException, IOException{
al=getMainUrl(down(url));
Util.println(al);
if(al.size()==0){
c.countDown();
System.exit(0);
return;
}
for(int i=0;i<al.size();i++){
StringBuffer sb=new StringBuffer();
StringBuffer openUrl = new StringBuffer();
openUrl.append("http://www.360buy.com/product/");
openUrl.append(al.get(i).toString().subSequence(al.get(i).toString().lastIndexOf(‘/‘)+1, al.get(i).toString().lastIndexOf(‘.‘)));
openUrl.append(".html");
// 557673
sb.append("http://d.360buy.com/fittingInfo/get?skuId=");
sb.append(al.get(i).toString().subSequence(al.get(i).toString().lastIndexOf(‘/‘)+1, al.get(i).toString().lastIndexOf(‘.‘)));
sb.append("&callback=Recommend.cbRecoFittings");
Util.println(sb.toString());
//map中保存的是产品name,price,折扣信息
Util.println("Al("+i+") down:"+sb.toString());
HashMap<String, String> hm=parseProduct(down(sb.toString()));
//用来匹配价格信息。匹配库存信息
filter(hm,openUrl.toString());//过滤价格,如果条件符合就打开浏览器
}
}
/**
* 一个验证方法
* @param hm 保存着价格信息
* @param url 产品页面
*/
public void filter(HashMap<String, String> hm,String url){//url既是产品页面
// view.Util.oenCMD.openWinExe(null,url);
// 是不是应该先查看库存?
String skuidkey=parseSkuidkey(url);
if(!hasStore(skuidkey)){
Util.println("-------------------------------------");
Util.println("没有库存了!");
Util.println("-------------------------------------");
//减掉计数,以便主线程判断
c.countDown();
//应该结束子线程哦?
return;
}
if(hm.get("skuid").equals("201602")){//判断//摩托罗拉skuid=201602
//这里的价格是写死了,运行前得改过来才行。
this.setPrice(499.0f);
//是不是应该打开控制台?
if(Float.parseFloat(hm.get("price"))<=this.getPrice()){
view.Util.oenCMD.openWinExe(null,url);
}
}else if(hm.get("skuid").equals("675647")){//天语skuid=675647
// //这里的价格是写死了,运行前得改过来才行。
// this.setPrice(699.0f);
// //是不是应该打开控制台?
// if(Float.parseFloat(hm.get("price"))<=this.getPrice()){
// view.Util.oenCMD.openWinExe(null,url);
// }
}
}
/**
* 解析了产品页面中name,skuid,price信息
* @param doc
* @return
*/
public static HashMap<String, String> parseProduct(Document doc){
String text=doc.text();
String docc=text.substring(text.indexOf("master")+9,text.indexOf("fittings")-3).replaceAll("[\\s]", "");
String[] ss=docc.split(",");
HashMap<String, String> hm=new HashMap<String, String>();
for(String it: ss){
String string=it.replaceAll("\"", "");
if(string.contains("\\u"))
string=unicodeDecode(string);
String[] str=string.split(":");
hm.put(str[0], str[1]);
}
Util.println(hm);
return hm;
}
/**
* 处理unicode字符,转换成显示字符(汉字),不太通用
* @param it: \u6a5d
* @return
*/
public static String unicodeDecode(String it){//有个缺点,就是前面的字符无法去掉
Util.println(it);
String regex="(\\\\u[0-9a-f]{4})";
Pattern pt= Pattern.compile(regex);
Matcher mc;
StringBuffer sb;
StringBuffer sba=new StringBuffer();
mc=pt.matcher(it);
while(mc.find()){
sb=new StringBuffer();
mc.appendReplacement(sba,sb.append((char )Integer.parseInt((mc.group(1).substring(2)), 16)).toString());
}
return sba.toString();
}
/**
* 返回文档对象(下载内容)
* @param url 下载页面
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static Document down(String url) throws ClientProtocolException, IOException{
Document doc = null;
DefaultHttpClient httpClient=new DefaultHttpClient();
Util.println("DownLoad:"+url);
HttpGet get=new HttpGet(url);
HttpResponse response;
response = httpClient.execute(get);
HttpEntity entity = response.getEntity();
doc = Jsoup.parse(entity.getContent(), "utf-8","");
//释放资源
EntityUtils.consume(entity);
//关闭连接
httpClient.getConnectionManager().shutdown();
return doc;
}
/**
* 加入了编码控制信息
* @param url 待下载页面
* @param code 编码
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static Document down(String url,String code) throws ClientProtocolException, IOException{
Document doc = null;
DefaultHttpClient httpClient=new DefaultHttpClient();
Util.println("DownLoad:"+url);
HttpGet get=new HttpGet(url);
HttpResponse response;
response = httpClient.execute(get);
HttpEntity entity = response.getEntity();
doc = Jsoup.parse(entity.getContent(), code,"");
//释放资源
EntityUtils.consume(entity);
//关闭连接
httpClient.getConnectionManager().shutdown();
return doc;
}
/**
* 用来解析 秒杀页面中的产品(收集)链接
* @param doc
* @return
*/
public static ArrayList<String> getMainUrl(Document doc){
if(doc.equals("")||doc==null)
return null;
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ArrayList<String> urls=new ArrayList<String>();
String rule="map[name=Map] >area[href~=product]";
/**
* 开始解析
*/
Elements elements=doc.select(rule);
for (Element e : elements) {
// Util.println(e.absUrl("abs:href"));
urls.add(e.absUrl("abs:href"));
}
return urls;
}
/**
* 获取skuidkey,用于查询商品库存信息
* @param url
* @return
*/
public static String parseSkuidkey(String url){
Document doc=null;
try {
doc=down(url,"gb2312");
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Util.println(doc.select("script"));
String text = null;
for(Element e : doc.select("script")){
if(e.data().contains("skuidkey:")){
text=e.data();
break;
}
}
//skuidkey:‘7D45919EA8242511DAA5CC7C6D7B351C‘
text=text.substring(text.indexOf("skuidkey:")+10, text.indexOf("skuidkey:")+42);
Util.println("---------------------------------");
Util.println(text);
return text;
}
/**
* 查看库存信息
* @param skuidkey
* @return
*/
public static boolean hasStore(String skuidkey){//这个地方没有处理,直接提取浏览器中的信息
String address = null;
boolean hasStore=false;
if(skuidkey!=null && !"".equals(skuidkey))
address="http://price.360buy.com/stocksoa/StockHandler.ashx?callback=getProvinceStockCallback&type=pcastock&skuid="+skuidkey+"&provinceid=1&cityid=2800&areaid=2850";
else{
Util.println("解析skuidkey错误");
}
try {
if(parseStore(down(address))){
hasStore=true;
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return hasStore;
}
/* if(array[1]=="34"||array[1]=="18"){
changeCart(false);
djdarea.stockInfoDom.html("<strong class=‘store-over‘>无货</strong>");
}
else if(array[1]=="0"){
changeCart(false);
djdarea.stockInfoDom.html("<strong class=‘store-over‘>无货</strong>");
}
else if(array[2]=="0"&&array[4]!="2"){
changeCart(false);
djdarea.stockInfoDom.html("很抱歉,该商品无法送至您选择的区域");
}
else if(array[1]=="33"||array[1]=="5"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>现货</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
else if(array[1]=="36"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>预订</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
else if(array[1]=="39"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>在途</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
else if(array[1]=="40"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>可配货</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
*/
/**
* 解析库存信息
* @param doc
* @return
*/
public static boolean parseStore(Document doc){
String text=doc.text();
String docc=text.substring(text.indexOf("-")-1,text.lastIndexOf(",")-1);
Util.println(docc);
String[] store=docc.split("-");
if(store[1].equals("34") || store[1].equals("18")){
//无货
Util.println("此地无货");
return false;
}else if(store[1].equals("33") || store[1].equals("5")){
//现货
Util.println("此地现货");
return true;
}
Util.println(store[1]);
return false;
}
//几个bean方法
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public float getDiscount() {
return discount;
}
public void setDiscount(float discount) {
this.discount = discount;
}
}
oenCMD.java
public class oenCMD {
// public static void main(String[] args) {
//// openWinExe(null);
// openExe(null,"http://www.baidu.com");
// }
//用 Java 调用windows系统的exe文件,比如notepad,calc之类
public static void openWinExe(String command,String url) {
if(command==null ||command.equals("")){
command = "chrome "+url;
}
Runtime rn = Runtime.getRuntime();
Process p = null;
try {
p = rn.exec(command);
} catch (Exception e) {
System.out.println("Error win exec!");
}
}
//调用其他的可执行文件,例如:自己制作的exe,或是 下载 安装的软件.
public static void openExe(String pathAndName,String url) {
if(pathAndName==null || pathAndName.equals("")){
pathAndName="C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe";
}
if(url!=null && !url.equals("")){
pathAndName+=" ";
pathAndName+=url;
}
Runtime rn = Runtime.getRuntime();
Process p = null;
try {
p = rn.exec(pathAndName);
} catch (Exception e) {
System.out.println("Error exec!");
}
}
}
标签:des style blog http color io os 使用 java
原文地址:http://my.oschina.net/u/1398304/blog/314101