本文要实现的一个功能是将异常封装,并在抛出时能映射到对应的中文提示,同时这个异常抛出中文信息可以动态变化。
简单思路:将异常码对应的code-value关系写到property文件中去,spring加载这个配置文件内容器中去。然后封装一个exception,每次抛出异常时就根据对应的code值去找到它对应的中文码值,并且要实现异常信息可以在运行时动态改变。对于第二点一般如何异常信息用枚举的话,动态更改参数不是很方便。所以结合spring来设计自己的一个异常类。
下面来讲讲步骤
1、定义PropertyPlaceholderConfigurer
专门用来读取配置文件到Spring中中中
package com.lin.config;
import java.io.IOException;
import java.util.Properties;
/**
* 初始化配置文件
* @author linbingwen
*
*/
public class PropertyPlaceholderConfigurer extends
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer {
private static Properties props;
public Properties mergeProperties() throws IOException {
props = super.mergeProperties();
Property.init(props);
return props;
}
public static String getProperty(String key) {
return props.getProperty(key);
}
public String getProperty(String key, String defaultValue) {
return props.getProperty(key, defaultValue);
}
}
使用方法为在spring的配置文件中application.xml:
<bean id="propertyConfigurer"
class="com.lin.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/*.properties</value>
</list>
</property>
<property name="fileEncoding" value="UTF-8"/>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
这样就将配置文件加载到Spring中去
配置文件的内容示例如下,它就放在ctsErrorCode.properties:
注意下面这个文件要改成iso标准编码
##/***
##* 公用错误码
##*/
CTS00000=处理成功
CTS99999=未知错误
CTSWB888=查无此记录
##/***
##* WB--业务WARN--公用错误码--CTSWBA01-CTSWBA99
##*/
CTSWBA01=【{0}】为空
CTSWBA02=参数【{0}】格式错误
CTSWBA03=参数【{0}】错误
CTSWBA04=参数【{0}】长度错误
CTSWBA05={0}不匹配
CTSWBA06=未查询到{0}
CTSWBA07=参数【{0}】应大于0
CTSWBA08={0}不能修改
CTSWBA09=参数【{0}】应大于或等于0
CTSWBA10={0}不存在
CTSWBA11=交易参考号重复
CTSWBA12=调用CIF接口根据{0}查询{1}结果为空
CTSWBA13=设置{0}发生异常
CTSWBA14={0}应大于或等于{1}
{}里面可以动态改变
定义一个用来取配置文件的工具:
package com.lin.config;
/**
* 用于在java类中取得配置文件变量的值
* @author linbingwen
*
*/
public class Property {
private static java.util.Properties property;
private Property() {
}
static void init(java.util.Properties props) {
property = props;
}
public static String getProperty(String key) {
return property.getProperty(key);
}
public static String getProperty(String key, String defaultValue) {
return property.getProperty(key, defaultValue);
}
}
2、封装异常类
package com.lin.exception;
import java.text.MessageFormat;
import com.lin.errorcode.ErrorCode;
/**
*
* <b>类说明:</b>Service层统一抛出的异常
*
* <p>
* <b>详细描述:</b>
*
* @author costin_law
* @since 2014-5-5
*/
public class ServiceException extends RuntimeException {
private static final long serialVersionUID = 6514891174875747380L;
private ErrorCode errorCode;
/** 异常错误码 **/
private String code;
/** 异常描述 **/
private String msg;
/** 扩展异常描述(包括msg) **/
private String extMsg;
/**
* ServiceException构造方法,有format字符组
* @param errorCode 错误码
* @param param format字符组
* @param extMsg 扩展信息,给出具体的错误值信息等
*/
public ServiceException(ErrorCode errorCode,String param[],String ... extMsg) {
super(null==errorCode ? "" : errorCode.getCode());
init(errorCode, param,extMsg);
}
/**
* ServiceException构造方法,有format字符组
* @param errCode
* @param paramsList
*/
public ServiceException(ErrorCode errCode, Object... paramsList) {
super(null==errCode ? "" : errCode.getCode());
Object[] params = null;
if ((paramsList != null) && (paramsList.length > 0)
&& ((paramsList[(paramsList.length - 1)] instanceof Throwable)))
{
Object[] newParam = new Object[paramsList.length - 1];
System.arraycopy(paramsList, 0, newParam, 0, newParam.length);
params = newParam;
super.initCause((Throwable)paramsList[(paramsList.length - 1)]);
}
else {
params = paramsList;
super.initCause(null);
}
this.errorCode = errCode;
this.code = null==errCode ? "" : errCode.getCode();
this.msg = null==errCode ? "" : MessageFormat.format(errCode.getMsg(),params);
this.extMsg = this.msg;
}
private void init(ErrorCode errorCode, String param[], String... extMsg) {
this.errorCode = errorCode;
this.code = null==errorCode ? "" : errorCode.getCode();
this.msg = null==errorCode ? "" : MessageFormat.format(errorCode.getMsg(),param);
StringBuilder builder = new StringBuilder(100);
builder.append(this.msg);
if(null != extMsg){
for(String ext : extMsg ){
builder.append("[").append(ext).append("]");
}
}
this.extMsg = builder.toString();
}
/**
*
* @param code 错误码
* @param msg 描述信息
*/
public ServiceException(String code, String msg) {
super(code+":"+msg);
this.code = code;
this.msg = msg;
this.extMsg = msg;
}
/**
* 带Exception的构造方法,传format字符数组
* @param errorCode 错误码基类
* @param e 异常
* @param extMsg 扩展信息,给出具体的错误值信息等
*/
public ServiceException(ErrorCode errorCode, Throwable e,String param[] , String ...extMsg ) {
super(null==errorCode ? "" : errorCode.getCode(), e);
init(errorCode, param, extMsg);
}
/**
*
* @param code 错误码
* @param msg 描述信息
* @param e 异常
*/
/*public ServiceException(String code, String msg,Throwable e) {
super(code+":"+msg, e);
this.code = code;
this.msg = msg;
}*/
/**
*
*
* 方法说明:异常错误码
*
* @return
*/
public String getCode() {
return code;
}
/**
*
*
* 方法说明:异常描述信息
*
* @return
*/
public String getMsg() {
return msg;
}
public String getExtMsg() {
return extMsg;
}
@Override
public String getMessage() {
return super.getMessage() + ","+extMsg;
}
public static void main(String[] args) {
}
public ErrorCode getErrorCode() {
return errorCode;
}
public void setErrorCode(ErrorCode errorCode) {
this.errorCode = errorCode;
}
}
每次异常抛出时都要指明一个ErrorCode的类,
package com.lin.errorcode;
public interface ErrorCode {
public String getCode();
public String getMsg();
}
它是一个接口,实现类如下:
package com.lin.errorcode;
import com.lin.config.Property;
/**
* 功能概要:CTS错误码
* @author linbingwen
*
*/
public enum CtsErrorCode implements ErrorCode {
/**
* 前三位固定:CTS 第四位表示日志级别:W/E 第五位系统错误类型:B业务类型/S系统类型 第六位:A公共错误码/B批量错误码/数字则为普通错误码
*/
/***
* 公用错误码
*/
SUCCESS("CTS00000"), // 处理成功
UNKHOWN_ERROR("CTS99999");// 未知错误
private String code;
private CtsErrorCode(String code) {
this.code = code;
}
@Override
public String getCode() {
return this.code;
}
@Override
public String getMsg() {
String msg = Property.getProperty(this.code);
return msg == null ? "" : msg;
}
}
注意这里的
String msg = Property.getProperty(this.code);
这里会从Spring中容器去取到配置文件。
3、使用
@Test
public void test(){
throw new ServiceException(CtsErrorCode.ERROR_FORMAT,"参数格式出错");
}
这里注意到异常信息有些部分可以动态传入进去。