今天在做一个工作,即jsp想mysql中查询数据后,以json格式返回到客户端(Extjs)中。
下面是解决方法和遇到的问题及解决。
jsp查询mysql昨天已说明,今天着重讨论返回json。
首先,使用JavaBean,让它负责生成json格式(这里做的只是关系数据的二元关系,json格式可以确定),在jsp里调用并传入参数即可,类似其他的第三方库。该JavaBean的源代码如下:
package com.jj.database.util;
import java.util.ArrayList;
public class Json {
public static void main(String[] args) {
// System.out.println("gernerating json.");
}
public String singleInfo="";
protected boolean _success=true;
protected String _error="";
protected ArrayList arrData=new ArrayList();
protected ArrayList dataItem=new ArrayList();
public String getError() {
return _error;
}
public void setError(String error) {
if(!error.equals(""))this._success=false;
this._error = error;
}
public boolean getSuccess() {
return _success;
}
public void setSuccess(boolean success) {
if(success) this._error="";
this._success = success;
}
public Json()
{
}
public void reSet()
{
arrData.clear();
dataItem.clear();
}
public void addItem(String name,String _value)
{
dataItem.add(name);
dataItem.add(_value);
}
//一个数组添加完毕,一个新的数组开始
public void addItemOk()
{
arrData.add(dataItem);
dataItem=new ArrayList();
}
public String ToString()
{
StringBuilder sb=new StringBuilder();
sb.append("{");
sb.append("/"datas/":");
sb.append("[");
int ad=arrData.size();
for(int i=0;i<ad;i++)
{
ArrayList arr=(ArrayList)(arrData.get(i));
sb.append("{");
int t=arr.size();
for(int j=0;j<t;j+=2)
{
if(j==t) break;
sb.append("/'");
sb.append(arr.get(j).toString());
sb.append("/'");
sb.append(":");
sb.append("/'");
sb.append(arr.get(j+1).toString());
sb.append("/'");
if(j<t-2) sb.append(",");
}
sb.append("}");
if(i<ad-1) sb.append(",");
}
sb.append("]");
sb.append("}");
return sb.toString();
}
}
public static void main(String[] args) {
// System.out.println("gernerating json.");
}
public String singleInfo="";
protected boolean _success=true;
protected String _error="";
protected ArrayList arrData=new ArrayList();
protected ArrayList dataItem=new ArrayList();
public String getError() {
return _error;
}
public void setError(String error) {
if(!error.equals(""))this._success=false;
this._error = error;
}
public boolean getSuccess() {
return _success;
}
public void setSuccess(boolean success) {
if(success) this._error="";
this._success = success;
}
public Json()
{
}
public void reSet()
{
arrData.clear();
dataItem.clear();
}
public void addItem(String name,String _value)
{
dataItem.add(name);
dataItem.add(_value);
}
//一个数组添加完毕,一个新的数组开始
public void addItemOk()
{
arrData.add(dataItem);
dataItem=new ArrayList();
}
public String ToString()
{
StringBuilder sb=new StringBuilder();
sb.append("{");
sb.append("/"datas/":");
sb.append("[");
int ad=arrData.size();
for(int i=0;i<ad;i++)
{
ArrayList arr=(ArrayList)(arrData.get(i));
sb.append("{");
int t=arr.size();
for(int j=0;j<t;j+=2)
{
if(j==t) break;
sb.append("/'");
sb.append(arr.get(j).toString());
sb.append("/'");
sb.append(":");
sb.append("/'");
sb.append(arr.get(j+1).toString());
sb.append("/'");
if(j<t-2) sb.append(",");
}
sb.append("}");
if(i<ad-1) sb.append(",");
}
sb.append("]");
sb.append("}");
return sb.toString();
}
}
遇到的问题是:将JavaBean源文件编译后,把class文件放在同一目录下。在jsp文件中使用<%@page import ="com.jj.database.util.Json"%>时,无法正确引入JavaBean,报错:
参考很久。大致的解决方法有:org.apache.jasper.JasperException: Exception in JSP:.......................
1)将<%javahome%>/lib/tools.jar拷贝到<%tomcat_home%>/common/lib下,然后重启tomcat。
2)在系统环境变量CLASSPATH中加入tools.jar的路径。
但1),2)在我机子上都没效果。
3)我的解决方案:
我的机子上的目录如下(<%tomcat_home%>下);
webapps
ROOT
myjsp
index.jsp
web-inf
classes
com
我将jsp页面放在myjsp中,然后把编译后的com包(包含class文件)拷贝到上面的目录的class下。最后重启tomcat。
然后在jsp中使用下面语句来引用这个JavaBean,<jsp:directive.page import="com.jj.database.util.Json"/>,当然也可以直接使用<%@page import ="com.jj.database.util.Json" %>,即可正确载入。
接下来jsp即可正常引用这个JavaBean,完成生成一个json格式字符串。下面是实例代码(rs是使用mysql查询的结果集):
Json json=new Json();
json.reSet();
json.setSuccess(true);
while(rs.next())
{
json.addItem("provinceid",(new Integer(rs.getInt(1))).toString());
json.addItem("provincename",rs.getString(2));
json.reSet();
json.setSuccess(true);
while(rs.next())
{
json.addItem("provinceid",(new Integer(rs.getInt(1))).toString());
json.addItem("provincename",rs.getString(2));
json.addItemOk();
}
out.print(json.ToString());
下面又遇到了问题,即当客户端向jsp请求数据是,使用上述页面产生结果。而在客户端extjs无法解析。使用firebug调试可看出(或看页面源代码),使用上述的方法返回的数据格式如下:
json-data(/r/n /r/n </body>/r/n</html>/r/n)。
弄了很长时间,终于发现原因了。原来是jsp页面的结构。如果你在jsp里添加了html页面的标签,那么在响应客户端请求时产生一个与jsp同构的html页面,它里面除了包含out.print输出的数据外,还有jsp本身的html结构,这给客户端解析带来麻烦。我的页面最后正好是:
<%
//jsp code, to output json data
%>
</body>
</html>
恰好是上面的json数据后面的28个字符。
解决的方法时去掉jsp中的html标签即可,这时即产生完整的json格式数据。
然后使用js中的eval函数,将接收到的json字符串转化为json对象,格式如下(设该字符串是str),
var jsondata = eval('('+str+')'),直接把str作为参数不行。这里jsondata就是一个json对象,你可以使用它或任意引用它里面的数据。以我这里的数据为例:
str ={datas:[{'provinceid':'1','provincename':'beijing'},{'provinceid':'2','provincename':'shanghai'}]}
转化后可以引用jsondata.datas[0].provinceid等,也可以直接把jsondata作为jsonStore的data参数,然后按照它的结构设计一个jsonReader即可。
下面的截图即为今天的成果
<无法显示>
下面仍有很长的路要走,继续努力。
参考