(本故事除了部分点明道姓并具有故事详细发生的具体时间点地等部分情节以外,其它内容纯属虚构,若有雷同,纯属巧合。)
主演: EasyJWeb、中庸之道、Spring。
配角:Struts、webwork、Velocity、JSP、hibernate、J2EE各层程序员。
在前面的两个例子中,主要给大家介绍了Spring的黄金庸俗组合以及华丽高雅组合来开发B/S应用。在我们用到的几个“轮子”当中,由于hibernate是当今公认最好的ORM系统,因此争议性不大。然而,Struts就未必了,Struts也是市场上使用得多的框架(尽管有那么多技术牛人说他的不是),然而很多人对Struts很是看不起眼,总是认为没有华丽的IOC、无法写出优雅、漂亮的代码,一些配置及FormBean搞起来很麻烦,因此,webwork或Tapestry等比他强很多。在网上,有时候甚至会看到有些人对struts学习者发出藐视的目光。
Webwork就真强了吗?市场才是王道吧,我不禁想问,不就引入了一些IOC
、拦截器功能,并与一些常用的组件集成摆了。存在即合理,所以各家粉丝没必要为这个PK。正好,现在struts与webwork开发团队已经合并了(为什么合并?当然是为了对付共同的敌人啊),可以不用PK了。但Tapestry、JSF、Spring MVC的粉丝又该怎么办?呵呵,是不是很有意思,打着不发明轮子大旗,发明了一个又一个的漂亮轮子给我们,让我们这些第三世界国家的粗人谁都舍不得丢下,一不小心就犯了选择恐惧症。看来作为一名程序员,身体以及精神都得健壮啊,要不,谁能折腾得起!这不,客户正在催命似的要看项目进展情况,而我们连选择什么框架都还没定呢!
有点晕了吧,还有更晕的。今天笔者不打算
用大家熟悉的框架作示例,所以就不用管各家粉丝怎么PK了(看他们PK也郁闷,还得翻译一次,有时一不小心还会跑调!)。本文将用一个你可能从没见过的国产开源框架来替换掉上例中的Struts及webwork,这个框架就是由国内EasyJF开源团队所开发的EasyJWeb框架。
提到EasyJWeb,我想前面提到的各种MVC框架的粉丝一定会联合起来,组成一个要技术有技术、要资历有资历的超强阵容来PK了。因为EasyJWeb是国产的,而其它的都是进口原装的,再加上EasyJWeb测试版本当前才发到0.5版,有很多地方都还不成熟,几个开发者技术水平又不怎么样,写的东西也是那么平庸、朴实,一不小心就被抓住小辫子。而EasyJWeb开发团队又急于想把这个框架介绍给大家,让大家帮助提建议、完善。
既然还不完善,那我为什么要用EasyJWeb而不选择其他呢?
原因跟大家跟大家喜欢其它的框架也一样,因为本人就是EasyJWeb的超级粉丝,我不支持他支持谁。
说得更直白一点,这好比俺村里大眼睛、长头发的小芳姑娘,不管从皮肤、外表、性格、习惯等各方面都比美国的小甜甜布兰妮更适合做偶老婆的道理一样。况且笔者大大小小框架也用了不少,自我感觉还是EasyJWeb使起来最顺手,代码少容易搞清楚框架的工作原理不说,提供的那些功能还都是我们项目中经常所需要的。
可笑也可悲的是,国内有的同行及媒体平台一看到有关EasyJWeb字眼,一看是国产的,好歹不分尽然就说是打广告,写的文章也不让登。偶滴神啊,要不是在大街上看到满街的黄皮夫、黑眼睛的路人甲乙丙丁,我还真以为自己身处西方资本主义国家了,对俺们社会主义国家搞的东西这么抵制。同样是开源项目,struts的心得体会你可以发,为什么关于EasyJWeb的心得体会你就不让发?(小样,谁说不给你发了?要发可以,拿金币来!)何苦呢,现在都WTO那么多年了。你整天翻译、搜集那些乱七八糟的国外小项目的动态啊什么的,累不累啊。不知情者还认为你是资本主义国家设在国内的宣传喉舌呢。
当然,这里说的只是非常少的个别特例,大多数前辈及平台还是很支持我们的。若没有国内众多前辈的鼓励、指点以及像“Java研究组织”类似的众多专业技术平台的支持,恐怕EasyJWeb早就死翘翘,今天大家也就看不到这篇文章了。
晕,八卦有点远了,下面进入正题吧。今天笔者探讨的一个重点就是如何在不动其它各层的情况下,替换掉上两篇“添删改查”示例中的MVC层。这也是我理解的多层结构中的一门艺术,这也是大家听到的组件或者构件的一个妙处。前辈们不都说吗?配置时代的编程,做软件就像搭积木,几个框框、架架、部件搭在一起,一个庞大的系统就被我们堆起来了。假如其中有些部件由于各种原因需要换,随便换就是了,其它的部分都不用动。J2EE的灵活、可维护性都体现在这些地方,由于Java的灵活,因此他有时候会带给我们类似于艺术工作者所特有的那种飘飘然的感觉,这也是笔者放弃微软的.Net,投入Java怀抱的原因。
由于本示例使用的是EasyJWeb,因此其它MVC框架的粉丝可以略过后面的技术细节内容,直接跳到后面有关“中庸之道”的论述中,否则不小心你也会被EasyJWeb迷住。
下面请看操作步骤,大家可以对照前两篇示例中的MVC部分的内容来看:
1、 写处理用户请求的Action。
跟Struts类似,EasyJWeb有一个Action,但这个Action因为使用的接口方式,不需要继承于框架特定的Action,只需要实现IWebAction即可,本例中,为了方便我们的Action直接继承EasyJWeb Tools中提供给我们的一个Action基类(你也可以不用继承他),下面是UserManageAction.java的代码。
package com.easyjweb.action;
import java.util.ArrayList;
import java.util.Collection;
import com.easyjf.util.CommUtil;
import com.easyjf.web.ActionContext;
import com.easyjf.web.Globals;
import com.easyjf.web.Module;
import com.easyjf.web.Page;
import com.easyjf.web.WebForm;
import com.easyjf.web.tools.AbstractCmdAction;
import com.easyjf.web.tools.IPageList;
import com.easyjf.web.tools.ListQuery;
import com.easyjf.web.tools.PageList;
import com.easyjf.example.business.IUser;
import com.easyjf.example.business.IUserService;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class UserManageAction extends AbstractCmdAction {
private IUserService userService;
public IUserService getUserService() {
return userService;
}
public void setUserService(IUserService userService)
{
this.userService=userService;
}
public Object doBefore(WebForm form, Module module) {
WebApplicationContext wac =WebApplicationContextUtils.getRequiredWebApplicationContext(ActionContext.getContext().getServletContext());
this.userService = (IUserService) wac.getBean("userService");
return null;
}
public Page doInit(WebForm form, Module module) {
return doQuery(form,module);
}
public Page doNew(WebForm form, Module module) {
return new Page("edit","/userEdit.html",Globals.PAGE_TEMPLATE_TYPE);
}
public Page doAdd(WebForm form, Module module) {
Page forward=null;
IUser obj=(IUser)form2Obj(form);
if(userService.save(obj))
{
form.addResult("msg","数据添加成功!");
forward=doQuery(form,module);
}
else
{
form.addResult("msg","数据添加失败");
forward=new Page("edit","/userEdit.html",Globals.PAGE_TEMPLATE_TYPE);
}
return forward;
}
public Page doUpdate(WebForm form, Module module) {
Page forward=null;
IUser obj=(IUser)form2Obj(form);
if(userService.update(obj))
{
form.addResult("msg","数据修改成功!");
forward=doQuery(form,module);
}
else
{
form.addResult("msg","数据修改失败");
forward=new Page("edit","/userEdit.html",Globals.PAGE_TEMPLATE_TYPE);
}
return forward;
}
public Page doEdit(WebForm form, Module module) {
Page forward=null;
IUser obj=(IUser)form2Obj(form);
if(obj!=null)
{
form.addPo(obj);
forward=new Page("edit","/userEdit.html",Globals.PAGE_TEMPLATE_TYPE);
}
else
{
form.addResult("msg","找不到数据!");
forward=doQuery(form,module);
}
return forward;
}
public Page doDel(WebForm form, Module module) {
IUser obj=(IUser)form2Obj(form);
if(userService.del(obj))
{
form.addResult("msg","数据删除成功!");
}
else
{
form.addResult("msg","数据修改失败");
}
return doQuery(form,module);
}
public Page doQuery(WebForm form, Module module) {
int currentPage=CommUtil.null2Int(form.get("page"));
int pageSize=CommUtil.null2Int(form.get("pageSize"));
if(currentPage<1)currentPage=1;
if(pageSize<1)pageSize=15;
String scope="1=1";
Collection paras=new ArrayList();
String orderType=CommUtil.null2String(form.get("orderType"));
String orderField=CommUtil.null2String(form.get("orderField"));
String userName=CommUtil.null2String(form.get("queryUserName"));
String tel=CommUtil.null2String(form.get("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,"","");
//保存查询结果
CommUtil.saveIPageList2WebForm(pList,form);
return new Page("list","/userList.html",Globals.PAGE_TEMPLATE_TYPE);
}
public Object form2Obj(WebForm form) {
String cid=(String)form.get("cid");
IUser user=null;
if(cid!=null && (!cid.equals("")))user=userService.read(cid);
if(user==null)user=userService.newUser();
return form.toPo(user);
}
}
2、 制作模板页面
类似于Struts示例中的JSP页面,只不过这里的模板页面使用的是Velocity脚本引擎。因此,不在有JSP中的相关语法,也没有一些让人头晕的自定义标签。所有标记集中归纳起来就只有4种用法,大家可以看看笔者在EasyJF开源团队官网上的一篇文章,题为:
《浅析MVC框架中View层的优雅设计及实例》。
模板不再存放在根目录,而是存放在web-inf\easyjweb目录,同样是两个模板,一个userEdit.html模板是用于显示用户录入表单,另外一个userList.html文件是用户列表页面。模板的全部内容可以从EasyJF开源团队官方网站下载,本示例中的全部完整代码中包含了该模板。
3、修改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>
<filter>
<filter-name>CharsetFilter</filter-name>
<filter-class>com.easyjf.web.CharsetFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharsetFilter</filter-name>
<servlet-name>easyjf</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>easyjf</servlet-name>
<servlet-class>com.easyjf.web.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>easyjf</servlet-name>
<url-pattern>*.ejf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>easyjf</servlet-name>
<url-pattern>/ejf/*</url-pattern>
</servlet-mapping>
</web-app>
配置文件跟前面两个例子中的差不多,只是多了一些中文过滤处理等内容,EasyJWeb已经考虑到经常遇到的中文问题。
大家可以拿Struts与EasyJWeb对比一下,我们少了两个步骤,一个是ActionForm Bean的定义,另外一个是配置struts-config.xml文件。其实EasyJWeb也有跟struts-config.xml类似的配置文件easyjf-web.xml,只不过我们这个例子中使用的是默认配置而已。
完整的示例代码下载:
当然,为什么我们能不修改其它的代码即换掉系统的MVC层,还是归功于Spring的IOC容器为我们管理了其它层组件。当然,这两三个示例中只使用了Spring最简单也是最常用的功能。