struts2单选
与动态复选框一样,具有动态选择的元素的单选按钮可以为您的Web页面增加很多复杂性,并且使用Struts,还可以轻松创建它们。
在本文中,我将向您展示如何通过嵌套Struts标签<logic:iterate/>
和<html:radio/>
来创建单选按钮组。 然后,我将指定的Form Bean引用到标签,并通过单选按钮值的String[]
数组进行迭代,为每个分配的value
属性分配一个相同的name
属性。
有关完整的示例源代码,请参见下载部分 。 看到相关信息 ,如果您需要下载Struts框架。
五步食谱
为了简单起见,我对单选按钮使用了与上次用于动态复选框相同的示例。 我的简单UI使用单选按钮元素在喜马拉雅山中显示String[]
数组山峰,并使用第二个selectedMountain String
表示所选的单选按钮。 单选按钮由创建按钮后调用JavaScript函数预先选择。
根据喜马拉雅山的示例,在Struts中创建动态选择的单选按钮的方法包括五部分:
- 一个伪造的数据类,用于容纳
mountains
和selectedMountain
数据。 - 一个表单bean,其中包含用于单选按钮的
String[]
数组和用于特定选择的按钮的String
。 - JSP的表单显示处于所需状态的单选按钮。
- 一个JSP,用于显示表单中选定的元素。
- 从表单页面到显示页面的简单
Action
类。
单选按钮配方和您上次学习的动态复选框配方之间的主要区别在于,Struts没有提供用于创建selected
值的自动工具,创建动态单选按钮通常需要该工具。 使用Struts JSP标记内置的功能预选checkbox
并select
输入类型相当简单,但是radio button
输入类型则需要不同的解决方案。 幸运的是,这很容易使用表单bean和两行JavaScript中的信息来完成,如我在步骤3中所示。
步骤1.创建数据层
我已经组装了一个假数据类来表示从业务层到应用程序视图层的数据,这是我关心的问题。 适当命名的FakeData
类包含两个静态的final方法,如清单1所示:
清单1. FakeData.java
/**
* class FakeData -- represents the business logic
*/
public class FakeData {
/**
* data for mountains
*/
public static final String[] MOUNTAINS =
{"Everest", "K2", "Kangchenjunga",
"Lhotse", "Makalu", "Cho Oyu"};
/**
* data for selected mountain
*/
public static final String SELECTED_MOUNTAIN = "Kangchenjunga";
}
创建伪造的数据层是一种有用的UI开发实践,因为最终应用程序通常无法使用最终应用程序使用的持久层。 您无需等待后端团队来完成工作,您可以轻松地开发一个伪造的数据层,该层模仿最终将发送给您的API和功能。 使用伪造的数据层,您可以继续进行UI开发并降低对其他团队的依赖。 由于数据层是伪造的,因此您还可以定义与项目其他部分的API连接,并确保在集成所有部分时遇到的问题更少。
步骤2.创建表单bean
最终将填充您的应用程序的值可能来自比清单1所示的框架更复杂的框架。关于我的波西米亚风格示例的好处是,清单2中的form Bean不必做任何繁重的工作,因此,它只是带有getter和setter的简单Java™对象。 实际值在调用构造函数时注入。
清单2. RadioTestForm.java
package com.strutsrecipes;
import org.apache.struts.action.ActionForm;
/**
* Radio Button Test Form to show an array of radio buttons and
*/
public class RadioTestForm extends ActionForm {
// ------------------------------ FIELDS ------------------------------
/**
* The selected Mountain
*/
private String selectedMountain;
/**
* The list of mountains for the radio button
*/
private String[] mountains;
// --------------------------- CONSTRUCTORS ---------------------------
/**
* Constructor -- using FakeData...
*/
public RadioTestForm() {
this.selectedMountain = FakeData.SELECTED_MOUNTAIN;
this.mountains = FakeData.MOUNTAINS;
}
// --------------------- GETTER / SETTER METHODS ---------------------
/**
* Getter for the mountains
*
* @return the mountains array
*/
public String[] getMountains() {
return this.mountains;
}
/**
* Setter for the mountains
*
* @param m the Mountains array
*/
public void setMountains(String[] m) {
this.mountains = m;
}
/**
* Getter for selectedMountain
*
* @return the selected mountain
*/
public String getSelectedMountain() {
return this.selectedMountain;
}
/**
* Setter for selectedMountain
*
* @param sm the selectedMountain
*/
public void setSelectedMountain(String sm) {
this.selectedMountain = sm;
}
}
为了清楚起见,我包括了Form Bean的所有Java代码。 请注意, Kangchenjunga
列在selectedMountain
和mountains
字段中,并在构造函数中实例化,并由我的FakeData
类填充。 至此,我已经有足够的信息将Kangchenjunga
传播到JSP,作为我的预选初始值。
步骤3.创建单选按钮JSP
清单3包含表单页面的JSP代码,其中包含单选按钮和我的预选值。 请注意,Java文件与逻辑,HTML和bean标记以及位于表单底部JavaScript函数之间的相关性。 我遍历mountains
集合以创建单选按钮。 完成此操作后,我将添加JavaScript并在其中填充selectedMountain
的值,以便与单选按钮数组进行比较以选择合适的单选按钮。
清单3.包含单选按钮和预选值的JSP
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<html:html locale="true">
<head>
<title><bean:message key="testForm.title"/></title>
<html:base/>
</head>
<body>
<h3><bean:message key="testForm.heading"/></h3>
<html:form action="/FormAction" name="testForm"
type="com.strutsrecipes.RadioTestForm">
<h4><bean:message key="testForm.instruction"/></h4>
<!-- gets the selected radio button -->
<bean:define id="selectedRadio" property="selectedMountain" name="testForm"/>
<!-- creates the radio button list -->
<logic:iterate id="mountain" property="mountains" name="testForm">
<%-- you need this hack to get the value of the mountains to the page --%>
<bean:define id="mountainValue">
<bean:write name="mountain"/>
</bean:define>
<html:radio property="selectedMountain"
value="<%=mountainValue%>"
styleId="<%=mountainValue%>"/>
<bean:write name="mountain"/><br/>
</logic:iterate><br/>
<html:submit/> <html:reset/>
<script type="text/javascript">
<!--
//Either of the following works.
//Uncomment the one you wish to try and comment the other out.
//var selectedRadio =
document.getElementById("<bean:write //name="selectedRadio"/>");
var selectedRadio =
document.forms["testForm"].elements["<bean:write name="selectedRadio"/>"];
selectedRadio.checked=true; -->
</script>
</html:form>
</body>
</html:html>
步骤4.创建显示页面
该显示页面与用于复选框配方的页面几乎相同,除了不需要迭代,因为只选择了一个值。 我需要做的就是列出在bean中选择的mountain
,如清单4所示:
清单4.显示页面的JSP。
<%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<%@taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%>
<%-- html code, etc... --%>
<bean:write name="mountain"/><br/>
<hr size=5 color="black"/>
<%-- some more html code, etc... --%>
步骤5.编写Action类
与该食谱的其他组件相比, Action
类的作用不大。 我在这里所做的只是获取String
数组和selectedMountain
值,并使它们可用于我的显示页面。
清单5. Action类
ipackage com.strutsrecipes;
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 javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* The Action for the Radio Button test
*/
public final class RadioTestAction extends Action {
// -------------------------- OTHER METHODS --------------------------
/**
* The Action for the Radio Button test
*/
public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response
)
throws ServletException, Exception {
// Extract attributes needed
String selectedMountains = ((RadioTestForm) form).getSelectedMountain();
System.out.println("htmlString RETURNED*********\n" + selectedMountains);
//Save your htmlString in the session
HttpSession session = request.getSession();
session.setAttribute(Constants.MOUNTAINS, selectedMountains);
return (mapping.findForward("success"));
}
}
里面的食谱
此食谱背后的真正力量是JavaScript。 首先,我在JSP表单内的清单5中为selectedMountain
字段定义了一个JSP脚本变量,如下所示:
<bean:define id="selectedRadio" property="selectedMountains" name="testForm"/>
在表单下方,我创建了一个由以下两行组成JavaScript函数:
var selRadio = document.getElementById("<bean:write name="selectedRadio"/>");
selRadio.checked=true;
在客户端脚本内部,我创建了一个selRadio
JavaScript变量,然后查找其id
(或预编译代码中的styleId
)与selectedRadio
变量匹配的文档中的所有元素。 我通过设置<html:radio/>
标记的styleId
属性以匹配其名称/值来实现此目的。 尽管JavaScript函数快速遍历页面上的ID,但它只是将单个单选按钮设置为selected 。
另一种方法
您可以使用此处显示JavaScript方法产生相同的结果:
var selectedRadio =
document.forms["testForm"].elements["<bean:writename="selectedRadio"/>"];
selectedRadio.checked=true;
该脚本仅区分表单元素的name
属性,而不区分id
。 两种实现方式均有效,因此选择哪种方式取决于您的要求和偏好。 JSP表单页面的实际输出类似于清单6:
清单6. JSP表单页面的输出
<input type="radio" name="selectedMountain" value="Everest" id="Everest"/>
Everest<br/>
<input type="radio" name="selectedMountain" value="K2" id="K2"/>
K2<br/>
<input type="radio" name="selectedMountain"
value="Kangchenjunga" checked="checked" id="Kangchenjunga"/>
Kangchenjunga<br/>
<input type="radio" name="selectedMountain" value="Lhotse" id="Lhotse"/>
Lhotse<br/>
<input type="radio" name="selectedMountain" value="Makalu" id="Makalu"/>
Makalu<br/>
<input type="radio" name="selectedMountain" value="Cho Oyu" id="Cho Oyu"/>
Cho Oyu<br/>
结论
正如我在上一篇文章的结论中提到的那样,缺少有关在Struts中创建动态元素的信息是与George Franciscus合作撰写Struts Recipes的强烈动机。 创建动态单选按钮的大部分沉默是由于太紧密地耦合服务器端和客户端信息和功能所固有的设计难题。 正如我在此处演示的那样,使用JavaScript和服务器端变量似乎是利用此功能的唯一方法,尽管您仍然冒着使客户端和服务器之间相互了解过多的风险。
是否承担“耦合”风险的决定由您决定。 做出决定的一个好过程是向自己大声解释优缺点。 如果您在那之后仍然愿意冒险-如果下一个立方体的人没有嘲笑您-您可能已经准备好冒险了。
翻译自: https://www.ibm.com/developerworks/web/library/j-sr4/index.html
struts2单选