Struts2는 자바로 웹 애플리케이션을 개발하기 위한 유명한 프레임워크 중 하나입니다. 최근에 많은 Struts2 튜토리얼을 작성했으며, 이 포스트에서는 면접을 돕기 위해 중요한 Struts2 면접 질문과 답변을 나열하고 있습니다.
Struts2 면접 질문
- Struts2란?
- Struts1과 Struts2의 차이점이나 Struts2가 Struts1보다 어떻게 우수한가요?
- Struts2의 핵심 구성 요소는 무엇인가요?
- Struts2의 인터셉터란 무엇인가요?
- Struts2 인터셉터가 구현한 디자인 패턴은 무엇인가요?
- Struts2에서 Action 클래스를 생성하는 다양한 방법은 무엇인가요?
- Struts2 액션과 인터셉터는 스레드로부터 안전한가요?
- Struts2의 프론트 컨트롤러는 어떤 클래스인가요?
- Struts2의 인터셉터의 이점은 무엇인가요?
- ValueStack과 OGNL은 무엇인가요?
- Struts2에 소개된 몇 가지 유용한 주석을 나열해보세요?
- 사용한 중요한 Struts2 상수를 몇 가지 제공하십시오?
- Struts2에서 액션 매핑에서 네임스페이스의 용도는 무엇인가요?
- 요청 매개변수를 액션 클래스 자바 빈 속성으로 매핑하는 데 책임이 있는 인터셉터는 무엇인가요?
- i18n 지원을 담당하는 인터셉터는 무엇인가요?
- 액션 클래스에 Action 인터페이스와 ActionSupport 클래스를 사용하는 것의 차이는 무엇이며, 어느 것을 선호하시나요?
- 액션 클래스에서 Servlet API Request, Response, HttpSession 등 객체를 어떻게 얻을 수 있나요?
- execAndWait 인터셉터의 용도는 무엇인가요?
- Struts2에서 토큰 인터셉터의 용도는 무엇인가요?
- Struts2 애플리케이션에 log4j를 통합하는 방법은 무엇인가요?
- 다양한 Struts2 태그는 무엇이며, 어떻게 사용할 수 있나요?
- Struts2에서 사용자 지정 유형 변환기란 무엇인가요?
- 자체 인터셉터를 작성하고 액션에 매핑하는 방법은 무엇인가요?
- 인터셉터의 라이프 사이클은 무엇인가요?
- 인터셉터 스택이란 무엇인가요?
- struts-default 패키지는 무엇이며 그 혜택은 무엇입니까?
- Struts2 액션 URI의 기본 접미사는 무엇이며 어떻게 변경할 수 있습니까?
- 결과 페이지의 기본 위치는 어디이며 어떻게 변경할 수 있습니까?
- Struts2 애플리케이션에서 파일을 업로드하는 방법은 무엇입니까?
- Struts2 애플리케이션을 개발할 때 따라야 할 모범 사례는 무엇입니까?
- Struts2에서 애플리케이션에서 throw된 예외를 어떻게 처리할 수 있습니까?
Struts2 인터뷰 질문과 답변
-
Struts2란 무엇입니까?
Apache Struts2는 자바로 웹 애플리케이션을 구축하기 위한 오픈 소스 프레임워크입니다. Struts2는 OpenSymphony WebWork 프레임워크를 기반으로 합니다. Struts1에서 크게 개선되어 더 유연하고 사용하기 쉽고 확장 가능합니다. Struts2의 핵심 구성 요소는 Action, Interceptors 및 Result 페이지입니다. Struts2는 Action 클래스를 생성하고 struts.xml 또는 주석을 통해 구성하는 여러 가지 방법을 제공합니다. 공통 작업을 위해 자체 Interceptors를 만들 수 있습니다. Struts2에는 많은 태그가 포함되어 있으며 OGNL 표현 언어를 사용합니다. 자체 유형 변환기를 생성하여 결과 페이지를 렌더링할 수 있습니다. 결과 페이지는 JSP와 FreeMarker 템플릿일 수 있습니다.
-
Struts1과 Struts2의 차이점은 무엇이며 Struts2가 Struts1보다 더 나은 점은 무엇입니까?
Struts2는 Struts1의 단점을 극복하고 더 유연하고 확장 가능하게 설계되었습니다. 주목할만한 몇 가지 차이점은 다음과 같습니다:
구성 요소 Struts1 Struts2 액션 클래스 Struts1 액션 클래스는 Abstract Class를 확장해야 하므로 확장할 수 없습니다. Struts2 액션 클래스는 유연하며 Action 인터페이스를 구현하거나 ActionSupport 클래스를 확장하거나 execute() 메서드만 가지고 있으면 만들 수 있습니다. 스레드 안정성 Struts1 액션 클래스는 싱글톤이며 스레드로부터 안전하지 않으므로 개발자는 다중 스레딩으로 인한 부작용을 피하기 위해 추가적인 주의가 필요합니다. Struts2 액션 클래스는 요청당 인스턴스화되므로 다중 스레딩이 없으며 스레드로부터 안전합니다. Servlet API 결합 Struts1 API는 Servlet API와 강하게 결합되어 있으며 Request 및 Response 객체가 액션 클래스의 execute() 메서드로 전달됩니다. Struts2 API는 Servlet API와 느슨하게 결합되어 있으며 폼 빈 데이터를 자동으로 액션 클래스 자바 빈 속성으로 매핑합니다. 그러나 Servlet API 클래스에 대한 참조가 필요한 경우 *Aware 인터페이스가 있습니다. 테스트 Struts1 액션 클래스는 Servlet API 결합 때문에 테스트하기 어렵습니다. Struts2 액션 클래스는 일반적인 자바 클래스처럼 동작하며 속성을 설정하여 쉽게 테스트할 수 있습니다. 요청 매개변수 매핑 Struts1은 요청 매개변수를 보유하기 위해 ActionForm 클래스를 생성하고 struts 구성 파일에 구성해야 합니다. Struts2 요청 매개변수 매핑은 실시간으로 수행되며 액션 클래스에 자바 빈 속성이나 ModelDriven 인터페이스를 구현하여 매핑에 사용할 자바 빈 클래스 이름을 제공하기만 하면 됩니다. 태그 지원 Struts1은 JSTL 태그를 사용하므로 제한됩니다. Struts2는 OGNL을 사용하며 다양한 종류의 UI, 제어 및 데이터 태그를 제공합니다. 더 다양하고 사용하기 쉽습니다. 유효성 검사 Struts1은 수동으로 validate() 메서드를 통해 유효성을 지원합니다. Struts2는 수동으로 유효성을 검사하거나 유효성 검사 프레임워크 통합을 지원합니다. 뷰 렌더링 Struts1은 뷰를 위해 표준 JSP 기술을 사용합니다. Struts2는 ValueStack를 사용하여 요청 매개변수 및 속성을 저장하며 OGNL과 Struts2 태그를 사용하여 이에 액세스할 수 있습니다. 모듈 지원 Struts1 모듈은 설계하기 복잡하며 별도의 프로젝트처럼 보입니다. Struts2는 패키지에 대한 “네임스페이스” 구성을 제공하여 쉽게 모듈을 생성할 수 있습니다. -
Struts2의 핵심 구성 요소는 무엇입니까?
Struts2의 핵심 구성 요소는 다음과 같습니다:
- Action 클래스
- 인터셉터
- 결과 페이지, JSP 및 FreeMarker 템플릿
- ValueStack, OGNL 및 태그 라이브러리

-
Struts2에서 interceptor란 무엇입니까?
인터셉터는 Struts2 프레임워크의 중추입니다. Struts2 인터셉터는 프레임워크에서 수행되는 대부분의 처리를 담당하며, 요청 매개변수를 액션 클래스로 전달하고, 서블릿 API 요청, 응답, 세션을 액션 클래스에서 사용할 수 있도록 만들며, 유효성 검사, i18n 지원 등을 수행합니다. ActionInvocation은 액션 클래스와 인터셉터를 캡슐화하고 순서대로 실행하는 역할을 합니다. ActionInvocation에서 가장 중요한 메서드는 다음 인터셉터 또는 액션을 호출하는 invoke() 메서드입니다. 이는 자바 EE 프레임워크에서 책임 연쇄 패턴의 가장 좋은 예 중 하나입니다.
-
Struts2 인터셉터에서 구현된 디자인 패턴은 무엇인가요?
Struts2 interceptors are based on intercepting filters design pattern. The invocation of interceptors in interceptor stack closely resembles Chain of Responsibility design pattern.
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.
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.
`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.
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.
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.
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
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>
```
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.
`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.
`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.
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.
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.
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.
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.
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).
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).
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).
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).
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.
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.
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.
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>
```
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.
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).
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.
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