例子:自动生成可以保存数据的HTML页面

类别:Java 点击:0 评论:0 推荐:

其实这是一个很简单的技术,在新闻网站中应用的很普遍。原理是将数据保存为硬盘文件,直接通过URL访问,用来减轻数据库访问的压力。


数据库与表:

mysql> use mysecondnews;
Database changed
mysql> desc news;
+---------+---------------+------+-----+---------+----------------+
| Field   | Type          | Null | Key | Default | Extra          |
+---------+---------------+------+-----+---------+----------------+
| id      | int(10)       |      | PRI | NULL    | auto_increment |
| title   | varchar(240)  |      |     |         |                |
| path    | varchar(240)  |      |     |         |                |
| content | text          |      |     |         |                |
| addtime | timestamp(14) | YES  |     | NULL    |                |
+---------+---------------+------+-----+---------+----------------+

 

Database.java://定义数据库

package org.eleaf.firstnews.database;

import java.sql.ResultSet;
public interface Database {
    String DATABASE = "mysecondnews";
    String USERNAME = "bitan";
    String PASSWORD = "bitan";
    String URL_PREFIX = "jdbc:mysql://localhost/" + DATABASE;
    String DRIVER = "org.gjt.mm.mysql.Driver";

    int doUpdate(String sql);
    ResultSet doSelect(String sql);
}

 

TouchDatabase.java://自定义JDBC接口类。为简单起见,未处理close()方法。
package org.eleaf.firstnews.database;

import java.sql.*;
public class TouchDatabase implements Database {
    private Connection          conn;
    private Statement           stmt;
    private PreparedStatement   prepstmt;

    private void init() throws SQLException, ClassNotFoundException {
        stmt = null;
        prepstmt = null;

        Class.forName(DRIVER);
        conn = DriverManager.getConnection(URL_PREFIX, USERNAME,
                PASSWORD);
    }
   
