人事部门管理系统(3) - [Struts]
为了页面可以显示中文,我们首先利用sturts的一个扩展功能,可以实现(相当于servlet中的过滤功能):
<controller contentType="text/html;charset=UTF-8" locale="true" processorClass="companypj.MyProRequestProcessor" />
struts_config中的controller标签写入这样的代码,表明在每次处理代码之前先进入MyProRequestProcessor类里面,我们看下这个类:
import org.apache.struts.action.RequestProcessor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.tiles.TilesRequestProcessor;
public class MyProRequestProcessor extends TilesRequestProcessor
{
protected boolean processPreprocess (HttpServletRequest request,
HttpServletResponse response)
{
try
{
request.setCharacterEncoding("UTF-8");
//other code
}
catch(Exception e){}
return true;
}
}
因为页面jsp使用的是utf-8,所以这里也做了下utf-8的预处理。重写原来的processPreprocess()方法,这个方法在父类TilesRequestProcessor里面是一个空的方法。为了方便我们以后使用,俗称的预处理功能。
下面我们看一下struts中的国际化配置:
<message-resources parameter="ApplicationResources" />
实在不愿意说国际化,这个工作就是民工的活,简单且繁重。。pass
下面还有两个插件,一个是tiles框架,一个validator框架,都是struts中的经典:
<set-property property="definitions-config" value="/WEB-INF/tiles-congfig.xml" />
<set-property property="definition-parser-validate" value="true"/>
</plug-in>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>
细心的朋友可能发现在sidebar页面有一个小太阳或小月亮的图标,后面跟随时间,来看看那段代码的实现吧:
在jsp页面有这样两行代码,一个是调出年月日,一个是调出图标:
<%=companypj.OtherBean.getTime()%>
<img src="<%=companypj.OtherBean.bgPhoto()%>" alt="" >
下面我们查看一下OtherBean类:
import java.util.*;
import java.text.SimpleDateFormat;
public class OtherBean {
public static String getTime() {
Date now = new Date();
SimpleDateFormat smpDateFormat =
new SimpleDateFormat("yyyy-MM-dd");
String buf = smpDateFormat.format(now);
return buf;
}
public static String bgPhoto() {
GregorianCalendar calendar = new GregorianCalendar();
String bgcolor = "";
String path1="img/time/1.gif";
String path2="img/time/2.gif";
int hour = calendar.get(Calendar.HOUR_OF_DAY)+8;
if(hour>6&&hour<18)
{
bgcolor=path1;
//return bgcolor;
}
else if(hour<=6)
{
bgcolor=path2;
//return bgcolor;
}
else if(hour>=18)
{
bgcolor=path2;
//return bgcolor;
}
System.out.println(hour);
System.out.println(bgcolor);
return bgcolor;
}
public static void main(String arg[]) {
new OtherBean().bgPhoto();
}
}
这里就可以清楚的看到为了图片会变化的原因了。另外,因为在虚拟机JVM上面跑,用的是GMT时间,必须+8才能是北京时间。
另外值得说一下的是,在超链接“查看员工”的时候,有一个以txt打开某员工的信息(为了方便保存档案,大多情况下是Excel,大同小异),它的处理过程是这样的:
<html:link page="/link4_one_loaddown.do" paramId="id" paramName="ID"><bean:message key="lable.emp.read.open"/></html:link>
在配置文件中的代码:
<forward name="link4_one_success" path="/link4_one_view.jsp">
</forward>
接着我们找到LoadDownAction:
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.Action;
import java.util.Collection;
import javax.sql.*;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.apache.struts.validator.DynaValidatorForm;
import java.io.*;
public class LoadDownAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
// DynaValidatorForm empDynForm = (DynaValidatorForm) form;
javax.servlet.ServletOutputStream servletoutputstream = null;
DataSource ds = getDataSource(request);
Log log = LogFactory.getLog("A");
String type = mapping.getParameter();
if (type.equals("link4_one_loaddown")) {
File f = null;
FileInputStream fileinputstream = null;
String downloadfilepath = "/WEB-INF/download/";//定义temp文件存在的目录
String filename = "testDownload.txt";//文件名
String path= request.getRealPath("/");//表示网站所在文件夹
String filepathname = path + downloadfilepath;
//写入文件完成
EmployeeBean empbean = new EmployeeBean(ds);
EmployeeVO emp = empbean.getEmployee(request.getParameter("id"));
//读出文件开始
try {
f = new File(filepathname, filename);
f.createNewFile();//创建文件
LoadDownBean loadbean=new LoadDownBean();
loadbean.writeFile(emp,f); //把人员信息和具体文件传入,写文件的具体过程
//做读出过程
fileinputstream = new FileInputStream(
filepathname+ filename);
servletoutputstream = response.getOutputStream();
response.reset();
response.setHeader("Content-disposition",
"attachment; filename=" + filename);
response.setContentType("text/plain;charset=gb2312");
int j = 0;
int k = 0;
byte abyte0[] = new byte[1024];
while ((k = fileinputstream.read(abyte0)) != -1) {
j += k;
servletoutputstream.write(abyte0);
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
//最后删除文件
try {
servletoutputstream.close();
fileinputstream.close();
File f1 = new File(filepathname+filename);
if (f1.exists()) {
System.out.println("linnan");
f1.delete(); //删除File.txt文件
}
} catch (Exception ex1) {
ex1.printStackTrace();
}
}
//跳转回页完成,把原来信息再显示
emp = empbean.getEmployee(request.getParameter("id"));
request.setAttribute(Constants.EMP_KEY, emp);
return mapping.findForward("link4_one_success");
}
return null;
}
}
request.getRealPath("/") 表示网站所在文件夹;
request.getRealPath(". /") 表示本网页所在文件夹;
request.getRealPath(". . /") 表示本网页文件夹的上层文件夹;
上面每一部我都写了注释,方便理解,再来看下LoadDownBean,它就是做在txt里面的具体写入些什么,包括简单的排版:
package companypj;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import java.io.*;
public class LoadDownBean {
Log log = LogFactory.getLog("A");
public void writeFile(EmployeeVO emp, File f) {
try {
FileWriter fw = new FileWriter(f);
BufferedWriter bw = new BufferedWriter(fw);
byte[] line = new byte[128];
bw.write("*****************************");
bw.write("*****************************");
bw.write("员工ID号:"+emp.getId());
bw.newLine(); //断行
//bw.write("\r\n");
bw.write("员工姓名:"+emp.getName());
bw.newLine();
bw.write("*****************************");
bw.write("*****************************");
bw.write("性别:"+emp.getSex());
bw.newLine();
bw.write("年龄:"+emp.getAge());
bw.newLine();
bw.write("月薪:"+emp.getSalary());
bw.newLine();
bw.write("所在部门:"+emp.getDepartment());
bw.newLine();
bw.write("婚否:"+emp.getMarriage());
bw.newLine();
bw.write("家庭住址:"+emp.getAddress());
bw.newLine();
bw.write("联系电话:"+emp.getPhone());
bw.newLine();
bw.write("员工简历:");
bw.write("\r\n");
bw.write(emp.getResume());
bw.flush(); //将数据更新至文件
fw.close(); //关闭文件流
bw.close();
} catch (Exception e) {
// out.println(e);
e.printStackTrace();
}
}
}
好了,该讲的重点,到这里都讲完了!
人事部门管理系统(2) - [与JAVA共舞]
添加部门表单页与上篇文章说的添加添加雇员程序思路大体一致,这里就不再赘述。下面我们看一下”管理部门员工 “功能的实现,主要思想:遍历和删除。如图:
数据库里写的东西很杂,呵呵。但我们主要关注的还是程序的实现!这个链接是link3.do,我们来看一下它在Stuts-config中的配置:
<action path="/link3" parameter="link3" type="companypj.Link3Action" validate="false" >
<forward name="link3_success" path="/link3.jsp">
</forward>
这里看到,没有作任何处理,它直接转到了Link3Action。那么我们看这个Atcion是怎么写的:
if (type.equals("link3")) {
log.info("return_link3..");
DepartmentBean depbean=new DepartmentBean(ds);
Collection DEPARTMENTS=depbean.getDepartments(); //取得所有部门信息
request.setAttribute(Constants.DEPARTMENTS_KEY,DEPARTMENTS);//request到下一个页面
return mapping.findForward(Constants_url.RETURN_LINK3_SUCCESS);//给sturts mapping传一个值
}
好了,转到getDepartments():
public Collection getDepartments()
{
log.info("提交所有部门数据集合");
return this.getDepartmentsHelper(Constants_sql.DEPARTMENT_ALL_SQL);
}
这里还是看不出什么,只是借助了Constants_sql类得到一个常量,上次我没有详细介绍过这里,这次我们来看看这个常量的定义:
public class Constants_sql {
public Constants_sql() {
}
public static final String DEPARTMENT_ADD_SQL=
"insert into department(name,description,leader,phone,address,starttime,info)values(?,?,?,?,?,?,?)";
public static final String DEPARTMENT_ALL_SQL="select * from department where name!='无部门' order by id desc"; //这里就是我们调用的常量
public static final String EMP_ADD_SQL=
"insert into employee (name,sex,age,salary,department,marriage,address,phone,resume) values(?,?,?,?,?,?,?,?,?)";
public static final String EMP_ALL_SQL="select * from employee where department!='无部门' order by id desc";
public static final String EMP_TEMP_ALL_SQL="select * from employee where department='无部门' order by id desc";
//public static final String
}
DEPARTMENT_ALL_SQL:把table department中所有name非'无部门'的记录取出,并降序排列。
回到getDepartments()方法,这个方法就是为了更好的解耦合,之后它再调用getDepartmentsHelper()方法,并且传入了一个String DEPARTMENT_ALL_SQL;getDepartments()方法:
private Collection getDepartmentsHelper(String sql) //遍历集合 帮助方法
{
Collection list=new ArrayList();
try {
Connection conn=ds.getConnection();
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery(sql);
while(rs.next())
{
DepartmentVO departmentvo=new DepartmentVO();
// log.info("取部门数据开始");
departmentvo.setId(rs.getInt("id"));
departmentvo.setName(rs.getString("name"));
departmentvo.setDescription(rs.getString("description"));
log.info(rs.getString("description"));
departmentvo.setLeader(rs.getString("leader"));
departmentvo.setPhone(rs.getString("phone"));
departmentvo.setAddress(rs.getString("address"));
departmentvo.setStarttime(rs.getString("starttime"));
departmentvo.setInfo(rs.getString("info"));
list.add(departmentvo);
// log.info("取部门数据结束");
}
conn.close();
stmt.close();
rs.close();
} catch (SQLException ex) {
ex.getMessage();
}
return list;
}
返回list,而list里面就是我们要的部门集合;拿着它返回页面遍历即可;就是上面的这两句:
request.setAttribute(Constants.DEPARTMENTS_KEY,DEPARTMENTS);//request到下一个页面
return mapping.findForward(Constants_url.RETURN_LINK3_SUCCESS);//给sturts mapping传一个值
返回的时候依旧是先调用一个常量类(我发现我那时写程序真够BT的了,BT..病态)
public static final String RETURN_LINK3_SUCCESS="link3_success";
把link3_success信息传给strut_config来处理,Struts这句话是用来接收它的:
<forward name="link3_success" path="/link3.jsp">
好了,现在我们来看看link3.jsp的组成,Tiles配置:
<definition extends="layout-definition" name="link3-definition">
<put name="content" value="return/departmentManage.jsp"></put>
</definition>
从这里看到,实际把权的是departmentManage.jsp页。看看它的信息:
<table cellpadding="0" cellspacing="5" width="100%" >
<tr>
<td width="14%"><bean:message key="lable.dept.row.id"/></td>
<td width="14%"><bean:message key="lable.dept.row.name"/></td>
<td width="14%"><bean:message key="lable.dept.row.leader"/></td>
<td width="14%"><bean:message key="lable.dept.row.add.emp"/></td>
<td width="14%"><bean:message key="lable.dept.row.delete.emp"/></td>
</tr>
<tr>
<td width="100%" colspan="5">
<page:pager dz="5">
<%int i=1; %>
<logic:iterate id="departments" name="DEPARTMENTS" type="companypj.DepartmentVO">
<table border="1" cellpadding="0" cellspacing="1" style="border-collapse: collapse" width="100%" >
<page:item nr="<%=i++%>">
<tr>
<td width="14%"><bean:write name="departments" property="id"/></td>
<td width="14%"><bean:write name="departments" property="name"/></td>
<td width="14%"><bean:write name="departments" property="leader"/></td>
<td width="14%"><html:link page="/link3_add.do">
<bean:message key="lable.dept.add.emp"/>
</html:link></td>
<td width="14%">
<bean:define id="dep_id" name="departments" property="id">
</bean:define>
<html:link page="/link3_delete.do" paramId="dep_id" paramName="dep_id">
<bean:message key="lable.dept.delete.emp"/>
</html:link>
</td>
</tr>
</page:item>
</table>
<br>
</logic:iterate>
</page:pager>
</td>
</tr>
</table>
<center>
<p>
<page:bt/>
<%@taglib uri="/WEB-INF/jpager.tld" prefix="page"%>这里的pager标签是分页用的插件,我们先不去考虑它,在最后的时候我再讲关于这个项目外的一些扩展功能。
从上面jsp我们可以看到logic遍历,还有一些很重要的东西,一个是添加员工到部门的功能,主要我的话,这个和添加新员工有一定的区别,是把一些'‘无部门’的员工加入到该部门。为什么会出现"无部门"员工呢?出于种种原因的考虑,主要是因为员工档案的重要性,所以这个项目的删除员工并非是作delete操作,还是update,把某员工的部门属性到上标记。也考虑到新员工不一定会直接配分到某部门,可能再过一段时间。再来还有一个逻辑性的问题,在删除一个部门的时候,员工必须先转移到别的部门,这么以来。删除员工的操作势必不可行。
<bean:message key="lable.dept.add.emp"/>
</html:link>
如图:

