Struts2 - 问题

Struts2 是基于 MVC 设计模式的流行且成熟的 Web 应用程序框架。 Struts2 不仅仅是 Struts 1 的下一个版本,而且是 Struts 架构的完全重写。

以下是一些可能迫使您考虑 Struts2 的出色功能 −

  • POJO 表单和 POJO 操作 − Struts2 已经废除了 Struts 框架不可或缺的一部分操作表单。使用 Struts2,您可以使用任何 POJO 来接收表单输入。同样,您现在可以将任何 POJO 视为操作类。

  • 标签支持 − Struts2 改进了表单标签,新标签使开发人员可以编写更少的代码。

  • AJAX 支持 − Struts2 已认识到 Web2.0 技术的接管,并通过创建 AJAX 标签将 AJAX 支持集成到产品中,其功能与标准 Struts2 标签非常相似。

  • 轻松集成 − 现在,由于 Struts2 提供多种集成功能,因此与其他框架(如 Spring、Tiles 和 SiteMesh)的集成变得更加容易。

  • 模板支持 − 支持使用模板生成视图。

  • 插件支持 − 通过使用插件可以增强和扩充核心 Struts2 行为。 Struts2 有许多可用的插件。

Struts2 中的模型-视图-控制器模式通过以下五个核心组件实现 −

  • 操作

  • 拦截器

  • 值堆栈 / OGNL

  • 结果 / 结果类型

  • 视图技术

以下是 Struct2 应用程序中请求的生命周期 −

  • 用户向服务器发送请求以获取某些资源(即页面)。

  • FilterDispatcher 查看请求,然后确定适当的操作。

  • 配置的拦截器功能适用,例如验证、文件上传等。

  • 执行选定的操作以执行请求的操作。

  • 再次,如果需要,配置的拦截器将用于执行任何后期处理。

  • 最后,视图准备结果并将结果返回给用户。

struts.xml 文件包含您将在开发操作时修改的配置信息。此文件可用于覆盖应用程序的默认设置,例如 struts.devMode = false 和属性文件中定义的其他设置。此文件可在文件夹 WEB-INF/classes 下创建。

constant 标签以及 name 和 value 属性将用于覆盖 default.properties 中定义的以下任何属性,就像我们刚刚设置 struts.devMode 属性一样。设置 struts.devMode 属性允许我们在日志文件中看到更多调试消息。

我们定义与要访问的每个 URL 相对应的 action 标签,并定义一个带有 execute() 方法的类,每当我们访问相应的 URL 时都会访问该方法。

结果决定执行操作后返回到浏览器的内容。从操作返回的字符串应该是结果的名称。结果按上述操作配置,或作为"全局"结果,可用于包中的每个操作。结果具有可选的名称和类型属性。默认名称值为"success"。

struts-config.xml 配置文件是 Web 客户端中视图和模型组件之间的链接。

在这里,您可以将 ActionForm 子类映射到名称。您可以在 struts-config.xml 文件的其余部分,甚至 JSP 页面上使用此名称作为 ActionForm 的别名。

此部分将您 webapp 上的页面映射到一个名称。您可以使用此名称来引用实际页面。这样可以避免在网页上硬编码 URL。

这是您声明表单处理程序的地方,它们也称为动作映射。

本节告诉 Struts 在哪里找到包含提示和错误消息的属性文件。

此配置文件提供了一种机制来更改框架。实际上,struts.properties 配置文件中包含的所有属性也可以使用 init-param 在 web.xml 中配置,也可以使用 struts.xml 配置文件中的 constant 标记进行配置。但是,如果您希望将所有内容分开并使其更具体,则可以在文件夹 WEB-INF/classes 下创建此文件。 此文件中配置的值将覆盖 struts2-core-x.y.z.jar 发行版中包含的 default.properties 中配置的默认值。

拦截器在概念上与 servlet 过滤器或 JDK 代理类相同。拦截器允许将横切功能与操作和框架分开实现。您可以使用拦截器 − 实现以下功能

  • 在调用操作之前提供预处理逻辑。

  • 在调用操作之后提供后处理逻辑。

  • 捕获异常以便执行替代处理。

创建自定义拦截器很容易;需要扩展的接口是 Interceptor 接口。

