华山论剑

一心一意做技术!

BlogJava 首页 新随笔 联系 聚合 管理
  31 Posts :: 0 Stories :: 447 Comments :: 0 Trackbacks
  (本故事除了部分点明道姓并具有故事详细发生的具体时间点地等部分情节以外,其它内容纯属虚构,若有雷同,纯属巧合。)

  谈到B/S,谈到J2EE,特别涉及到Java Web的部分,我们就会想到三层或多层构架,为什么要多层,肯定是因为一两层已经无法达到用户的需求,技术进步了,三层或多层很多时候其系统的健壮性、可维护性等都较之提升了很多。
  在本系列文章的前两篇中,我们基本上没有涉及到Spring技术的部分,因此,今天换换味,主要给出一个比较简单、实用,也是最庸俗的spring示例。也即实现一个数据表的添删改查操作,笔者采用struts+hibernate+spring黄金庸俗组合来实现。示例比较简单,因此spring的高手及高高手可以忽略示例中的技术细节部分,当然,也请有时间的前辈不吝赐教有关代码的书写方法及技术。
 
  示例程序运行效果,先睹为快:http://www.easyjf.com/html/bbs/20060509/1571738935251539.htm?ejid=1139563413901115
 
  主演:Spring、系统设计师、数据库开发工程师、Web开发工程师、主程序员、系统集成及部署工程师。

  配角:数据库管理员、美工及页面设计MM、html,JSP、Struts、My Sql、hibernate。
 
  下面就是直杀正题吧!
 
第一步:系统设计

  现在你扮演的是系统设计师角色,系统设计师通常都不用管也不想知道你要用什么方法去实现他的东西,他只给你画出草图,制订规矩、条款等,他甚至可以不用知道Java中还有Class这个东西存在。他也不用管你用什么方式存放数据,用什么数据库中间件来操作数据。
  但他站得高,看得远,为了以后的可维护性、灵活性,考虑到会使用多种数据库,以及多种数据库中间件等,因此会先对系统设计建模,通过UML等方式来描述系统流程、组织结构等。同时还会通过使用接口定义出相应的商业逻辑。下面是本例子中的两个业务逻辑层的接口。

第一个是“用户”这一实体的描述,IUser.java,代码如下:
package com.easyjf.example.business;
public interface IUser { 
 public String getBirthday();//生日
 public void setBirthday(String birthday);
 public String getCid();//主键cid
 public void setCid(String cid);
 public String getEmail();//用户邮件email
 public void setEmail(String email);
 public String getIntro();//用户简介intro
 public void setIntro(String intro);
 public String getPassword();//用户密码password
 public void setPassword(String password);
 public String getTel() ;//用户电话tel
 public void setTel(String tel);
 public String getUserName();//用户名userName
 public void setUserName(String userName);
}
第二个是围绕“用户”这一实体所提供的有关服务描述,IUserService.java,代码如下:

package com.easyjf.example.business;
import java.util.Collection;
import java.util.List;
public interface IUserService {
 public IUser newUser(); //创建一个新的用户
 public IUser read(String cid);//根据主键cid读取一个用户
 public List query(String scope,Collection paras);//用户查询
 public IUser readByName(String userName);//根据用户名读取一个用户
 public IUser login(String userName,String password,String ip);//用户登录 
 public boolean save(IUser user);//保存用户
 public boolean update(IUser user);//修改用户
 public boolean del(IUser user);//删除用户
}
 
  除了上面这些,系统设计师还会根据系统需求给出一些具体的设计方法,对系统各层之间的接口规范,Action层使用的框架或模式等。他的工作就算完成了,下面就该程序员、数据库管理员以及页面设计人员等表演了。这些角色在我们实际项目中很多时候是同步进行的,可谓花开N朵。然而本文为了能让新同学把这个示例能跑起来,所以就简单分了一下步骤,以便新同学按步骤进行。
 
第二步:数据库设计及建表 (数据库管理员)
  随便选择一个数据库My SQL,MS SQL或Oracle均可,先建设一张表,表名叫User,字段如下:
