Struts2 面試問題與答案

Struts2 是開發 Java 網絡應用程序的著名框架之一。最近,我寫了很多 Struts2 教程,在這篇文章中,我列出了一些重要的 Struts2 面試問題,並附上了答案,以幫助你應對面試。

Struts2 面試問題

  1. 什麼是 Struts2?
  2. Struts1 和 Struts2 之間有什麼區別,或者 Struts2 怎樣比 Struts1 更好?
  3. Struts2 的核心組件有哪些?
  4. Struts2 中的攔截器是什麼?
  5. Struts2 攔截器實現了哪種設計模式?
  6. 在 Struts2 中創建 Action 類的不同方式有哪些?
  7. Struts2 的 Action 和攔截器是否是線程安全的?
  8. 在 Struts2 中,哪個類是前端控制器?
  9. Struts2 中攔截器的好處是什麼?
  10. 什麼是 ValueStack 和 OGNL?
  11. 列舉一些在Struts2中引入的有用的註釋?
  12. 提供一些你使用過的重要的Struts2常數?
  13. 在Struts2中的動作映射中,命名空間的作用是什麼?
  14. 哪個攔截器負責將請求參數映射到動作類Java Bean屬性?
  15. 哪個攔截器負責i18n支持?
  16. 在操作類中使用Action接口和ActionSupport類有什麼區別,你更喜歡使用哪個?
  17. 如何在操作類中獲取Servlet API的Request、Response、HttpSession等對象?
  18. execAndWait攔截器的作用是什麼?
  19. token攔截器在Struts2中的作用是什麼?
  20. 如何在Struts2應用程序中集成log4j?
  21. 有哪些不同的Struts2標籤?我們如何使用它們?
  22. Struts2中的自定義類型轉換器是什麼?
  23. 如何編寫我們自己的攔截器並將其映射到操作?
  24. 攔截器的生命周期是什麼?
  25. 什麼是攔截器堆棧?
  26. struts-default套件是什麼,它有什麼好處?
  27. Struts2動作URI的默認後綴是什麼,我們如何更改它?
  28. 結果頁的默認位置是什麼,我們如何更改它?
  29. 我們如何在Struts2應用程序中上傳文件?
  30. 在開發Struts2應用程序時應遵循的最佳實踐是什麼?
  31. 我們如何在Struts2中處理應用程序拋出的異常?

Struts2面試問題與答案

  1. 什麼是Struts2?

    Apache Struts2是一個用於Java的開源框架,用於構建Web應用程序。Struts2基於OpenSymphony WebWork框架。它在Struts1的基礎上進行了很大的改進,使其更加靈活、易於使用和擴展。Struts2的核心組件包括Action、攔截器和結果頁。Struts2提供了許多創建Action類和通過struts.xml或通過註釋配置它們的方式。我們可以為常見任務創建自己的攔截器。Struts2提供了許多標籤,並使用OGNL表達式語言。我們可以創建自己的類型轉換器來呈現結果頁。結果頁可以是JSP和FreeMarker模板。

  2. Struts1和Struts2之間有什麼區別,或者Struts2比Struts1更好在哪裡?

    Struts2旨在克服Struts1的缺點,使其更靈活、可擴展。一些顯著的區別包括:

    組件 Struts1 Struts2
    操作類 Struts1操作類被強制擴展一個抽象類,這使得它不可擴展。 Struts2操作類靈活,我們可以通過實現Action接口、擴展ActionSupport類或只是具有execute()方法來創建它們。
    線程安全性 Struts1操作類是單例的,不是線程安全的,這使得開發人員需要額外小心,以避免由於多線程而產生的任何副作用。 Struts2操作類每個請求實例化一次,所以沒有多線程,使它們是線程安全的。
    Servlet API耦合 Struts1 API與Servlet API緊密耦合,並且請求和響應對象被傳遞到操作類的execute()方法中。 Struts2 API與Servlet API鬆散耦合,並自動將表單bean數據映射到操作類Java bean屬性中,我們通常使用。然而,如果我們需要引用Servlet API類,則有*Aware接口可用。
    測試 Struts1操作類由於與Servlet API耦合而難以測試。 Struts2操作類像普通的Java類一樣,我們可以通過實例化它們並設置它們的屬性來輕鬆測試它們。
    請求參數映射 Struts1要求我們創建ActionForm類來保存請求參數,並且我們需要在struts配置文件中進行配置。 Struts2請求參數映射是即時完成的,我們只需要在操作類中具有Java bean屬性,或者實現ModelDriven接口以提供要用於映射的Java bean類名稱。
    標籤支持 Struts1使用JSTL標籤,因此受到限制。 Struts2使用OGNL並提供不同類型的UI、控制和數據標籤。它更加多功能且易於使用。
    驗證 Struts1通過手動validate()方法支持驗證 Struts2既支持手動驗證,也支持驗證框架集成。
    視圖渲染 Struts1使用標準的JSP技術將bean值提供給JSP頁面進行視圖呈現。 Struts2使用ValueStack來存儲請求參數和屬性,我們可以使用OGNL和Struts2標籤來訪問它們。
    模塊支持 Struts1模塊設計較為複雜,看起來像是獨立的項目。 Struts2提供了“命名空間”配置,用於包中輕鬆創建模塊。
  3. Struts2的核心組件有哪些?

    Struts2的核心組件包括:

    1. Action類
    2. 攔截器
    3. 結果頁,JSP或FreeMarker模板
    4. ValueStack、OGNL和標籤庫
