2012-06-01 17:37:51.0|分类: struts|浏览量: 1834
首先解释一下几个名词: request.getRequestDispatcher()是请求转发,前后页面共享一个request ; response.sendRedirect()是重新定向,前后页面不是一个request。 RequestDispatcher.forward()是在服务器端运行; HttpServletResponse.sendRedirect()是通过向客户浏览器发送命令来完成. 所以RequestDispatcher.forward()对于浏览器来说是“透明的”; 而HttpServletResponse.sendRedirect()则不是。 这么光说,一定很难理解,看一个例子。 情景:qq登录上,你直接点击邮箱他就会直接登录邮箱。 假如请求路径:http://localhost:8080/test/web/skiplogin.action?url=/mail/productManage.action&sessionid=1000111&&phoneId=100000 action中会把url,sessionid,phoneId解析出来,然后跳转到url,假如你是用的是 RequestDispatcher dispatcher = request.getRequestDispatcher(url_pa); // dispatcher.forward(request, response); // 使用这个方法转发,地址不变,这是在服务器端完成的 浏览器上的地址栏里的路径是不会变的。 假如使用response.sendRedirect(basePath+finalLocation); 浏览器上的路径就会变成:http://localhost:8080/test/mail/productManage.action。 struts2 result返回类型type="redirect"时,查看它的源代码其实就是做了一次重新跳转。 * $Id: ServletRedirectResult.java 1188965 2011-10-25 23:19:48Z mcucchiara $ package org.apache.struts2.dispatcher; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.config.entities.ResultConfig; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.util.logging.Logger; import com.opensymphony.xwork2.util.logging.LoggerFactory; import com.opensymphony.xwork2.util.reflection.ReflectionException; import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler; import org.apache.struts2.ServletActionContext; import org.apache.struts2.dispatcher.mapper.ActionMapper; import org.apache.struts2.dispatcher.mapper.ActionMapping; import org.apache.struts2.views.util.UrlHelper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*; import static javax.servlet.http.HttpServletResponse.SC_FOUND; /** * <!-- START SNIPPET: description --> * * Calls the {@link HttpServletResponse#sendRedirect(String) sendRedirect} * method to the location specified. The response is told to redirect the * browser to the specified location (a new request from the client). The * consequence of doing this means that the action (action instance, action * errors, field errors, etc) that was just executed is lost and no longer * available. This is because actions are built on a single-thread model. The * only way to pass data is through the session or with web parameters * (url?name=value) which can be OGNL expressions. * * <!-- END SNIPPET: description --> * <p/> * <b>This result type takes the following parameters:</b> * * <!-- START SNIPPET: params --> * * <ul> * * <li><b>location (default)</b> - the location to go to after execution.</li> * * <li><b>parse</b> - true by default. If set to false, the location param will * not be parsed for Ognl expressions.</li> * * <li><b>anchor</b> - Optional. Also known as "fragment" or colloquially as * "hash". You can specify an anchor for a result.</li> * </ul> * * <p> * This result follows the same rules from {@link StrutsResultSupport}. * </p> * * <!-- END SNIPPET: params --> * * <b>Example:</b> * * <pre> * <!-- START SNIPPET: example --> * <!-- * The redirect URL generated will be: * /foo.jsp#FRAGMENT * --> * <result name="success" type="redirect"> * <param name="location">foo.jsp</param> * <param name="parse">false</param> * <param name="anchor">FRAGMENT</param> * </result> * <!-- END SNIPPET: example --> * </pre> * */ public class ServletRedirectResult extends StrutsResultSupport implements ReflectionExceptionHandler { private static final long serialVersionUID = 6316947346435301270L; private static final Logger LOG = LoggerFactory.getLogger(ServletRedirectResult.class); protected boolean prependServletContext = true; protected ActionMapper actionMapper; protected int statusCode = SC_FOUND; protected boolean suppressEmptyParameters = false; protected Map<String, String> requestParameters = new LinkedHashMap<String, String>(); protected String anchor; public ServletRedirectResult() { super(); } public ServletRedirectResult(String location) { this(location, null); } public ServletRedirectResult(String location, String anchor) { super(location); this.anchor = anchor; } @Inject public void setActionMapper(ActionMapper mapper) { this.actionMapper = mapper; } public void setStatusCode(int code) { this.statusCode = code; } /** * Set the optional anchor value. * * @param anchor */ public void setAnchor(String anchor) { this.anchor = anchor; } /** * Sets whether or not to prepend the servlet context path to the redirected * URL. * * @param prependServletContext * <tt>true</tt> to prepend the location with the servlet context * path, <tt>false</tt> otherwise. */ public void setPrependServletContext(boolean prependServletContext) { this.prependServletContext = prependServletContext; } public void execute(ActionInvocation invocation) throws Exception { if (anchor != null) { anchor = conditionalParse(anchor, invocation); } super.execute(invocation); } /** * Redirects to the location specified by calling * {@link HttpServletResponse#sendRedirect(String)}. * * @param finalLocation * the location to redirect to. * @param invocation * an encapsulation of the action execution state. * @throws Exception * if an error occurs when redirecting. */ protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { ActionContext ctx = invocation.getInvocationContext(); HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST); HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE); if (isPathUrl(finalLocation)) { if (!finalLocation.startsWith("/")) { ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager()); String namespace = null; if (mapping != null) { namespace = mapping.getNamespace(); } if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) { finalLocation = namespace + "/" + finalLocation; } else { finalLocation = "/" + finalLocation; } } // if the URL's are relative to the servlet context, append the servlet context path if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) { finalLocation = request.getContextPath() + finalLocation; } ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode()); if (resultConfig != null) { Map<String, String> resultConfigParams = resultConfig.getParams(); for (Map.Entry<String, String> e : resultConfigParams.entrySet()) { if (!getProhibitedResultParams().contains(e.getKey())) { String potentialValue = e.getValue() == null ? "" : conditionalParse(e.getValue(), invocation); if (!suppressEmptyParameters || ((potentialValue != null) && (potentialValue.length() > 0))) { requestParameters.put(e.getKey(), potentialValue); } } } } StringBuilder tmpLocation = new StringBuilder(finalLocation); UrlHelper.buildParametersString(requestParameters, tmpLocation, "&"); // add the anchor if (anchor != null) { tmpLocation.append('#').append(anchor); } finalLocation = response.encodeRedirectURL(tmpLocation.toString()); } if (LOG.isDebugEnabled()) { LOG.debug("Redirecting to finalLocation " + finalLocation); } sendRedirect(response, finalLocation);//////看这个方法 } protected List<String> getProhibitedResultParams() { return Arrays.asList(DEFAULT_PARAM, "namespace", "method", "encode", "parse", "location", "prependServletContext", "suppressEmptyParameters", "anchor"); } /** * Sends the redirection. Can be overridden to customize how the redirect is * handled (i.e. to use a different status code) * * @param response * The response * @param finalLocation * The location URI * @throws IOException */ protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException { if (SC_FOUND == statusCode) { response.sendRedirect(finalLocation);//就是做了一个这样的事情 } else { response.setStatus(statusCode); response.setHeader("Location", finalLocation); response.getWriter().write(finalLocation); response.getWriter().close(); } } private static boolean isPathUrl(String url) { // filter out "http:", "https:", "mailto:", "file:", "ftp:" // since the only valid places for : in URL's is before the path specification // either before the port, or after the protocol return (url.indexOf(':') == -1); } /** * Sets the suppressEmptyParameters option * * @param suppressEmptyParameters * The new value for this option */ public void setSuppressEmptyParameters(boolean suppressEmptyParameters) { this.suppressEmptyParameters = suppressEmptyParameters; } /** * Adds a request parameter to be added to the redirect url * * @param key * The parameter name * @param value * The parameter value */ public ServletRedirectResult addParameter(String key, Object value) { requestParameters.put(key, String.valueOf(value)); return this; } public void handle(ReflectionException ex) { // Only log as debug as they are probably parameters to be appended to the url LOG.debug(ex.getMessage(), ex); } }
我action中写的代码: import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @SuppressWarnings("serial") public class SkipLoginAction extends Action { @Inject private PhoneService phoneService; /** * @return * @throws ActionException */ public void index() throws ActionException { try { HttpServletRequest request =getRequest(); HttpServletResponse response = getResponse(); AuthBean authBean = null; // RequestDispatcher dispatcher = request.getRequestDispatcher(url_pa); // dispatcher.forward(request, response); // 使用这个方法转发,地址不变,这是在服务器端完成的 //客户端传来的参数 String sessionid = request.getParameter("sessionid"); String finalLocation = request.getParameter("url"); String phoneId = request.getParameter("phoneId"); String contextpath = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + contextpath; if(!StringUtils.isBlank(finalLocation) && !StringUtils.isBlank(sessionid) ){ if(!finalLocation.startsWith("/")){ finalLocation = "/" + finalLocation; } HttpSession session = request.getSession(); authBean = getAuthBean(); if(authBean!=null){ if(phoneId.equals(authBean.getPhoneId())){ response.sendRedirect(basePath+finalLocation); return; } } ////获得数据库中的user中的sessionid字段 Phone phone = phoneService.findPhoneByPhoneId(phoneId); if(phone!=null){ if( sessionid.equals(phone.getSessionid())){ // 用户登陆成功 authBean = null; authBean = new AuthBean(); 。。。。 response.sendRedirect(basePath+finalLocation); return; } } } //最后不符合条件统一跳到登陆界面 finalLocation = "/web/login.index"; response.sendRedirect(basePath+finalLocation); } catch (Exception e) { throw new ActionException("失败"); } } }
|