实际操作将通过 invocation.invoke() 调用使用拦截器执行。因此,您可以根据需要进行一些预处理和后处理。

框架本身通过首次调用 ActionInvocation 对象的invoke() 来启动该过程。每次调用invoke() 时,ActionInvocation 都会查阅其状态并执行接下来的拦截器。当所有配置的拦截器都被调用后,invoke() 方法将导致操作本身被执行。

Action 类管理应用程序的状态,结果类型管理视图。

默认结果类型是 dispatcher,用于分派到 JSP 页面。

dispatcher 结果类型是默认类型,如果未指定其他结果类型,则使用该类型。它用于转发到服务器上的 servlet、JSP、HTML 页面等。它使用 RequestDispatcher.forward() 方法。

重定向结果类型调用标准 response.sendRedirect() 方法,导致浏览器向给定位置创建新请求。 我们可以在 <result...> 元素的主体中提供位置,也可以将其作为 <param name = "location">元素。

值堆栈是一组多个对象,它们按提供的顺序保存以下对象 −

  • 临时对象 − 在执行页面期间会创建各种临时对象。例如,在 JSP 标记中循环的集合的当前迭代值。

  • 模型对象 − 如果您在 struts 应用程序中使用模型对象,则当前模型对象将放置在值堆栈上的操作之前。

  • 操作对象 − 这将是正在执行的当前操作对象。

  • 命名对象 −这些对象包括 #application、#session、#request、#attr 和 #parameters,并引用相应的 servlet 范围。

对象图导航语言 (OGNL) 是一种强大的表达语言,用于引用和操作 ValueStack 上的数据。OGNL 还有助于数据传输和类型转换。

ActionContext 映射由以下 −

  • application − 应用程序范围变量。

  • session − 会话范围变量。

  • root / 值堆栈 − 所有操作变量都存储在此处。

  • request − 请求范围变量。

  • parameters − 请求参数。

  • atributes −存储在页面、请求、会话和应用程序范围中的属性。

Struts 中的文件上传可以通过预定义的拦截器 FileUpload 拦截器进行,该拦截器可通过 org.apache.struts2.interceptor.FileUploadInterceptor 类获得,并作为 defaultStack 的一部分包含在内。

以下是控制文件上传过程的 Struts2 配置属性 −

  • struts.multipart.maxSize − 接受文件上传的最大文件大小(以字节为单位)。默认值为 250M。

  • struts.multipart.parser − 用于上传多部分表单的库。默认情况下为 jakarta。

  • struts.multipart.saveDir − 存储临时文件的位置。默认情况下是javax.servlet.context.tempdir。

fileUplaod拦截器使用几个默认的错误消息键 −

  • struts.messages.error.uploading − 文件无法上传时发生的一般错误。

  • struts.messages.error.file.too.large −当上传的文件大于 maximumSize 所指定的值时发生。

  • struts.messages.error.content.type.not.allowed −当上传的文件与指定的预期内容类型不匹配时发生。

您可以在 WebContent/WEB-INF/classes/messages.properties 资源文件中覆盖这些消息的文本。

在 Struts 的核心中,我们有一个验证框架,它帮助应用程序在执行操作方法之前运行规则以执行验证。 Action 类应扩展 ActionSupport 类,以便执行验证方法。

当用户按下提交按钮时,Struts 2 将自动执行验证方法,如果方法中列出的任何 if 语句为真,Struts 2 将调用其 addFieldError 方法。如果添加了任何错误,则 Struts 2 将不会继续调用执行方法。相反,Struts 2 框架将返回输入作为调用操作的结果。

因此,当验证失败且 Struts 2 返回输入时,Struts 2 框架将重新显示视图文件。由于我们使用了 Struts 2 表单标签,Struts 2 会自动将错误消息添加到表单字段的正上方。

这些错误消息是我们在 addFieldError 方法调用中指定的。addFieldError 方法有两个参数。第一个是错误适用的表单字段名称,第二个是要显示在该表单字段上方的错误消息。

进行验证的第二种方法是将 xml 文件放在操作类旁边。 Struts2 基于 XML 的验证提供了更多验证选项,如电子邮件验证、整数范围验证、表单验证字段、表达式验证、正则表达式验证、必需验证、必需字符串验证、字符串长度验证等。