Struts 2 Architecture Diagram
  1. 什麼是 Struts2 中的攔截器?

    攔截器是 Struts2 框架的支柱。Struts2 攔截器負責大部分框架處理的工作,如將請求參數傳遞給操作類、使Servlet API的請求、響應和會話可用於操作類、驗證、i18n 支持等。ActionInvocation 負責封裝操作類和攔截器,按順序觸發它們。在 ActionInvocation 中最重要的方法是 invoke() 方法,該方法跟蹤攔截器鏈並調用下一個攔截器或操作。這是 Java EE 框架中職責鏈模式的最佳示例之一。

  2. Struts2攔截器實現了哪種設計模式?

Struts2 interceptors are based on intercepting filters design pattern. The invocation of interceptors in interceptor stack closely resembles Chain of Responsibility design pattern.
  1. 在Struts2中創建Action類的不同方法有哪些?

Struts2 provide different ways to create action classes.
1.  By implementing Action interface
2.  Using Struts2 @Action annotation
3.  By extending ActionSupport class
4.  Any normal java class with execute() method returning String can be configured as Action class.
  1. Struts2的action和攔截器是否線程安全?

Struts2 Action classes are thread safe because an object is instantiated for every request to handle it. Struts2 interceptors are singleton classes and a new thread is created to handle the request, so it's not thread safe and we need to implement them carefully to avoid any issues with shared data.
  1. 在Struts2中,Front Controller是哪個類別?

`org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter` is the Front Controller class in Struts2 and every request processing starts from this class. Earlier versions of Struts2 uses `org.apache.struts2.dispatcher.FilterDispatcher` as Front Controller class.
  1. Struts2中攔截器的好處是什麼?

Some of the benefits of interceptors are:
-   Interceptor plays a crucial role in achieving high level of separation of concerns.
-   Struts2 interceptors are configurable, we can configure it for any action we want.
-   We can create our own custom interceptors to perform some common tasks such as request params logging, authentication etc. This helps us in taking care of common tasks at a single location, achieving low maintenance cost.
-   We can create interceptors stack to use with different actions.
  1. ValueStack和OGNL是什麼?

ValueStack is the storage area where the application data is stored by Struts2 for processing the client requests. The data is stored in `ActionContext` objects that use ThreadLocal to have values specific to the particular request thread. Object-Graph Navigation Language (OGNL) is a powerful Expression Language that is used to manipulate data stored on the ValueStack. As you can see in architecture diagram, both interceptors and result pages can access data stored on ValueStack using OGNL.
  1. 列舉一些在 Struts2 中引入的有用的註釋?

