스트럿츠 2에 도입된 중요한 요소 중에 하나로 Action 객체가 실행하기 전/후에 호출된다.
⋅ 모든 액션 요청(Action Request)에 대해 공통적으로 적용되어야 하는 공통 기능들을 제공하는 모듈
⋅ 인터셉터의 시작은 ActionInvocation 이 담당한다
⋅ 액션 프록시가 ActionInvocation 의 invoke() 메소드를 호출 할 때 인터셉터의 실행이 시작된다.
⋅ 인터셉터의 작업이 끝나면, 또 다시 ActionInvocation 의 invoke() 메소드를 다시 호출
-> invoke() 에서드는 실행할 추가 인터셉터가 존재하는지 조사
-> 실행할 인터셉터가 존재한다면, 그 인터셉터의 interceptor() 메소드를 호출하는 식으로 인터셉터 체인을 형성 -> 만약 더 실행 할 인터셉터가 존재하지 않는다면, 액션을 호출한 후 result를 실행
⋅ 스트럿츠2가 자체적으로 기본적인 인터셉터들은 제공하고 있으며, 디폴트 XML(struts-default.xml) 파일에 정의되어 있다.
- 사용자 정의의 interceptor을 넣어버리게 되면 기본적으로 사용하고 있던 interceptor 가 작동이 안됨
- 하나라도 사용자정의 인터셉터를 넣어버리면 인터셉터간의 연결고리가 끊어지기 때문
- 그래서 '그 다음 interceptor를 실행시켜' 하고 명시해줘야함
- interceptor가 여러개면 순차적으로 실행되고 Action을 실행
- 모든 Action에 적용할 수도 있고 부분적으로도 가능
- 내 프로젝트에 필요한 인터셉터를 묶음으로 만들 수 있음 (하나의 묶음안에는 보통 3~5개의 인터셉터들이 들어있을것임)
- 해당 action에서 내가 필요한 묶음만 부르면 됨 (interceptor의 묶음을 stack이라고 부름)
- 내부적으로 만들어놓은 params 같은 인터셉터는 그 명을 바꾸면 안된다.
[대표적인 Struts2에서 제공하는 interceptor들]
⋅ modelDriven : 액션이 ModelDriven 인터페이스를 구현하였다면 getModel() 결과를 ValueStack에 넣어 준다
⋅ params : 요청 파라미터들을 액션에 저장한다.
⋅ prepare : 액션이 Preparable 인터페이스를 구현하였다면 prepare() 메소드를 호출한다.
write.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="<%=cp %>/inter/save.action" method="post">
이름: <input type="text" name="userName"/><br/>
패스워드: <input type ="text" name="userPwd"/><br/>
<input type="submit" value="전송"/>
</form>
</body>
</html>
view.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setCharacterEncoding("UTF-8");
String cp = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
이름: ${userName}<br/>
패스워드: ${userPwd }<br/>
</body>
</html>
struts-inter.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="inter" extends="default" namespace="/inter">
<!-- Spring에서는 이런식으로 객체 생성 많이함. new로 안하고 -->
<!-- 인터셉터 객체 생성 -->
<interceptors>
<interceptor name="myTimer" class="com.inter.TimerIntercepter"></interceptor>
</interceptors>
<action name="write">
<result>/interTest/write.jsp</result>
</action>
<!-- method의 이름은 건네줄 필요가 없음 execute니깐 알아서 실행되니깐 -->
<!-- 명시: params 인터셉터 실행시켜 -->
<action name="save" class="com.inter.TestAction">
<interceptor-ref name="myTimer"/>
<interceptor-ref name="params"/>
<result name="success">/interTest/view.jsp</result>
</action>
</package>
</struts>
TestAction.java
package com.inter;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction extends ActionSupport{
// dto를 바로 넘기듯이
// 이렇게 낱개로 .jsp로 넘긴다고 생각하면 됨
// => 이걸 struts2가 넘겨주고 있는 것임 (struts2의 core에 코딩이 되어있음)
private static final long serialVersionUID = 1L;
private String userName;
private String userPwd;
// 이 변수들도 Struts2의 내부적으론 자동이 아니라 params라는 바구니에 사실 담겨간거임
// params: 내부적으로 사용하는 변수
// 자동으로 넘기는 작업도 => interceptor임.
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
// 당연히 여기다가 이렇게 dto 만들 수 있음.
// 길어지니깐 항상 dto를 분리시킨거
// 원래는 1단계. Domain Object 방식 이용해서
// ( {user.userId} 이렇게 써야함)
// ModelDriven한테 dto를 맡기면 {userId} 이렇게 쓸 수 있는 거고
// 결론) dto를 지금 Action에다가 넣어놨으므로
// 객체 생성하는 prepare()도 필요 없고 ModelDriven도 필요 없음
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
TimerIntercepter.java
package com.inter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class TimerIntercepter extends AbstractInterceptor{
private static final long serialVersionUID = 1L;
private static Log log =
LogFactory.getLog(TimerIntercepter.class);
//이 class를 실행하다가 만들어지는 로그를 이 log 변수에 담아라
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// 인터셉터 실행 전 (Action 실행 전에 실행되는 인터셉터)
long start = System.currentTimeMillis();
String result = invocation.invoke(); // Action 실행해주는 애
// 반환값이 success이냐 input이냐
// 인터셉터 실행 후 (Action 갔다가 돌아오는 길에 실행되는 인터셉터)
long end = System.currentTimeMillis();
// Action 실행 전에 하는것임
// client가 요청 -> 인터셉터(여러개올 수 있음) -> Action
// Action의 결과는 success, input
log.info("실행시간: " + (end-start) + "ms");
// 로그방식으로 찍어보기
// System.out.println();
return null;
}
}
Interceptor - Stack으로 묶어서 저장하기
struts.xml - 공통적인 환경세팅 (interceptor도 여기다가 넣음)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<!-- 공통적인 환경세팅을 여기다가 해주면 됨 -->
<struts>
<package name="default" extends="struts-default" namespace="">
<result-types>
<result-type name="tiles"
class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<interceptors>
<interceptor-stack name="myBasicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="params"/>
</interceptor-stack>
<interceptor-stack name="myPrepareParamStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="params"/>
</interceptor-stack>
<interceptor-stack name="myFileUploadPrepareParamStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="params"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myBasicStack"/>
<global-results>
<result name="error">/exception/error.jsp</result>
</global-results>
</package>
<!-- package의 name은 아무의미없음. 중복되지만 않게 주면 됨 -->
<!-- struts-default : core의 xml파일을 읽어낸 것임 -->
<!-- 주소창에 /로 오는 모든것 -->
<include file="struts-temp.xml"/>
<include file="struts-board.xml"/>
</struts>
'Struts2 + iBatis' 카테고리의 다른 글
[iBatis/MyBatis에러] Caused by: org.xml.sax.SAXParseException: Element type "if" must be declared. (0) | 2020.11.08 |
---|---|
MyBatis 에서 #{} 과 ${}의 차이 (0) | 2020.11.03 |