modeldriven
In my earlier posts for Struts 2 for Beginners and Struts 2 Annotation Example, you will notice that the java bean properties are part of Action classes. Actually this is not a good design because most of the times, we would want to have bean classes to hold the application elements data and we want to use them across the application.
在我先前关于Struts 2的初学者和Struts 2注释示例的文章中 ,您会注意到Java bean属性是Action类的一部分。 实际上,这并不是一个很好的设计,因为在大多数情况下,我们希望使用bean类来保存应用程序元素数据,并且希望在整个应用程序中使用它们。
Struts 2 provide two different approaches through which we can separate java bean properties from action classes and thus reuse the same java bean with different action classes, business logic or in different JSP pages. These approaches are – Object-backed action classes and ModelDriven action classes.
Struts 2提供了两种不同的方法,通过它们我们可以将Java Bean属性与动作类分开,从而将相同的Java Bean与不同的动作类,业务逻辑或在不同的JSP页面中复用。 这些方法是– 对象支持的动作类和ModelDriven动作类。
We will understand both the approaches with simple struts 2 web application. Our final project will look like below image.
我们将通过简单的struts 2 Web应用程序来理解这两种方法。 我们的最终项目将如下图所示。
I am using annotations to create action classes, that’s why there is no struts.xml file. Also I have converted the dynamic web project to maven and added struts 2 dependencies in pom.xml, that’s why you don’t see any struts jar in lib directory.
我正在使用注释来创建动作类,这就是为什么没有struts.xml文件的原因。 另外,我已经将动态Web项目转换为maven,并在pom.xml中添加了struts 2依赖项,这就是为什么在lib目录中看不到任何struts jar的原因。
Before we move on to action classes for both approaches, we will look into the common components of the web application.
在继续介绍这两种方法的动作类之前,我们将研究Web应用程序的通用组件。
web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Struts2FormDataExample</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
pom.xml
pom.xml
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Struts2FormDataExample</groupId>
<artifactId>Struts2FormDataExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.15.1</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>2.3.15.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
</project>
Common Java Bean with some properties and getter-setter methods.
具有某些属性和获取方法的通用Java Bean。
package com.journaldev.struts2.beans;
public class User {
private String userID;
private String password;
private String userName;
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
Now let’s move to the implementation of Object-backed and ModelDriven action classes.
现在,让我们转到对象支持和模型驱动动作类的实现。
对象支持的动作类 (Object-backed Action Class)
For object-backed action classes, we need change in action classes as well as request and response HTML/JSP pages. In action class, we have to add a class level variable for the java bean.
package com.journaldev.struts2.actions; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.ResultPath; import org.apache.struts2.convention.annotation.Results; import com.journaldev.struts2.beans.User; import com.opensymphony.xwork2.Action; @org.apache.struts2.convention.annotation.Action("loginObject") @Namespace("/") @ResultPath("/") @Results({ @Result(name = "success", location = "homeObject.jsp"), @Result(name = "input", location = "loginObject.jsp") }) public class LoginObjectBackedAction implements Action { @Override public String execute() throws Exception { if("pankaj".equals(getUser().getUserID()) && "admin".equals(getUser().getPassword())){ getUser().setUserName("Pankaj Kumar"); return SUCCESS; }else{ return INPUT; } } private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
Above action class is self explanatory, the only point to note is the variable name of User bean “user”. We have to use the same name in request and response pages. Let’s look at the request and response JSP pages.
loginObject.jsp
Notice the textfield names are user.userID and user.password. It’s clear that the first part is same as User variable in action class and second part is same as User class variables.
Did you noticed that in action class execute() method, we are setting userName variable value, we will use it in response JSP page.
homeObject.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Welcome Page</title> </head> <body> <h3> Welcome <s:property value="user.userName"></s:property> </h3> </body> </html>
Now when we execute above action, we get following response pages.
That’s all for object-driven action classes implementation, let’s move to the implementation of Modeldriven action classes.
对于对象支持的操作类,我们需要更改操作类以及请求和响应HTML / JSP页面。 在动作类中,我们必须为java bean添加一个类级别的变量。
上面的动作类是不言自明的,唯一需要注意的是User bean“ user”的变量名。 我们必须在请求和响应页面中使用相同的名称。 让我们看一下请求和响应JSP页面。
loginObject.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <%@ taglib uri="/struts-tags" prefix="s"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Login Page</title> </head> <body> <h3>Welcome User, please login below</h3> <s:form action="loginObject"> <s:textfield name="user.userID" label="User Name"></s:textfield> <s:textfield name="user.password" label="Password" type="password"></s:textfield> <s:submit value="Login"></s:submit> </s:form> </body> </html>
注意,文本字段名称为user.userID和user.password。 显然,第一部分与动作类中的User变量相同,第二部分与User类变量相同。
您是否注意到在动作类execute()方法中,我们正在设置userName变量值,我们将在响应JSP页面中使用它。
homeObject.jsp
现在,当我们执行上述操作时,我们将获得以下响应页面。
这就是对象驱动的动作类实现的全部内容,让我们转向模型驱动的动作类的实现。
模型驱动动作类 (ModelDriven Action Class)
For ModelDriven action classes, we have to implement
com.opensymphony.xwork2.ModelDriven
interface. This interface is type-parameterized using Java Generics and we need to provide the type as our bean class. ModelDriven interface contains only one method getModel() that we need to implement and return the bean object.The other important point to note is that action class should have a class level variable for the bean and we need to instantiate it. Our ModelDriven action class looks like below.
package com.journaldev.struts2.actions; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.ResultPath; import org.apache.struts2.convention.annotation.Results; import com.journaldev.struts2.beans.User; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ModelDriven; @org.apache.struts2.convention.annotation.Action("loginModelDriven") @Namespace("/") @ResultPath("/") @Results({ @Result(name = "success", location = "homeModelDriven.jsp"), @Result(name = "input", location = "loginModelDriven.jsp") }) public class LoginModelDrivenAction implements Action, ModelDriven<User> { @Override public String execute() throws Exception { if("pankaj".equals(user.getUserID()) && "admin".equals(user.getPassword())){ user.setUserName("Pankaj Kumar"); return SUCCESS; }else{ return INPUT; } } @Override public User getModel() { return user; } private User user = new User(); }
Our request and result pages look like below code.
loginModelDriven.jsp
homeModelDriven.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Welcome Page</title> </head> <body> <h3>Welcome <s:property value="userName"></s:property></h3> </body> </html>
Notice that in JSP pages, we don’t need to prefix the HTML tags name with action class bean variable name. However we need to make sure that names match with the java bean class variable name.
When we execute this action, we get following response pages.
Thats all for implementation of ModelDriven action classes.
对于ModelDriven动作类,我们必须实现
com.opensymphony.xwork2.ModelDriven
接口。 该接口使用Java泛型进行了类型参数化,我们需要将类型作为bean类提供。 ModelDriven接口仅包含一个我们需要实现并返回Bean对象的方法getModel() 。另一个需要注意的重要点是,动作类应该为Bean提供一个类级别的变量,我们需要实例化它。 我们的ModelDriven动作类如下所示。
我们的请求和结果页面类似于以下代码。
loginModelDriven.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <%-- Using Struts2 Tags in JSP --%> <%@ taglib uri="/struts-tags" prefix="s"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Login Page</title> </head> <body> <h3>Welcome User, please login below</h3> <s:form action="loginModelDriven"> <s:textfield name="userID" label="User Name"></s:textfield> <s:textfield name="password" label="Password" type="password"></s:textfield> <s:submit value="Login"></s:submit> </s:form> </body> </html>
homeModelDriven.jsp
注意,在JSP页面中,我们不需要在HTML标记名称之前添加动作类bean变量名称。 但是,我们需要确保名称与Java bean类变量名称匹配。
当我们执行此操作时,我们得到以下响应页面。
这就是实现ModelDriven动作类的全部。
If you look into both the approaches, ModelDriven approach is easy to implement and maintain as it doesn’t require change in the JSP pages.
如果您同时研究这两种方法,那么ModelDriven方法就易于实现和维护,因为它不需要在JSP页面中进行更改。
Further Reading: You know there are four different ways to create Action classes in Struts 2, learn about them as Struts 2 Action.
进一步阅读:您知道在Struts 2中创建Action类有四种不同的方法,作为Struts 2 Action了解它们。
翻译自: https://www.journaldev.com/2178/struts-2-action-object-backed-and-modeldriven-example
modeldriven