上一篇我们搭建了项目环境【从零写javaweb框架】(一)搭建开发环境,接下来要做的是定义和加载框架的配置项
第一步:定义配置项
打开上一篇创建好的demo1示例项目,在src/main/resources目录下创建一个smart.properties文件,内容如下:
#MySQL驱动 smart.framework.jdbc.driver=com.mysql.jdbc.Driver #数据库url,不同数据库的url格式会有所不同,详情请百度 smart.framework.jdbc.url=jdbc:mysql://localhost:3306/demo #数据库的账户名与密码 smart.framework.jdbc.username=root smart.framework.jdbc.password=root #demo1项目的基础包名 smart.framework.app.base_package=org.smart4j.demo1 #JSP的基础路径 smart.framework.app.jsp_path=/WEB-INF/view/ #静态资源文件的基础路径(如js、css、图片等) smart.framework.app.asset_path=/asset/
第二步:加载配置项
现在已经有配置文件了,我们在这一步要做的是读取配置文件,首先写一个读取配置文件的工具类PropsUtil(注意:从这一步开始要切换到框架项目上进行):
package org.smart4j.framework.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * desc : 属性文件工具类 * Created by Lon on 2018/1/21. */ public final class PropsUtil { private static final Logger LOGGER = LoggerFactory.getLogger(PropsUtil.class); /** * 加载属性文件 */ public static Properties loadProps(String fileName){ Properties props = null; InputStream is = null; try { is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName); if (is == null){ throw new FileNotFoundException(fileName + "file is not found"); } props = new Properties(); props.load(is); } catch (IOException e){ LOGGER.error("load properties file failure", e); } finally { if (is != null){ try { is.close(); } catch (IOException e){ LOGGER.error("close input stream failure", e); } } } return props; } /** * 获取字符型属性(默认值为空字符串) */ public static String getString(Properties props, String key){ return getString(props, key, ""); } /** * 获取字符型属性(可指定默认值) */ public static String getString(Properties props, String key, String defaultValue){ String value = defaultValue; if (props.containsKey(key)){ value = props.getProperty(key); } return value; } /** * 获取数值型属性(默认为0) */ public static int getInt(Properties props, String key){ return getInt(props, key, 0); } /** * 获取数值型属性(可指定默认值) */ public static int getInt(Properties props, String key, int defaultValue){ int value = defaultValue; if (props.containsKey(key)){ value = CastUtil.castInt(props.getProperty(key)); } return value; } /** * 获取布尔型属性(默认为false) */ public static boolean getBoolean(Properties props, String key){ return getBoolean(props, key, false); } /** * 获取布尔型属性(可指定默认值) */ public static boolean getBoolean(Properties props, String key, boolean defaultValue){ boolean value = defaultValue; if (props.containsKey(key)){ value = CastUtil.castBoolean(props.getProperty(key)); } return value; } }
可以看到PropsUtil依赖了CastUtil这个工具类,这个类也需要我们来写,它的主要功能是类型转换:
package org.smart4j.framework.util; /** * desc : 类型转换工具 * Created by Lon on 2018/1/21. */ public final class CastUtil { /** * 转为String */ public static String castString(Object obj){ return CastUtil.castString(obj, ""); } /** * 转为String(提供默认值) */ public static String castString(Object obj, String defaultValue){ return obj != null ? String.valueOf(obj) : defaultValue; } /** * 转为double */ public static double castDouble(Object obj){ return castDouble(obj, 0); } /** * 转为double(提供默认值) */ public static double castDouble(Object obj, double defaultValue){ double value = defaultValue; if (obj != null){ String strValue = castString(obj); if (StringUtil.isNotEmpty(strValue)){ try { value = Double.parseDouble(strValue); } catch (NumberFormatException e){ value = defaultValue; } } } return value; } /** * 转为long */ public static long castLong(Object obj){ return castLong(obj, 0); } /** * 转为long(提供默认值) */ public static long castLong(Object obj, long defaultValue){ long value = defaultValue; if (obj != null){ String strValue = castString(obj); if (StringUtil.isNotEmpty(strValue)){ try { value = Long.parseLong(strValue); } catch (NumberFormatException e){ value = defaultValue; } } } return value; } /** * 转为int */ public static int castInt(Object obj){ return castInt(obj, 0); } /** * 转为int(提供默认值) */ public static int castInt(Object obj, int defaultValue){ int value = defaultValue; if (obj != null){ String strValue = castString(obj); if (StringUtil.isNotEmpty(strValue)){ try { value = Integer.parseInt(strValue); } catch (NumberFormatException e){ value = defaultValue; } } } return value; } /** * 转为boolean(提供默认值) */ public static boolean castBoolean(Object obj){ return castBoolean(obj, false); } /** * 转为boolean(提供默认值) */ public static boolean castBoolean(Object obj, boolean defaultValue){ boolean value = defaultValue; if (obj != null){ value = Boolean.parseBoolean(castString(obj)); } return value; } }
CastUtil里面又用到了StringUtil,它是我们对commons-lang3中的StringUtils进一步封装:
package org.smart4j.framework.util; import org.apache.commons.lang3.StringUtils; /** * desc : 字符串工具 * Created by Lon on 2018/1/21. */ public class StringUtil { /** * 判断字符串是否为空,这里会先去除字符串两端的空格再作判断 */ public static boolean isEmpty(String str){ if (str != null){ str = str.trim(); } return StringUtils.isEmpty(str); } /** * 判断字符串是否为非空 */ public static boolean isNotEmpty(String str){ return !isEmpty(str); } }
顺便我们再把 commons-collections4的集合工具类也进一步封装(以后会用到的):
package org.smart4j.framework.util; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import java.util.Collection; import java.util.Map; /** * desc : 集合工具类 * Created by Lon on 2018/1/21. */ public final class CollectionUtil { /** * 判断Collection是否为空 */ public static boolean isEmpty(Collection<?> collection){ return CollectionUtils.isEmpty(collection); } /** * 判断Collection是否非空 */ public static boolean isNotEmpty(Collection<?> collection){ return !isEmpty(collection); } /** * 判断Map是否为空 */ public static boolean isEmpty(Map<?, ?> map){ return MapUtils.isEmpty(map); } /** * 判断Map是否非空 */ public static boolean isNotEmpty(Map<?, ?> map){ return !MapUtils.isEmpty(map); } }
到此,我们一口气写了4个工具类,这些类以后还会经常用到。
然后我们再次步入正题:如何读取smart.properties文件中的配置呢,现在需要先写一个ConfigConstant类来维护配置文件中各项配置的名称:
package org.smart4j.framework; /** * desc : 框架配置常量 * Created by Lon on 2018/1/21. */ public interface ConfigConstant { //对应配置文件名称 String CONFIG_FILE = "smart.properties"; //对应数据库连接配置项 String JDBC_DRIVER = "smart.framework.jdbc.driver"; String JDBC_URL = "smart.framework.jdbc.url"; String JDBC_USERNAME = "smart.framework.jdbc.username"; String JDBC_PASSWORD = "smart.framework.jdbc.password"; //分别对应项目基础包名、JSP路径、静态资源基础路径 String APP_BASE_PACKAGE = "smart.framework.app.base_package"; String APP_JSP_PATH = "smart.framework.app.jsp_path"; String APP_ASSET_PATH = "smart.framework.app.asset_path"; }
最后一步就是借助刚才写的PropsUtil工具类来实现ConfigHelper,其实就是通过定义一些静态方法让它有能力获取smart.properties中的配置项:
package org.smart4j.framework.helper; import org.smart4j.framework.ConfigConstant; import org.smart4j.framework.util.PropsUtil; import java.util.Properties; /** * desc : 属性文件助手类 * Created by Lon on 2018/1/21. */ public final class ConfigHelper { private static final Properties CONFIG_PROPS = PropsUtil.loadProps(ConfigConstant.CONFIG_FILE); /** * 获取JDBC驱动 */ public static String getJdbcDriver(){ return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_DRIVER); } /** * 获取JDBC URL */ public static String getJdbcUrl(){ return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_URL); } /** * 获取JDBC用户名 */ public static String getJdbcUsername(){ return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_USERNAME); } /** * 获取JDBC密码 */ public static String getJdbcPassword(){ return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_PASSWORD); } /** * 获取应用的JSP路径 */ public static String getAppJspPath(){ return PropsUtil.getString(CONFIG_PROPS,ConfigConstant.APP_JSP_PATH, "/WEB-INF/view/"); } /** * 获取应用的静态资源路径 */ public static String getAppAssetPath(){ return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_ASSET_PATH, "/asset/"); } }
可以看到 ConfigHelper的最后两个方法设置了它们的默认值,也就是说,如果在配置文件中没有特别指明该配置项的值,那么就会用到它们的默认值。至此,配置方面先讲到这里,毕竟这章已经写得很长了...哈哈,最后附上完成这章内容后的框架项目(图一)和实例项目demo1(图二)的完整目录图,这样就会比较清晰了:
图一: 图二:
总结:
这一章写了4个常用工具类,1个维护常量的类,并且通过依赖它们用ConfigHelper实现了配置文件的读取,下一篇将会写一个类加载器,用来加载基础包名下的所有类(类似于Spring的扫包功能,如扫一个包下含有某个注解的全部类)。