WebDW的后台服务器程序发布(Java源代码)

今天决定把WebDW的后台相关Java代码共享出来.
其实蛮简单的一个东西,以后根据需要再详细完善吧.
/**
 * 
 */
package com.liu;

import javax.servlet.http.*;
import javax.servlet.*;
import java.sql.*;
import java.util.*;
import javax.naming.*;
import javax.sql.DataSource;
import java.util.Hashtable;
import java.io.*;

//import oracle.jdbc.pool.*;

/**
 * @author user
 *
 */
public class TableServlet extends HttpServlet {
	//transHash里面保存了所有事务,key是事务Id,字符型,value是一个TransSql对象
	public static Hashtable transHash = new Hashtable();

	private String s_ok = "OK";

	private String s_error = "ERROR";

	private String s_oper_query = "1"; //select sql命令 

	private String s_oper_exec = "2"; //update,delete sql命令

	private String s_oper_tablelist = "3"; //得到所有表列表的命令

	private String s_oper_columnlist = "4"; //得到某张表所有列的命令

	private String s_oper_beginTrans = "begintrans"; //开始一个事务的命令

	private String s_oper_addcommand = "addcommand"; //在事务中增加sql指令

	private String s_oper_commit = "commit"; //提交一个事务,收到这个命令,后台开始执行

	private String s_oper_rollback = "rollback"; //回滚一个事务,收到这个命令后,后台终止

	private String s_oper_getdwdefine = "getdwdefine"; //从后台检索数据窗口的定义格式
	
	private String s_oper_getvbfile = "getvbfile";	//从后台检索VB相关的原始文件内容
	
	private static Integer transId = new Integer(0);		//当前事务编号,以后递增
	
	private String ClassInfo="";
	public void init(ServletConfig config) throws ServletException {
		System.out.println("____________TableServlet init....");
	}