cid,代表主键,username-用户名,password-密码,email-电子邮件,tel-电话,birthday-生日,intro-简介,为了演示方便,我们全部字段设置成字符型。
  下面是在My SQL中的表结构脚本:
CREATE TABLE `user` (
  `cid` char(16) NOT NULL,
  `username` char(30) NOT NULL,
  `password` char(30) NOT NULL,
  `email` varchar(50) default NULL,
  `tel` varchar(50) default NULL,
  `birthday` varchar(20) default NULL,
  `intro` varchar(500) default NULL,
  PRIMARY KEY  (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
 
 
第三步:随便选择一种MVC框架写Web部份(Web开发工程师)

  晕,类Class都没看见一个就要写Action了啊?
  新手别叫,这里演示的是一种现代、先进、高雅、华丽、贵族式的编程及设计方法!(晕,不准吐!),J2EE中提倡的是面向接口编程,所以,系统设计师都给了你UML图,甚至连详细的Java接口都给你了,已经够多了,快动手吧。
  本例MVC使用的Struts框架,因此整个开发流程大致有下面的几个步骤。

1、 先根据IUser接口,写一个ActionForm,代码如下:
package com.easyjf.struts.form;
import org.apache.struts.action.ActionForm;
public class UserForm extends ActionForm {
 private String cid;
 private String userName;
 private String password;
 private String email;
 private String tel;
 private String birthday;
 private String intro;
 
 public String getCid() {
  return cid;
 }
 public void setCid(String cid) {
  this.cid = cid;
 }
 …
    //其它的getter、stter方法在此略过。
}
 
2、写Action

  根据用户的需求说明及设计师的相关模式或规范建议等,写一个处理“添删改查”等操作的Action,本文全部写到一个UserManageAction.java 中,代码如下:
package com.easyjf.struts.action;
import java.util.ArrayList;
import java.util.Collection;
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;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.easyjf.example.business.IUser;
import com.easyjf.example.business.IUserService;
import com.easyjf.struts.form.UserForm;
import com.easyjf.util.CommUtil;
import com.easyjf.web.tools.IPageList;
import com.easyjf.web.tools.ListQuery;
import com.easyjf.web.tools.PageList;
public class UserManageAction extends Action {
 private IUserService userService; 
 public IUserService getUserService() {
  return userService;
 }
 public void setUserService(IUserService userService)
 {
  this.userService=userService;
 }
 public ActionForward execute(ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response) throws Exception {
  WebApplicationContext wac =WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServlet().getServletContext());
  this.userService = (IUserService) wac.getBean("userService");
  String command=request.getParameter("easyJWebCommand");
  if(command==null || "".equals(command)||"list".equals(command)||"query".equals(command))
  {
   return doQuery(mapping,form,request,response);
  }
  else if("new".equals(command))
  {
   return mapping.findForward("edit");
  }
  else if("add".equals(command))
  {
   return doAdd(mapping,form,request,response);
  }
  else if("edit".equals(command))
  {
   return doEdit(mapping,form,request,response);
  }
  else if("update".equals(command))
  {
   return doUpdate(mapping,form,request,response);
  }
  else if("del".equals(command))
  {
   return doDel(mapping,form,request,response);
  }  
  return super.execute(mapping,form,request,response);
 }
 public ActionForward doEdit(ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response)
 {  
    UserForm vo=(UserForm)form;    
   IUser user=null;
   if(vo.getCid()!=null && (!vo.getCid().equals("")))user=userService.read(vo.getCid());
   if(user==null)user=userService.newUser();
     if(user!=null)
     {      
       vo.setCid(user.getCid());
       vo.setUserName(user.getUserName());
       vo.setPassword(user.getPassword());
       vo.setTel(user.getTel());
       vo.setEmail(user.getEmail());
       vo.setIntro(user.getIntro());
       vo.setBirthday(user.getBirthday());
       return mapping.findForward("edit");
     }
     else
     {
      request.setAttribute("msg","找不到数据!"); 
      return doQuery(mapping,form,request,response);
     }
 }
 public ActionForward doUpdate(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)
 {
  IUser  obj=(IUser)form2Po(form);
     if(userService.update(obj))
     {
      request.setAttribute("msg","数据修改成功!");
      return doQuery(mapping,form,request,response);
     }
     else
     {
      request.setAttribute("msg","数据修改失败"); 
      return mapping.getInputForward();
     }
 }
 public ActionForward doAdd(ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response)
 {
  IUser  obj=form2Po(form);
  if(obj==null)
  {
   request.setAttribute("msg","无法创建要保存的对象,添加失败!");
   return mapping.getInputForward();
  }        
     if(userService.save(obj))
     {
      request.setAttribute("msg","数据添加成功!");
      return doQuery(mapping,form,request,response);
     }
     else
     {
      request.setAttribute("msg","数据添加失败"); 
      return mapping.getInputForward();
     }   
 }
 public ActionForward doQuery(ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response)
 {
  int currentPage=CommUtil.null2Int(request.getParameter("page"));
  int pageSize=CommUtil.null2Int(request.getParameter("pageSize"));
  if(currentPage<1)currentPage=1;
  if(pageSize<1)pageSize=15;
  String scope="1=1";
  Collection paras=new ArrayList();  
  String orderType=CommUtil.null2String(request.getParameter("orderType"));
  String orderField=CommUtil.null2String(request.getParameter("orderField"));  
  String userName=CommUtil.null2String(request.getParameter("queryUserName"));
  String tel=CommUtil.null2String(request.getParameter("queryTel"));    
  if(!userName.equals(""))
  {
   scope+=" and userName like ?";
   paras.add("%"+userName+"%");
  }
  if(!tel.equals(""))
  {
   scope+=" and tel like ?";
   paras.add("%"+tel+"%");
  }  
  if(orderField.equals(""))//默认按用户名排序
  {
  orderField="userName";
  orderType="desc";    
  } 
  if(!orderField.equals(""))
  {
  scope +=" order by "+orderField;
  if(!orderType.equals(""))scope+=" "+orderType;
  } 
  IPageList pList=new PageList(new ListQuery(userService.query(scope,paras)));
  pList.doList(pageSize,currentPage,"","");
  if(pList!=null){
   request.setAttribute("list",pList.getResult());
   request.setAttribute("pages",new Integer(pList.getPages()));
   request.setAttribute("rows",new Integer(pList.getRowCount()));
   request.setAttribute("page",new Integer(pList.getCurrentPage()));  
   request.setAttribute("gotoPageHTML",CommUtil.showPageHtml(pList.getCurrentPage(),pList.getPages()));
   }
  request.setAttribute("orderType",orderType);
  request.setAttribute("orderField",orderField);
  return mapping.findForward("list");
 }
 public ActionForward doDel(ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response)
 {
  UserForm vo=(UserForm)form;    
  IUser user=null;
  if(vo.getCid()!=null && (!vo.getCid().equals("")))user=userService.read(vo.getCid()); 
     if(user!=null && userService.del(user))
     {
      request.setAttribute("msg","数据删除成功!");      
     }
     else
     {
      request.setAttribute("msg","数据修改失败"); 
     }    
     return doQuery(mapping,form,request,response);
 }
 public IUser form2Po(ActionForm form) {
     UserForm vo=(UserForm)form;    
  IUser user=null;
  if(vo.getCid()!=null && (!vo.getCid().equals("")))user=userService.read(vo.getCid());
  if(user==null)user=userService.newUser();
  user.setUserName(vo.getUserName());
  user.setBirthday(vo.getBirthday());
  user.setEmail(vo.getEmail());
  user.setTel(vo.getTel());
  user.setPassword(vo.getPassword());
  user.setIntro(vo.getIntro());
  return user;
 }  
}
  注意了,Action中使用的都是IUser,IUsrService等接口,其中execute方法中有一句有点不一样:
 WebApplicationContext wac =WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServlet().getServletContext());
  this.userService = (IUserService) wac.getBean("userService");
  这就是传说中强大的Spring IOC的使用。因为有了他,我们的Web开发人员也不用知道这个IUserService究竟是什么东西了,有时候也无法知道。你想想,你在做这一步的时候,可能另外分工做后台商业逻辑层的伙伴还没有把IUserService的实现写出一个来呢。Web开发人员需要用的IUserService的时候,直接通过类似的方法找Spring取就是了。Spring一个角色是扮演IOC容器中间件嘛,他都没有谁还有呢?
  本例中有关com.easyjf.web.tools、com.easyjf.util等包只是使用了EasyJWeb的分页业务引擎及一些实用工具,没有其它功能,否则代码就会更多了。大家可以下载EasyJWeb的源码看到详细实现方式。
 
