一,为什么要DIY
当前,成熟的java web框架有很多种,我们为什么还要自己弄一个呢?我的看法如下:
首先,现在的主流框架过于庞大,使用起来过于繁琐,这一点从ROR给java带来的冲击就能看出来,
用ROR开发一个web程序如此简单,反思java,难道我们真的需要那么多复杂的步骤吗?
其次,现在的用户越来越追求画面的体验,而java主流框架产生的时间相对比较早,对web2.0的考虑相对少一些,
对ajax的封装不足,框架处理这类问题比较笨拙。
另外,java框架太注重自身的发展,缺乏和新事物的融合,在某种程度上阻碍了自身的进步。
二,DIY的原则
第一,简单就是美。围绕解决用户的需求这个核心,方案越简洁高效越好。例如,我们没有必要为了某种形式写一大堆get,set方法。
第二,坚持自己认为正确的方向。比如说有人不喜欢SQL,希望把对数据库的操作封装起来,进而实现对数据库产品无依赖的编程,
但是,我不这么认为,我喜欢SQL,SQL是高效的,如果把oracle提供的递归查询弃置不用,而是自己编程实现,复杂度不必说了,
就执行效率而言,同前者不可同日而语。我认为一个复杂的项目必须针对具体的数据库产品的特性编程,毕竟程序运转中,
代码是固定的,而不断变化的是数据,我们必须事先对数据库有足够的重视,而不是事后把责任推给DBA。所以,在我的DIY框架中
使用SQL是正常的。
第三,博采众长。只要不违反知识产权,很多好的,开源的东西,我们尽可能的采用。当然,使用前你要确定这些东西是安全可靠的。
三,DIY举例
下面对一个具体的组合框架进行刨析,希望对大家有所启发,起到抛砖引玉的作用。
先介绍一下该框架的原理。说白了很简单,就是利用jquery增强画面效果,用json进行数据传递。其实网络中介绍jquery+ajax+json的文章很多,
但是,都是说返回一个json,用它的内容渲染页面,我在这里更近了一步,不但回来的是json,传到后台的数据也是json,
并在此基础上做了一些封装。
需要引入的外部资源:jquery.js,著名的js库;json2.js,js的json工具;org.json,java操作json的类包;sqlitejdbc-v053.jar,
sqlite的jdbc驱动,因为只是做一个demo所以用了一个我知道的最简单的数据库。
json_param.js 算是一个jquery插件。把dom中的内容做成json;包装了一下jQuery.ajax,使其调用更简单。
// Add a dom parameter to json.
$(document).ready(function(){
jQuery.jsonParam = {
jsonRetn: new Object(),
registParaToJson: function(dom){
if (dom.is("table")) {
var arryData = new Array();
$('tr:gt(0)', dom).each(function(){
var curRow = new Object();
$('td', $(this)).each(function(index){
if ($(this).children().is("input[type=text]")) {
curRow[index] = $('input[type=text]:eq(0)', this).val();
}
else if ($(this).children().is("input[type=radio]")) {
curRow[index] = $('input[type=radio]:eq(0)', this).attr("checked");
}
else if ($(this).children().is("input[type=checkbox]")) {
curRow[index] = $('input[type=checkbox]:eq(0)', this).attr("checked");
}
else if ($(this).children().is("select")) {
curRow[index] = $('select:eq(0)', this).val();
}
else {
curRow[index] = "";
}
});
arryData.push(curRow);
});
$.jsonParam.jsonRetn[dom.attr('id')] = arryData;
}
else if (dom.is("input[type=text]") || dom.is("select")) {
$.jsonParam.jsonRetn[dom.attr('id')] = dom.val();
}
else if (dom.is("input[type=checkbox]") || dom.is("input[type=radio]")) {
$.jsonParam.jsonRetn[dom.attr('id')] = dom.attr("checked");
}
},
passEventToJson: function(even){
$.jsonParam.jsonRetn.passEvent = even;
},
getParamFromJson: function(){
return JSON.stringify($.jsonParam.jsonRetn);
},
ajaxJson: function(url, callback){
return jQuery.ajax({
type: "post",
url: url,
dataType: "json",
data: {'param':$.jsonParam.getParamFromJson()},
success: callback
});
}
}
});
first.jsp 一个jsp,注意$.jsonParam.registParaToJson往后台传值的使用。
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >
<html>
<head>
<title></title>
<script src="script/jquery.js" type="text/javascript"></script>
<script src="script/json2.js" type="text/javascript"></script>
<script src="script/json_param.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#contentdiv').html(' ');
$("#idm").change( function() {
$.jsonParam.passEventToJson('idm');
$.jsonParam.registParaToJson($('#idm'));
$.jsonParam.ajaxJson("SecondServlet",
function(response){
$('#contentdiv').empty();
$.each(response, function(entryIdex, entry){
$('#contentdiv').append(entry['MAIN_DISH']);
});
}
);
});
$("#b_pass").click( function() {
$.jsonParam.passEventToJson('b_pass');
$.jsonParam.registParaToJson($('#idm'));
$.jsonParam.registParaToJson($('#t_demo'));
//~ $.jsonParam.ajaxJson("SecondServlet",
//~ function(response){
//~ $('#ret_table').empty();
//~ var htm = '<table border="1">';
//~ $.each(response, function(entryIdex, entry){
//~ htm += '<tr>'
//~ htm += '<td>' + entry['0'] + ' </td>'
//~ htm += '<td>' + entry['1'] + ' </td>'
//~ htm += '<td>' + entry['2'] + ' </td>'
//~ htm += '</tr>'
//~ });
//~ htm += '</table>'
//~ $('#ret_table').append(htm);
//~ }
//~ );
$("#param").attr("value", $.jsonParam.getParamFromJson());
$("#form1").attr("action", "SecondServlet");
$("#form1").submit();
return true;
});
});
</script>
</head>
<body>
<DIV id=main>
<form id="form1" method="post" action="">
<div id="databox">
<select id="idm" >
<option value="0" selected="selected">What's for Dinner?...</option>
<option value="1">Monday</option>
<option value="2">Tuesday</option>
<option value="3">Wednesday</option>
<option value="4">Thursday</option>
<option value="5">Friday</option>
<option value="6">Saturday</option>
</select>
<p id="contentdiv"> </p>
</div>
<div>
<input type="button" value="pass" id="b_pass" class="test_button" />
<br />
<table id="t_demo" border="1">
<tr>
<th>No.</th>
<th>content</th>
<th>select</th>
<th>chk</th>
</tr>
<tr>
<td> <input type="radio" name="radio" checked="checked" /></td>
<td> <input type="text" size="12" /></td>
<td>
<select name="Cats" size="1" >
<option value="0" selected="selected">----</option>
<option value="1">Calico</option>
<option value="2">Tortie</option>
<option value="3">Siamese</option>
</select>
</td>
<td><input type="checkbox" /></td>
</td>
</tr>
<tr>
<td> <input type="radio" name="radio" /></td>
<td> <input type="text" size="12" /></td>
<td>
<select name="Cats" size="1" >
<option value="0" selected="selected">----</option>
<option value="1">Calico</option>
<option value="2">Tortie</option>
<option value="3">Siamese</option>
</select>
</td>
<td><input type="checkbox" /></td>
</tr>
<tr>
<td> <input type="radio" name="radio" /></td>
<td> <input type="text" size="12" /></td>
<td>
<select name="Cats" size="1" >
<option value="0" selected="selected">----</option>
<option value="1">Calico</option>
<option value="2">Tortie</option>
<option value="3">Siamese</option>
</select>
</td>
<td><input type="checkbox" /></td>
</tr>
</table>
</div>
<input type="hidden" id="param" name="param"/>
<p id="ret_table"></p>
</form>
</DIV>
</body>
</html>
SecondServlet.java,后台Servlet,注意jreq.GetParameterFromJson中的参数,他的命名就是jsp中dom的id名,约定大于配置。
package org.demo;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.common.*;
/**
* The simplest possible servlet.
*
* @author chengj
*/
public class SecondServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String param=request.getParameter("param");
JsonRequest jreq = new JsonRequest(param);
String resWrite = "";
SecondEnty enty = new SecondEnty();
if ("idm".equals((String)jreq.GetParameterFromJson("passEvent")))
{
String key = (String)jreq.GetParameterFromJson("idm");
resWrite = enty.getDish(key);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.println(resWrite);
}
else if ("b_pass".equals((String)jreq.GetParameterFromJson("passEvent"))) {
resWrite = enty.getDetail((ArrayList)jreq.GetParameterFromJson("t_demo"));
request.setAttribute("param",resWrite);
RequestDispatcher rd = request.getRequestDispatcher("/jsp/second.jsp");
rd.forward(request, response);
}
}
}
SecondEnty.java,SecondServlet的业务相关类。
package org.demo;
import java.io.*;
import java.util.*;
import java.sql.*;
import org.common.*;
/**
* The simplest possible servlet.
*
* @author chengj
*/
public class SecondEnty extends DBAccess {
private Connection conn = null;
public String getDish(String key) {
String retJson = null;
try {
PreparedStatement prep = super.conn.prepareStatement("SELECT day, main_dish FROM menu where qsid = ?");
prep.setString(1, key);
retJson = JsonResponse.GetQuery(prep.executeQuery());
return retJson;
} catch(Exception e) {
System.out.println(e.toString());
return null;
}
}
public String getDetail(ArrayList table) {
ArrayList retTable = new ArrayList();
for (int i = 0; i < table.size(); i++) {
ArrayList arrRow = (ArrayList)table.get(i);
if (arrRow.get(3).equals("true")) {
retTable.add(table.get(i));
}
}
return JsonResponse.GetTable(retTable);
}
}
下面是两个公共类,负责request到json,以及json到response的转换任务
package org.common;
import java.util.*;
import org.json.*;
/**
*
*
* @author chengj
*/
public class JsonRequest {
private JSONObject data;
public JsonRequest(String param){
try {
this.data = new JSONObject(param);
} catch(JSONException e) {
System.out.println(e.toString());
}
}
public Object GetParameterFromJson(String key) {
try {
return GetParameterFromJson(key, data);
} catch(JSONException e) {
System.out.println(e.toString());
return null;
}
}
private Object GetParameterFromJson(String key, JSONObject data) throws JSONException {
if (data.get(key) instanceof String) {
return (String)data.get(key);
}
if (data.get(key) instanceof Boolean) {
return ((Boolean)data.get(key)).toString();
}
if (data.get(key) instanceof JSONArray) {
JSONArray dataArray = (JSONArray)data.get(key);
ArrayList arrTable = new ArrayList();
for (int i = 0; i < dataArray.length(); i++) {
JSONObject dataRow = dataArray.getJSONObject(i);
ArrayList arrRow = new ArrayList();
for (int j = 0; j < dataRow.length(); j++)
{
arrRow.add(GetParameterFromJson(String.valueOf(j), dataRow));
}
arrTable.add(arrRow);
}
return arrTable;
}
return data.get(key);
}
}
package org.common;
import java.util.*;
import java.io.*;
import org.json.*;
import java.sql.*;
/**
*
*
* @author chengj
*/
public class JsonResponse {
public static String GetQuery(ResultSet rs) {
try {
ResultSetMetaData rsmd = rs.getMetaData();
StringWriter sw = new StringWriter();
JSONWriter writer = new JSONWriter(sw);
writer.array();
while (rs.next()) {
writer.object();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
writer.key(rsmd.getColumnName(i).toUpperCase());
writer.value(rs.getString(i));
}
writer.endObject();
}
writer.endArray();
rs.close();
return sw.getBuffer().toString();
} catch(SQLException e) {
System.out.println(e.toString());
return null;
} catch(JSONException e) {
System.out.println(e.toString());
return null;
}
}
public static String GetTable(ArrayList tdata){
try {
StringWriter sw = new StringWriter();
JSONWriter writer = new JSONWriter(sw);
writer.array();
for (int i = 0; i < tdata.size(); i++) {
writer.object();
ArrayList arrRow = (ArrayList)tdata.get(i);
for (int j = 0; j < arrRow.size(); j++) {
writer.key(String.valueOf(j));
writer.value((String)arrRow.get(j));
}
writer.endObject();
}
writer.endArray();
return sw.getBuffer().toString();
} catch(JSONException e) {
System.out.println(e.toString());
return null;
}
}
}
DBAccess.java,连接数据库的类
package org.common;
import java.util.*;
import java.sql.*;
/**
*
*
* @author chengj
*/
public class DBAccess {
public Connection conn = null;
public DBAccess() {
try {
Class.forName("org.sqlite.JDBC");
this.conn = DriverManager.getConnection("jdbc:sqlite:test.db3");
} catch(ClassNotFoundException e) {
System.out.println(e.toString());
} catch(SQLException e) {
System.out.println(e.toString());
}
}
protected void finalize() {
try {
this.conn.close();
} catch(SQLException e) {
System.out.println(e.toString());
}
}
}
second.jsp,第二个页面
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >
<html>
<head>
<title></title>
<script src="script/jquery.js" type="text/javascript"></script>
<script src="script/json2.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#ret_table').empty();
var htm = '<table border="1">';
var objret = JSON.parse('<%= request.getAttribute("param") %>');
for(i=0; i<objret.length; i++){
htm += '<tr>';
htm += '<td>' + objret[i]['0'] + ' </td>';
htm += '<td>' + objret[i]['1'] + ' </td>';
htm += '<td>' + objret[i]['2'] + ' </td>';
htm += '</tr>';
}
htm += '</table>'
$('#ret_table').append(htm);
$("#b_back").click( function() {
$("#form1").attr("action", "HelloWorldExample");
$("#form1").submit();
return true;
});
});
</script>
</head>
<body>
<form id="form1" method="post" >
<p>second jsp</p>
<p id="ret_table"></p>
<input type="button" value="back" id="b_back" />
</form>
</body>
</html>
后记:
以上只是一个大概的构思框架,最近没有java的项目,所以也没有机会在实际中使用,完善,所以很简陋。希望有兴趣的朋友补充。