	/**
	 * 提供后台调用服务的Servlet程序
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws javax.servlet.ServletException, java.io.IOException {
		request.setCharacterEncoding("GBK"); //设置为GBK编码方式,处理中文

		int beginpos = 0; //默认从第一条开始
		int readnum = 100; //默认读取100条记录

		System.out.println("enter service TableServlet.Welcome.");
		String operType = request.getParameter("opertype");
		String command = request.getParameter("command");
		String param = request.getParameter("param");
		String strans = request.getParameter("transid");
		
		System.out.println("command="+command);
		if (request.getParameter("beginpos") != null
				&& request.getParameter("beginpos").trim().length() > 0) {
			beginpos = Integer.parseInt(request.getParameter("beginpos"));
		}

		if (request.getParameter("readnum") != null
				&& request.getParameter("readnum").trim().length() > 0) {
			readnum = Integer.parseInt(request.getParameter("readnum"));
		}

		int col = 0;

		if (operType == null)
			operType = "";
		if (command == null)
			command = "";
		if (param == null)
			param = "";

		response.setContentType("text/html;charset=GBK");
		ServletOutputStream out = response.getOutputStream();

		Connection conn = null;
		Statement stat = null;
		ResultSet rs = null;

		if (operType.equals("")) {
			out.print(s_ok);
			return;
		}
		
		try {
			conn = getConnection();
			conn.setAutoCommit(false);
			stat = conn.createStatement();
		} catch (Exception e) {
			e.printStackTrace();
			out.print("OK");
			return;
		}



		//如果命令参数是得到所有table的列表
		//那么构建一个SQL语句出来
		//目前仅支持Oracle数据库
		//其他数据库待以后进行明确的支持(等候升级)
		if (operType.equals(s_oper_tablelist)) {
			//Warning:这一语句仅对Oracle有效
			command = "select TNAME,TABTYPE from tab";
		}

		if (operType.equals(s_oper_columnlist)) {
			//Warning:这一语句仅对Oracle有效
			command = "Select CNAME from col where TNAME='" + command + "'";
		}
		//查询请求,当请求是s_oper_query和s_oper_tablelist时执行此流程
		if (operType.equals(s_oper_query) || operType.equals(s_oper_tablelist)
				|| operType.equals(s_oper_columnlist)) {
			try {
				doExecuteSelect(stat, rs, out, command, col, beginpos, readnum);
				conn.rollback();
			} catch (Exception e) {
				try{
					conn.rollback();
				}catch(Exception e1){
					e1.printStackTrace();
				}
				e.printStackTrace();
				out.println(e.toString());
			}
		}

		//执行请求
		if (operType.equals(s_oper_exec)) {
			try {
				doExecuteUpdate(command, stat, conn);

			} catch (Exception e) {
				try{
					conn.rollback();
				}catch(Exception e1){
					e1.printStackTrace();
				}
				e.printStackTrace();
				out.println(e.toString());
			}
		}

		//接收前台请求,准备启动一个事务(虚拟事务)
		if (operType.equals(s_oper_beginTrans)){
			try{
				doBeginTransaction(out);
			}catch(Exception e){
				e.printStackTrace();
			}
		}

		//事务中增加命令请求
		if (operType.equals(s_oper_addcommand)){
			doAddCommand(strans,command);
		}

		//事务提交请求,根据事务编号,把事务中的sql命令一一提交
		if (operType.equals(s_oper_commit)){
			try{
				doCommit(strans,conn,stat);
			}catch(Exception e){
				try{
					e.printStackTrace();
					Integer transId = new Integer(strans);
					TransSql sql = (TransSql)transHash.get(transId);
					if (sql == null ){
						//do nothing
					}else{
						sql.result ="commit failed";
						sql.commitDt = new java.util.Date().toString();
					}							
					conn.rollback();
					out.println(e.toString());
				}catch(Exception e1){
					e1.printStackTrace();
				}
			}
		}
		
		//事务取消请求,根据事务变化,把事务取消掉,这样就不用和后台交互了
		if(operType.equals(s_oper_rollback)){
			doRollback(strans);
		}
		
		//得到数据窗口定义的要求
		//根据给定的数据窗口的名字,检索后台的文件名
		//如果找到这个文件,把文件打开,返回给前台
		//如果出现错误,在后台打印错误信息
		if(operType.equals(s_oper_getdwdefine)){
			try{
				doGetDWFile(command,out);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		//得到VB源文件的要求
		//根据给定的VB源代码名称,检索文件名
		//找到这个文件,将文件传回给前台
		if (operType.equals(s_oper_getvbfile)){
			try{
				doGetVBFile(command,out);
			}catch(Exception e){
				e.printStackTrace();
			}			
		}
		//其他情况下,直接返回s_ok.
		out.print(s_ok);

		//TODO:关闭数据库连接
		try {
			if (rs != null)
				rs.close();
			if (stat != null)
				stat.close();
			if (conn != null)
				conn.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Database connection close failed.");
		}finally{
			try{
				conn.close();
			}catch(Exception e2){
				e2.printStackTrace();
			}
		}
	}



	/**
	 * 得到数据库连接,此处采用weblogic配置的连接池来处理
	 * 对获得连接的方式进行修改,直接建立一个连接
	 * @return
	 * @throws Exception
	 */
	private Connection getConnection() throws Exception {
		
//		Context initCtx = new InitialContext();
//		Context envCtx = (Context) initCtx.lookup("java:comp/env");
//		DataSource ds = (DataSource) envCtx.lookup("jdbc/tableedit");
//		Connection conn = ds.getConnection();
		String configfile="com/liu/database.properties";		
		
		String url="";
		String driver="";
		String userid="";
		String passwd="";
		//Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		//Connection conn = DriverManager.getConnection(url,"dba","sql");
	  	ClassLoader loader = (new CEmpty()).getClass().getClassLoader();
	  	InputStream stream = loader.getResourceAsStream(configfile);
	  	Properties prop = new Properties();
	    prop.load(stream);
	    
	    url = prop.getProperty("url");
	    driver = prop.getProperty("driver");
	    userid = prop.getProperty("userid");
	    passwd = prop.getProperty("passwd");
	    
	    Class.forName(driver);
	    Connection conn = DriverManager.getConnection(url,userid,passwd);
		return conn;
	}
	/**
	 * 执行Select命令的方法,从主方法中独立出来。
	 * Warning:经过测试,通过这个接口实际上可以执行任何的SQL命令
	 * 因此必须对可以执行的SQL命令进行筛选,切不可直接提交执行,否则
	 * 后果将难以预测
	 * 最好的办法是专门为这个方法开一个ReadOnly权限的用户和连接来执行
	 * @param stat
	 * @param rs
	 * @param out
	 * @param command
	 * @param col
	 * @param beginpos
	 * @param readnum
	 * @throws Exception
	 */
	private void doExecuteSelect(Statement stat, ResultSet rs,
			ServletOutputStream out, String command, int col, int beginpos,
			int readnum) throws Exception {
		System.out.println("Sql = " + command);
		//TODO:对command命令进行解析,分析是否是一个Select命令
		//如果不是,则直接拒绝执行,否则很容易造成系统的崩溃和失败
		rs = stat.executeQuery(command);
		ResultSetMetaData meta = rs.getMetaData();
		String sline = "";
		for (col = 1; col <= meta.getColumnCount(); col++) {
			if (col < meta.getColumnCount()) {
				sline += meta.getColumnName(col) + "\t";
			} else {
				sline += meta.getColumnName(col);
			}
		}
		out.println(sline);
		System.out.println("colname=" + sline);
		while (beginpos > 0) {
			if (rs.next()) {
				beginpos--;
			} else {
				break;
			}
		}
		// beginpos现在是一个指示变量,如果上面的循环正常结束
		// beginpos应该等于0
		// 否则beginpos不为0
		while (rs.next() && beginpos == 0 && readnum > 0) {
			sline = "";
			for (col = 1; col <= meta.getColumnCount(); col++) {
				if (col < meta.getColumnCount()) {
					sline += rs.getString(col) + "\t";
				} else {
					sline += rs.getString(col);
				}
			}
			readnum--;
			out.println(sline);
		}
	}

