浅谈struts2的缺点

6 篇文章 0 订阅
6 篇文章 0 订阅

 Struts2的缺点是在ajax结合开发时,无论后台是否报错(非ServletException),页面中异步请求$.ajax都执行的是success对应的函数,即在$.ajax中定义的error:function(){ ... }失效了。这个缺点是由struts的错误处理机制导致的,下面进行详细的说明。

先贴出Struts2中DefaultActionInvation的serviceAction方法,也是Struts2运行机制的核心方法

 public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
                              ActionMapping mapping) throws ServletException {

        Map<String, Object> extraContext = createContextMap(request, response, mapping, context);

        // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
        boolean nullStack = stack == null;
        if (nullStack) {
            ActionContext ctx = ActionContext.getContext();
            if (ctx != null) {
                stack = ctx.getValueStack();
            }
        }
        if (stack != null) {
            extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
        }

        String timerKey = "Handling request from Dispatcher";
try {
            UtilTimerStack.push(timerKey);
            String namespace = mapping.getNamespace();
            String name = mapping.getName();
            String method = mapping.getMethod();


            Configuration config = configurationManager.getConfiguration();
            ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                    namespace, name, method, extraContext, true, false);


            request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

            // if the ActionMapping says to go straight to a result, do it!
            if (mapping.getResult() != null) {
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            } else {
                proxy.execute();
            }

            // If there was a previous value stack then set it back onto the request
            if (!nullStack) {
                request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
            }
    } catch (ConfigurationException e) {
         // WW-2874 Only log error if in devMode
         if(devMode) {
                String reqStr = request.getRequestURI();
                if (request.getQueryString() != null) {
                    reqStr = reqStr + "?" + request.getQueryString();
                }
                LOG.error("Could not find action or result\n" + reqStr, e);
            }
         else {
                    if (LOG.isWarnEnabled()) {
          LOG.warn("Could not find action or result", e);
                    }
         }
            sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);//产生错误的模板页面,并返回到客户端
} catch (Exception e) {
            sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);//产生错误的模板页面,并返回到客户端
        } finally {
            UtilTimerStack.pop(timerKey);
        }
    }
由以上源代码可知,由DefaultActionInvocation做的事情依次如下:

 1、创建ActionContext

 2、创建值栈

 3、创建ActionProxy

 4、执行ActionProxy中的拦截器的拦截方法

 5、执行Action的方法

 6、执行结果集(响应页面或跳转到另一个action)

上述4、 5、 6步中如果抛出配置信息错误(ConfigurationException)和非ServletException异常,则会在方法内部以try、

catch的方式自行处理,即以框架自定义的错误模板(response.getWriter.print)的方式响应页面。

 虽然Servlet也是通过response响应错误页面,struts并没有沿用Servlet在相应错误页面时设置响应状态码(成功200,错误则404

、405等),贴出Servlet的service方法源码一部分如下:

  if(method.equals("GET"))
        {
            long lastModified = getLastModified(req);
            if(lastModified == -1L)
            {
                doGet(req, resp);
            } else
            {
                long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                if(ifModifiedSince < lastModified)
                {
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else
                {
                    resp.setStatus(304);
                }
            }
        } else
        if(method.equals("HEAD"))
        {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
        } else
        if(method.equals("POST"))
            doPost(req, resp);


protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if(protocol.endsWith("1.1"))
            resp.sendError(405, msg);
        else
            resp.sendError(400, msg);
    }

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if(protocol.endsWith("1.1"))
            resp.sendError(405, msg);
        else
            resp.sendError(400, msg);
    }

也就是说Servlet在响应页面时,还设置了响应状态码,以供前台ajax判断服务器响应是否异常,从而调用$.ajax({})中

success和error(根据服务器的响应码)指定的函数。这样能够给开发者发送有利的信号。而Struts2由于没设置响应码

这一步,因此即使后台有(非ServletException)异常,$.ajax也会调用success对应的回调函数,data就是错误模板页面。。

如此,相较于Servlet而言,在与ajax结合开发时,若后台代码出现异常,Struts2并不会在服务器控制台报错,前台js也不能

根据服务器响应码执行对应的回调函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值