xml 文件需要命名为 '[action-class]'-validation.xml。

以下是 Struts2 中可用的各种字段级和非字段级验证类型的列表 −

  • 日期验证器

  • 双重验证器

  • 电子邮件验证器

  • 表达式验证器

  • 整数验证器

  • 正则表达式验证器

  • 必需验证器

  • 必需字符串验证器

  • 字符串长度验证器

  • url 验证器

国际化 (i18n) 是规划和实施产品和服务的过程,以便它们可以轻松适应特定的本地语言和文化,这一过程称为本地化。国际化过程有时称为翻译或本地化启用。

Struts2 通过以下位置的资源包、拦截器和标记库提供本地化,即国际化 (i18n) 支持 −

  • UI 标记。

  • 消息和错误。

  • 在操作类中。

资源文件最简单的命名格式是 −

bundlename_language_country.properties

此处的 bundlename 可以是 ActionClass、Interface、SuperClass、Model、Package、Global 资源属性。下一部分 language_country 表示国家/地区语言环境,例如西班牙语(西班牙)语言环境由 es_ES 表示,英语(美国)语言环境由 en_US 表示等。此处您可以跳过可选的国家/地区部分。

当您通过其键引用消息元素时,Struts 框架将按以下顺序搜索相应的消息包 −

  • ActionClass.properties

  • Interface.properties

  • SuperClass.properties

  • model.properties

  • package.properties

  • struts.properties

  • global.properties

StrutsTypeConverter 类通过重写两个方法 convertFromString() 和 convertToString() 告诉 Struts 如何将 Environment 转换为字符串,反之亦然。

Struts 2 附带三个内置主题 −

  • 简单主题 − 一个没有"花哨"的极简主题。例如,textfield 标签呈现 HTML <input/> 标签,没有标签、验证、错误报告或任何其他格式或功能。

  • xhtml 主题 − 这是 Struts 2 使用的默认主题,提供简单主题提供的所有基本功能,并添加了一些功能,如 HTML 的标准两列表格布局、每个 HTML 的标签、验证和错误报告等。

  • css_xhtml 主题 −此主题提供了简单主题提供的所有基本功能,并添加了几个功能,例如基于 CSS 的标准两列布局,使用 <div> 作为 HTML Struts 标记,为每个 HTML Struts 标记添加标签,并根据 CSS 样式表进行放置。

Struts 通过使用"异常"拦截器使异常处理变得简单。"异常"拦截器包含在默认堆栈中,因此您无需执行任何额外操作即可对其进行配置。它开箱即用,可供您使用。

@Results 注解是结果的集合。在 @Results 注解下,我们可以有多个 @Result 注解。

@Results({
   @Result(name = "success", value = "/success.jsp"),
   @Result(name = "error", value = "/error.jsp")
})
public class Employee extends ActionSupport{
 ...
}

@result 注解的名称与执行方法的结果相对应。它们还包含应根据 execute() 的返回值提供哪个视图的位置。

@Result(name = "success", value = "/success.jsp")
public class Employee extends ActionSupport{
 ...
}

这用于修饰 execute() 方法。Action 方法还接受一个值,该值是调用操作的 URL。

public class Employee extends ActionSupport{
   private String name;
   private int age;
   @Action(value = "/empinfo")
   public String execute() {
      return SUCCESS;
   }
}

@After 注解标记需要在主操作方法执行并执行结果后调用的操作方法。返回值将被忽略。

public class Employee extends ActionSupport{
   @After
   public void isValid() throws ValidationException {
      // 验证模型对象,如果失败则抛出异常
   }
   public String execute() {
      // 执行安全操作
      return SUCCESS;
   }
}

@Before 注解标记需要在主操作方法和结果执行之前调用的操作方法。返回值被忽略。

public class Employee extends ActionSupport{
   @Before
   public void isAuthorized() throws AuthenticationException {
      // 授权请求,如果失败则抛出异常
   }
   public String execute() {
      // 执行安全行动
      return SUCCESS;
   }
}

@BeforeResult 注解标记需要在结果之前执行的操作方法。返回值被忽略。

