Anyframe Web에서는 Synchronized Token 이라는 진보된 방법을 통해 선언적으로 Form submit 중복으로 인한 오 동작을 방지할 수 있는 기능을 제공한다.
Form Submit 중복은 다음과 같은 다양한 경우에 발생할 수 있다.
boolean valid = isTokenValid(request, true);
if (valid) {
// TODO: submit 할 때 수행할 로직을 넣을 것
System.out.println("status: performed");
} else {
// TODO: init / reload 할 때 수행할 로직을 넣을 것
System.out.println("status: initialized or reloaded");
}
saveToken(request);
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="<%= session.getAttribute(org.apache.struts.Globals.TRANSACTION_TOKEN_KEY) %>">
public class DefaultActionMapping extends ActionMapping {
boolean validateToken = false;
boolean resetToken = false;
boolean saveToken = false;
public DefaultActionMapping() {
super();
setScope("request");
}
public boolean isResetToken() { return resetToken; }
public boolean isValidateToken() {return validateToken;}
public void setResetToken(boolean b) {resetToken = b;}
public void setValidateToken(boolean b) {validateToken = b; }
public boolean isSaveToken() {return saveToken;}
public void setSaveToken(boolean b) {saveToken = b;}
}
<action-mappings type="anyframe.web.struts.common.action.DefaultActionMapping"> <!-- 사용자 회원 정보 수정 화면 이동 --> <action input="/empListUser.do" name="userForm" path="/empGetUser" type="com.sds.emp.user.web.GetUserAction" scope="request" validate="false" roles="admin,user"> <set-property property="saveToken" value="true"/> <forward name="success" path="/sample/user/updateUser.jsp" /> </action> <!-- 회원 정보 수정 --> <action input="/sample/user/updateUser.jsp" name="userForm" path="/empUpdateUser" type="com.sds.emp.user.web.UpdateUserAction" scope="request" validate="false" roles="admin,user"> <set-property property="validateToken" value="true"/> <set-property property="resetToken" value="true"/> <forward name="success_list" path="/empListUser.do" /> <forward name="success_update" path="/empGetUser.do" /> </action> … 하략 …
<set-property property="saveToken" value="true"/>
public ActionForward postProcess(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response,
ActionForward forward) throws Exception {
boolean saveToken = false;
if (mapping instanceof DefaultActionMapping) {
DefaultActionMapping t_mapping = (DefaultActionMapping) mapping;
saveToken = t_mapping.isSaveToken();
}
if (saveToken) {
saveToken(request);
}
return forward;
}
<set-property property="validateToken" value="true"/> <set-property property="resetToken" value="true"/>
public void preProcess(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
boolean validateToken = false;
boolean resetToken = false;
if (mapping instanceof DefaultActionMapping) {
DefaultActionMapping t_mapping = (DefaultActionMapping) mapping;
validateToken = t_mapping.isValidateToken();
resetToken = t_mapping.isResetToken();
}
if (validateToken) {
if (!isTokenValid(request, resetToken)) {
throw new InvalidTokenException("common.msg.invalidtoken.error");
}
}
}
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="<%= session.getAttribute(org.apache.struts.Globals.TRANSACTION_TOKEN_KEY) %>">
<!-- 신규 회원 등록 화면 이동 --> <action path="/empAddUserView" type="anyframe.web.struts.common.action.DefaultForwardAction" parameter="addUserView"> <set-property property="saveToken" value="true"/> </action>