Some of the important annotations introduced in Struts2 are:
1.  @Action to create action class
2.  @Actions to configure single class for multiple actions
3.  @Namespace and @Namespaces for creating different modules
4.  @Result for result pages
5.  @ResultPath for configuring result pages location
  1. 提供一些您使用過的重要的 Struts2 常數?

Some of the Struts2 constants that I have used are:

1.  **struts.devMode** to run our application in development mode. This mode does reload properties files and provides extra logging and debugging feature. It's very useful while developing our application but we should turn it off while moving our code to production.
2.  **struts.convention.result.path** to configure the location of result pages. By default Struts2 look for result pages at {WEBAPP-ROOT}/{Namespace}/ and we can change the location with this constant.
3.  **struts.custom.i18n.resources** to define global resource bundle for i18n support.
4.  **struts.action.extension** to configure the URL suffix to for Struts2 application. Default suffix is .action but sometimes we might want to change it to .do or something else.

We can configure above constants in the struts.xml file like below.

```
<constant name="struts.devMode" value="true"></constant>
<constant name="struts.action.extension" value="action,do"></constant>
<constant name="struts.custom.i18n.resources" value="global"></constant>
<constant name="struts.convention.result.path" value="/"></constant>
```
  1. 在 Struts2 中,動作映射中的命名空間有什麼作用?

Struts2 namespace configuration allows us to create modules easily. We can use namespace to separate our action classes based on their functionality, for example admin, user, customer etc.
  1. 哪個攔截器負責將請求參數映射到動作類 Java Bean 屬性?

`com.opensymphony.xwork2.interceptor.ParametersInterceptor` interceptor is responsible for mapping request parameters to the Action class java bean properties. This interceptor is configured in struts-default package with name "params". This interceptor is part of basicStack and defaultStack interceptors stack.
  1. 哪個攔截器負責 i18n 支持?

`com.opensymphony.xwork2.interceptor.I18nInterceptor` interceptor is responsible for i18n support in Struts2 applications. This interceptor is configured in struts-default package with name "i18n" and it's part of i18nStack and defaultStack.
  1. 使用Action接口和ActionSupport类在我们的动作类中有什麼區别,您更偏好哪一個?

We can implement Action interface to create our action classes. This interface has a single method execute() that we need to implement. The only benefit of using this interface is that it contains some constants that we can use for result pages, these constants are SUCCESS, ERROR, NONE, INPUT and LOGIN. ActionSupport class is the default implementation of Action interface and it also implements interfaces related to Validation and i18n support. ActionSupport class implements Action, Validateable, ValidationAware, TextProvider and LocaleProvider interfaces. We can override the validate() method of ActionSupport class to include field level validation login in our action classes. Depending on the requirements, we can use any of the approaches to creating Struts 2 action classes, my favorite is ActionSupport class because it helps in writing validation and i18n logic easily in action classes.
  1. 我們如何在操作類中獲取Servlet API的Request、Response、HttpSession等對象?

Struts2 action classes don't provide direct access to Servlet API components such as Request, Response, and Session. However, sometimes we need these access in action classes such as checking HTTP method or setting cookies in response. That's why Struts2 API provides a bunch of \*Aware interfaces that we can implement to access these objects. Struts2 API uses dependency injection to inject Servlet API components in action classes. Some of the important Aware interfaces are SessionAware, ApplicationAware, ServletRequestAware, and ServletResponseAware. You can read more about them in How to get [Servlet API Session in Struts2 Action Classes](/community/tutorials/get-servlet-session-request-response-context-attributes-struts-2-action) tutorial.
  1. execAndWait攔截器的作用是什麼?

Struts2 provides execAndWait interceptor for long running action classes. We can use this interceptor to return an intermediate response page to the client and once the processing is finished, final response is returned to the client. This interceptor is defined in the struts-default package and implementation is present in `ExecuteAndWaitInterceptor` class. Check out [Struts2 execAndWait interceptor example](/community/tutorials/struts2-execandwait-interceptor-example-for-long-running-actions) to learn more about this interceptor and how to use it.
  1. 在Struts2中,令牌拦截器的用途是什麼?