public class Employee extends ActionSupport{
   @BeforeResult
   public void isValid() throws ValidationException {
    // 验证模型对象,如果失败则抛出异常
   }
   public String execute() {
      // 执行动作
      return SUCCESS;
   }
}

此验证注解检查字段是否存在任何转换错误,如果存在则应用它们。

public class Employee extends ActionSupport{
   @ConversionErrorFieldValidator(message = "Default message", 
                        key = "i18n.key", shortCircuit = true)
   public String getName() {
       return name;
   }
}

此验证注解检查日期字段的值是否在指定范围内。

public class Employee extends ActionSupport{
   @DateRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   min = "2005/01/01", max = "2005/12/31")
   public String getDOB() {
       return dob;
   }
}

此验证注解检查双精度字段的值是否在指定范围内。如果未设置最小值和最大值,则不会执行任何操作。

public class Employee extends ActionSupport{
   @DoubleRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   minInclusive = "0.123", maxInclusive = "99.987")
   public String getIncome() {
       return income;
   }
}

此验证注解检查字段是否包含非空字符串,是否为有效的电子邮件地址。

public class Employee extends ActionSupport{
   @EmailValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getEmail() {
       return email;
   }
}

此非字段级验证器验证提供的正则表达式。

@ExpressionValidator(message = "Default message", key = "i18n.key",
shortCircuit = true, expression = "an OGNL expression" )

此验证注解检查数字字段的值是否在指定范围内。如果未设置最小值和最大值,则不会执行任何操作。

public class Employee extends ActionSupport{
   @IntRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   min = "0", max = "42")
   public String getAge() {
       return age;
   }
}

此注解使用正则表达式验证字符串字段。

@RegexFieldValidator( key = "regex.field", expression = "yourregexp")

此验证注解检查字段是否为非空。注解必须在方法级别应用。

public class Employee extends ActionSupport{
   @RequiredFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getAge() {
       return age;
   }
}

此验证注解检查字符串字段是否不为空(即非空且长度 > 0)。

public class Employee extends ActionSupport{
   @RequiredStringValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, trim = true)
   public String getName() {
       return name;
   }
}

此验证器检查字符串字段的长度是否正确。它假定该字段是字符串。如果未设置 minLength 和 maxLength,则不会执行任何操作。

public class Employee extends ActionSupport{
   @StringLengthFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   trim = true, minLength = "5",  maxLength = "12")
   public String getName() {
       return name;
   }
}

此验证器检查字段是否为有效 URL。

public class Employee extends ActionSupport{
   @UrlValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getURL() {
       return url;
   }
}

如果要使用多个相同类型的注解,则这些注解必须嵌套在 @Validations() 注解中。

public class Employee extends ActionSupport{
  @Validations(
   requiredFields =
      {@RequiredFieldValidator(type = ValidatorType.SIMPLE, 
      fieldName = "customfield", 
      message = "You must enter a value for field.")},
   requiredStrings =
      {@RequiredStringValidator(type = ValidatorType.SIMPLE, 
      fieldName = "stringisrequired", 
      message = "You must enter a value for string.")}
   )
   public String getName() {
       return name;
   }
}

此注解可用于自定义验证器。使用 ValidationParameter 注解提供其他参数。

@CustomValidator(type ="customValidatorName", fieldName = "myField")

这是类型级别类型转换的标记注解。转换注解必须在类型级别应用。

@Conversion()
   public class ConversionAction implements Action {
}

此注解设置 CreateIfNull 进行类型转换。CreateIfNull 注解必须在字段或方法级别应用。

@CreateIfNull( value = true )
private List<User> users;

此注解设置 Element 进行类型转换。Element 注解必须在字段或方法级别应用。

@Element( value = com.acme.User )
private List<User> userList;

此注解设置类型转换的 Key。Key 注解必须在字段或方法级别应用。

@Key( value = java.lang.Long.class )
private Map<Long, User> userMap;

此注解设置类型转换的 KeyProperty。KeyProperty 注解必须在字段或方法级别应用。

@KeyProperty( value = "userName" )
protected List<User> users = null;

此注解用于类和应用程序范围的转换规则。TypeConversion 注解可应用于属性和方法级别。

@TypeConversion(rule = ConversionRule.COLLECTION, 
converter = "java.util.String")
public void setUsers( List users ) {
   this.users = users;
}