Struts2之前台表单传值到后台Action方法总结

时间:2022-11-17 17:10:07

在正式讲解之前,先交代一下项目版本,Struts2的版本是struts-2.3.30稳定版本,至于如何快速搭建以及正确的选择Struts2必要的Jar文件,以struts-2.3.30为例,首先建议大家直接从官网直接下载struts-2.3.30.zip文件,解压缩后,会得到如下所示目录结构:

Struts2之前台表单传值到后台Action方法总结

在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;

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;
}
}
用此种方式传值的时候一定要注意:比如表单里面有一项<input type="text" name="companyName">,那么在对应的Action类型,必须提供setCompanyName()方法,即Action类中的属性不用在乎是否与表单输入项的name属性值一致,因为底层是通过调用setter方法给属性赋值的,但是一般在实际开发中,尽可能地保持一致;

这种方式的优点是清楚地知道表单有哪些项,哪些项传递到当前的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">
公司简称:<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>
这第二种方式较之于第一种使得Action类简洁的许多,更契合于MVC设计模式,保持了代码的整洁性,如果硬要说缺点的话那就是对表单造成了侵入性,表单需要配合Action类里面的属性名字取值,不是太好;

(三)第三种方式是采用Struts2里面模型驱动的方式,需要用到Model Driven Interceptor,由于默认的Interceptor Stack里面含有这个拦截器,所以所有的Action类可以放心使用,这种方式需要Action类额外实现ModelDriven<T>接口,并提供该接口方法getModel()的实现,如下:

form表单不做任何改动:

   <form action="addCompany">
公司简称:<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>
同样需要提供一个javabean类

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;
}

}
最后看一看Action类的变化

package com.struts2.controller;

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;
}
}
这第三种方式,同样可以实现接受前台表单数据的功能,Action类同样整洁,问题也在于对代码造成了侵入性!

综上三种方式,没有哪一种是用来传值最恰当的方式,只有合适的场景才需要选择合适的方式,建议大家把这三种方式牢牢掌握,以便于应对各种需求的考验!!