我开始写一个登录页面,我的初步测试显示,当我第一次输入login.jsp时,验证方法被调用两次,但是当我提交登录表单时却没有。我想了解为什么lca
被调用两次以及如何阻止它。
首先,这是我的struts.xml:
validate()
这是我的<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<constant name="struts.devMode" value="true"/>
<constant name="struts.i18n.reload" value="true" />
<constant name="struts.ui.theme" value="simple"/>
<constant name="struts.custom.i18n.resources"
value="resources.i18n.portalLogin, resources.i18n.errors"/>
<constant name="struts.action.extension" value="action"/>
<constant name="struts.ognl.allowStaticMethodAccess" value="true" />
<!-- Configuration for the default package. -->
<package name="default" extends="json-default">
<interceptors>
<interceptor name="security"
class="login.interceptor.SecurityInterceptor"/>
<interceptor-stack name="appDefaultStack">
<interceptor-ref name="jsonValidationWorkflowStack"/>
<interceptor-ref name="defaultStack">
<param name="exception.logEnabled">true</param>
<param name="exception.logLevel">ERROR</param>
<!--
Exclude the jQuery no-cache parameter and the jQuery Displaytag
parameters from processing by the ParametersInterceptor
-->
<param name="params.excludeParams">_,d-\d+-[sop]</param>
</interceptor-ref>
<interceptor-ref name="security"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="appDefaultStack" />
<global-results>
<result name="error">/jsp/error/systemError.jsp</result>
<result name="security">/jsp/error/accessDenied.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception"/>
</global-exception-mappings>
<action name="Login" class="login.action.Login">
<result name="input">/jsp/login.jsp</result>
<result name="success" type="redirect">
<param name="ActionName">LoginRedirect</param>
</result>
</action>
</package>
</struts>
:
index.jsp
这是我的<!DOCTYPE HTML>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() +
":" + request.getServerPort() + path;
// prevent caching these pages at clients.
response.setHeader("Cache-Control", "no-cache"); // HTTP 1.1
response.setHeader("Pragma", "no-cache"); // HTTP 1.0
response.setDateHeader("Expires", 0); // prevents caching at proxy
%>
<html>
<head>
<base href="<%=basePath%>">
<title>Login</title>
</head>
<script>
location.href = '<%= basePath %>/Login.action';
</script>
<body>
Please go to the <a href="<%= basePath %>/Login.action">Login</a> page.<br>
</body>
</html>
:
login.jsp
这是我的Login.java动作:
<%@ taglib prefix='s' uri='/struts-tags' %>
<%@ taglib prefix='tiles' uri='/tiles' %>
<tiles:insertDefinition name='fullLayout'>
<tiles:putAttribute name='title' cascade='true'>
<s:text name='layout.title'/>
</tiles:putAttribute>
<tiles:putAttribute name='content' cascade='true'>
<s:text name='instructions.text'/>
<s:form name='Login' action='Login' method='POST' validate='true' focusElement="userId"
autocomplete='off'>
<div class='userIdInput'>
<label class='formLabel required' for='userId'>
<s:text name='text.userID' />
</label>
<s:textfield cssClass='inputText' name='userId' id='userId' value="%{userId}" />
</div>
<div class='passwordInput'>
<label class='formLabel required' for='password'>
<s:text name='text.password' />
</label>
<s:textfield cssClass='inputText' name='password' id='password' type='password' />
</div>
<input id='Login' type='submit' title='<s:text name="login.submit" />'
value='<s:text name="login.submit" />'>
</s:form>
</tiles:putAttribute>
</tiles:insertDefinition>
这是我的package login.action;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;
import logging.Logger;
import common.util.StringUtils;
/**
* The main Action class for this application
*/
public class Login extends ActionSupport implements ServletRequestAware {
private static final long serialVersionUID = 1L;
private HttpServletRequest httpRequest;
private String userId;
private String password;
/* (non-Javadoc)
* @see com.opensymphony.xwork2.Action#execute()
*/
@Override
public String execute() {
Logger.debug(this, "execute(" + hashCode() + "): Begin");
boolean debug = Logger.canLogDebug(this);
HttpSession session = httpRequest.getSession();
if ((userId == null || userId.isEmpty()) &&
(password == null || password.isEmpty())) {
if (debug) {
Logger.debug(this, " No userID and no Password.");
Logger.debug(this, "execute End");
}
return INPUT;
}
if (debug) {
Logger.debug(this, "userId = " + userId);
Logger.debug(this,
" password is " +
((password == null || password.isEmpty()) ? "not " : "") +
"set");
}
Logger.debug(this, "execute End");
return SUCCESS;
}
/**
* @return String
*/
public String getUserId() {
return userId;
}
/**
* @param String userId
*/
public void setUserId(String userId) {
Logger.debug(this, "in setUserId(" + userId + ")");
this.userId = userId;
}
/**
* @param String password
*/
public void setPassword(String password) {
Logger.debug(this, "in setPassword(" + password + ")");
this.password = password;
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.ActionSupport#validate()
*/
@Override
public void validate() {
Logger.debug(this, "validate(" + hashCode() + "): Begin");
if ((userId == null || userId.isEmpty()) &&
(password == null || password.isEmpty())) {
if (Logger.canLogDebug(this)) {
Logger.debug(this, " No userID and no Password.");
Logger.debug(this, "validateLogin: End");
}
return;
}
if ((userId == null || userId.isEmpty())) {
Logger.debug(this, " No userID.");
addActionError(getText("missing.required",
new String[] {getText("text.userID")}));
}
if ((password == null || password.isEmpty())) {
Logger.debug(this, " No Password.");
addActionError(getText("missing.required",
new String[] {getText("text.password")}));
}
Logger.debug(this, "validate: End");
}
/* (non-Javadoc)
* @see ServletRequestAware#setServletRequest(HttpServletRequest)
*/
@Override
public void setServletRequest(HttpServletRequest httpRequest) {
this.httpRequest = httpRequest;
}
}
:
SecurityInterceptor.java
最后,这是我记录的信息:
初始JSP条目
package login.interceptor;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import logging.Logger;
public class SecurityInterceptor extends AbstractInterceptor
implements ServletRequestAware {
private static final long serialVersionUID = 1L;
HttpServletRequest servletRequest = null;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
boolean debug = Logger.canLogDebug(this);
if (debug) {
Logger.debug(this, "intercept: Begin");
Logger.debug(this, "invocation = " +
invocation.getAction().getClass().getName());
}
//TODO: Siteminder integration
Logger.debug(this, "intercept: End");
return invocation.invoke();
}
/* (non-Javadoc)
* @see ServletRequestAware#setServletRequest(HttpServletRequest)
*/
@Override
public void setServletRequest(HttpServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
}
表格提交后
2016/01/21 15:17:50.470| DEBUG| login.action.Login| validate(12565027): Begin
2016/01/21 15:17:50.473| DEBUG| login.action.Login| No userID and no Password.
2016/01/21 15:17:50.475| DEBUG| login.action.Login| validateLogin: End
2016/01/21 15:17:50.480| DEBUG| login.action.Login| validate(12565027): Begin
2016/01/21 15:17:50.480| DEBUG| login.action.Login| No userID and no Password.
2016/01/21 15:17:50.480| DEBUG| login.action.Login| validateLogin: End
2016/01/21 15:17:50.480| DEBUG| login.interceptor.SecurityInterceptor| intercept: Begin
2016/01/21 15:17:50.480| DEBUG| login.interceptor.SecurityInterceptor| invocation = login.action.Login
2016/01/21 15:17:50.480| DEBUG| login.interceptor.SecurityInterceptor| intercept: End
2016/01/21 15:17:50.480| DEBUG| login.action.Login| execute(12565027): Begin
2016/01/21 15:17:50.480| DEBUG| login.action.Login| No userID and no Password.
2016/01/21 15:17:50.480| DEBUG| login.action.Login| execute End
答案 0 :(得分:2)
因为您在默认使用的拦截器堆栈中引用了两次。两个堆栈都包含validation
拦截器,它调用validate
。
<interceptor-ref name="jsonValidationWorkflowStack"/>
<interceptor-ref name="defaultStack">
只需删除第二个,第一个堆栈包括basicStack
,这是您的应用程序应该使用的最小值。您可以在自定义堆栈或操作中添加其他拦截器。