在正式讲解之前,先交代一下项目版本,Struts2的版本是struts-2.3.30稳定版本,至于如何快速搭建以及正确的选择Struts2必要的Jar文件,以struts-2.3.30为例,首先建议大家直接从官网直接下载struts-2.3.30.zip文件,解压缩后,会得到如下所示目录结构:
在apps目录里面有五个Struts2官方的项目案例,既然是官方案例,肯定是能够正常运行的,找到struts2-blank.war解压缩后,找到对应的lib文件、web.xml、struts.xml文件,剩下的工作复制粘贴就可以了,好了环境搭建就说到这,回到正题,其实各种软件开发都是一个前后台交互的过程,那么struts2是如何处理前台表单和后台action交互的,总共有三种常用方式,好的,下面以此示例讲解:
(一)JSP页面中,form表单中输入项的name属性值与Struts2中XXXAction类中属性名一致,上代码:
JSP页面的form表单代码:
<form action="addCompany2">
公司简称:<input type="text" name="companyName"><br />
公司全称:<input type="text" name="fullName"><br />
官方网站:<input type="text" name="web"><br />
公司地址:<input type="text" name="address"><br />
邮 编:<input type="text" name="postcode"><br />
联系电话:<input type="text" name="phone"><br />
公司邮箱:<input type="text" name="email"><br />
<input type="submit" value="添加"> <input type="reset" value="清空">
</form>
AddCompanyAction的代码:
package com.struts2.controller;用此种方式传值的时候一定要注意:比如表单里面有一项<input type="text" name="companyName">,那么在对应的Action类型,必须提供setCompanyName()方法,即Action类中的属性不用在乎是否与表单输入项的name属性值一致,因为底层是通过调用setter方法给属性赋值的,但是一般在实际开发中,尽可能地保持一致;
import com.opensymphony.xwork2.ActionSupport;
public class AddCompanyAction extends ActionSupport {
private String companyName;
private String fullName;
private String web;
private String address;
private String postcode;
private String phone;
private String email;
@Override
public String execute() throws Exception {
return SUCCESS;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public void setWeb(String web) {
this.web = web;
}
public void setAddress(String address) {
this.address = address;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setEmail(String email) {
this.email = email;
}
}
这种方式的优点是清楚地知道表单有哪些项,哪些项传递到当前的Action类中,缺点是:Action类过于庞大,如果有十几项甚至几十项输入项的话,光属性和setter方法就要占据上百行,所以此种方式适合输入项较少的场合使用;
(二)采用Struts2内置的OGNL的方式,首先要做的就是将所有表单输入项的name属性值放置到一个普通的javabean类里面,相应地提供setter和getter方法,如下:
package com.struts2.domain;
public class Company {
private String companyName;
private String fullName;
private String web;
private String address;
private String postcode;
private String phone;
private String email;
public Company() {
super();
}
public Company(String companyName, String fullName, String web,
String address, String postcode, String phone, String email) {
super();
this.companyName = companyName;
this.fullName = fullName;
this.web = web;
this.address = address;
this.postcode = postcode;
this.phone = phone;
this.email = email;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getWeb() {
return web;
}
public void setWeb(String web) {
this.web = web;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
然后对AddCompanyAction类做一些改动,会发现Action类瞬间简洁了好多
package com.struts2.controller;
import com.opensymphony.xwork2.ActionSupport;
import com.struts2.domain.Company;
public class AddCompanyAction3 extends ActionSupport {
private Company company;
@Override
public String execute() throws Exception {
return SUCCESS;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
最后看一下form表单的改动,会发现每个表单输入项的name属性值前面额外添加了对应Action属性的名称:
<form action="addCompany3">这第二种方式较之于第一种使得Action类简洁的许多,更契合于MVC设计模式,保持了代码的整洁性,如果硬要说缺点的话那就是对表单造成了侵入性,表单需要配合Action类里面的属性名字取值,不是太好;
公司简称:<input type="text" name="company.companyName"><br />
公司全称:<input type="text" name="company.fullName"><br />
官方网站:<input type="text" name="company.web"><br />
公司地址:<input type="text" name="company.address"><br />
邮 编:<input type="text" name="company.postcode"><br />
联系电话:<input type="text" name="company.phone"><br />
公司邮箱:<input type="text" name="company.email"><br />
<input type="submit" value="添加"> <input type="reset" value="清空">
</form>
(三)第三种方式是采用Struts2里面模型驱动的方式,需要用到Model Driven Interceptor,由于默认的Interceptor Stack里面含有这个拦截器,所以所有的Action类可以放心使用,这种方式需要Action类额外实现ModelDriven<T>接口,并提供该接口方法getModel()的实现,如下:
form表单不做任何改动:
<form action="addCompany">同样需要提供一个javabean类
公司简称:<input type="text" name="companyName"><br />
公司全称:<input type="text" name="fullName"><br />
官方网站:<input type="text" name="web"><br />
公司地址:<input type="text" name="address"><br />
邮 编:<input type="text" name="postcode"><br />
联系电话:<input type="text" name="phone"><br />
公司邮箱:<input type="text" name="email"><br />
<input type="submit" value="添加"> <input type="reset" value="清空">
</form>
package com.struts2.domain;最后看一看Action类的变化
public class Company {
private String companyName;
private String fullName;
private String web;
private String address;
private String postcode;
private String phone;
private String email;
public Company() {
super();
}
public Company(String companyName, String fullName, String web,
String address, String postcode, String phone, String email) {
super();
this.companyName = companyName;
this.fullName = fullName;
this.web = web;
this.address = address;
this.postcode = postcode;
this.phone = phone;
this.email = email;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getWeb() {
return web;
}
public void setWeb(String web) {
this.web = web;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
package com.struts2.controller;这第三种方式,同样可以实现接受前台表单数据的功能,Action类同样整洁,问题也在于对代码造成了侵入性!
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.struts2.domain.Company;
/*
* 这种将表单数据封装到后台对象属性的方式叫做模型驱动,模型驱动的实现方式
* 1、实现ModelDriven<T>接口
* 2、在对应的Action下面,提供一个要封装表单数据的属性,即18行代码所示
* 3、实现getModel方法,返回在2处的属性名字
* 如果一个Action类没有实现ModelDriven这个接口,那么比如form表单有个name为web的表单项,
* 那么Struts2会默认调用当前action类的setWeb方法,否则会调用getModel()方法返回值得setWeb方法
*/
public class AddCompanyAction2 extends ActionSupport implements ModelDriven<Company>{
private Company company = new Company();
@Override
public String execute() throws Exception {
return SUCCESS;
}
@Override
public Company getModel() {
return company;
}
}
综上三种方式,没有哪一种是用来传值最恰当的方式,只有合适的场景才需要选择合适的方式,建议大家把这三种方式牢牢掌握,以便于应对各种需求的考验!!