假如定义一个Action需要做登录操作
第一种做法是在Action中定义登录所需要的属性,userName,password,然后在进行封装,称之为属性传参
Action代码:
@SuppressWarnings("serial")
public class UserAction2 extends ActionSupport{
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String login() {
if ("admin".equals(userName) && "000000".equals(password)) {
return "success";
}
return "input";
}
}
提交参数的页面代码:
<body>
<form action="UserAction2" method="post">
用户名:<input type="text" name="userName"/></br>
密 码:<input type="password" name="password"/></br>
<input type="submit" value="enter"/>
</form>
</body>
其中action="UserAction2" 指定了要请求的<action>的name,name="userName"代表文本框的内容由Action中的userName属性接收
登录成功在JSP页面中可以使用 <s:property value="userName"/>获取UserAction2中userName属性的值
后来我们发现,如果实体类中的属性较多,那么相应的Action中也要定义相同的属性,并提供setter,getter,显然,这种操作方式不太合适,于是有了第二种方式:JavaBean方式接收参数
同样以登录为例:
首先需要创建实体类:
public class User {
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
然后,在UserAction2中定义实体类对象来接收客户端上传的参数,当然也要在Action中对实体类对象提供setter,getter方法
代码如下:
@SuppressWarnings("serial")
public class UserAction2 extends ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String login(){
if ("admin".equals(user.getUserName()) && "000000".equals(user.getPassword())) {
return "success";
}
return "input";
}
}
提交参数的页面代码:
<body> <form action="UserAction2" method="post"> 用户名:<input type="text" name="user.userName"/></br> 密 码:<input type="password" name="user.password"/></br> <input type="submit" value="enter"/> </form> </body>
登录成功相应的JSP页面中使用 <s:property value="user.userName"/>获取Action中的属性的value也要修改。
但是不难发现这种做法会使得JSP页面上的表单域中的命名变长,于是有了第三种方法使得前两种方法的缺点都可以被改善,它则是:使用ModelDriven机制
这种方式任然需要实体类,
让UserAction2实现一个ModelDriven接口,同时实现接口中的方法:getModel()。如下所示:
@SuppressWarnings("rawtypes") public class UserAction2 implements ModelDriven{ //用于接收页面用户名和密码的对象 private User user = new User(); @Override public User getModel() { return user; } public String doLogin(){ if ("admin".equals(user.getUserName()) && "000000".equals(user.getPassword())) { return "success"; } return "input"; } }
提交参数的页面代码:
<body>
登录成功在JSP页面中可以使用 <s:property value="userName"/>获取UserAction2中userName属性的值
<form action="UserAction2" method="post">
用户名:<input type="text" name="userName"/></br>
密 码:<input type="password" name="password"/></br>
<input type="submit" value="enter"/>
</form>
</body>
不难发现第三中方式的实现要比前两种简单的多,为什么呢?
ModelDriven背后的机制? ModelDriven背后的机制就是ValueStack。界面通过:userName/password这样的名称,就能够被直接赋值给user对象,这证明user对象正是ValueStack中的一个root对象!
那么,为什么user对象会在ValueStack中呢?它是什么时候被压入ValueStack的呢?
答案是:ModelDrivenInterceptor,
ModelDrivenInterceptor是缺省的拦截器链的一部分,当一个请求经过ModelDrivenInterceptor的时候,在这个拦截器中,会判断当前要调用的Action对象是否实现了ModelDriven接口,如果实现了这个接口,则调用getModel()方法,并把返回值(本例是返回user对象)压入ValueStack。
这时候,UserAction中的user对象其实和ValueStack是同一个user对象,在JSP中,直接通过userName访问,访问的就是ValueStack中的user对象
这种方式使用了一种先进的编程思想:控制反转(IOC)或依赖注入,,它分离了初始化对象和使用对象的代码,使得类的职责更加单一明确,降低了耦合度。