    /**
     * Constructor for Statement.
     *
     */
    public TouchDatabase() {
        try {
            this.init();
            stmt = conn.createStatement();
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } catch (ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
    }
   
    /**
     * Constructor for PreparedStatement.
     * @param sql Pre-compile SQL string.
     */
    public TouchDatabase(String sql) {
        try {
            this.init();
            prepstmt = conn.prepareStatement(sql);
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } catch (ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
    }

   
    public int doUpdate(String sql) {
        // TODO 自动生成方法存根
        try {
            return stmt.executeUpdate(sql);
        } catch (SQLException sqle) {
            sqle.printStackTrace();
            return 0;
        }
    }


    public ResultSet doSelect(String sql) {
        // TODO 自动生成方法存根
        try {
            return stmt.executeQuery(sql);
        } catch (SQLException sqle) {
            sqle.printStackTrace();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public void setField(int index, String field) {
        try {
            prepstmt.setString(index, field);
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        }
    }

    public ResultSet doPrepareSelect() {
        try {
            return prepstmt.executeQuery();
        } catch (SQLException sqle) {
            sqle.printStackTrace();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

 

 

News.java://新闻文章的数据结构
package testnews;
public class News {
 private String id;
    private String title;
    private String path;
    private String content;
    private String addtime;
 /**
  * @return 返回 addtime。
  */
 public String getAddtime() {
  return addtime;
 }
 /**
  * @param addtime 要设置的 addtime。
  */
 public void setAddtime(String addtime) {
  this.addtime = addtime;
 }
 /**
  * @return 返回 content。
  */
 public String getContent() {
  return content;
 }
 /**
  * @param content 要设置的 content。
  */
 public void setContent(String content) {
  this.content = content;
 }
 /**
  * @return 返回 id。
  */
 public String getId() {
  return id;
 }
 /**
  * @param id 要设置的 id。
  */
 public void setId(String id) {
  this.id = id;
 }
 /**
  * @return 返回 path。
  */
 public String getPath() {
  return path;
 }
 /**
  * @param path 要设置的 path。
  */
 public void setPath(String path) {
  this.path = path;
 }
 /**
  * @return 返回 title。
  */
 public String getTitle() {
  return title;
 }
 /**
  * @param title 要设置的 title。
  */
 public void setTitle(String title) {
  this.title = title;
 }
}

 

DoneNews.java://通过JDBC接口类操作数据库
package testnews;

import java.util.*;
import java.sql.*;
import org.eleaf.firstnews.database.*;
public class DoneNews {
 public Vector getAllNews() {
        Vector vNews = new Vector();
        String sql = "SELECT * FROM news";
        TouchDatabase tdata = new TouchDatabase();
        ResultSet rs = tdata.doSelect(sql);
        try {
            while (rs.next()) {
                News news = new News();
                news.setId(rs.getString("id"));
                news.setTitle(rs.getString("title"));
                news.setPath(rs.getString("path"));
                news.setContent(rs.getString("content"));
                news.setAddtime(rs.getString("addtime"));
                vNews.addElement(news);
            }
        } catch (SQLException sqle) {
         sqle.printStackTrace();
        }
        return vNews;
    }
    public boolean addNews(News news) {
        boolean success = false;
        if (news != null) {
         String sql = "INSERT news (title,path,content) VALUES('" +
                news.getTitle() + "','" + news.getPath() + "','" +
                    news.getContent() + "')";
            TouchDatabase tdata = new TouchDatabase();
            success = (0 != tdata.doUpdate(sql));
        }
        return success;
    }
}

 

 

WriteNews.java://写数据流到硬盘。并调用DoneNews.addNews()方法。
package testnews;

import java.io.*;
import java.util.*;
public class WriteNews {
    private final String MIDDLE_DIR = "";//可自定义衔接目录。
    private final String FILE_SUFFIX = ".html";//可自定义文件后缀名。
 public boolean write(News news, String realPathPrefix, Calendar calendar) {
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        String fileName = calendar.getTimeInMillis() + FILE_SUFFIX;
        String realPath = realPathPrefix + MIDDLE_DIR + year + "\\" + month +
            "\\" + dayOfMonth + "\\";
        try {
            if (!mkDirs(realPath)) {
             //throw new IOException("make dir('" + realPath + "') unsuccessfully!");
            }
           
            FileOutputStream fos = new FileOutputStream(new File(realPath + fileName));
            byte[] conBytes = news.getContent().getBytes();
            fos.write(conBytes);
            fos.close();
        } catch (IOException ioe) {
         ioe.printStackTrace();
            return false;
        }
       
        String newsPath = year + "/" + month + "/" + dayOfMonth + "/" + fileName;
        news.setPath(newsPath);
        return new DoneNews().addNews(news);
    }
    private boolean mkDirs(String realPath) {
        boolean success = false;
        File path = new File(realPath);
     if(!path.exists()) {
      success = path.mkdirs();
        }
        return success;
    }
}

 

 

 

form.jsp://输入表单

<%@ page language="java" %>
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title>Lomboz JSP</title>
</head>
<body bgcolor="#FFFFFF">
<FORM METHOD=POST ACTION="save.jsp">
<INPUT TYPE="text" NAME="title"><BR>
<TEXTAREA NAME="content" ROWS="10" COLS="50"></TEXTAREA><BR>
<INPUT TYPE="submit">
</FORM>
</body>
</html>

 

save.jsp://保存数据.为简单起见,这里未对输入数据做任何字符过滤或转化工作。

<%@ page language="java" %>
<%@ page import="java.util.*,testnews.*" %>
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title>Lomboz JSP</title>
</head>
<body bgcolor="#FFFFFF">
<%
    String title = request.getParameter("title");
    String content = request.getParameter("content");
    if (title == null | content == null) {
        response.sendRedirect("form.jsp");
        return;
    }
    News news = new News();
    news.setTitle(title);
    news.setContent(content);
    String realPathPrefix = application.getRealPath("/");
    Calendar calendar = Calendar.getInstance();
    boolean success = new WriteNews().write(news, realPathPrefix, calendar);
    String message = "";
    if (success) {
        message = "Add the news successfully. Please return.";
    } else {
        message = "Add the news unsuccessfully. Please return.";
    }
%>
    <%=message%><br>
    <a href="form.jsp">return to form.jsp</a><br>
    <a href="show.jsp">go to show.jsp</a><br>
</body>
</html>

 

show.jsp://显示链接

<%@ page language="java" %>
<%@ page import="java.util.*,testnews.*" %>
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title>Lomboz JSP</title>
</head>
<body bgcolor="#FFFFFF">
<%
    Vector vNews = new DoneNews().getAllNews();
    if (vNews != null) {
        for (int i=0; i<vNews.size(); i++) {
            News news = (News) vNews.elementAt(i);
            %>
`           <a href="<%=request.getContextPath()%>/<%=news.getPath()%>"><%=news.getTitle()%></a><br>
            <%
        }  
    }
%>
</body>
</html>

然后就可以以类似如下的网址访问文章了:
http://localhost:2000/secondnews/2004/10/31/1099234459546.html

本文地址:http://com.8s8s.com/it/it14035.htm