Struts 1存在的问题
因为Struts 1框架是在Model 2的基础上发展起来的,因此它完全是基于Servlet API的,所以在Struts 1的业务逻辑控制器内,充满了大量的Servlet API。
看下面的Action代码片段:
//业务逻辑控制器必须继承Struts 1提供的Action类
public class LoginAction extends Action
{
//处理用户请求的execute方法
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)throws
AuctionException
{
//获取封装用户请求参数的ActionForm对象
//将其强制类型转换为登录用的ActionForm
LoginForm loginForm = (LoginForm)form;
//当用户名为scott,密码为tiger时返回成功
if ("scott".equals(loginForm.getUsername()
&& "tiger".equals(loginForm.getPassword())
{
//处理成功,返回一个ActionForward对象
return mapping.findForward("success");
}
else
{
//处理失败,返回一个ActionForward对象
return mapping.findForward("success");
}
}
}
当我们需要测试上面Action类的execute方法时,该方法有4个参数:ActionMapping、ActionForm、HttpServletRequest和HttpServletResponse,初始化这4个参数比较困难,尤其是HttpServletRequest和HttpServletResponse两个参数,通常由Web容器负责实例化。
因为HttpServletRequest和HttpServletResponse两个参数是Servlet API,严重依赖于Web服务器。因此,一旦脱离了Web服务器,Action的测试非常困难。
(3)代码严重依赖于Struts 1 API,属于侵入式设计
正如从上面代码片段中所看到的,Struts 1的Action类必须继承Struts 1的Action基类,实现处理方法时,又包含了大量Struts 1 API:如ActionMapping、ActionForm和ActionForward类。这种侵入式设计的最大弱点在于,一旦系统需要重构时,这些Action类将完全没有利用价值,成为一堆废品。
可见,Struts 1的Action类这种侵入式设计导致了较低的代码复用。
注意这里是依赖比较严重,只要用API就会依赖,不用API,还用框架干吗。
Struts2肯定是为解决Struts1的问题而来:
WebWork存在如下优点:
图1.8 WebWork的数据流图
public class LoginAction implements Action
{
//该字符串常量将作为Action的返回值
private final static String LOGINFAIL="loginfail";
//该Action封装的两个请求参数
private String password;
private String username;
//password请求参数对应的getter方法
public String getPassword()
{
return password;
}
//password请求参数对应的setter方法
public void setPassword(String password)
{
this.password = password;
}
//username请求参数对应的getter方法
public String getUsername()
{
return username;
}
//username请求参数对应的setter方法
public void setUsername(String username)
{
this.username = username;
}
//处理用户请求的execute方法
public String execute() throws Exception
{
if ("yeeku".equalsIgnoreCase(getUsername())
&& "password".equals(getPassword()))
{
ActionContext ctx = ActionContext.getContext();
//将当前登录的用户名保存到Session
Map session = ctx.getSession();
session.put("username",getUsername());
return SUCCESS;
}
else
{
return LOGINFAIL;
}
}
}
实现一个接口和继承一个类是完全不同的概念:实现一个接口对类的污染要小得多,该类也可以实现其他任意接口,还可以继承一个父类;但一旦已经继承一个父类,则意味着该类不能再继承其他父类。
也可以不实现Action接口:
public class LoginAction
{
//封装用户请求参数的username属性
private String username;
//封装用户请求参数的password属性
private String password;
//username属性的getter方法
public String getUsername()
{
return username;
}
//username属性的setter方法
public void setUsername(String username)
{
this.username = username;
}
//password属性的getter方法
public String getPassword()
{
return password;
}
//password属性的setter方法
public void setPassword(String password)
{
this.password = password;
}
//处理用户请求的execute方法
public String execute() throws Exception
{
//如果用户名为scott,密码为tiger,则登录成功
if (getUsername().equals("scott")
&& getPassword().equals("tiger") )
{
return "success";
}
else
{
return "error";
}
}
}