One of the major problems with web applications is the double form submission. If not taken care, double form submission could result in charging double amount to customer or updating database values twice. We can use a token interceptor to solve the double form submission problem. This interceptor is defined in the struts-default package but it's not part of any interceptor stack, so we need to include it manually in our action classes. Read more at [Struts2 token interceptor](/community/tutorials/struts2-token-interceptor-example) example.
  1. 如何在Struts2应用程序中集成log4j?

Struts2 provides easy integration of log4j API for logging purpose, all we need to have is log4j configuration file in the WEB-INF/classes directory. You can check out the sample project at [Struts2 Log4j integration](/community/tutorials/struts2-and-log4j-integration-example-project).
  1. 有哪些不同的Struts2标签?我们如何使用它们?

Struts2 provides a lot of custom tags that we can use in result pages to create views for client request. These tags are broadly divided into three categories- Data tags, Control tags and UI tags. We can use these tags by adding these in JSP pages using taglib directive.

```
<%@ taglib uri="/struts-tags" prefix="s" %>
```

Some of the important Data tags are property, set, push, bean, action, include, i18n and text tag. Read more at [Struts2 Data Tags](/community/tutorials/struts-2-data-tags-example-tutorial). Control tags are used for manipulation and navigation of data from a collection. Some of the important Control tags are if-elseif-else, iterator, append, merge, sort, subset and generator tag. Read more at [Struts2 Control Tags](/community/tutorials/struts-2-control-tags-example-tutorial). Struts2 UI tags are used to generate HTML markup language, binding HTML form data to action classes properties, type conversion, validation, and i18n support. Some of the important UI tags are form, textfield, password, textarea, checkbox, select, radio and submit tag. Read more about them at [Struts2 UI Tags](/community/tutorials/struts-2-ui-tags-form-checkbox-radio-select-submit).
  1. Struts2中的自定义类型转换器是什么?

Struts2 support OGNL expression language and it performs two important tasks in Struts 2 – data transfer and type conversion. OGNL is flexible and we can easily extend it to create our own custom converter class. Creating and configuring custom type converter class is very easy. The first step is to fix the input format for the custom class. The second step is to implement the converter class. Type converter classes should implement `com.opensymphony.xwork2.conversion.TypeConverter` interface. Since in web application, we always get the request in form of String and send the response in the form of String, Struts 2 API provides a default implementation of TypeConverter interface, StrutsTypeConverter. StrutsTypeConverter contains two abstract methods – convertFromString to convert String to Object and convertToString to convert Object to String. For implementation details, read [Struts2 OGNL Example Tutorial](/community/tutorials/struts2-ognl).
  1. 我們如何編寫自己的攔截器並映射其操作?

We can implement `com.opensymphony.xwork2.interceptor.Interceptor` interface to create our own interceptor. Once the interceptor class is ready, we need to define that in struts.xml package where we want to use it. We can also create interceptor stack with our custom interceptor and defaultStack interceptors. After that we can configure it for action classes where we want to use our interceptor. One of the best example of using custom interceptor is to validate session, read more about it at [Struts2 Interceptor Tutorial](/community/tutorials/struts-2-interceptor-example).
  1. 攔截器的生命週期是什麼?

Interceptor interface defines three methods - init(), destroy() and intercept(). init and destroy are the life cycle methods of an interceptor. Interceptors are Singleton classes and Struts2 initialize a new thread to handle each request. init() method is called when interceptor instance is created and we can initialize any resources in this method. destroy() method is called when application is shutting down and we can release any resources in this method. intercept() is the method called every time client request comes through the interceptor.
  1. 什麼是攔截器堆疊?

An interceptor stack helps us to group together multiple interceptors in a package for further use. struts-default package creates some of the mostly used interceptor stack - basicStack and defaultStack. We can create our own interceptor stack at the start of the package and then configure our action classes to use it.
  1. struts-default包是什么,它有哪些好处?