	/**
	 * 执行Update类型的SQL命令的方法
	 *
	 */
	private void doExecuteUpdate(String command, Statement stat, Connection conn)
			throws Exception {
		System.out.println("Sql = " + command);
		//TODO:对传入的SQL命令,一定要进行分析判断,避免破坏性的SQL命令插入
		if (command == null && command.trim().length() < 1) {
			// do nothing
		} else {
			String[] sqls = command.split("----------");
			int i;
			for (i = 0; i < sqls.length; i++) {
				System.out.println("sqls[i]:" + sqls[i]);
				if (sqls[i] == null || sqls[i].trim().length() == 0) {
					break;
				} else {
					stat.executeUpdate(sqls[i]);
				}
			}
			conn.commit();
		}
	}
	/**
	 * 在服务器上启动一个虚拟事务的方法
	 * @param out
	 */
	private void doBeginTransaction(ServletOutputStream out) throws Exception {
		System.out.println("enter begintrans");
		//同步化代码,避免事务编号重复
		synchronized(transId){
			int id = transId.intValue();
			id ++;
			if (id >= 1000) id =0;
			transId = new Integer(id);	//得到事务编号
		}
		TransSql sql = (TransSql)transHash.get(transId);
		if (sql!=null){
			transHash.remove(transId);	//如果事务编号已经使用,那么删除之
		}
		 sql = new TransSql();
		 sql.transId = transId.intValue();
		 sql.beginDT =new java.util.Date().toString();
		 transHash.put(transId, sql);	//将事务对象放入Hash中
		 System.out.println(transId.toString());
		 out.println(transId.toString());	//返回事务对象的编号给客户端		
	}
	
