用Java Servlet构建旗帜广告系统

  对于一个商务网站来说,广告系统是必不可少的。一个好的广告系统是一个网站稳定收入的基础。而旗帜广告(banner)则是网站广告中占绝大部分的广告,因此开发一个旗帜广告系统就非常重要了。利用Java Servlet我们可以很轻松的构建属于我们自己的旗帜广告系统。
  我们一般在网页上放上一些图片,设置它们的链接指向广告客户的网页,然后产生日志文件存放浏览的人数,浏览者的IP等信息,这就是开发旗帜广告系统的一般思路。
  下面,我想结合一个例程来介绍一下如何使用Java Servlet来构建旗帜广告系统。这下面这个例子中,你必须使用在你的HTML文件中使用<IMG>标签。
  用法有三种是:
  1)Banner?config_file或Banner?config=config_file
  例如:
  <IMG height=125 src="http://localhost/servlet/Banner?config_file"width=125>
  用这种方法你就可以显示不同的图片了。
  2)你也可以为每一幅图片设置自己的重定向URL。只需在你的设置中添加文件描述,见下面的例子,Servlet也需要更多的描述参数:
  <IMG height=60 src="http://localhost/servlet/Banner?config=config_file&mode=1"width=468>
  这样你就可以支持标准的旗帜广告了。
  3)你也可以在同一个页面上有多个旗帜广告。你只需要在参数中加入“id=某个整数值”就可以了。这个值必须是一个你的页面内唯一的整数值!例如,对于第一个banner的描述为:
  <IMG height=60 src="http://localhost/servlet/Banner?config=config_file&mode=1&id=1"width=468>
  第二个为:
  <IMG height=125 src="http://localhost/servlet/Banner?config=config_file&mode=1&id=2"width=125>
  有的朋友会问了,config_file是什么文件呀?它是一个文本文件,用来描述Servlet的设置信息。你能在你的主机的任何地方保存这个文件。现把参数介绍一下,这个配置文件有三个参数:分别为
  1、dir=some_directory
  解释:dir是你的旗帜广告文件存放的目录,可以使用的图片格式有JPG,GIF,PNG,JPEG等。这个参数是必须有的,否则系统会报错。
  2、bannerfilename=some_url
  解释:banner文件使用下面的格式,例如:
  banner.gif=http://www.yesky.com/
  banner.jpg=http://www.yesky.com/
  3、log=some_directory_to_store_log_file
  解释:存放日志文件的目录,可以是服务器上的任何目录。
  附录1、日志文件(log file)及格式
  Banner系统每天会自动产生两个日志文件。分别为ddmmyyyyv.txt和ddmmyyyyc.txt。第一个文件保存浏览banner的记录,第二个文件保存重定向的记录。两个文件都是文本文件,每一行包括一条记录。纪录格式是:
  IP地址日期图片文件用户代理重定向记录(只用于*c.txt文件),字段之间用空格隔开。
  附录2、Banner.java源程序:
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  public class Banner extends HttpServlet
  {
  public Banner(){}
  //读取配置文件内容
  private boolean readConfig(String sConfig,Hashtable hashtable)
  {
  try
  {
  BufferedReader bufferedreader=new BufferedReader(new InputStreamReader(new FileInputStream(sConfig)));//设置缓冲区读入一个配置文件
  String sLineInformation1;//
  while((sLineInformation1=bufferedreader.readLine())!=null)
  {
  sLineInformation1=sLineInformation1.trim();//去除字符串中的空格
  if(sLineInformation1.length()>0)//如果字符串sLineInformation1的长度大于零{
  int i=sLineInformation1.indexOf("=");
  if(i>0&&i<sLineInformation1.length()-1&&sLineInformation1.charAt(0)!="#"&&!sLineInformation1.startsWith("//"))//配置文件的每一行参数必须以不为#或//开头的字符串
  hashtable.put(sLineInformation1.substring(0,i).trim().toLowerCase(),sLineInformation1.substring(i+1).trim());
  }
  }
  bufferedreader.close();
  File file=new File(sConfig);//创建一个配置文件
  hashtable.put("edited",String.valueOf(file.lastModified()));
  }
  catch(Exception _ex)
  {
  return false;
  }
  String sDirInfo2=(String)hashtable.get("dir");//取得目录参数
  if(sDirInfo2!=null)//如果目录参数是空值
  {
  if(!sDirInfo2.endsWith(separator))//如果sDirInfo2不是以分隔符结尾,那么
  {
  sDirInfo2=sDirInfo2+separator;//给sDirInfo2加上分隔符
  hashtable.remove("dir");//移去哈希表变量中的dir
  hashtable.put("dir",sDirInfo2);
  }
  File file1=new File(sDirInfo2);
  String as[]=file1.list();
  if(as==null){
  hashtable.remove("dir");
  }
  sDirInfo2=(String)hashtable.get("log");
  if(sDirInfo2!=null)
  {
  if(!sDirInfo2.endsWith(separator))
  {
  sDirInfo2=sDirInfo2+separator;
  hashtable.remove("log");
  hashtable.put("log",sDirInfo2);
  }
  File file2=new File(sDirInfo2);
  String as1[]=file2.list();
  if(as1==null){
  hashtable.remove("log");
  }
  return true;
  }
  private Hashtable getConfig(String s)//取得配置
  {
  Hashtable hashtable=(Hashtable)cfgs.get(s);
  if(hashtable!=null)//如果配置不为空
  try
  {
  String s1=(String)hashtable.get("edited");
  File file=new File(s);
  if(!s1.equals(String.valueOf(file.lastModified()))){
  //如果s1的值不等于文件最后一次修改的值,则hashtable的内容为空值
  hashtable=null;
  }
  catch(Exception _ex)//捕获Exception _ex错误
  {
  hashtable=null;
  }
  if(hashtable!=null)
  return hashtable;
  hashtable=new Hashtable();
  if(!readConfig(s,hashtable))
  {
  return null;
  }
  else
  {
  cfgs.put(s,hashtable);
  return hashtable;
  }
  }
  public void init(ServletConfig servletconfig)//初始化配置参数
  throws ServletException{
  //如果出错,抛出一个ServletException错误
  super.init(servletconfig);
  separator=System.getProperty("file.separator");//取得分隔符
  cfgs=new Hashtable();//设置配置变量
  logs=new Hashtable();//设置日志变量
  System.out.println("?Wayne Zheng");//屏幕输出我的邮箱地址
  }
  public void destroy()
  {
  }
  public void doPost(HttpServletRequest request,HttpServletResponse response)
  //发送POST请求
  throws ServletException,IOException
  {doGet(request,response);}
  public void doGet(HttpServletRequest httpservletrequest,HttpServletResponse httpservletresponse)//读取GET
  throws ServletException,IOException
  {
  String strConfig=httpservletrequest.getQueryString();
  //读取请求字符串
  if(strConfig==null)//如果字符串为空
  strConfig="";//那么设置strConfig为空
  if(strConfig.length()==0)
  //如果strConfig长度为零,那么显示错误信息
  {
  errorMessage("无配置信息!",httpservletresponse);
  return;
  }
  String strConfig1=getFromQuery(s,"config=");//同上
  if(strConfig1.length()==0){
  strConfig1=strConfig;
  Hashtable hashtable=getConfig(strConfig1);
  if(hashtable==null)
  {
  errorMessage("配置信息错误!",httpservletresponse);
  return;
  }
  if(hashtable.get("dir")==null)
  //如果哈希表中dir为空值,则输出错误信息
  {
  errorMessage("不能打开数据目录",httpservletresponse);
  return;
  }
  String strConfigMode2=getFromQuery(strConfig,"mode=");//读取配置中的mode值
  if(strConfigMode2.length()==0){//如果没有mode值
  strConfigMode2="1";//则设mode值为1
  String strConfigId3=getFromQuery(strConfig,"id=");//读取配置中的id值
  if(strConfigId3.length()==0){file://如果没有id值
  strConfigId3="1";//则设id值为1
  HttpSession httpsession=httpservletrequest.getSession(true);
  if(strConfigMode2.equals("1"))
  file://如果strConfigMode2的值为1,则显示banner广告
  {
  showBanner(hashtable,strConfigId3,httpsession,httpservletrequest,httpservletresponse);
  return;
  }
  else//否则转向banner所指的站点
  {
  goToSite(hashtable,strConfigId3,httpsession,httpservletrequest,httpservletresponse);
  return;
  }
  }
  private void goToSite(Hashtable hashtable,String s,HttpSession httpsession,HttpServletRequest httpservletrequest,HttpServletResponse httpservletresponse)//转向站点
  throws IOException//如果有任何错误,抛出IOException错误
  {
  String sitename1;//定义站点名
  if(httpsession==null)//如果httpsession为空
  {
  sitename1=getFirstSite(hashtable);//站点名为哈希表中的第一个站点名
  }
  else//否则
  {
  Hashtable hashtable1=(Hashtable)httpsession.getValue("旗帜广告系统,Wayne Zheng");
  if(hashtable1==null){//如果哈希表hashtable1为空值,则
  sitename1=getFirstSite(hashtable);//站点名为哈希表(hashtable)中的第一个站点名
  else
  sitename1=(String)hashtable1.get(s);
  }
  if(sitename1==null)
  //如果站点名为空值则站点名为默认值http://www.yesky.com
  sitename1="http://www.yesky.com";
  String s2;
  if(hashtable.get("log")!=null&&(s2=getFileByUrl(hashtable,s1))!=null){
  writeLog(hashtable,s2,sitename1,"c",httpservletrequest);
  httpservletresponse.sendRedirect(sitename1);
  }
  private void showBanner(Hashtable hashtable,String s,HttpSession httpsession,HttpServletRequest httpservletrequest,HttpServletResponse httpservletresponse)
  throws IOException
  {
  String s1=(String)hashtable.get("dir");
  File file=new File(s1);
  Vector vector;
  if(file==null)
  {
  vector=new Vector();
  }
  else
  {
  String as[]=file.list();
  vector=getGraphFiles(as);
  }
  if(vector.size()==0)
  {
  httpservletresponse.setContentType("text/html");
  PrintWriter out=httpservletresponse.getWriter();
  out.println("目录是空的!");
  out.flush();
  out.close();
  return;
  }
  int i;
  if(httpsession!=null)
  synchronized(hashtable.get("dir"))
  {
  Integer integer;
  int j;
  if((integer=(Integer)httpsession.getValue("bi"))==null){
  j=0;
  else
  j=integer.intValue();
  if(j>=vector.size()){
  j=0;
  i=j;
  if(++j>=3){
  j=0;
  httpsession.putValue("bi",new Integer(j));
  }
  else
  i=0;
  String s2=(String)vector.elementAt(i);
  String s3;
  if(httpsession!=null&&(s3=getUrl(hashtable,s2))!=null)
  {
  Hashtable hashtable1;
  if((hashtable1=(Hashtable)httpsession.getValue("旗帜广告系统,Wayne Zheng"))==null){
  hashtable1=new Hashtable();
  hashtable1.put(s,s3);
  httpsession.putValue("旗帜广告系统,Wayne Zheng",hashtable1);
  }
  if(hashtable.get("log")!=null){
  writeLog(hashtable,s2,"v",httpservletrequest);
  outputBanner(s2,hashtable,httpservletresponse);
  vector=null;
  }
  private void writeLog(Hashtable logHashtable,String logString,String logString1,String logString2,HttpServletRequest httpservletrequest)//写日志的函数
  {
  String logString3=(String)hashtable.get("log");
  String logString4=getLogString(logString,httpservletrequest)+"\""+logString1+"\"";
  GregorianCalendar gregoriancalendar=new GregorianCalendar();
  //获取当前的时间
  gregoriancalendar.setTime(new Date());
  String logString5=logString3+stringDate(gregoriancalendar)+logString2+".txt";//以时间戳和“c”或“v”为文件名来写日志文件
  saveLog(hashtable,logString5,logString4);
  }
  private void writeLog(Hashtable logHashtable,String logString,String logString1,HttpServletRequest httpservletrequest)file://写日志文件
  {
  String logString2=(String)logHashtable.get("log");
  String logString3=getLogString(logString,httpservletrequest);
  GregorianCalendar gregoriancalendar=new GregorianCalendar();
  gregoriancalendar.setTime(new Date());
  String logString4=logString2+stringDate(gregoriancalendar)+logString1+".txt";
  saveLog(logHashtable,logString4,logString3);
  }
  private void saveLog(Hashtable hashtable,String s,String s1)//把日志文件保存在硬盘上
  {
  synchronized(hashtable.get("log"))
  {
  try
  {
  FileWriter filewriter=new FileWriter(s,true);
  PrintWriter printwriter=new PrintWriter(filewriter);
  printwriter.println(s1);
  printwriter.flush();
  printwriter.close();
  filewriter.close();
  }
  catch(Exception _ex){}
  }
  }
  private String getLogString(String s,HttpServletRequest httpservletrequest)
  //取得日志字符串
  {
  String s1=httpservletrequest.getRemoteAddr();
  //取得远程的访问者的IP地址
  String s2=httpservletrequest.getHeader("User-Agent");
  String s3=httpservletrequest.getHeader("Referer");
  String s4="\""+s+"\"";
  if(s1==null)
  s1="-";
  if(s2==null)
  s2="-";
  else
  s2="\""+s2+"\"";
  if(s3==null)
  s3="-";
  else
  s3="\""+s3+"\"";
  return s1+"["+new Date()+"]"+s4+""+s3+""+s2;
  }
  private String stringDate(Calendar calendar)//取得时间戳
  {
  String s=String.valueOf(calendar.get(1));
  String s1=String.valueOf(calendar.get(2));
  if(s1.length()==1)
  s1="0"+s1;
  s=s+s1;
  s1=String.valueOf(calendar.get(5));
  if(s1.length()==1)
  s1="0"+s1;
  return s+s1;
  }
  private String getFileByUrl(Hashtable hashtable,String s)
  {
  for(Enumeration enumeration=hashtable.keys();enumeration.hasMoreElements();)
  //hashtable的keys()方法返回了哈希表关键字的枚举,enumeration的hasMoreElements()方法测试枚举重是否还有其他元素
  {
  String s1=(String)enumeration.nextElement();
  //让s1的值为enumeration的下一个元素值
  if(s.equals(hashtable.get(s1)))//如果s的值为s1的值,则
  return s1;//返回s1的值
  }
  return null;
  }
  private String getFirstSite(Hashtable hashtable)//取得第一个站点的名字
  {
  String s=(String)hashtable.get("dir");
  File file=new File(s);
  if(file==null)
  return null;
  String as[]=file.list();
  Vector vector=getGraphFiles(as);
  //设置Vector向量变量来获取图形文件
  if(vector.size()==0)//如果没有图形文件,则返回空值
  return null;
  else
  return getUrl(hashtable,(String)vector.elementAt(0));
  }
  private String getUrl(Hashtable hashtable,String s)//取得URL
  {
  String s1=s.toLowerCase();//设置s1为s的小写形式
  for(Enumeration enumeration=hashtable.keys();enumeration.hasMoreElements();)
  {
  String s2=(String)enumeration.nextElement();
  if(s1.equals(s2.toLowerCase()))
  return(String)hashtable.get(s2);
  }
  return null;
  }
  private void outputBanner(String s,Hashtable hashtable,HttpServletResponse httpservletresponse)//输出banner广告
  throws IOException//如果有错则抛出IOException错误
  {
  String s1=(String)hashtable.get("dir")+s;
  httpservletresponse.setHeader("Cache-control","no-store");
  httpservletresponse.setHeader("Pragma","no-cache");
  httpservletresponse.setDateHeader("Expires",1L);
  httpservletresponse.setContentType("image/"+s.substring(s.indexOf(".")+1));
  javax.servlet.ServletOutputStream servletoutputstream=httpservletresponse.getOutputStream();
  dumpFile(s1,servletoutputstream);
  servletoutputstream.flush();
  servletoutputstream.close();
  }
  private boolean dumpFile(String s,OutputStream outputstream)
  {
  byte abyte0[]=new byte[4096];
  boolean flag=true;
  try
  {
  FileInputStream fileinputstream=new FileInputStream(s);
  int i;
  while((i=fileinputstream.read(abyte0))!=-1)
  outputstream.write(abyte0,0,i);
  fileinputstream.close();
  }
  catch(Exception _ex)
  {
  flag=false;
  }
  return flag;
  }
  private Vector getGraphFiles(String as[])//获得图片文件
  {
  Vector vector=new Vector();
  if(as==null)//如果as为空值,则返回vector中的值
  return vector;
  for(int i=0;i<as.length;i++)//as.length为as[]数组长度
  {
  String s=as<i>.toUpperCase();//设置图片文件文件名的每个字符为大写
  if(isGraphFile(s))//如果为图片格式
  vector.addElement(as<i>);//加入向量中
  }
  return vector;
  }
  private boolean isGraphFile(String stringFileName)
  //判断文件是否为图形格式
  {
  int i=stringFileName.indexOf(".");//
  if(i&lt;=0||i==stringFileName.length()-1)
  return false;
  //判断文件是否以GIF、JPG、JPEG或PNG结尾
  String stringExtendFileName1=stringFileName.substring(i+1);
  return stringExtendFileName1.equals("GIF")||stringExtendFileName1.equals("JPG")||stringExtendFileName1.equals("JPEG")||stringExtendFileName1.equals("PNG");
  }
  private void errorMessage(String s,HttpServletResponse httpservletresponse)
  throws IOException
  {
  httpservletresponse.setContentType("text/html");
  PrintWriter out=httpservletresponse.getWriter();
  out.println("");
  out.println("");
  out.println("");
  out.println("");
  out.println("");
  out.println("
  "+s+"
  ");
  out.println("");
  out.println("");
  out.flush();
  out.close();
  }
  private String getFromQuery(String strQuery,String strQuery1)
  {
  if(strQuery==null)
  return"";
  int i;
  if((i=strQuery.indexOf(strQuery1))&lt;0)
  return"";
  String strQuery2=strQuery.substring(i+strQuery1.length());
  if((i=strQuery2.indexOf("&"))&lt;0)
  return strQuery2;
  else
  return strQuery2.substring(0,i);
  }
  public String getServletInfo()
  {
  return"旗帜广告系统,Wayne Zheng";
  }
  private static final String CPR="?Wayne Zheng";
  private static final String DEFAULT_SITE="www.yesky.com";
  private static final String BANNER_SESSION="旗帜广告系统,Wayne Zheng";
  private static final String DIR="dir";
  private static final String LOG="log";
  private static final String BANNERINDEX="bi";
  private static final String EDITED="edited";
  private static final String VIEW_POSTFIX="v";
  private static final String CLICK_POSTFIX="c";
  private static final String CONFIG="config";
  private static final String MODE="mode";
  private static final String ID="id";
  private static final int BUFFER_SIZE=4096;
  static String separator="/";
  private static Hashtable cfgs;
  private static Hashtable logs;
  }