struts-default is an abstract package that defines all the Struts2 interceptors and commonly used interceptor stack. It is advisable to extend this package while configuring our application package to avoid configuring interceptors again. This is provided to help developers by eliminating the trivial task of configuring interceptor and result pages in our application.
  1. Struts2操作URI的默认后缀是什么,我们如何更改它?

The default URI suffix for Struts2 action is .action, in Struts1 default suffix was .do. We can change this suffix by defining struts.action.extension constant value in our Struts2 configuration file as:

```
<constant name="struts.action.extension" value="action,do"></constant>
```
  1. 结果页面的默认位置是什么,我们如何更改它?

By default Struts2 looks for result pages in {WEBAPP-ROOT}/{Namespace}/ directory but sometimes we want to keep result pages in another location, we can provide struts.convention.result.path constant value in Struts2 configuration file to change the result pages location. Another way is to use @ResultPath annotation in action classes to provide the result pages location.
  1. 在Struts2应用程序中如何上传文件?

File Upload is one of the common tasks in a web application. That's why Struts2 provides built-in support for file upload through FileUploadInterceptor. This interceptor is configured in the struts-default package and provide options to set the maximum size of a file and file types that can be uploaded to the server. Read more about FileUpload interceptor at [Struts2 File Upload Example](/community/tutorials/struts-2-file-upload-example).
  1. 在開發Struts2應用程式時應該遵循哪些最佳實踐?

Some of the best practices while developing Struts2 application are:
1.  Always try to extend struts-default package while creating your package to avoid code redundancy in configuring interceptors.
2.  For common tasks across the application, such as logging request params, try to use interceptors.
3.  Always keep action classes java bean properties in a separate bean for code reuse and implement ModelDriven interface.
4.  If you have custom interceptor that you will use in multiple actions, create interceptor stack for that and then use it.
5.  Try to divide your application in different modules with namespace configuration based on functional areas.
6.  Try to use Struts2 tags in result pages for code clarify, if needed create your own type converters.
7.  Use development mode for faster development, however make sure production code doesn't run in dev mode.
8.  Use Struts2 i18n support for resource bundles and to support localization.
9.  Struts2 provides a lot of places where you can have resource bundles but try to keep one global resource bundle and one for action class to avoid confusion.
10.  struts-default package configures all the interceptors and creates different interceptor stacks. Try to use only what is needed, for example if you don't have localization requirement, you can avoid i18n interceptor.
  1. 如何在Struts2中處理應用程式拋出的異常?

Struts2 provides a very robust framework for exception handling. We can specify global results in packages and then map specific exceptions to these result pages. The exception mapping can be done at the global package level as well as the action level. It's a good idea to have exception result pages to provide some information to the user when some unexpected exception occurs that is not processed by the application. The sample configuration in the struts.xml file looks like below.

```
<package name="user" namespace="/" extends="struts-default">
 
<global-results>
    <result name="exception">/exception.jsp</result>
    <result name="runtime_exception">/runtime_exception.jsp</result>
    <result name="error">/error.jsp</result>
</global-results>
 
<global-exception-mappings>
    <exception-mapping exception="java.lang.Exception" result="exception"></exception-mapping>
    <exception-mapping exception="java.lang.Error" result="error"></exception-mapping>
    <exception-mapping exception="java.lang.RuntimeException" result="runtime_exception"></exception-mapping>
</global-exception-mappings>
 
    <action name="myaction" class="com.journaldev.struts2.exception.MyAction">
    </action>
    <action name="myspecialaction" class="com.journaldev.struts2.exception.MySpecialAction">
    <exception-mapping exception="java.io.IOException" result="login"></exception-mapping>
    <result name="login">/error.jsp</result>
    </action>
</package>
```

Read more at [Struts2 Exception Handling Example](/community/tutorials/struts2-exception-handling-example-tutorial).

這就是有關Struts2面試問題和答案的全部內容,如果你遇到了任何我漏掉的重要問題,請通過評論告訴我。

Source:
https://www.digitalocean.com/community/tutorials/struts2-interview-questions-and-answers