在这里,我们就可以看到所有”无部门“人员列表。
jsp页面,我全部是用<bean:message标签来做的,lable.dept.add.emp对应资源文件中的uc码,也就是”添加“。link3_add.do,那我们跟着这条线走吧。。
Link3Action:
if(type.equals("link3_add"))
{
log.info("link3_temp..");
EmployeeBean empbean=new EmployeeBean(ds);
Collection EMPSTEMP=empbean.getTempEmps(); //这里就看到了取得TEMP员工的方法
request.setAttribute(Constants.EMPS_TEMP_KEY,EMPSTEMP);
return mapping.findForward(Constants_url.RETURN_LINK3_ADD_SUCCESS);
}
看一下getTempEmps()方法,下面的一系列程序是在做找到所有没有部门的员工:
public Collection getTempEmps() { //获得所有无部门的员工
return this.getEmployeesHelper(Constants_sql.EMP_TEMP_ALL_SQL);
}
这里值得注意的是SQL的写法EMP_TEMP_ALL_SQL:
接着看实质的方法getEmployeesHelper:
private Collection getEmployeesHelper(String sql) {
Collection list = new ArrayList();
try {
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
EmployeeVO employeeVO = new EmployeeVO();
log.info("取人员信息开始");
employeeVO.setId(rs.getInt("id"));
employeeVO.setName(rs.getString("name"));
employeeVO.setSex(rs.getString("sex"));
employeeVO.setAge(rs.getInt("age"));
employeeVO.setSalary(rs.getString("salary"));
employeeVO.setDepartment(rs.getString("department"));
employeeVO.setMarriage(rs.getString("marriage"));
employeeVO.setAddress(rs.getString("address"));
employeeVO.setPhone(rs.getString("phone"));
employeeVO.setResume(rs.getString("resume"));
list.add(employeeVO);
log.info("取人员信息结束");
}
conn.close();
stmt.close();
rs.close();
} catch (SQLException ex) {
}
return list;
}
OK,已经取得list集合,返回,并遍历显示到页面即可!
下面这个是删除部门中员工的链接:
<bean:define id="dep_id" name="departments" property="id">
</bean:define>
<html:link page="/link3_delete.do" paramId="dep_id" paramName="dep_id">
<bean:message key="lable.dept.delete.emp"/>
先要确定某一部门的id,得到id后,相应的去数据库中找到集合。如图:

在Action中的取得方法:
if(type.equals("link3_delete"))
{
log.info("delete ready..");
EmployeeBean empbean=new EmployeeBean(ds);
Collection DEPTEMPS=empbean.getDepartemtDemployees(request.getParameter("dep_id"));
request.getSession().setAttribute("DEP_ID",request.getParameter("dep_id"));
//保存部门ID号,以便删除之后可以返回页
request.setAttribute(Constants.DEPT_EMPS_KEY,DEPTEMPS);
return mapping.findForward(Constants_url.RETURN_LINK3_Delete_READY);
}
最先调用的方法getDepartemtDemployees():
public Collection getDepartemtDemployees(String dep_id) { //指定部门中的员工
log.info("该部门是:" + dep_id);
String sql_dep =
"select * from employee where department=(select name from department where id=" +
dep_id + ")";
log.info(sql_dep);
return this.getEmployeesHelper(sql_dep);
}
这里的SQL挺有意思,带有子查询,当然写法很多,不止这一种。
接着转入帮助方法getEmployeesHelper();帮助方法都是一样,上面已经写出,不再重复。不过写到现在,可以明显看出,实际操作的方法并不多,都是经过bean前的一个方法中转——解耦。
好了,接下来说一下删除部门中的某一个成员:
上面说到把某部门的所有成员遍历到页面显示,返回的集合是:
下面到对应的jsp页面来看下:
<logic:iterate id="dept_emps" name="DEPTEMPS">
<page:item nr="<%=i++%>">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" width="100%">
<tr>
<td width="33%"><bean:write name="dept_emps" property="id"/>��</td>
<td width="33%"><bean:write name="dept_emps" property="name"/></td>
<td width="34%">
<bean:define id="ID" name="dept_emps" property="id"/>
<html:link page="/link3_deleted.do" paramId="id" paramName="ID">
<bean:message key="lable.delete.emp.this"/>
</html:link>
</td>
</tr>
</table>
<br>
</page:item>
</logic:iterate>
这里可以看出,name已经接收了返回的集合,并做了遍历,而删除按钮lable.delete.emp.this做了一个超链,带有传参:传的是员工的id号,我们下面看看后台它的运作过程:
if(type.equals("link3_deleted"))
{
EmployeeBean empbean=new EmployeeBean(ds);
empbean.deleteEmployee(request.getParameter("id"));//删除某个员工
Collection DEPTEMPS=empbean.getDepartemtDemployees(String.valueOf(request.getSession().getAttribute("DEP_ID")));//再取部门人员
log.info("转发回页面");
request.setAttribute(Constants.DEPT_EMPS_KEY,DEPTEMPS);
return mapping.findForward(Constants_url.RETURN_LINK3_DeleteD_SUCCESS);
}
return null;
}
中间层调用了两个方法,一个是删除员工,为了删除后保持页面的一致性,再重新遍历一下该部门的所有员工:
而部门ID已经存入了session中,为DEP_ID。先看deleteEmployee():
public void deleteEmployee(String id) {
try {
log.info("1");
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
String sql_update = "update employee set department='无部门' where id=" +
id + "";
log.info(sql_update);
stmt.executeUpdate(sql_update);
log.info("2");
conn.close();
stmt.close();
} catch (SQLException ex) {
}
删除方法够简单的,传进id,update把dep字段改成"无部门"就OK。
重新遍历出员工和上一个超级链接做的是一样的工作,然后还是返回刚才的页面,可以看见新的数据。
(1) 在tag.asp中找到以下代码:
<a href="default.asp?tag=<%=Server.URLEncode(log_Tag(1))%>" title="共包含 <%=log_Tag(2)%> 篇日志"><span style="font-size:<%=getTagSize(log_Tag(2))%>px"><%=log_Tag(1)%></span></a>
将其改为:
<a href="default.asp?tag=<%=Server.URLEncode(log_Tag(1))%>" style="font-size:12px;line-height:250%" title="共包含 <%=log_Tag(2)%> 篇日志"><%=log_Tag(1)%><span style="font-size:11px;color:#ccc">[<%=log_Tag(2)%>]</span></a>
(2) 在common文件夹下找到cache.asp,在“写入标签Tag缓存”中找到
Select tag_id,tag_name,tag_count FROM blog_tag
将其改为
Select tag_id,tag_name,tag_count FROM blog_tag orDER BY tag_count DESC,tag_id ASC
(3) 重建数据缓存。
人事部门管理系统(1) - [与JAVA共舞]
下面介绍我去年11月编写的一套人事部门管理系统,项目用时一周(需求分析2天,美工设计2天,其余时间为代码实现)。如图:

需求文档的地址:http://www.new321.com/blog/attachments/month_0703/person_xuqiu.htm
从需求文档可以看出,这个项目的布局是由Tiles框架完成的。我们要作的是首先设计出一个完成的框架布局结构页layout.jsp.然后在其中定义其他页面分布位置。此项目共有四部分组成:siderbar.jsp用来作左侧列表选择,header.jsp用来放置logo,footer.jsp用于作者声明,另外一个至关重要的部分是可变的——随着siderbar.jsp的超链接选择而变。有了这种思想以后就可以写tiles-config了:
<definition name="layout-definition" path="/layout.jsp">
<put name="sidebar" value="sidebar.jsp"></put>
<put name="header" value="header.jsp"></put>
<put name="content"></put>
<put name="footer" value="footer.jsp"></put>
</definition>
从上面可以看出内容是可变的,这段代码是接下来所有代码的父级代码,用于作继承之用。
接下来作一个内容页:
<definition extends="layout-definition" name="index-definition">
<put name="content" value="indexContent.jsp"></put>
</definition>
从name大致可以看出这个是为了index首页来使用的。而在index.jsp页面写入代码
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<tiles:insert definition="index-definition">
</tiles:insert>
这样即可,其实我们最关心的是列表(siderbar)及其内容(contents)部分。它们之间的互动性是我们使用tiles框架的原因。
列表的第一个超链接是"添加员工":
<html:link page="/link1.do"><font color="#000000" style="text-decoration: none"><bean:message key="link.add.emp"/></font></html:link>
link.add.emp分别对应两份bundle文件——这里使用了中英文国际化。国际化是一种反复的简单劳动,这里就不多作阐述了。我们关心的是link1.do的走向,看sturts-config:
<action path="/link1" parameter="link1" type="companypj.AddEmployeeAction" validate="false">
<forward name="link1_success" path="/link1.jsp">
</forward>
进入AddEmployeeAction
图1-1,AddEmployeeAction全部代码:
public class AddEmployeeAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
DynaValidatorForm empDynForm=(DynaValidatorForm)form;
Log log=LogFactory.getLog("A");
String type=mapping.getParameter();
DataSource ds=getDataSource(request);
if(type.equals("link1"))
{
log.info("return_link1..");
DepartmentBean departmentbean=new DepartmentBean(ds);
Collection onlydep=departmentbean.getOnlyDepartments();//这里转入部门类,取出部门集合
request.getSession().setAttribute(Constants.ONLYDEPARTMENTS_KEY,onlydep);//集合保存,并传入下一页面
return mapping.findForward(Constants_url.RETURN_LINK1_SUCCESS);
}
if(type.equals("link_addemp"))
{
EmployeeBean empbean=new EmployeeBean(ds);
//String address=empDynForm.get("address").toString();
empbean.addEmployee(empDynForm);
return mapping.findForward(Constants_url.RETURN_ADD_EMP_READY);
}
return null;
}
}
再来看下面的getOnlyDepartments()方法,用于取出部门的方法
public Collection getOnlyDepartments() //只找出所有部门的集合,这个方法多此一举,都是动态数据即时更新的,所有没必要用它,当写着玩了~
{
Collection list=new ArrayList();
Collection departments = this.getDepartments();//跳转
Iterator i = departments.iterator();
while(i.hasNext()) {
DepartmentVO Onlydepartments=(DepartmentVO) i.next();
log.info("Onlydep:"+Onlydepartments.getName());
Onlydepartments.setName(Onlydepartments.getName()); //筛选后重新放入
list.add(Onlydepartments);
}
return list;
}
。。。不看不知道,当初我还写了不少没用的解释,哈哈!注意这里有个跳转,跳转到另一个方法,接着看:
public Collection getDepartments()
{
log.info("提交所有部门数据集合");
return this.getDepartmentsHelper(Constants_sql.DEPARTMENT_ALL_SQL);
}
这个方法也只是为了层次清晰和重用性,接着把一条SQL丢给下面赶事实的方法getDepartmentsHelper():
private Collection getDepartmentsHelper(String sql) //遍历集合 帮助方法
{
Collection list=new ArrayList();
try {
Connection conn=ds.getConnection();
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery(sql);
while(rs.next())
{
DepartmentVO departmentvo=new DepartmentVO();
log.info("取部门数据开始");
departmentvo.setId(rs.getInt("id"));
departmentvo.setName(rs.getString("name"));
departmentvo.setDescription(rs.getString("description"));
log.info(rs.getString("description"));
departmentvo.setLeader(rs.getString("leader"));
departmentvo.setPhone(rs.getString("phone"));
departmentvo.setAddress(rs.getString("address"));
departmentvo.setStarttime(rs.getString("starttime"));
departmentvo.setInfo(rs.getString("info"));
list.add(departmentvo);
log.info("取部门数据结束");
}
conn.close();
stmt.close();
rs.close();
} catch (SQLException ex) {
ex.getMessage();
}
return list;
}
OK,拿到了所有部门的所有信息;回到上面那句:
看来当时我是想作一个优化,减轻页面的负担,而在后台多了下些功夫,现在想来大可不必,不如直接另写一个找差name的SQL语句。。我当时大脑在想些什么哩。。
回到图1-1中的
存入session中,返回到添加员工表单;

箭头所指,就是我们刚才作遍历出来的部门集合位置。
回到了link1.jsp,而在tiles中实际表单位置是CreateEmployee.jsp:
<definition extends="layout-definition" name="link1-definition">
<put name="content" value="return/CreateEmployee.jsp"></put>
</definition>
下面找CreateEmployee.jsp代码,代码太多,我把主要的写上,至于其他部分感兴趣可以去下载我整个项目来看,我提供了下载。
这里是拿到部门集合在表单上的遍历:
<html:select property="department">
<logic:iterate id="onlydep" name="ONLYDEPARTMENTS" type="companypj.DepartmentVO" scope="session">
<option value="<bean:write name="onlydep" property="name"/>">
<bean:write name="onlydep" property="name"/>
</option>
</logic:iterate>
</html:select>
name拿到了集合,type转型成VO以作分类遍历,scope指定去session中拿。
再来看看表单的提交
在struts-config中找到:
<action input="/link1.jsp" name="EmpForm" path="/link_addemp" parameter="link_addemp"
scope="request" type="companypj.AddEmployeeAction" validate="true" >
看到还是转入AddEmployeeAction,图1-1。但是validate="true",表明先要进行表单验证,那么我们就去看一下配置文件validation:
<formset>
<form name="EmpForm">
<field property="name" depends="required">
<arg0 key="label.emp.name"/>
</field>
<field property="age" depends="required">
<arg0 key="label.emp.age"/>
</field>
<field property="salary" depends="required">
<arg0 key="label.emp.salary"/>
</field>
</form>
</formset>
简单的让人觉得可怜哈,都不为空就行!
PS:这里是作得动态表单,而下一个超链接的部门添加是用了静态表单。别的就没有太多差别,思想都一样!
如果验证通过,转入Action中处理,看代码:
if(type.equals("link_addemp"))
{
EmployeeBean empbean=new EmployeeBean(ds);
//String address=empDynForm.get("address").toString();
empbean.addEmployee(empDynForm);
return mapping.findForward(Constants_url.RETURN_ADD_EMP_READY);
}
addEmployee方法把form接收过去:
public void addEmployee(DynaValidatorForm empDynForm) {
EmployeeVO employeeVO = this.NynaIntoEmp(empDynForm);
String strSQL="{call demo_empadd(?,?,?,?,?,?,?,?,?)}";//存储过程
this.executeEmpHelper(employeeVO, strSQL);
}
这里我作的是一个存储过程:
Create PROCEDURE demo_empadd
@inparam1 varchar(10),@inparam2 varchar(20),@inparam3 int,
@inparam4 varchar(10),@inparam5 varchar(20),@inparam6 varchar(10),
@inparam7 varchar(20),
@inparam8 varchar(10),@inparam9 varchar(40)
AS insert into employee(name,sex,age,salary,department,marriage,address,phone,resume)values
(@inparam1,@inparam2,@inparam3,@inparam4,@inparam5,@inparam6,@inparam7,@inparam8,@inparam9)
GO
接着再转到executeEmpHelper()方法来作实际工作,这时传入了一个VO,和一个存储过程的指令:
private void executeEmpHelper(EmployeeVO employeeVO, String sql) { //帮助方法
try {
Connection conn = ds.getConnection();
java.sql.CallableStatement pstm=conn.prepareCall(sql);
//PreparedStatement pstm = conn.prepareStatement(sql);
log.info("雇员信息开始加入");
pstm.setString(1, employeeVO.getName());
pstm.setString(2, employeeVO.getSex());
pstm.setInt(3, employeeVO.getAge());
pstm.setString(4, employeeVO.getSalary());
pstm.setString(5, employeeVO.getDepartment());
pstm.setString(6, employeeVO.getMarriage());
pstm.setString(7, employeeVO.getAddress());
pstm.setString(8, employeeVO.getPhone());
// log.info("1");
pstm.setString(9, employeeVO.getResume());
// log.info("2");
pstm.executeUpdate();
log.info("雇员信息加入结束");
} catch (SQLException ex) {
}
}
OK,从图1-1中的Action传回一个信号,config接收到
添加完成!
1.继承 ActionForm 的类的所有字段必须为 String 型
2.由于 Date 型转换为 String 需设置 DateFormat ,所以你 Bean 里的日期字段最好用 String
这样就不会出现类型转换错误了。
PS:其实我以前还真没遇到过这样的错误,呵呵。不管怎样,转换之后错误还真就解决了。。。
public class CalendarTest
{
public static void main(String[] args)
{
GregorianCalendar d = new GregorianCalendar();//定义d作为当前日期
int today = d.get(Calendar.DAY_OF_MONTH);
int month = d.get(Calendar.MONTH);
d.set(Calendar.DAY_OF_MONTH, 1);// 设置当前日期d开始月份
int weekday = d.get(Calendar.DAY_OF_WEEK);
System.out.println("Sun Mon Tue Wed Thu Fri Sat");//打印日历头
for (int i = Calendar.SUNDAY; i < weekday; i++ )//缩排日历
System.out.print(" ");
do
{
int day = d.get(Calendar.DAY_OF_MONTH);// 打印天
if (day < 10) System.out.print(" ");
System.out.print(day);
if (day == today)// 做当前天的标记 *
System.out.print("* ");
else
System.out.print(" ");
if (weekday == Calendar.SATURDAY)// 逢星期六开始一个新的行
System.out.println();
d.add(Calendar.DAY_OF_MONTH, 1);//增加 d 到下一天
weekday = d.get(Calendar.DAY_OF_WEEK);
}
while (d.get(Calendar.MONTH) == month);
if (weekday != Calendar.SUNDAY) // 当d 是下个月的第一天退出循环
System.out.println();
}
}