	/**
	 * 在事务中增加命令的方法,一次增加一条命令
	 * @param command
	 * @param transId
	 * @throws Exception
	 */
	private void doAddCommand(String stransId,String command){
		Integer transId = new Integer(stransId);
		TransSql sql = (TransSql)transHash.get(transId);
		if (sql == null || command == null || command.trim().equals("")){
			//do nothing
		}else{
			if (sql.transSQL.equals("") ){
				sql.transSQL = command;
			}else{
				sql.transSQL = sql.transSQL + "\r\n" +command;
			}
		}
	}
	/**
	 * 提交指定的事务对象
	 * @param stransId
	 */
	private void doCommit(String stransId,Connection conn,Statement stat) throws Exception{
		Integer transId = new Integer(stransId);
		TransSql sql = (TransSql)transHash.get(transId);
		if (sql == null || sql.result.trim().length()>0  ){
			//do nothing
		}else{
			sql.result ="commit begin";
			String[] sqls = sql.transSQL.split("\r\n");
			int i;
			for (i = 0; i < sqls.length; i++) {
				System.out.println("sqls[i]:" + sqls[i]);
				if (sqls[i] == null || sqls[i].trim().length() == 0) {
					break;
				} else {
					stat.executeUpdate(sqls[i]);
				}
			}
			conn.commit();	
			sql.commitDt = new java.util.Date().toString();
			sql.result = "commit finish";
		}		
	}
	
	/**
	 * 废弃指定的事务对象
	 * @param stransId
	 */
	private void doRollback(String stransId){
		Integer transId = new Integer(stransId);
		TransSql sql = (TransSql)transHash.get(transId);
		if (sql == null || sql.result.trim().length()>0  ){
			//do nothing
		}else{
			sql.result ="rollback";
			sql.commitDt = new java.util.Date().toString();
		}		
	}	
	/**
	 * 从后台服务器上检索DW的文件内容,传递到前台去
	 * @param command	command中代表数据窗口的文件名,如果无后缀,代表.srd文件
	 * @param out		输出流
	 */
	private void doGetDWFile(String command,ServletOutputStream out)throws Exception{
		String filepath="C://webdwfile//dwfile//";
		String filename="";
		if (command.indexOf(".") > 0){
			filename = filepath + command;
		}else{
			filename = filepath + command+".srd" ;
		}
		System.out.println("Want file:"+filename);			
		File dwfile = new File(filename);
		if (dwfile.exists()){//如果文件存在,才操作,否则不操作
			FileReader  fstream = new FileReader(filename);
			BufferedReader  in = new BufferedReader(fstream);
			String record = "";
            while ((record = in.readLine()) !=null) {
            	out.println (record);	//文件输出到输出流去
            }
            in.close(); //关闭文件输入流
		}		
	}

	/**
	 * 从后台服务器上检索VB项目的相关文件内容,传递到前台去
	 * 只读取C://VBSource//目录下文件
	 * 目前只支持这一个目录
	 * @param command	command中代表数据窗口的文件名,如果无后缀,代表.srd文件
	 * @param out		输出流
	 */
	private void doGetVBFile(String command,ServletOutputStream out)throws Exception{
		String filepath="C://webdwfile//VBfile//";
		String filename="";
		filename = filepath + command;

		System.out.println("Want VB file:"+filename);			
		File vbfile = new File(filename);
		if (vbfile.exists()){//如果文件存在,才操作,否则不操作
			FileReader  fstream = new FileReader(filename);
			BufferedReader  in = new BufferedReader(fstream);
			String record = "";
            while ((record = in.readLine()) !=null) {
            	out.println (record);	//文件输出到输出流去
            }
            in.close(); //关闭文件输入流
		}		
	}

}


上面的代码是一个Servlet,在web.xml里面映射成/Table这样一个名字.
另外有个类TransSql,这个类用来存储事务的结构.
package com.liu;

public class TransSql {

	public int transId = 0; // 事务的编号,0代表无事务

	public String transSQL = ""; // 事务所要执行的多个SQL命令,相互之间用:\r\n进行分割

	public String beginDT = ""; // 事务开始时间

	public String commitDt = ""; // 事务提交时间

	public String result = ""; // 事务执行结果

}


另外有一个database.properties文件,配置数据库的连接信息,Servlet里面调用
#driver for EA Demo V5 odbc
#url		=jdbc:odbc:EAS Demo DB V3
#driver	=sun.jdbc.odbc.JdbcOdbcDriver
#userid	=dba
#passwd	=sql

#driver for Oracle scott user
url		=jdbc:oracle:thin:@localhost:1521:finance
driver	=oracle.jdbc.OracleDriver
userid	=scott
passwd	=tiger


你可能感兴趣的:(java,oracle,sql,jdbc,vb)