之前写了如何登陆,另外在数据库的USER表里添加了一个标志字段,这样做有些不方便,就是用户被强制的登入登出;先不管这些,下面要做的就是search页面,还要实现对搜索结果的操作。
使用简单的bean和logic标签完成多数据显示,具体的实现方法:
search.jsp
<%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
使用到的标签库
<html>
<head>
<title>Search Page</title>
<html:base/>
</head>
<body bgcolor="white">
<html:form action = "/search">
<table border="0" width = "100%">
<tr>
<th align = "right"><bean:message key="search.key.appname"/></th>
可以尝试使用多一点的bean:message标签,这样可以使用不同的资源文件实现所谓的“国际化”;
<td align = "left"><html:text property="appname"/>(Optional)</td>
</tr>
<tr>
<th align="right"><bean:message key="search.key.taskname"/></th>
<td align="left"><html:text property="bugname"/>(Optional)</td>
</tr>
<tr>
<td align="right"><input type= submit value = "Get the values"/></td>
</tr>
</table>
</html:form>
<logic:present name="searchForm" property="results">
logic:present用来判断searchForm的results属性是否有值,有的话运行下面的语句;没有就跳到标签结束处。
<hr width="100%" size="1" noshade = "true">
<bean:size id="size" name="searchForm" property="results"/>
bean:size取得list变量的长度,这里是我们要的结果的条数;
<logic:equal name="size" value="0">
<center>
<font color="red"><b>No Bugs Found</b></font>
</center>
</logic:equal>
<logic:greaterThan name="size" value="0">
<table border="1">
<tr>
<th>Project</th>
<th>Project Status</th>
<th>Task</th>
<th>Task Status</th>
<th>Task Report</th>
<th>Task Solution</th>
<th>Report-er</th>
<th>Report Date</th>
<th>Check-er</th>
<th>Check Date</th>
<th>Fix-er</th>
<th>Fix Date</th>
<th>Used Time</th>
<th>Recheck-er</th>
<th>Recheck Date</th>
<th/>
</tr>
<logic:iterate id="result" name="searchForm" property="results">
<tr>
<th><bean:write name="result" property="p_name"/></th>
<th><bean:write name="result" property="p_status"/></th>
<th><bean:write name="result" property="t_name"/></th>
<th><bean:write name="result" property="t_status"/></th>
<th><bean:write name="result" property="t_problem"/></th>
<th><bean:write name="result" property="t_solution"/></th>
<th><bean:write name="result" property="t_rpt"/></th>
<th><bean:write name="result" property="t_rpt_date"/></th>
<th><bean:write name="result" property="t_chk"/></th>
<th><bean:write name="result" property="t_chk_date"/></th>
<th><bean:write name="result" property="t_fix"/></th>
<th><bean:write name="result" property="t_fix_date"/></th>
<th><bean:write name="result" property="t_time"/></th>
<th><bean:write name="result" property="t_rchk"/></th>
<th><bean:write name="result" property="t_rchk_date"/></th>
这种实现方法中核心的代码:使用bean:write标签写入java bean里面的数据,这个bean很普通,一些get/set方法,具体实现看下面的代码。
<th><html:button property=""/>
这个东西是用来操作每个结果的,比如修改、改变状态等等。当然,这里可能会用到LookupDispatchAction类,这个类在之后的我会使用到,这里不作介绍。
</tr>
</logic:iterate>
</table>
</logic:greaterThan>
</logic:present>
<html:errors/>
</body>
</html>
我们来看看这个jsp文件,很简单,有就显示,没有不显示,这样会增加页面的使用面积。那么,Form文件和Action文件是怎么结合bean完成从持久层到表现层的数据传输的呢?换句话说,就是如何将数据从数据库中取出来并显示在IE里?
我做了一个概括,这很有趣:
1_ 在Form中写一个可以接收从bean传输过来的list对象;
2_ 写一个bean,将数据库的每个column以bean元素的属性的方式存储在一定的数据格式中,常用的有list,set等;
3_ 在Action里填充bean的属性值,实现bean与数据库的对话;
然后你就会发现,数据显示在IE中了;而需要注意的是bean:write对应的prepority属性就是bean里定义的属性,他们的名字是严格对应的。
searchForm.java
package com.XXX.actionform;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
/**
*
* @author tony
*/
public class searchForm extends ActionForm{
private String appname;
private String bugname;
private List results;
public String getAppname(){
return this.appname;
}
public void setAppname(String appname){
this.appname = appname;
}
public String getBugname(){
return this.bugname;
}
public void setBugname(String bugname){
this.bugname = bugname;
}
public List getResults(){
return this.results;
}
public void setResults(List results){
this.results = results;
}
public void reset(ActionMapping mapping, HttpServletRequest request){
appname = null;
bugname = null;
results = null;
}
}
然后,在写一个普通的bean:Task.java
package com.XXX.bean;
/**
*
* @author tony
*/
public class task {
/** Creates a new instance of task */
public task(String p_name,String t_name,String t_status,String t_solution,String p_status,
String rpt,String rpt_date,String rchk,String rchk_date,String fix,String f_date,
String chk,String chk_date,String t_problem,String fix_time) {
this.t_chk = chk;
this.t_chk_date = chk_date;
this.t_fix_date = f_date;
this.t_fix = fix;
this.t_time = fix_time;
this.p_name = p_name;
this.p_status = p_status;
this.t_problem = t_problem;
this.t_rchk = rchk;
this.t_rchk_date = rchk_date;
this.t_rpt = rpt;
this.t_rpt_date = rpt_date;
this.t_name = t_name;
this.t_solution = t_solution;
this.t_status = t_status;
}
private String p_name;
private String t_name;
private String t_status;
private String t_solution;
private String p_status;
private String t_rpt;
private String t_rpt_date;
private String t_rchk;
private String t_rchk_date;
private String t_fix;
private String t_fix_date;
private String t_chk;
private String t_chk_date;
private String t_problem;
private String t_time;
public String getP_name(){
return this.p_name;
}
public void setP_name(String pn){
this.p_name = pn;
}
public String getT_name(){
return this.t_name;
}
public void setT_name(String tn){
this.t_name = tn;
}
public String getT_status(){
return this.t_status;
}
public void setT_status(String status){
this.t_status = status;
}
public String getT_solution(){
return this.t_solution;
}
public void setT_solution(String solution){
this.t_solution = solution;
}
public String getP_status(){
return this.p_status;
}
public void setP_status(String status){
this.p_status = status;
}
public String getT_rpt(){
return this.t_rpt;
}
public void setT_rpt(String name){
this.t_rpt = name;
}
public String getT_rpt_date(){
return this.t_rpt_date;
}
public void setT_rpt_date(String date){
this.t_rpt_date = date;
}
public String getT_chk(){
return this.t_chk;
}
public void setT_chk(String name){
this.t_chk = name;
}
public String getT_chk_date(){
return this.t_chk_date;
}
public void setChk_date(String date){
this.t_chk_date = date;
}
public String getT_rchk(){
return this.t_rchk;
}
public void setT_rchk(String name){
this.t_rchk = name;
}
public String getT_rchk_date(){
return this.t_rchk_date;
}
public void setT_rchk_date(String date){
this.t_rchk_date = date;
}
public String getT_fix(){
return this.t_fix;
}
public void setT_fix(String name){
this.t_fix = name;
}
public String getT_fix_date(){
return this.t_fix_date;
}
public void setT_fix_date(String date){
this.t_fix_date = date;
}
public String getT_time(){
return this.t_time;
}
public void setT_time(String time){
this.t_time = time;
}
public String getT_problem(){
return this.t_problem;
}
public void setT_problem(String desc){
this.t_problem = desc;
}
}
我单独建个package存放这些bean(以后可能会很多);那么,Action中就是填充bean的属性并把他们和Form连接的关键步骤:
searchAction.java
package com.XXX.action;
import com.esc.actionform.searchForm;
import com.esc.database.Query;
import com.esc.bean.task;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
/**
*
* @author tony
*/
public class searchAction extends Action{
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){
int rownum;
rownum = 0;
String command = null;
String appname = null;
String bugname = null;
searchForm sf = (searchForm)form;
Query qry = new Query();
ArrayList results = new ArrayList();
try{
command = " select ";
command = command + " tasks.TASK_NAME, tasks.TASK_STATUS, tasks.TASK_SOLUTION, taskreport.REPORT_BY, ";
command = command + " taskreport.CHECK_BY, taskreport.FIX_BY,taskreport.RECHECK_BY, ";
command = command + " taskreport.REPORT_DATE, taskreport.CHECK_DATE, taskreport.FIX_DATE, ";
command = command + " taskreport.RECHECK_DATE, taskreport.CHECK_PROBLEM, taskreport.FIX_TIME, ";
command = command + " project.PROJ_NAME,project.PROJ_STATUS ";
command = command + " from taskreport,tasks, project ";
command = command + " where ";
command = command + " taskreport.TASK_ID = tasks.TASK_ID and ";
command = command + " taskreport.PROJ_ID = project.PROJ_ID ";
appname = sf.getAppname();
bugname = sf.getBugname();
if (appname != null && appname.length() > 0){
command += " AND project.PROJ_NAME = '" + sf.getAppname() + "' ";
}
if (bugname != null && bugname.length() > 0){
command += " AND tasks.TASK_NAME = '" + sf.getBugname() + "' ";
}
ResultSet rs = qry.getResult(command);
//rownum = qry.getRowNum(rs);
rownum = qry.getRowNum(rs);
int i = 0;
String[] p_name = new String[rownum];
String[] t_name = new String[rownum];
String[] t_status = new String[rownum];
String[] p_status = new String[rownum];
String[] t_rpt = new String[rownum];
String[] t_rpt_date = new String[rownum];
String[] t_chk = new String[rownum];
String[] t_chk_date = new String[rownum];
String[] t_fix = new String[rownum];
String[] t_fix_date = new String[rownum];
String[] t_rchk = new String[rownum];
String[] t_rchk_date = new String[rownum];
String[] t_problem = new String[rownum];
String[] t_solution = new String[rownum];
String[] t_time = new String[rownum];
task[] tasks = new task[rownum];
if(rownum == 0){
return mapping.findForward("failed");
}else{
for (rs.first(); !rs.isAfterLast(); rs.next()){
p_name[i] = rs.getString("PROJ_NAME");
t_name[i] = rs.getString("TASK_NAME");
t_chk[i] = rs.getString("CHECK_BY");
t_rpt[i] = rs.getString("REPORT_BY");
t_fix[i] = rs.getString("FIX_BY");
t_rchk[i] = rs.getString("RECHECK_BY");
t_chk_date[i] = rs.getString("CHECK_DATE");
t_rpt_date[i] = rs.getString("REPORT_DATE");
t_fix_date[i] = rs.getString("FIX_DATE");
t_rchk_date[i] = rs.getString("RECHECK_DATE");
t_status[i] = rs.getString("TASK_STATUS");
p_status[i] = rs.getString("PROJ_STATUS");
t_problem[i] = rs.getString("CHECK_PROBLEM");
t_solution[i] = rs.getString("TASK_SOLUTION");
t_time[i] = rs.getString("FIX_TIME");
tasks[i] = new task(p_name[i], t_name[i], t_status[i], t_solution[i], p_status[i], t_rpt[i], t_rpt_date[i],
t_rchk[i], t_rchk_date[i], t_fix[i], t_fix_date[i], t_chk[i], t_chk_date[i], t_problem[i], t_time[i]);
results.add(tasks[i]);
i++;
}
sf.setResults(results);
}
}catch(SQLException e){
e.printStackTrace();
return mapping.findForward("failed");
}finally{
qry.closedb();
}
return mapping.findForward("success");
}
}
很简单的做法,完成了每个系统必须的功能;注意红色的代码,他们之间有着密切的联系。
如果你发现这个代码在运行的时候出现Null Pointer的Exception,呵呵,不要紧,这是个很简单的问题,试着自己想想答案,或许你会找到编写代码的乐趣;那么,给你们一个答案:
ResultSet在默认的情况下是个forward only的,一个简单的方法,记得database包么?修改query类的ResultSet的定义如下:
Statement smt = conn.createStatement(rs.TYPE_SCROLL_INSENSITIVE, rs.CONCUR_READ_ONLY);
然后,你会发现getRowNum的方法不是官方的,ok,需要知道的是java没有提供得到结果集条数的方法,我在query类中实现了这个方法,也是常用的:
public int getRowNum(ResultSet rsset) throws SQLException {
int rownum;
rownum = 0;
try{
for(rsset.first(); !rsset.isAfterLast() ; rsset.next()){
rownum ++;
}
}catch(SQLException e){
e.printStackTrace();
return -1;
}
return rownum;
}
嘿嘿,你会发现有了这个方法,这个类会有很大的作用。
“一个人做一个大而实用的系统,没人相信这是可能的。team的理论开始扎根,我想问:中国软件的独狼在哪里?也就是马云称为' 疯子' 的人,他们不会被同化,有着自己的眼光和方向"--------木匠语录