Struts2 - 面试问题



亲爱的读者,这些Struts2 面试问题是专门为了让您熟悉在Struts2 编程面试中可能遇到的问题类型而设计的。根据我的经验,优秀的面试官在面试过程中很少计划提出特定的问题,通常会从主题的一些基本概念开始提问,然后根据进一步的讨论以及您的回答继续提问。

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

以下是一些可能促使您考虑使用 Struts2 的优秀特性:

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

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

  • AJAX 支持 − Struts2 认识到 Web2.0 技术的兴起,并在产品中集成了 AJAX 支持,创建了与标准 Struts2 标签功能非常相似的 AJAX 标签。

  • 易于集成 − 与其他框架(如 Spring、Tiles 和 SiteMesh)的集成现在变得更加容易,Struts2 提供了各种集成选项。

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

  • 插件支持 − 可以通过使用插件增强和扩展核心 Struts2 行为。Struts2 提供了许多插件。

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

  • Action

  • 拦截器

  • 值栈 / OGNL

  • 结果 / 结果类型

  • 视图技术

以下是 Struts2 应用程序中请求的生命周期:

  • 用户向服务器发送请求,请求某些资源(例如页面)。

  • FilterDispatcher 查看请求,然后确定相应的 Action。

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

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

  • 再次应用配置的拦截器,如果需要进行任何后处理。

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

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

constant 标签连同 name 和 value 属性将用于覆盖 default.properties 中定义的任何属性,例如我们刚刚设置的 struts.devMode 属性。设置 struts.devMode 属性允许我们在日志文件中查看更多调试消息。

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

结果确定在执行 Action 后返回给浏览器的內容。Action 返回的字符串应该是结果的名称。结果配置为每个 Action,如上所示,或者作为“全局”结果,可用于包中的每个 Action。结果具有可选的 name 和 type 属性。默认名称值为“success”。

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

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

此部分将 Web 应用程序上的页面映射到名称。您可以使用此名称引用实际页面。这避免在网页上硬编码 URL。

在这里,您声明表单处理程序,它们也被称为 Action 映射。

此部分告诉 Struts 在哪里可以找到您的属性文件,其中包含提示和错误消息。

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

从概念上讲,拦截器与 servlet 过滤器或 JDK 的 Proxy 类相同。拦截器允许在 Action 和框架之外实现横切功能。您可以使用拦截器实现以下功能:

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

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

  • 捕获异常,以便可以执行备用处理。

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

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

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

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

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

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

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

值栈是一组多个对象,按以下顺序保存对象:

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

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

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

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

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

ActionContext 映射包含以下内容:

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

  • session − 会话范围的变量。

  • root / value stack − 所有 Action 变量都存储在这里。

  • request − 请求范围的变量。

  • parameters − 请求参数。

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

在 Struts 中,可以通过一个预定义的拦截器来上传文件,这个拦截器叫做 FileUpload 拦截器,它由 org.apache.struts2.interceptor.FileUploadInterceptor 类提供,并且包含在 defaultStack 中。

以下 Struts2 配置属性控制着文件上传过程:

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

  • struts.multipart.parser − 用于上传 multipart 表单的库。默认为 jakarta。

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

FileUpload 拦截器使用了一些默认的错误消息键:

  • 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 方法之前运行规则以执行验证。Action 类应扩展 ActionSupport 类,以便执行 validate 方法。

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

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

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

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

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

以下是 Struts2 中提供的各种字段级和非字段级验证的列表:

  • 日期验证器

  • 双精度验证器

  • 电子邮件验证器

  • 表达式验证器

  • 整数验证器

  • 正则表达式验证器

  • 必填验证器

  • 必填字符串验证器

  • 字符串长度验证器

  • URL 验证器

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

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

  • UI 标签。

  • 消息和错误。

  • 在 action 类中。

资源文件的简单命名格式如下:

bundlename_language_country.properties

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

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

  • ActionClass.properties

  • Interface.properties

  • SuperClass.properties

  • model.properties

  • package.properties

  • struts.properties

  • global.properties

StrutsTypeConverter 类告诉 Struts 如何通过覆盖 convertFromString() 和 convertToString() 两个方法将环境转换为字符串并反之亦然。

Struts 2 带有三个内置主题:

  • simple 主题 − 一个最小的主题,没有“花里胡哨”。例如,textfield 标签呈现 HTML <input/> 标签,没有标签、验证、错误报告或任何其他格式或功能。

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

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

Struts 通过使用“exception”拦截器使异常处理变得容易。“exception”拦截器包含在 default stack 中,因此您无需执行任何额外操作来配置它。它开箱即用,随时可以使用。

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

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

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

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

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

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

@After 注解标记一个 action 方法,该方法需要在主 action 方法和结果执行后调用。返回值被忽略。

public class Employee extends ActionSupport{
   @After
   public void isValid() throws ValidationException {
      // validate model object, throw exception if failed
   }
   public String execute() {
      // perform secure action
      return SUCCESS;
   }
}

@Before 注解标记一个 action 方法,该方法需要在主 action 方法和结果执行前调用。返回值被忽略。

public class Employee extends ActionSupport{
   @Before
   public void isAuthorized() throws AuthenticationException {
      // authorize request, throw exception if failed
   }
   public String execute() {
      // perform secure action
      return SUCCESS;
   }
}

@BeforeResult 注解标记一个 action 方法,该方法需要在结果之前执行。返回值被忽略。

public class Employee extends ActionSupport{
   @BeforeResult
   public void isValid() throws ValidationException {
    // validate model object, throw exception if failed
   }
   public String execute() {
      // perform action
      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;
   }
}

此验证注解检查双精度字段的值是否在指定范围内。如果既没有设置 min 也没有设置 max,则不会执行任何操作。

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" )

此验证注解检查数字字段的值是否在指定范围内。如果既没有设置 min 也没有设置 max,则不会执行任何操作。

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 注解必须应用于类型级别。

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

接下来是什么?

此外,您可以回顾一下您之前完成的与该主题相关的作业,并确保您能够自信地谈论它们。如果您是应届毕业生,面试官不会期望您回答非常复杂的问题,而是您必须使自己的基础概念非常牢固。

其次,如果您无法回答一些问题,这实际上并不重要,但重要的是,无论您回答了什么,都必须自信地回答。因此,在面试期间要保持自信。我们在 tutorialspoint 祝您面试顺利,并祝您未来的工作一切顺利。干杯 :-)

struts_questions_answers.htm
广告