了解mvc
mvc是model,view,controller的缩写,mvc是application开发的设计模式,也就是大家所知道的model2.在mvc的设计模式中,要求在application开发中你把商业逻辑,界面显示,数据分离。也就是分别在model,view,controller实现:数据,控制(商业逻辑),显示(页面显示).
在以前或者说传统的web application开发方式当中,如asp,php,jsp(model 1)开发当中,我们在asp(php,jsp)中实现一切,如:从数据库中取到我们需要的数据,并根据数据之间的关联和实际的需要按照某种方式把他显示在页面中以及从页面提交的表单中提取数据,根据商业逻辑从数据库查询相关数据,或者把数据写入数据库。也就是说我们在asp(php,jsp)实现一切包括:界面显示,商业逻辑,数据存取。这样带来的后果就是你所写的asp(php,jsp)没有层次,并且html和script(javascript、jscript,asp、php、jsp源代码)相互嵌套.可维护性差,最要命的是在web application通常显示一块是由美工完成的,很多时候也是你先写好asp、php、jsp然后美工进行美化,很有可能你发现经过美工处理完以后你的代码已经面目全非了。你不得不把你的代码重新组织。
在mvc模式中这个问题的解决办法是:view中负责显示,view一般从controller得到已经处理\过的数据,然后显示在页面当中,应该说这样在html中嵌套很少的script.基本上美工的修改不大会废掉你的劳动成果。
在使用java开发web application有几种符合mvc设计模式的开发方式让你选择。
1:jsp+servlet+javabean(ejb)
2:jsp+javabean(controller)+javabean(ejb)(model)
3:tdk(turbine,velocity…)
4:xsp
5:jsp+struts+javabean(ejb)
我个人认为后面两种比较好,其他几种都有可取的地方特别是使用tdk因为有一个比较好的工具可以自动生成很多代码,至于它的缺点在后面几种开发方式的比较当中我会介绍。
struts1.1的新功能
struts1.1与1.0相比加了一些很不错的功能。最主要是表单验证上功能增强。在struts1.1数据的验证不象以前在action中在validator具体实现,而是在validation.xml通过配置实现这样做的好处就是重用性加强了很多。
struts1.1实现的主要组成
主要包括:action,actionform,actionmapping,actionforward,开发当中最主要写的是action,actionform根据需要可以写或不写。下面我就一一具体介绍。
action
an action is an adapter between the contents of an incoming http request and the corresponding business logic that should be executed to process this request.
上面是struts开发小组对action的描述,说action实际上request和business logic中间的适配器.通俗的说就是从表单中取到数据并穿给商业逻辑操作进行一系列的操作,然后返回相应的操作信息。
actionform
an actionform is a javabean optionally associated with one or more actionmappings. such a bean will have had its properties initialized from the corresponding request parameters before the corresonding actions execute() method is called.
actionform实际上就是把从request取到的数据封装并进行校验,然后把合法的数据给action进行处理。实际上actionform除了进行数据校验之外另外更重要的是在表单回写的时候作用很大。反而在1.1以后数据校验的大部分工作在validation.xml去实现。
actionmapping,actionforward
actionmapping主要是用与配置和描述相关属性使用的。先看下在struts-config.xml
中的配置文件一段配置描述:
<action-mappings>
<!– registration action –>
<action path="/usereg"
type="com.bingo.finance.action.useregaction"
name="useregform"
scope="request"
validate="true"
input="/usereg.jsp">
<forward name="success" path="/msg.jsp"/>
</action>
</action-mappings>
actionmapping就是用来描述一个action的url、具体实现的文件、相对应的actionform 数据属性(request or session)、是否需要进行数据校验和回写、以及处理完成后可能跳转的url.
而actionforward你就可以理解为action 操作完成后的跳转url,action在处理完相关操作后,返回的是一个actionforward也就是告诉struts我做完这个操作下一步到哪儿去。
构建struts1.1运行环境
我的配置是居于tomcat4.0以上版本讨论,其他的appserver大致相同。
1:得到struts1.1
http://jakarta.apache.org/builds/jakarta-struts/release/v1.1-b1/jakarta-struts-1.1-b1.zip
2:设置
把struts.jar copy到$tomcat_home/common/lib 或你使用struts的appaction下的web-inf/lib下
在你使用struts的appaction下web.xml中增加下列配置
<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>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<taglib>
<taglib-uri>/web-inf/struts-html.tld</taglib-uri>
<taglib-location>/web-inf/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/web-inf/struts-logic.tld</taglib-uri>
<taglib-location>/web-inf/struts-logic.tld</taglib-location>
</taglib>
<!– nested tag library descriptor –>
<taglib>
<taglib-uri>/web-inf/struts-nested.tld</taglib-uri>
<taglib-location>/web-inf/struts-nested.tld</taglib-location>
</taglib>
<!– template tag library descriptor –>
<taglib>
<taglib-uri>/web-inf/struts-template.tld</taglib-uri>
<taglib-location>/web-inf/struts-template.tld</taglib-location>
</taglib>
struts1.1中提供了很详细的例子,你可以仔细看看.
接下来你该根据需要配置struts-config.xml,以下是一个简单的例子
<?xml version="1.0" encoding="iso-8859-1" ?>
<!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>
<!– ========== form bean definitions =================================== –>
<form-beans>
<!– registration form bean –>
<form-bean name="useregform"
type="com.bingo.finance.action.userform"/>
</form-beans>
<!– ========== global forward definitions ============================== –>
<global-forwards>
<forward name="error" path="/error.jsp"/>
</global-forwards>
<!– ========== action mapping definitions ============================== –>
<action-mappings>
<!– registration action –>
<action path="/usereg"
type="com.bingo.finance.action.useregaction"
name="useregform"
scope="request"
validate="true"
input="/usereg.jsp">
<forward name="success" path="/msg.jsp"/>
</action>
</action-mappings>
<!– ========== message resources definitions =========================== –>
<message-resources
parameter="com.bingo.finance.common.displaymsg"/>
<!– ========== plug ins configuration ================================== –>
<!– add multiple validator resource files by setting the pathname property –>
<plug-in classname="org.apache.struts.validator.validatorplugin">
<set-property property="pathname" value="/web-inf/validator-rules.xml"/>
<set-property property="pathname" value="/web-inf/validation.xml"/>
</plug-in>
</struts-config>
上面的英文我相信你能够看懂。我就不做解释了。你需要继续配置validation.xml了,看如下
简单的例子.
<form-validation>
<formset>
<form name="useregform">
<field property="username"
depends="required,mask,minlength,maxlength">
<arg0 key="common_username"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<var>
<var-name>mask</var-name>
<var-value>^\w+$</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>5</var-value>
</var>
<var>
<var-name>maxlength</var-name>
<var-value>20</var-value>
</var>
</field>
<field property="password"
depends="required,mask,minlength,maxlength">
<arg0 key="common_password"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<var>
<var-name>mask</var-name>
<var-value>^\w+$</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>5</var-value>
</var>
<var>
<var-name>maxlength</var-name>
<var-value>20</var-value>
</var>
</field>
<field property="nickname"
depends="required,mask,minlength,maxlength">
<arg0 key="common_nickname"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<var>
<var-name>mask</var-name>
<var-value>^\w+$</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>5</var-value>
</var>
<var>
<var-name>maxlength</var-name>
<var-value>20</var-value>
</var>
</field>
<field property="superpass"
depends="required,mask,minlength,maxlength">
<arg0 key="common_superpass"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<var>
<var-name>mask</var-name>
<var-value>^\w+$</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>10</var-value>
</var>
<var>
<var-name>maxlength</var-name>
<var-value>20</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
上面validation.xml就是告诉struts我的useregform取到的数据应该做下面的验证
username是必须不能为空的并且最小长度为5,最大长度是20.
…………….
password,nickname,superpass基本一样我就不做更多说明.至次配置基本结束,我们要开始写第一个struts 了。
开发struts1.1
usereg.jsp
为了考虑页面的灵活性,在页面中显示的所有元素我都放在properties文件中并由com.bingo.finance.common.htmlmsg这个文件取到.
===================================================================
<%@ page contenttype="text/html;charset=gbk" %>
<%@ page import="java.io.*"%>
<%@ page import="com.bingo.finance.common.htmlmsg"%>
<%@ taglib uri="/web-inf/struts-html.tld" prefix="html" %>
<%@ taglib uri="/web-inf/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/web-inf/struts-bean.tld" prefix="bean" %>
<html>
<head>
<title><%=htmlmsg.title_regiset%></title>
<meta http-equiv="content-type" content="text/html; charset=gb2312">
</head>
<body bgcolor="#ffffff" text="#000000">
<form name="usereg" method="post" action="usereg.esp">
<!–在struts中默认的后缀是.do你可以根据需要自己修改–>
<table width="100%" border="0" cellspacing="1" cellpadding="1">
<tr align="center">
<td colspan="2"><%=htmlmsg.title_regiset%></td>
</tr>
<tr>
<td width="49%" align="right"><%=htmlmsg.common_username%>:</td>
<td width="51%">
<!–为了实现回写在struts中建议你使用tag使用如下写法代替一般的写法
<html:text property="username" size="20" maxlength="30" styleclass="css" styleid="userid"/>
上面的代码你看不懂你需要进一步了解tag.
–>
<input type="text" name="username" size="20" maxlength="20">
</td>
</tr>
<tr>
<td width="49%" align="right"><%=htmlmsg.common_password%>:</td>
<td width="51%">
<input type="password" name="password" size="20" maxlength="20">
</td>
</tr>
<tr>
<td width="49%" align="right"><%=htmlmsg.common_nickname%>:</td>
<td width="51%">
<input type="text" name="nickname" size="20" maxlength="20">
</td>
</tr>
<tr>
<td width="49%" align="right"><%=htmlmsg.common_superpass%>:</td>
<td width="51%">
<input type="password" name="superpass" size="20" maxlength="20">
</td>
</tr>
<tr>
<td width="49%" align="right">
<input type="submit" name="submit" value="<%=htmlmsg.action_regiset%>">
</td>
<td width="51%">
<input type="reset" name="submit2" value="<%=htmlmsg.common_reset%>">
</td>
</tr>
</table>
</form>
</body>
</html>
useregactiom.java
===========================================================
package com.bingo.finance.action;
//java import
import java.io.ioexception;
import java.util.locale;
//servlet import
import javax.servlet.servletexception;
import javax.servlet.http.httpsession;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
//struts import
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.apache.struts.util.messageresources;
//finance import
import com.bingo.finance.action.userform;
import com.bingo.finance.manager.usermanager;
import com.bingo.finance.entity.user;
public class useregaction extends action {
//在struts1.1以前使用perform
//struts1.1使用execute替代perform
public actionforward execute(actionmapping mapping,
actionform form,
httpservletrequest request,
httpservletresponse response)
throws ioexception, servletexception {
try{
userform userform=(userform)form;
usermanager usermanager=new usermanager();
user user=usermanager.formtoentity(userform);
usermanager.add(user);
//insert into database a userinfo
}catch(exception ex){
return mapping.findforward("error");
}
return mapping.findforward("success");
//forward is "/msg.jsp"
}
}
userform.java
=========================================================================
package com.bingo.finance.action;
import java.util.*;
import java.io.serializable;
//servlet import
import javax.servlet.servletexception;
import javax.servlet.http.httpsession;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
//struts import
import org.apache.struts.action.actionmapping;
import org.apache.struts.validator.validatorform;
public class userform extends validatorform implements serializable{
//在struts1.1以前通常form继承actionform
//实际上validatorform是继承actionform
//为什么要加一层validatorform是为了校验而做的
private string id;
private string username;
private string password;
private string nickname;
private string superpass;
public userform(){
}
/****/
public string getid(){
return this.id;
}
/****/
public void setid(string _id){
this.id=_id;
}
/****/
public string getusername(){
return this.username;
}
/****/
public void setusername(string _username){
this.username=_username;
}
/****/
public string getpassword(){
return this.password;
}
/****/
public void setpassword(string _password){
this.password=_password;
}
/****/
public string getnickname(){
return this.nickname;
}
/****/
public void setnickname(string _nickname){
this.nickname=_nickname;
}
/****/
public string getsuperpass(){
return this.superpass;
}
/****/
public void setsuperpass(string _superpass){
this.superpass=_superpass;
}
/**show this class info**/
public string tostring(){
stringbuffer info=new stringbuffer();
info.append("….id is:"+id);
info.append("….username is:"+username);
info.append("….password is:"+password);
info.append("….nickname is:"+nickname);
info.append("….superpass is:"+superpass);
return info.tostring();
}
public void reset(actionmapping mapping, httpservletrequest request) {
id=null;
username=null;
password=null;
nickname=null;
superpass=null;
}
}
usermanager.java ,user.java文件我就不提供了,这一部分在实际的开发当中根据需要自己去处理,也就是为了把数据插入数据库。
现在一个简单的注册用户你就开发完成了。很简单吧。呵呵,继续努力…但其中还有很多 细节你需要进一步了解,我只把你领到门了,你必须自己去研究一些东西,比如说,我希望我的用户多一个email字段和一个年龄字段我应该如何做,而且我希望validation.xml的验证有email合法验证,年龄必须大于0而且一定是整数。那我应该如何做?我只能告诉你加两个字段你需要修改form 增加字段,同时相应文件也要修改。在struts中email的验证非常简单。好好看例子吧,好好研究validator-rules.xml,这个我认为struts1.1最好的功能增加(struts1.0没有这个文件)。struts中提供了一个非常灵活而且重用极高的验证机制。
struts和其他开发方式的比较
使用struts开发至少带来如下好处:
1:层次结构非常清晰,也使得分工很明确。
2:重用度很高,连数据验证都可以重用,还有一个更好的重用就是form,action是可以很好的重用的。
3:可维护性好。这是居于第一点的。
……………..
下面我说一个struts的不足之处,如果你使用或者了解tdk你就会觉得,tdk中可以自动生成很多java源代码的确可以节省不少工作量,struts中也可以做的很好。我自己开发了一个工具,功能还不够强大。在我的计划当中,我希望form,javabean(封装数据相当于ejb中的entity bean),甚至包括操作数据库的method都自动生成,还有validation.xml也可以动态的生成。然而因为下一个原因:struts到目前为止还不是一个比较成熟的项目。他的改动实在是太大了。1.0和0.5就有很大的改动。所以我的计划有变。我希望在1.1完全推出来再做开发(1.1现在是beta版)。同时我也给craig r. mcclanahan(struts开发的team leader)写过信听取他的建议.