Merge remote-tracking branch 'origin/后台运营yy' into 后台运营yy

后台运营yy
yangyang 8 months ago
commit b3680db247

@ -6,9 +6,13 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
// ObjectUtil类继承自SerializeTranscoder主要用于实现对象的序列化、反序列化以及提供对象相等性比较的功能。
public class ObjectUtil extends SerializeTranscoder {
// 重写父类的serialize方法用于将给定的对象进行序列化操作即将对象转换为字节数组的形式以便在某些场景下如存储到Redis中进行传输或持久化存储。
@Override
public byte[] serialize(Object value) {
// 如果传入要序列化的对象为null则抛出空指针异常因为无法对null对象进行序列化操作。
if (value == null) {
throw new NullPointerException("Can't serialize null");
}
@ -16,54 +20,76 @@ public class ObjectUtil extends SerializeTranscoder {
ByteArrayOutputStream bos = null;
ObjectOutputStream os = null;
try {
// 创建一个ByteArrayOutputStream它用于在内存中缓冲要序列化的对象数据最终可以转换为字节数组形式。
bos = new ByteArrayOutputStream();
// 创建一个ObjectOutputStream它基于ByteArrayOutputStream用于将对象以Java的序列化机制写入到输出流中。
os = new ObjectOutputStream(bos);
// 使用ObjectOutputStream将传入的对象写入到输出流中进行实际的序列化操作。
os.writeObject(value);
// 关闭ObjectOutputStream释放相关资源一般在写入完成后进行关闭操作确保数据正确写入到输出流中。
os.close();
// 关闭ByteArrayOutputStream释放其占用的内存资源此时内部缓冲的数据已经准备好可以转换为字节数组了。
bos.close();
// 将ByteArrayOutputStream中缓冲的数据转换为字节数组这就是最终序列化后的结果赋值给result变量以便返回。
result = bos.toByteArray();
} catch (IOException e) {
// 如果在序列化过程中出现IO异常比如对象不支持序列化、流操作出现问题等
// 则抛出一个非法参数异常并将原始的IO异常作为原因附带上方便排查问题表明传入的对象可能无法进行序列化操作。
throw new IllegalArgumentException("Non-serializable object", e);
} finally {
// 无论是否成功完成序列化操作都要关闭ObjectOutputStream和ByteArrayOutputStream释放资源避免内存泄漏等问题。
close(os);
close(bos);
}
return result;
}
// 重写父类的deserialize方法用于将给定的字节数组进行反序列化操作即将字节数组转换回原始的对象形式通常用于从存储如Redis中读取数据后还原对象。
@Override
public Object deserialize(byte[] in) {
Object result = null;
ByteArrayInputStream bis = null;
ObjectInputStream is = null;
try {
if (in != null) {
// 首先判断传入的字节数组是否为null如果为null则不进行后续的反序列化操作直接返回null。
if (in!= null) {
// 创建一个ByteArrayInputStream它以传入的字节数组作为数据源用于后续通过输入流读取数据进行反序列化操作。
bis = new ByteArrayInputStream(in);
// 创建一个ObjectInputStream它基于ByteArrayInputStream用于按照Java的序列化机制从输入流中读取数据并还原为对象。
is = new ObjectInputStream(bis);
// 使用ObjectInputStream从输入流中读取数据并还原为对象这是实际的反序列化操作将还原后的对象赋值给result变量。
result = is.readObject();
// 关闭ObjectInputStream释放相关资源确保反序列化操作完成后资源正确释放。
is.close();
// 关闭ByteArrayInputStream释放其占用的内存资源。
bis.close();
}
} catch (IOException e) {
// 如果在反序列化过程中出现IO异常比如读取流出现问题、数据格式不正确等打印异常堆栈信息方便排查问题。
e.printStackTrace();
} catch (ClassNotFoundException e) {
// 如果在反序列化过程中出现找不到对应类的异常(比如还原对象时找不到对象对应的类定义),同样打印异常堆栈信息,便于查找问题所在。
e.printStackTrace();
} finally {
// 无论是否成功完成反序列化操作都要关闭ObjectInputStream和ByteArrayInputStream释放资源避免内存泄漏等问题。
close(is);
close(bis);
}
return result;
}
// 定义一个静态方法equals用于比较两个对象是否相等遵循Java中对象相等性比较的常规规则。
public static boolean equals(Object o1, Object o2) {
// 如果两个对象引用完全相同即指向同一个内存地址则直接返回true表示它们相等。
if (o1 == o2) {
return true;
} else if (o1 == null || o2 == null) {
// 如果其中一个对象为null而另一个不为null则返回false表示它们不相等。
return false;
} else {
// 如果两个对象都不为null调用对象的equals方法一般需要重写该方法来定义具体的相等性逻辑来比较它们是否相等并返回相应的结果。
return o1.equals(o2);
}
}
}
}

@ -1,13 +1,20 @@
package com.tamguo.config.redis;
// PoolConfigBean类用于封装与连接池相关的配置参数通过定义相应的属性、构造方法以及访问器getter和setter方法方便对这些配置信息进行设置和获取操作同时重写了toString方法用于方便地输出配置信息的字符串表示形式。
public class PoolConfigBean {
// 表示连接池中允许的最大活动连接数,即同一时刻能够同时从连接池中获取并使用的最大连接数量。
private int max_active;
// 表示连接池中允许的最大空闲连接数,即连接池中可以闲置的最大连接数量,当空闲连接数超过这个值时,多余的空闲连接可能会被回收。
private int max_idle;
// 表示从连接池中获取连接时,最长的等待时间(单位通常为毫秒),如果在这个时间内无法获取到可用连接,则可能会抛出相应的异常,提示获取连接超时。
private long max_wait;
// 默认的无参构造方法用于创建PoolConfigBean类的实例在没有传入初始参数时可以使用后续可以通过对应的setter方法来设置各个属性的值。
public PoolConfigBean() {
}
// 带参数的构造方法用于在创建PoolConfigBean类实例时同时初始化各个配置属性的值方便一次性设置好相关的连接池配置信息。
public PoolConfigBean(int max_active, int max_idle, long max_wait) {
super();
this.max_active = max_active;
@ -15,33 +22,39 @@ public class PoolConfigBean {
this.max_wait = max_wait;
}
// 获取max_active属性值的方法外部代码可以通过调用这个方法获取连接池中允许的最大活动连接数。
public int getMax_active() {
return max_active;
}
// 设置max_active属性值的方法外部代码可以通过调用这个方法来设置连接池中允许的最大活动连接数。
public void setMax_active(int max_active) {
this.max_active = max_active;
}
// 获取max_idle属性值的方法外部代码可以通过调用这个方法获取连接池中允许的最大空闲连接数。
public int getMax_idle() {
return max_idle;
}
// 设置max_idle属性值的方法外部代码可以通过调用这个方法来设置连接池中允许的最大空闲连接数。
public void setMax_idle(int max_idle) {
this.max_idle = max_idle;
}
// 获取max_wait属性值的方法外部代码可以通过调用这个方法获取从连接池中获取连接时的最长等待时间。
public long getMax_wait() {
return max_wait;
}
// 设置max_wait属性值的方法外部代码可以通过调用这个方法来设置从连接池中获取连接时的最长等待时间。
public void setMax_wait(long max_wait) {
this.max_wait = max_wait;
}
// 重写toString方法用于将PoolConfigBean类的实例以特定的字符串格式进行表示方便在调试、日志输出等场景下直观地查看连接池配置信息的具体内容。
@Override
public String toString() {
return "PoolConfig [max_active=" + max_active + ", max_idle=" + max_idle + ", max_wait=" + max_wait + "]";
}
}
}

@ -1,11 +1,18 @@
package com.tamguo.config.redis;
// RedisServerNodeBean类用于封装Redis服务器节点的相关信息通过定义相应的属性、构造方法以及对应的访问器getter和setter方法方便对这些信息进行设置、获取以及以字符串形式展示等操作。
public class RedisServerNodeBean {
// 用于存储Redis服务器的IP地址通过该IP地址可以定位到对应的Redis服务器所在的网络位置以便建立连接。
private String ip;
// 用于存储Redis服务器监听的端口号客户端通过指定的IP地址和对应的端口号来与Redis服务器进行通信交互。
private int port;
// 表示是否需要进行身份验证例如密码验证才能连接到该Redis服务器true表示需要验证false表示不需要验证。
private boolean needAuth;
// 如果needAuth为true即需要进行身份验证时此属性用于存储连接Redis服务器所需的验证密码或其他认证凭据以确保连接的合法性。
private String auth;
// 构造方法用于创建RedisServerNodeBean类的实例并在实例化时初始化各个属性的值传入的参数分别对应Redis服务器节点的IP地址、端口号、是否需要认证以及认证凭据密码
public RedisServerNodeBean(String ip, int port, boolean needAuth, String auth) {
this.ip = ip;
this.port = port;
@ -13,41 +20,49 @@ public class RedisServerNodeBean {
this.auth = auth;
}
// 获取ip属性值的方法外部代码可以通过调用这个方法获取Redis服务器节点的IP地址信息。
public String getIp() {
return ip;
}
// 设置ip属性值的方法外部代码可以通过调用这个方法来修改Redis服务器节点的IP地址信息。
public void setIp(String ip) {
this.ip = ip;
}
// 获取port属性值的方法外部代码可以通过调用这个方法获取Redis服务器节点的端口号信息。
public int getPort() {
return port;
}
// 设置port属性值的方法外部代码可以通过调用这个方法来修改Redis服务器节点的端口号信息。
public void setPort(int port) {
this.port = port;
}
// 获取needAuth属性值的方法外部代码可以通过调用这个方法获取表示是否需要对Redis服务器进行身份验证的布尔值。
public boolean isNeedAuth() {
return needAuth;
}
// 设置needAuth属性值的方法外部代码可以通过调用这个方法来修改表示是否需要对Redis服务器进行身份验证的布尔值。
public void setNeedAuth(boolean needAuth) {
this.needAuth = needAuth;
}
// 获取auth属性值的方法外部代码可以通过调用这个方法获取连接Redis服务器所需的认证凭据如密码信息。
public String getAuth() {
return auth;
}
// 设置auth属性值的方法外部代码可以通过调用这个方法来修改连接Redis服务器所需的认证凭据如密码信息。
public void setAuth(String auth) {
this.auth = auth;
}
// 重写toString方法用于将RedisServerNodeBean类的实例以特定的字符串格式进行表示方便在调试、日志输出等场景下直观地展示Redis服务器节点的相关信息内容。
@Override
public String toString() {
return "RedisServer [ip=" + ip + ", port=" + port + ", needAuth=" + needAuth + ", auth=" + auth + "]";
}
}
}

@ -16,89 +16,126 @@ import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
// 标识该类是一个Spring组件在Spring容器启动时会被扫描并实例化其Bean名称为"redisConfigure"用于配置和管理Redis相关的连接等操作。
@Component("redisConfigure")
// 实现InitializingBean接口意味着该类在所有属性被设置后会执行afterPropertiesSet方法来进行一些初始化操作通常用于加载配置等前置准备工作。
public class RedisXMLConfigure implements InitializingBean {
// 创建一个日志记录器实例用于记录与该类相关的操作日志方便在运行过程中排查问题以及查看关键信息记录的日志类别基于当前类RedisXMLConfigure。
private static final Logger logger = Logger.getLogger(RedisXMLConfigure.class);
// 用于存储Redis键的前缀是一个静态变量在整个应用中可以统一为Redis中的键添加特定的前缀方便管理和区分不同用途的键。
private static String preKey;
// 用于存储解析后的XML配置文档对象后续通过操作这个对象来获取各种Redis配置相关的元素和属性信息初始化为null后续在初始化方法中进行赋值。
private static Document document = null;
// 定义一个ShardedJedisPool对象用于管理多个Redis节点的连接池通过它可以获取到ShardedJedis连接实现对Redis集群等多节点环境下的数据访问。
private ShardedJedisPool shardedJedisPool;
// 实现InitializingBean接口的方法在Spring容器完成属性注入后自动调用用于进行Redis相关配置的初始化工作比如加载XML配置文件、解析配置信息、创建连接池等操作。
@Override
public void afterPropertiesSet() throws Exception {
// 创建一个XMLConfiguration对象用于读取和解析XML配置文件它可能封装了一些底层的XML解析相关的逻辑。
XMLConfiguration xmlConfiguration = new XMLConfiguration();
// 定义要加载的Redis配置文件的路径和文件名这里指定为"redis.xml"表示从类路径下查找该文件来获取Redis配置信息。
String REDIS_PATH = "redis.xml";
InputStream stream = null;
try {
// 通过类加载器获取指定路径下的配置文件输入流,如果获取不到(即配置文件不存在或路径错误),则记录错误日志并抛出运行时异常,表示加载配置文件失败。
stream = this.getClass().getClassLoader().getResourceAsStream(REDIS_PATH);
if (stream == null) {
logger.error("load redis.xml failed!!!" + REDIS_PATH);
throw new RuntimeException("load redis.xml failed");
}
logger.info("Redis XML config path:" + REDIS_PATH);
// 使用xmlConfiguration对象读取配置文件输入流中的内容如果读取成功返回true则将解析后的文档对象赋值给document变量以便后续使用若读取失败则记录错误日志。
if (xmlConfiguration.readConfigFile(stream)) {
document = xmlConfiguration.getDocument();
} else {
logger.error("load redis.xml failed!!!");
}
} finally {
if (null != stream)
// 无论是否成功读取配置文件都要关闭输入流释放相关资源避免资源泄漏通过判断输入流是否为null来进行关闭操作。
if (null!= stream)
stream.close();
}
//初始化参数
// 调用初始化方法用于初始化Redis键的前缀信息从解析后的XML配置中获取相应的值进行设置。
initPreKey();
// 调用方法初始化连接池的配置参数从XML配置中读取相关属性值创建并返回一个PoolConfigBean对象该对象封装了如最大空闲连接数、最大等待时间等连接池配置信息。
PoolConfigBean pcb = initPoolConfigBean();
// 调用方法解析配置文件中关于Redis服务器节点的信息读取每个服务器节点的IP、端口、是否需要认证以及认证密码等信息返回一个包含多个RedisServerNodeBean对象的列表。
List<RedisServerNodeBean> rsnbs = initRedisServerNodeBeans();
//实现shardedJedisPool
// 创建一个JedisPoolConfig对象用于配置Jedis连接池的相关参数后续会基于这个配置对象来创建ShardedJedisPool连接池。
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 注意这里没有设置maxActive可能在当前配置逻辑中有其他考虑比如依赖默认值或者后续有特殊处理而是设置了最大空闲连接数和最大等待时间从之前初始化得到的PoolConfigBean对象中获取相应的参数值进行设置。
//no maxActive config
jedisPoolConfig.setMaxIdle(pcb.getMax_idle());
jedisPoolConfig.setMaxWaitMillis(pcb.getMax_wait());
shardedJedisPool = new ShardedJedisPool(jedisPoolConfig,getJedisShardInfo(rsnbs));
if(shardedJedisPool == null){
// 创建ShardedJedisPool连接池对象传入配置好的JedisPoolConfig对象以及根据解析得到的Redis服务器节点信息转换而来的JedisShardInfo列表用于管理多个Redis节点的连接池方便后续获取连接进行数据操作。
shardedJedisPool = new ShardedJedisPool(jedisPoolConfig, getJedisShardInfo(rsnbs));
if (shardedJedisPool == null) {
// 如果创建连接池失败返回值为null则抛出运行时异常表示Redis配置文件存在错误导致无法正确创建连接池。
throw new RuntimeException("config redis.xml error");
}
}
/**
* jedis
* XMLPoolConfigBean
*/
private PoolConfigBean initPoolConfigBean() {
PoolConfigBean poolConfigBean = new PoolConfigBean();
// 通过文档对象查找名为"pool"的XML元素获取配置文件中关于连接池的配置节点假设配置文件中以特定的XML结构来定义连接池相关属性。
Element poolElement = (Element) document.getElementsByTagName("pool").item(0);
int max_active = poolElement.hasAttribute("maxActive") ? Integer.parseInt(poolElement.getAttribute("maxActive")) : -1;
int max_idle = poolElement.hasAttribute("maxIdle") ? Integer.parseInt(poolElement.getAttribute("maxIdle")) : -1;
long max_wait = poolElement.hasAttribute("maxWait") ? Long.parseLong(poolElement.getAttribute("maxWait")) : -1;
// 判断"pool"元素是否有"maxActive"属性如果有则将其解析为整数并赋值给max_active变量否则将其设置为 -1表示可能使用默认值或者后续有其他处理逻辑来确定该参数
int max_active = poolElement.hasAttribute("maxActive")? Integer.parseInt(poolElement.getAttribute("maxActive")) : -1;
// 类似地,获取"maxIdle"属性的值如果存在则解析为整数赋值给max_idle变量否则设置为 -1。
int max_idle = poolElement.hasAttribute("maxIdle")? Integer.parseInt(poolElement.getAttribute("maxIdle")) : -1;
// 获取"maxWait"属性的值存在则解析为长整型赋值给max_wait变量否则设置为 -1。
long max_wait = poolElement.hasAttribute("maxWait")? Long.parseLong(poolElement.getAttribute("maxWait")) : -1;
// 通过PoolConfigBean对象的setter方法将获取到的各个参数值设置到对象中以便后续返回并用于创建JedisPoolConfig对象时设置相应的连接池参数。
poolConfigBean.setMax_active(max_active);
poolConfigBean.setMax_idle(max_idle);
poolConfigBean.setMax_wait(max_wait);
return poolConfigBean;
}
/**
* redisserver
* XMLRedisIPRedisServerNodeBeanRedis
*/
private List<RedisServerNodeBean> initRedisServerNodeBeans() {
List<RedisServerNodeBean> redisServers = new ArrayList<RedisServerNodeBean>();
// 通过文档对象查找所有名为"server"的XML元素获取配置文件中定义的所有Redis服务器节点的配置节点列表后续遍历该列表来解析每个服务器节点的详细信息。
NodeList serverElements = document.getElementsByTagName("server");
int serverLen = serverElements.getLength();
if (serverLen < 1) {
logger.error("redis.servers.server must have one !");
// 如果没有找到任何"server"元素即没有配置Redis服务器节点信息记录错误日志并返回null表示配置不合法。
logger.error("redis.servers.server must have one!");
return null;
}
for (int i = 0; i < serverLen; i++) {
// 遍历每个"server"元素获取对应的Element对象用于解析该服务器节点的具体属性信息。
Element serverElement = (Element) serverElements.item(i);
String temp_ip = serverElement.hasAttribute("ip") ? serverElement.getAttribute("ip") : null;
// 获取"server"元素中"ip"属性的值如果存在则赋值给temp_ip变量否则设置为null表示IP地址未配置这是不符合要求的情况后续会进行相应的错误处理
String temp_ip = serverElement.hasAttribute("ip")? serverElement.getAttribute("ip") : null;
if (temp_ip == null) {
// 如果IP地址为空记录错误日志并返回null表示配置不合法因为IP地址是连接Redis服务器必需的信息。
logger.error("redis.servers.server.ip must be supplied!");
return null;
}
String temp_port = serverElement.hasAttribute("port") ? serverElement.getAttribute("port") : "6379";
String temp_needAuth = serverElement.hasAttribute("needAuth") ? serverElement.getAttribute("needAuth") : "false";
// 获取"server"元素中"port"属性的值如果存在则赋值给temp_port变量否则默认设置为"6379"Redis默认端口号确保端口号有一个合理的值。
String temp_port = serverElement.hasAttribute("port")? serverElement.getAttribute("port") : "6379";
// 获取"server"元素中"needAuth"属性的值如果存在则赋值给temp_needAuth变量否则默认设置为"false",表示默认不需要进行身份验证。
String temp_needAuth = serverElement.hasAttribute("needAuth")? serverElement.getAttribute("needAuth") : "false";
String temp_auth = null;
// need auth
// 如果"needAuth"属性的值为"true",即表示需要进行身份验证,那么获取"auth"属性的值认证密码如果不存在则记录错误日志并返回null表示配置不合法因为需要认证时密码是必需的。
if ("true".equals(temp_needAuth)) {
temp_auth = serverElement.hasAttribute("auth") ? serverElement.getAttribute("auth") : null;
temp_auth = serverElement.hasAttribute("auth")? serverElement.getAttribute("auth") : null;
if (null == temp_auth) {
logger.error("since needAuth is true,auth must be supplied!");
return null;
@ -107,11 +144,14 @@ public class RedisXMLConfigure implements InitializingBean {
RedisServerNodeBean rs = null;
try {
// 尝试创建一个RedisServerNodeBean对象传入解析得到的IP地址、端口号、是否需要认证的布尔值以及认证密码如果需要认证等信息将创建的对象赋值给rs变量。
// 如果端口号解析为整数失败即不是合法的数字格式会捕获NumberFormatException异常记录错误日志并返回null表示配置不合法。
rs = new RedisServerNodeBean(temp_ip, Integer.parseInt(temp_port), Boolean.parseBoolean(temp_needAuth), temp_auth);
} catch (NumberFormatException e) {
logger.error("port must be a number!\n" + e.getMessage());
return null;
}
// 将创建好的代表Redis服务器节点配置信息的对象添加到列表中最终返回包含所有服务器节点配置信息的列表。
redisServers.add(rs);
}
return redisServers;
@ -119,55 +159,71 @@ public class RedisXMLConfigure implements InitializingBean {
/**
* JedisShardInfo
* @param redisServers
* @return
* RedisList<RedisServerNodeBean>ShardedJedisPoolJedisShardInfo
* JedisShardInfoRedisIP便使
*
* @param redisServers RedisinitRedisServerNodeBeans
* @return JedisShardInfoShardedJedisPoolRedis
*/
private List<JedisShardInfo> getJedisShardInfo(List<RedisServerNodeBean> redisServers) {
if(redisServers == null){
if (redisServers == null) {
// 如果传入的Redis服务器节点列表为null记录错误日志并返回null表示参数不合法无法进行后续的转换操作。
logger.error("redisServers must not be empty null");
return null;
}
int serverLen = redisServers.size();
if (serverLen < 1) {
// 如果列表中没有任何元素即没有配置有效的Redis服务器节点记录错误日志并返回null表示不符合要求因为连接池至少需要一个有效的节点信息来创建。
logger.error("redisServers must not be empty ");
return null;
}
List<JedisShardInfo> servers = new ArrayList<JedisShardInfo>(serverLen);
for (int i = 0; i < serverLen; i++) {
// 遍历传入的Redis服务器节点列表获取每个RedisServerNodeBean对象代表一个服务器节点的配置信息。
RedisServerNodeBean redisServer = redisServers.get(i);
// 创建一个JedisShardInfo对象传入该服务器节点的IP地址和端口号信息用于构建与该节点的连接相关信息初始状态下不包含密码信息如果需要认证后续再单独设置
JedisShardInfo jedisShardInfo = new JedisShardInfo(redisServer.getIp(), redisServer.getPort());
if (redisServer.isNeedAuth()) {
// 如果该服务器节点需要进行身份验证通过RedisServerNodeBean对象的isNeedAuth方法判断则设置对应的认证密码从RedisServerNodeBean对象中获取密码信息并设置到JedisShardInfo对象中。
jedisShardInfo.setPassword(redisServer.getAuth());
}
// 将配置好的JedisShardInfo对象添加到列表中最终返回包含所有服务器节点连接信息的JedisShardInfo列表用于创建ShardedJedisPool连接池。
servers.add(jedisShardInfo);
}
return servers;
}
/*
* rediskey
* XMLRedispreKey便Redis
*/
private void initPreKey() {
Element preKeyElement = (Element) document.getElementsByTagName("preKey").item(0);
preKey = preKeyElement.hasAttribute("value") ? preKeyElement.getAttribute("value") : "";
preKey = preKeyElement.hasAttribute("value")? preKeyElement.getAttribute("value") : "";
}
// 获取Redis键前缀的方法外部代码可以通过调用该方法获取当前配置的Redis键前缀信息用于在操作Redis时为键添加合适的前缀。
public String getPreKey() {
return preKey;
}
/**
* jedis
* @return
* ShardedJedisPoolShardedJedis便Redis
*
* @return ShardedJedisRedis
*/
public ShardedJedis getConnection() {
return shardedJedisPool.getResource();
}
/**
* jedis
* @param resource
* 使ShardedJedisShardedJedisPool便
*
* @param resource ShardedJedisgetConnection使
*/
public void closeConnection(ShardedJedis resource) {
resource.close();
}
}
}

@ -2,14 +2,24 @@ package com.tamguo.config.redis;
import java.io.Closeable;
// SerializeTranscoder是一个抽象类用于定义对象序列化和反序列化相关的操作规范同时提供了一个用于关闭可关闭资源实现了Closeable接口的对象的通用方法
// 具体的序列化和反序列化逻辑需要由继承它的子类去实现。
public abstract class SerializeTranscoder {
// 抽象方法serialize用于将给定的对象进行序列化操作将对象转换为字节数组的形式。
// 具体的序列化实现细节由继承该抽象类的子类来定义不同的子类可以根据实际需求采用不同的序列化策略如Java原生序列化、JSON序列化等
// 参数value表示要进行序列化的对象返回值为序列化后的字节数组。
public abstract byte[] serialize(Object value);
// 抽象方法deserialize用于将给定的字节数组进行反序列化操作将字节数组还原为原始的对象形式。
// 同样,具体的反序列化实现由子类负责,要根据序列化时采用的策略来正确还原对象。
// 参数in表示要进行反序列化的字节数组返回值为反序列化后得到的对象。
public abstract Object deserialize(byte[] in);
// 定义一个方法close用于关闭实现了Closeable接口的资源对象如输入输出流等以释放相关的系统资源避免资源泄漏等问题。
// 参数closeable表示要关闭的可关闭资源对象如果传入的对象不为null则尝试调用其close方法进行关闭操作若关闭过程中出现异常则打印异常堆栈信息以便排查问题。
public void close(Closeable closeable) {
if (closeable != null) {
if (closeable!= null) {
try {
closeable.close();
} catch (Exception e) {
@ -17,4 +27,4 @@ public abstract class SerializeTranscoder {
}
}
}
}
}

@ -8,25 +8,37 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
// XMLConfiguration类主要用于读取和解析XML配置文件并提供获取解析后文档对象Document的方法支持通过文件名和输入流InputStream两种方式来加载配置文件进行解析。
public class XMLConfiguration {
// 用于存储解析后的XML文档对象初始化为null在成功读取并解析配置文件后会将对应的Document对象赋值给该变量方便后续获取和使用解析结果。
private Document document = null;
// 通过指定的配置文件名称字符串形式的文件名及路径来读取并解析XML配置文件若解析成功则返回true若出现异常导致解析失败document仍为null则返回false。
public boolean readConfigFile(String configFilename) {
// 创建一个DocumentBuilderFactory实例它是用于创建DocumentBuilder对象的工厂类通过它可以按照默认配置创建用于解析XML文档的DocumentBuilder。
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
// 使用DocumentBuilderFactory创建一个DocumentBuilder对象该对象用于实际解析XML文档将其解析为内存中的Document对象表示形式。
DocumentBuilder db = dbf.newDocumentBuilder();
// 调用DocumentBuilder的parse方法传入配置文件的名称路径作为参数尝试解析该XML配置文件并将解析后的Document对象赋值给document变量。
document = db.parse(configFilename);
} catch (IOException e) {
// 如果在解析过程中出现IO异常例如文件不存在、无法读取文件等情况打印异常堆栈信息方便排查问题但不中断程序执行继续执行后续的返回值判断逻辑。
e.printStackTrace();
} catch (Exception e) {
// 捕获其他可能出现的异常除了IO异常之外的比如XML格式错误等导致解析失败的异常同样打印异常堆栈信息以便查找问题所在然后继续执行返回值判断逻辑。
e.printStackTrace();
}
// 判断解析后的Document对象是否为null如果为null说明解析过程出现问题导致没有成功获取到有效的文档对象返回false表示读取配置文件失败否则返回true表示成功。
if (document == null) {
return false;
}
return true;
}
// 通过给定的输入流InputStream来读取并解析XML配置文件逻辑与readConfigFile(String configFilename)方法类似若解析成功则返回true失败则返回false。
// 常用于从类路径下获取资源流或者其他来源的输入流来解析配置文件的场景。
public boolean readConfigFile(InputStream stream) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
@ -43,11 +55,13 @@ public class XMLConfiguration {
return true;
}
// 获取解析后的XML文档对象的方法外部代码可以通过调用该方法获取之前成功解析配置文件后得到的Document对象以便进一步操作文档中的元素、属性等内容。
public Document getDocument() {
return document;
}
// 受保护的方法用于设置解析后的XML文档对象一般在类内部或者子类中可以根据需要调用该方法来更新document变量的值通常不是由外部直接调用而是在特定的内部逻辑中使用。
protected void setDocument(Document document) {
this.document = document;
}
}
}
Loading…
Cancel
Save