3、美工及设计制作人员做界面,完成后交由我们Web开发人员加JSP代码。

 
  JSP部分主要有两个页面,userEdit.jsp主要是一个用户信息录入表单。userList.jsp是用户信息列表页面。这一部分大家一定都轻车熟路了吧,由于篇幅、页面、版面等都有限,就不把详细代码扔出来污染环境了。请新手直接到EasyJF开源团队官网下载完整的示例代码,其中包括了这两个JSP页面。下载地址:
  
  http://www.easyjf.com/html/bbs/20060509/1571738935251539.htm?ejid=1139563413901115
 
4、配置Struts配置文件struts-config.xml

struts-config.xml的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
  <data-sources />
  <form-beans >
  <form-bean name="userForm" type="com.easyjf.struts.form.UserForm" />
  </form-beans>
  <action-mappings >
    <action attribute="userForm" input="/userEdit.jsp" name="userForm"
      path="/userManage"  scope="request"
      type="com.easyjf.struts.action.UserManageAction">
      <forward  name="edit" path="/userEdit.jsp" />
      <forward  name="list" path="/userList.jsp" />
    </action>   
  </action-mappings>
  <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
  <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" />
 </plug-in> 
</struts-config>
 
5、最后还差一步,就是配置web.xml文件。

Web.xml文件内容如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param> 
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener> 
 <servlet>
  <servlet-name>action</servlet-name>  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
   <param-name>config</param-name>
   <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>   
 </servlet>
 <servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
</web-app>
  工作都完了,自己在检查检查,可以作一些单元测试等工作,并把接口用说明文档写好交给老大吧。

  下面我们再看看其它角色的表演!
   
  详情请看:玩玩Spring之struts+hibernate+spring添删改查示例(二)
posted on 2006-05-09 08:14 大峡 阅读(4038) 评论(9)  编辑  收藏

Feedback

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-05-09 08:27 原创专栏 开源学习
哎!又见小飞刀.  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-05-09 08:32 大峡
呵呵,今天可是赶了个大早啊:-)
在这个示例中,webwork及easyjweb的action都只有140行代码,而struts有200多行。  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-05-09 14:18 aspirin
工作都完了,自己在检查检查,可以作一些单元测试等工作?为什么在工作做完了在考虑单元测试呢?  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-05-09 18:41 大峡
@aspirin

这里只是完Web工程师的工作完了,不是所有的步骤完了。请继续往下看!  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-05-12 11:21 wufeng
在org.hibernate.engine.SessionImplementor中并没有createQuery(String)的方法,请问楼主在com.easyjf.example.business.hibernate中
的HibIdGenerator.java中Query query1=session.createQuery(hql);如何用  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-05-12 11:55 大峡
HibIdGenerator.java实现org.hibernate.id.IdentifierGenerator接口,会由hibernate自己调用,请参考一下hibernate的定义的主键生成源码。

createQuery(String)方法有没有,请多看看API!
  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-06-22 12:53 阿达
@大峡
确实没有  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2006-07-05 17:05 过客0898
我都导入了hibernate3.1和hibernate3.0的所有包都编译不了HibIdGenerator.java这个文件。为什么?
提示这些包没有:
--------------------
import org.hibernate.engine.SessionImplementor;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.Query;
import org.hibernate.dialect.Dialect;
import org.hibernate.type.Type;  回复  更多评论
  

# re: 玩玩Spring之struts+hibernate+spring添删改查示例(一) 2007-03-31 12:16 来过了

要用hibernate3.05,3.0 you createQuery 方法却少一个什么ConnectionReleaseMode类. 3.1 就没有createQuery的方法.楼主最好把你用的版本都写上.hibernate也是,删除一个方法p都不吭一声. 干嘛不用deprecate标签.这样可以兼容...真是烂  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: