Сопоставление обработчика исключений Struts 2 с действием - PullRequest
12 голосов
/ 21 апреля 2011

В Struts 2 настроено перенаправление любого исключения java.lang.Exception в специальное действие, которое регистрирует исключение. Мое перенаправление работает, но мое действие всегда получает нулевое исключение (даже когда я явно выбрасываю исключение). Вот мой файл struts.xml:

<global-results>
    <result name="errHandler" type="chain">
    <param name="actionName">errorProcessor</param>
    </result>
</global-results>

<global-exception-mappings>
     <exception-mapping exception="java.lang.Exception" result="errHandler" />
</global-exception-mappings>

<action name="errorProcessor" class="myErrorProcessor">
      <result name="error">/error.jsp</result>
</action>

<action name="throwExceptions" class="throwExceptions">
      <result name="success">done.jsp</result>
</action>

В моем обработчике ошибок у меня есть следующее:

public class myErrorProcessor extends ActionSupport {

   private Exception exception;

   public String execute() {
         System.out.println("null check: " + (exception == null));
         return "error";
   }

   public void setException(Exception exception) {
         this.exception = exception;
   }

   public Exception getException() {
         return exception;
   }
}

В классе throwsException у меня есть следующее:

public String execute() {
     int x = 7 / 0;
     return "success";
}

Когда я запускаю свою программу, обработчик исключений всегда получает нулевое исключение. Я использую тип цепочки для перенаправления в обработчик исключений. Нужно ли реализовывать какой-то интерфейс ExceptionAware? Вызывается ли метод установки исключений Struts 2 помимо setException?

Примечание: я пытался следовать этому руководству при написании этой программы.

Ответы [ 2 ]

7 голосов
/ 28 апреля 2012

Использование Struts2 версии 2.3.1.2 Я не получаю нулевое исключение в моем обработчике ошибок, все работает так, как объявлено.Убедитесь, что вы используете неизмененный стек по умолчанию.

Что касается надежных источников, мы можем ссылаться на документацию перехватчика для ExceptionMappingInterceptor и Цепной перехватчик .ExceptionMappingInterceptor помещает ExceptionHolder в стек значений, который, в свою очередь, предоставляет свойство исключения.Перехватчик цепочки копирует все свойства в стеке значений в цель.Так как ExceptionHolder находится в стеке, если есть установщик для Exception, он будет установлен.

Вот все файлы, которые создают рабочий пример:

struts.xml (хранится очень похоже навопросы):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <constant name="struts.devMode" value="true" />
    <constant name="struts.ui.theme" value="simple" />
    <package  name="kenmcwilliams"  namespace="/" extends="struts-default">
        <global-results>
            <result name="errHandler" type="chain">
                <param name="actionName">errorProcessor</param>
            </result>
        </global-results>
        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="errHandler" />
        </global-exception-mappings>
        <action name="errorProcessor" class="com.kenmcwilliams.test.myErrorProcessor">
            <result name="error">/WEB-INF/content/error.jsp</result>
        </action>
        <action name="throwExceptions" class="com.kenmcwilliams.kensocketchat.action.Bomb">
            <result name="success">/WEB-INF/content/bomb.jsp</result>
        </action>
    </package>
</struts>

MyErrorProcessor.java

package com.kenmcwilliams.test;

import com.opensymphony.xwork2.ActionSupport;

public class MyErrorProcessor extends ActionSupport {

    private Exception exception;

    @Override
    public String execute() {
        System.out.println("Is exception null: " + (exception == null));
        System.out.println(""
                + exception.getMessage());
        return "error";
    }

    public void setException(Exception exceptionHolder) {
        this.exception = exceptionHolder;
    }

    public Exception getException() {
        return exception;
    }
}

Bomb (просто создает исключение RuntimeException):

package com.kenmcwilliams.kensocketchat.action;

import com.opensymphony.xwork2.ActionSupport;

public class Bomb extends ActionSupport{
    @Override
    public String execute() throws Exception{
        throw new RuntimeException("Hello from Exception!");
    }
}

Просмотр для бомбы (/ WEB-INF / content/bomb.jsp) [ Никогда недоступен ]

<%@taglib prefix="s" uri="/struts-tags"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>The Bomb!</title>
    </head>
    <body>
        <h1>The Bomb!</h1>
    </body>
</html>

Просмотр на ошибку (/WEB-INF/content/error.jsp)

<%@taglib prefix="s" uri="/struts-tags"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Global Error Handler</title>
    </head>
    <body>
        <h1>Global Error Handler</h1>
        <s:property value="exception.stackTrace"/>
    </body>
</html>

Вывод:

Я вижу рендер error.jsp, и на консоли glassfish отображается следующее:

INFO: Is exception null: false
INFO: Hello from Exception!
5 голосов
/ 04 мая 2011

У меня была та же проблема, что и у вас!

Несмотря на то, что заполнение поля exception в Struts намного чище, создается впечатление, что заполнение этого поля не происходит (как вы указали). Чтобы обойти это, я удалил поле исключения (и его метод получения / установки) из своего класса обработчика исключений (ваш класс myErrorProcessor) и заменил его на метод для «ручного» извлечения исключения из ValueStack:

/**
 * Finds exception object on the value stack
 * 
 * @return the exception object on the value stack
 */
private Object findException() {        
    ActionContext ac = ActionContext.getContext();
    ValueStack vs = ac.getValueStack();
    Object exception = vs.findValue("exception");       

    return exception;
}

Затем я могу использовать instanceof, чтобы убедиться, что исключение Object - это тип, который я ожидал, и затем соответствующим образом обработать это исключение (например, запись сообщений, найденных в пользовательском объекте Exception, в базу данных). *

Дайте мне знать, как это работает для вас! :)

...