`

Struts 声明式异常处理和个性化异常处理

阅读更多
首先我们的国际化资源文件中有
user.not.found = 用户不能找到,用户名称=[{0}]
user.password.error = user.password.error


第一种 声明式异常处理

为国际化配置文件中的每个key,设计一个异常。

用户登录验证,用户名错误抛出UserNotFoundException,密码错误抛出PasswordErrorException
public void login(String username, String password) {
		if (!"admin".equals()) {
			throw new UserNotFoundException();
		}
		if (!"admin".equals(password)) {
			throw new PasswordErrorException();
		}
	}


struts-config.xml文件中,<exception/>的key对应国际化配置文件中key,type是对应的异常处理类
<global-exceptions>
	<!-- 为所有Action使用的,全局异常 -->
		<exception key="user.not.found" type="demo.struts.UserNotFoundException"/>
		<exception key="user.password.error" type="demo.struts.PasswordErrorException"/>
	</global-exceptions>
		
	<action-mappings>
		<action path="/login"
				type="demo.struts.LoginAction"
				name="loginForm"
				scope="request"
				validate="false"
				input="/login.jsp"
		>	
		<!-- path 错误时候 跳转的页面,优先级高于 action中的input -->
		<!-- 为每一个action配置 
			<exception key="user.not.found" type="demo.struts.UserNotFoundException" path="/login_error.jsp"/>
			<exception key="user.password.error" type="demo.struts.PasswordErrorException" path="/login_error.jsp"/>
		-->
			<forward name="success" path="/login_success.jsp"/>
			<forward name="error" path="/login.jsp"/>
		</action>
		
		<action path="/changelang"
				type="demo.struts.ChangeLanguageAction"
		>
			<forward name="index" path="/index.jsp"/>
		</action>

	</action-mappings>


Struts的RequestProcessor类
 protected ActionForward processException(HttpServletRequest request,
                                             HttpServletResponse response,
                                             Exception exception,
                                             ActionForm form,
                                             ActionMapping mapping)
        throws IOException, ServletException {

        // 是否在配置了Exception
        ExceptionConfig config = mapping.findException(exception.getClass());
        // 找到的config就是下面这条信息
        // <exception key="user.not.found" type="demo.struts.UserNotFoundException" path="/login_error.jsp"/>
        if (config == null) {
        // 没有配置,struts不管了,往web容器里抛,看在web.xml文件中是否配置,
        // 如果仍没有配置,则把异常显示到页面上
            log.warn(getInternal().getMessage("unhandledException",
                                              exception.getClass()));
            if (exception instanceof IOException) {
                throw (IOException) exception;
            } else if (exception instanceof ServletException) {
                throw (ServletException) exception;
            } else {
                throw new ServletException(exception);
            }
        }

        // struts异常默认处理类
        try {
            ExceptionHandler handler = (ExceptionHandler)
            RequestUtils.applicationInstance(config.getHandler());
            return (handler.execute(exception, config, mapping, form,
                                    request, response));
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }



struts默认的exceptionHandler
    public ActionForward execute(
        Exception ex,
        ExceptionConfig ae,
        ActionMapping mapping,
        ActionForm formInstance,
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException {

        ActionForward forward = null;
        ActionMessage error = null;
        String property = null;

        // 在<exception>中配置了path,返回actionForward就是path中的配置
        if (ae.getPath() != null) {
            forward = new ActionForward(ae.getPath());
        } else {
        // 没有配置的话,返回actionForward就是<action>中的input
            forward = mapping.getInputForward();
        }

        // Figure out the error
        if (ex instanceof ModuleException) {
            error = ((ModuleException) ex).getActionMessage();
            property = ((ModuleException) ex).getProperty();
        } else {
        // 我们写的程序抛出的异常都是这种情况
        // 从国际化文件中,根据key取
        // ae.getKey() -- 拿到<exception>中key值 user.not.found
            error = new ActionMessage(ae.getKey(), ex.getMessage());
            // 集合ActionMessages中的key,和国际化资源文件中的key一样
            property = error.getKey();
        }

        this.logException(ex);

        // Store the exception
        request.setAttribute(Globals.EXCEPTION_KEY, ex);
        // 放到ActionMessages集合中 getScope()默认request
        this.storeException(request, property, error, forward, ae.getScope());

        return forward;
    }




第二种 个性化异常处理

public void login(String username, String password) {
		if (!"admin".equals(username)) {
                        //user.not.found资源文件中的key, username 占位符
			throw new ErrorCodeException("user.not.found", username);
		}
		if (!"admin".equals(password)) {
			throw new ErrorCodeException("user.password.error");
		}


    <global-exceptions>
        <!-- key值随便配一个 具体的是在程序中控制-->
        <!-- type异常类 handler异常处理类 都是由我们来写和控制 -->
        <exception key="error.exception" type="demo.struts.ErrorCodeException" handler="demo.struts.ErrorCodeExceptionHandler"/>
    </global-exceptions>


public class ErrorCodeException extends RuntimeException {

	// 错误码就是国际化资源文件的key
	private String errorCode;

	// 占位符
	private Object[] args;

	public ErrorCodeException(String errorCode) {
		this(errorCode, null);
	}

	public ErrorCodeException(String errorCode, Object arg) {
		this(errorCode, new Object[]{arg});
	}
	
	public ErrorCodeException(String errorCode, Object[] args){
		this.errorCode = errorCode;
		this.args = args;
	}

	// 只提供get方法
	public String getErrorCode() {
		return errorCode;
	}

	public Object[] getArgs() {
		return args;
	}



public class ErrorCodeExceptionHandler extends ExceptionHandler {

	public ActionForward execute(Exception ex, ExceptionConfig ae,
			ActionMapping mapping, ActionForm formInstance,
			HttpServletRequest request, HttpServletResponse response)
			throws ServletException {

		// 不是ErrorCodeException,我们不处理
		if (!(ex instanceof ErrorCodeException)) {
			return super.execute(ex, ae, mapping, formInstance, request, response);
		}
		
		ActionForward forward = null;
		ActionMessage error = null;
		String property = null;

		// Build the forward from the exception mapping if it exists
		// or from the form input
		if (ae.getPath() != null) {
			forward = new ActionForward(ae.getPath());
		} else {
			forward = mapping.getInputForward();
		}

		// Figure out the error
		if (ex instanceof ModuleException) {
			error = ((ModuleException) ex).getActionMessage();
			property = ((ModuleException) ex).getProperty();
		} else {
			// 原来的代码 error = new ActionMessage(ae.getKey(), ex.getMessage());
			// ae.getKey() 拿出的key是配置文件中<exception>写的,因为所有异常都用同一个key
            // 无法找到国际化资源文件中的key,好在我们在抛异常时,把key写进异常的errorCode中
            
            ErrorCodeException ece = (ErrorCodeException) ex;
            // 拿到errorCode
            String errorCode = ece.getErrorCode();
            // 拿到占位符
            Object[] args = ece.getArgs();
            
            error = new ActionMessage(errorCode, args);
            property = error.getKey();
        }

        this.logException(ex);

        // Store the exception
        request.setAttribute(Globals.EXCEPTION_KEY, ex);
        this.storeException(request, property, error, forward, ae.getScope());

        return forward;

    }



如果我们不想写国际化配置文件,在程序中之际页面提示内容

 <!-- 用默认的handler也能能执行 -->
<exception key="error.exception" type="demo.struts.AppException" handler="demo.struts.AppExceptionHandler"/>


# 只有一个占位符
error.exception={0}


	public void login(String username, String password) {
		if (!"admin".equals(username)) {
                        // 直接写内容
			throw new AppException("用户不能找到【" + username + "】");
		}
		if (!"admin".equals(password)) {
			throw new ErrorCodeException("密码错误");
		}
	}


public class AppException extends RuntimeException {
	public AppException(String msg){
		super(msg);
	}
}


public class AppExceptionHandler extends ExceptionHandler {

	public ActionForward execute(Exception ex, ExceptionConfig ae,
			ActionMapping mapping, ActionForm formInstance,
			HttpServletRequest request, HttpServletResponse response)
			throws ServletException {

		if(!(ex instanceof AppException)){
			return super.execute(ex, ae, mapping, formInstance, request, response);
		}
		
		ActionForward forward = null;
		ActionMessage error = null;
		String property = null;

		// Build the forward from the exception mapping if it exists
		// or from the form input
		if (ae.getPath() != null) {
			forward = new ActionForward(ae.getPath());
		} else {
			forward = mapping.getInputForward();
		}

		// Figure out the error
		if (ex instanceof ModuleException) {
			error = ((ModuleException) ex).getActionMessage();
			property = ((ModuleException) ex).getProperty();
		} else {
			
			AppException appe = (AppException) ex;
			// ae.getKey() 没用
			// appe.getMessage() ("用户不能找到【" + username + "】
			error = new ActionMessage(ae.getKey(), appe.getMessage());
			property = error.getKey();
		}

		this.logException(ex);

		// Store the exception
		request.setAttribute(Globals.EXCEPTION_KEY, ex);
		this.storeException(request, property, error, forward, ae.getScope());

		return forward;

	}


附件是两个的myeclipse工程
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics