最近公司的数据库服务器突然罢工,许多功能不能使用了,而项目又紧急的需要编写和维护数据库内容,不得已只能在本地搭建一个简单的Web服务器去操作本地数据库的内容了。其实之前在搞三大框架的时候也用过类似的功能比如Struts2的json-plugin,获取JSON形式的数据。只是眼下使用框架却显得臃肿很多,所以只能自己动手去写一个Servlet服务,目的很明确:”在前端页面能够获取从数据库中读取的表的数据,包括其ColumnName,length当然还有哦Rows“。就是这么简单,废话不多说直接开干。
以下是web.xml相关代码片段
<servlet>
<servlet-name>DataAgencyServlet</servlet-name>
<servlet-class>com.xxc.servlet.DataAgencyServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>NonDataAgencyServlet</servlet-name>
<servlet-class>com.xxc.servlet.NonDataAgencyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DataAgencyServlet</servlet-name>
<url-pattern>/DataAccessServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>NonDataAgencyServlet</servlet-name>
<url-pattern>/NonDataAgencyServlet</url-pattern>
</servlet-mapping>
这里声明了两个Servlet类,分别作为Update语句和Select语句JAVA类的映射,当然简单的Servlet的配置就只需要上述的内容添加到web.xml中,这里就不再赘诉Servlet相关概念了。
在编写JAVA类之前需要一个lib环境:
json-lib-2.4-jdk15.jar
ezmorph-1.0.6.jar
commons-logging.jar
commons-lang.jar
commons-collections.jar
commons-beanutils.jar
其中最主要的就是json-lib,它的作用就是自动生成JSON形式的数据格式,其他都是它的依赖包,可以在网上搜索一下就能再到其下载地址了,这里就不贴不出来了。
之后就是写Servlet类
package com.xxc.servlet;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import com.xxc.bean.SingleColumn;
import com.xxc.jdbc.Dbcom;
/**
*获取json形式数据servlet类
*@package_name com.xxc.servlet
*/
public class DataAgencyServlet extends HttpServlet{
/**
*
* 继承HttpServlet后所需实现的POST方法,用于页面POST请求
*
*/
public void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.setHeader("Cache-Control","no-cache");
String sql = req.getParameter("sql");
sql = new String(sql.getBytes("iso-8859-1"),"GBK");
ArrayList<TreeMap<String,String>> arry = getData(sql);
//用到SingleColumn类,用于存放列名和值
ArrayList<ArrayList<SingleColumn>> rowsColumn = new ArrayList<ArrayList<SingleColumn>>();
JSONArray jsonarray = JSONArray.fromObject(arry);
for(int index=0;index<arry.size();index++){
TreeMap<String,String> map = arry.get(index);
ArrayList<SingleColumn> arrayColumn = new ArrayList<SingleColumn>();
for(Map.Entry<String, String> entry:map.entrySet()){
SingleColumn sc = new SingleColumn();
sc.setColumnName(entry.getKey());
sc.setValue(entry.getValue());
arrayColumn.add(sc);
}
rowsColumn.add(arrayColumn);
}
//json 对象,这里可以看成页面上获取的JSON 对象,在这其中可以进行元素节点添加等操作
JSONObject jsonobj = new JSONObject();
//添加子节点
jsonobj.element("rows", jsonarray);
jsonobj.element("rowsColumn", rowsColumn);
jsonobj.put("rowSize", jsonarray.size());
resp.getWriter().write(jsonobj.toString());
}
/**
* 传入SQL获取数据库中数据,返回一个存有Map对象的ArrayList数组,Map对象主要存放一行数据库查询获得的数据
* @param sql
* @return
*/
public static ArrayList<TreeMap<String,String>> getData(String sql){
ArrayList<TreeMap<String,String>> arry = new ArrayList<TreeMap<String,String>>();
String innerSql = sql;
//通用JDBC连接类
Dbcom dbcom = new Dbcom();
Connection conn = null;
try {
conn = dbcom.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(innerSql);
ResultSetMetaData rsmd = rs.getMetaData();
while(rs.next()){
TreeMap<String,String> map = new TreeMap<String,String>();
int i = rsmd.getColumnCount();
for(int j=1;j<=i;j++){
map.put(rsmd.getColumnName(j), rs.getString(j));
}
map.put("length", String.valueOf(i));
arry.add(map);
}
dbcom.closeConnection(conn);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return arry;
}
}
不难看出其实上述类就是一个最简单的Servlet类,其中doGet方法被我去掉了,可以自行添加上,在上述代码中主要是将数据库中查询所得的数据一条一条的存放的一个Array中,之后便由json-lib自动将Array转换成jsonArray对象,在JAVA中可以直接创建json对象,对其进行操作,常用操作是对json对象添加子节点
jsonObj.element(key, value)
之后将创建完成的对象写入response中在页面上就可以得到我们要获取的数据了。
SingleColumn类,用于存放列名和值
package com.yjjx.bean;
/**
*
*@file_name SingleColumn.java
*@package_name com.xxc.bean
*/
public class SingleColumn {
private String columnName;
private String value;
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
之后是数据库通用类,网上方法很多不一定要用此方法
package com.xxc.jdbc;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.Vector;
public class Dbcom {
private static String className = null;
private static String url = null;
private static String user = null;
private static String password = null;
private static int minCon = 1; // 最小连接数
private static List<Connection> listCon = new Vector<Connection>(); // 连接池
/**
* 初始化连接池
*/
static {
loadProperties();
try {
for (int i = 0; i < minCon; i++) {
listCon.add(getCon());
}
} catch (SQLException e) {
System.out.println("---------------初始化资源连接失败!---------------");
e.printStackTrace();
}
System.out.println("---------------初始化"+listCon.size()+"个资源连接!---------------");
}
/**
* 读取资源文件配置、加载驱动
* @throws IOException
* @throws ClassNotFoundException
*/
private static void loadProperties() {
ResourceBundle rb;
try {
rb = ResourceBundle.getBundle("conn");
className = rb.getString("conn.driver");
url = rb.getString("conn.url");
user = rb.getString("conn.user");
password = rb.getString("conn.password");
String smin = rb.getString("conn.minCon");
if ((smin != null) && (!("".equals(smin.trim()))))
minCon = Integer.valueOf(smin).intValue();
Class.forName(className);
} catch (Exception e) {
System.out.println("---------------读取资源文件异常!--------------");
className = "oracle.jdbc.driver.OracleDriver";
url = "jdbc:oracle:thin:@localhost:1521:orcl";
user = "orcl";
password = "orcl";
try {
Class.forName(className);
} catch (Exception e2) {
System.out.println("---------------加载驱动异常!--------------");
e2.printStackTrace();
}
}
}
/**
* 获取数据库连接。。。
* @return
* @throws SQLException
*/
private static Connection getCon() throws SQLException {
System.out.println("---------------新建连接资源!---------------");
if ((className == null) || (url == null) || (password==null))
loadProperties();
return DriverManager.getConnection(url, user, password);
}
/**
* 在连接池里拿取连接、如果没有了、调用方法新建连接
* @return
* @throws SQLException*/
public static Connection getConnection() throws SQLException {
if ((listCon != null) && (listCon.size() > 0))
return listCon.remove(listCon.size() - 1);
return getCon();
}
/**
* 当连接小于最大连接数时、将连接放入连接池、否则关闭数据库连接
* @param con
* @throws SQLException
*/
public static void closeConnection(Connection conn) throws Exception {
if ((conn != null) && (!(conn.isClosed())))
if ((listCon != null) && (listCon.size() < minCon))
listCon.add(conn);
else
conn.close();
}
}
在上述数据库连接方法中需要在src目录下面配置一个properties文件,文件名为conn.properties
conn.driver=oracle.jdbc.driver.OracleDriver
conn.url=jdbc\:oracle\:thin\:@localhost1521\:orcl
conn.user=orcl
conn.password=orcl
conn.minCon=3
conn.maxCon=10
好了,到这里一个方便的直接从页面上获取数据库数据的应用就写好了,可以用于页面数据功能测试,或者处理一些需要反复操作的事情。这是一个测试应用难免会有疏漏之处,请另行指正。