Maven学习(五):maven的灵活构建

来源:互联网 发布:优畅网络是真的吗 编辑:程序博客网 时间:2024/06/07 12:40

一、实现资源过滤

(一)maven-resources-plugin 插件

1、Maven 区别对待Java代码文件和资源文件,maven-compiler-plugin用来编译Java代码,maven-resources-plugin则用来处理资源文件。默认的主资源文件目录是 src/main/resources。

2、很多用户会需要添加额外的资源文件目录,这个时候就可以通过配置maven-resources-plugin来实现。实现资源的过滤只需要添加 <filtering>true</filtering> 标签。

<!-- 资源过滤过滤 src/main/resources --><resources><resource><directory>src/main/resources</directory><filtering>true</filtering></resource><resource><directory>config</directory></resource></resources>

(二)资源过滤

1、两个资源文件夹:src/main/resources 和 config 。定义了同样的数据库配置。



jdbc.driverClassName = ${db.driver}jdbc.url = ${db.url}jdbc.username = ${db.username}jdbc.password = ${db.password}

2、定义资源文件及制定需要过滤的资源文件。(在<build> 标签)

<!-- 资源过滤过滤 src/main/resources --><resources><resource><directory>src/main/resources</directory><filtering>true</filtering></resource><resource><directory>config</directory></resource></resources>

两个文件都被指定为资源文件,并且对src/main/resources 下文件是实现过滤。


3、利用 <profiles> 定义灵活构建的属性。

<!-- 定义灵活构建的属性 --><profiles><!-- DEV开发环境属性 --><profile><id>DEV</id><properties><db.driver>com.mysql.jdbc.Driver</db.driver><db.url>jdbc:mysql://localhost:3306/dev_oa_0303</db.url><db.username>dev-name</db.username><db.password>dev-password</db.password></properties><!-- 激活方式:    1、命令行:mvn clean install -PDEV,UAT     2、setting中配置: <activeProfiles><activeProfile>dev</activeProfile></activeProfiles> 3、存在属性激活:<activation><property><name>a</name></property></activation>存在属性a 4、存在属性值:<activation><property><name>test</name><value>1</value></property></activation> 存在属性test=1,即激活。可以命令行:mvn clean install -Dtest=1; 5、默认激活:<activeByDefault>true</activeByDefault>. --><activation><activeByDefault>true</activeByDefault></activation></profile><!--UAT测试环境属性 --><profile><id>UAT</id><properties><db.driver>com.mysql.jdbc.Driver</db.driver><db.url>jdbc:mysql://localhost:3306/uat_oa_0505</db.url><db.username>uat-name</db.username><db.password>uat-password</db.password></properties></profile></profiles>

1)一个 profile 代表一个动态项,使用不同的Id 区分。这个Id 作为 -P 的参数使用。

2)使用properties 标签定义属性,这边属性的标签名需要与配置文件中${key}一致。

3)激活方式:

①、命令行激活:mvn clean install -PDEV,UAT 

②、setting中配置激活: 使用<activeProfiles><activeProfile>dev</activeProfile></activeProfiles>标签。 

③、存在属性激活:<activation><property><name>a</name></property></activation>存在属性激活

④、存在属性值:<activation><property><name>test</name><value>1</value></property></activation> ,存在属性test=1,即激活。可以在命令行:mvn clean install -Dtest=1; 

⑤、默认激活:<activeByDefault>true</activeByDefault>


4、动态构建: 运行时输入 clean install ,使用默认激活的 profile 配置。

1)两个文件都被作为配置文件处理。


2)其中 jdbc.properties 中的属性引用被动态替换了。并且是被默认的 id = DEV 的profile 替换。



5、运行时输入 clean install -PUAT,激活使用 id=UAT 的profile 配置。




二、创建web项目

1、Maven学习 (三) 使用m2eclipse创建web项目


三、一个成功的灵活构建项目实例

(一)简介

1、三类配置文件:都放在src/main/resources 下

1)配置文件总类:

application-file.properties,定义了需要的配置文件,其中A、B为通用的配置,而C则动态构建。



2)新建local 和 product两个环境的私有配置文件:application.local.properties 和 application.product.properties

3)所有的配置文件如下:



2、pom配置:

1)profiles 动态构建如下:默认激活 dev 。

<profiles><profile><id>dev</id><properties><dev.mode>true</dev.mode><env.prop.application.file>application.local.properties        </env.prop.application.file></properties><activation><activeByDefault>true</activeByDefault></activation></profile><profile><id>product</id><properties><dev.mode>true</dev.mode><env.prop.application.file>application.product.properties        </env.prop.application.file></properties></profile></profiles>

2)对资源文件进行过滤

<!-- 资源过滤过滤 src/main/resources --><resources><resource><directory>${basedir}/src/main/resources</directory><filtering>true</filtering></resource></resources>


3)配置Tomcat 插件。

<!-- tomcat的插件 --><plugin><groupId>org.codehaus.mojo</groupId><artifactId>tomcat-maven-plugin</artifactId><version>1.1</version><configuration><path>/${project.build.target.file.name}</path></configuration></plugin>

4)如运行命令:clean install -Pproduct ,那么会动态替换application-file.properties 配置文件中的各环境的私有配置。如:



(二)配置文件读取类

1、需要定义一个配置文件的读取类,业务需求为,先读取application-file.properties ,然后按照顺序,依次读取其中配置的三个配置文件。这样配合Maven的动态构建,就实现了不同环境读取不同的配置文件。

2、默认的 Properties 类时无序的,我们需要实现一个有序的Properties 类。

package util;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Properties;import java.util.Set;import org.apache.commons.lang3.ArrayUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.io.DefaultResourceLoader;import org.springframework.core.io.Resource;import org.springframework.core.io.ResourceLoader;import org.springframework.util.DefaultPropertiesPersister;import org.springframework.util.PropertiesPersister;/** * 系统属性工具类 * PropertyUtil * @title * @desc * @author SAM-SHO * @Jan 15, 2015 */public class PropertyUtil {private static Logger logger = LoggerFactory.getLogger(PropertyUtil.class);private static Properties properties;private static PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();private static ResourceLoader resourceLoader = new DefaultResourceLoader();private static final String DEFAULT_ENCODING = "UTF-8";/** * 初始化读取配置文件,读取的文件列表位于classpath下面的application-files.properties *  *  * 多个配置文件会用最后面的覆盖相同属性值 *  * @throws IOException *             读取属性文件时 */public static void init() throws IOException {String fileNames = "application-file.properties";innerInit(fileNames);}/** * 初始化读取配置文件,读取的文件列表位于classpath下面的application-[type]-files.properties *  *  * 多个配置文件会用最后面的覆盖相同属性值 *  * @param type *            配置文件类型,application-[type]-files.properties *  * @throws IOException *             读取属性文件时 */public static void init(String type) throws IOException {String fileNames = "application-" + type + "-files.properties";innerInit(fileNames);}/** * 内部处理 *  * @param fileNames * @throws IOException */private static void innerInit(String fileNames) throws IOException {ClassLoader loader = Thread.currentThread().getContextClassLoader();InputStream resourceAsStream = loader.getResourceAsStream(fileNames);// 默认的Properties实现使用HashMap算法,为了保持原有顺序使用有序MapProperties files = new LinkedProperties();files.load(resourceAsStream);Set<Object> fileKeySet = files.keySet();String[] propFiles = new String[fileKeySet.size()];List<Object> fileList = new ArrayList<Object>();fileList.addAll(files.keySet());for (int i = 0; i < propFiles.length; i++) {String fileKey = fileList.get(i).toString();propFiles[i] = files.getProperty(fileKey);}logger.debug("读取属性文件:{}", ArrayUtils.toString(propFiles));;properties = loadProperties(propFiles);Set<Object> keySet = properties.keySet();for (Object key : keySet) {logger.debug("property: {}, value: {}", key, properties.getProperty(key.toString()));}}/** * 载入多个properties文件, 相同的属性在最后载入的文件中的值将会覆盖之前的载入. 文件路径使用Spring Resource格式, * 文件编码使用UTF-8. *  * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer */public static Properties loadProperties(String... resourcesPaths) throws IOException {Properties props = new Properties();for (String location : resourcesPaths) {logger.debug("Loading properties file from:" + location);InputStream is = null;try {Resource resource = resourceLoader.getResource(location);is = resource.getInputStream();propertiesPersister.load(props, new InputStreamReader(is, DEFAULT_ENCODING));} catch (IOException ex) {logger.info("Could not load properties from classpath:" + location + ": " + ex.getMessage());} finally {if (is != null) {is.close();}}}return props;}/** * 获取键值对Map *  * @return */public static Map<String, String> getKeyValueMap() {Set<String> keys = getKeys();Map<String, String> values = new HashMap<String, String>();for (String key : keys) {values.put(key, get(key));}return values;}/** * 获取所有的key *  * @return */public static Set<String> getKeys() {return properties.stringPropertyNames();}/** * 获取属性值 *  * @param key *            键 * @return 值 */public static String get(String key) {String propertyValue = properties.getProperty(key);logger.debug("获取属性:{},值:{}", key, propertyValue);return propertyValue;}public static void main(String[] args) {try {PropertyUtil.init();} catch (IOException e) {e.printStackTrace();}}}

package util;import java.io.PrintStream;import java.io.PrintWriter;import java.util.Collection;import java.util.Collections;import java.util.Enumeration;import java.util.LinkedHashMap;import java.util.Map;import java.util.Properties;import java.util.Set;/** * 有序Properties */public class LinkedProperties extends Properties {    private static final long serialVersionUID = 1L;    private Map<Object, Object> linkMap = new LinkedHashMap<Object, Object>();    public void clear() {        linkMap.clear();    }    public boolean contains(Object value) {        return linkMap.containsValue(value);    }    public boolean containsKey(Object key) {        return linkMap.containsKey(key);    }    public boolean containsValue(Object value) {        return linkMap.containsValue(value);    }    public Enumeration elements() {        throw new RuntimeException("Method elements is not supported in LinkedProperties class");    }    public Set entrySet() {        return linkMap.entrySet();    }    public boolean equals(Object o) {        return linkMap.equals(o);    }    public Object get(Object key) {        return linkMap.get(key);    }    public String getProperty(String key) {        Object oval = get(key); //here the class Properties uses super.get()        if (oval == null) return null;        return (oval instanceof String) ? (String) oval : null; //behavior of standard properties    }    public boolean isEmpty() {        return linkMap.isEmpty();    }    public Enumeration keys() {        Set keys = linkMap.keySet();        return Collections.enumeration(keys);    }    public Set keySet() {        return linkMap.keySet();    }    public void list(PrintStream out) {        this.list(new PrintWriter(out, true));    }    public void list(PrintWriter out) {        out.println("-- listing properties --");        for (Map.Entry e : (Set<Map.Entry>) this.entrySet()) {            String key = (String) e.getKey();            String val = (String) e.getValue();            if (val.length() > 40) {                val = val.substring(0, 37) + "...";            }            out.println(key + "=" + val);        }    }    public Object put(Object key, Object value) {        return linkMap.put(key, value);    }    public int size() {        return linkMap.size();    }    public Collection values() {        return linkMap.values();    }}


(三)项目启动时,读取配置的Servlet。

1、PropertiesServlet 的代码如下:

package servlet;import java.io.IOException;import java.util.Set; import javax.servlet.Servlet;import javax.servlet.ServletConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import util.PropertyUtil; /** * classpath下面的属性配置文件读取初始化类 * PropertiesServlet * @title * @desc * @author SAM-SHO * @Jan 15, 2015 */public class PropertiesServlet extends HttpServlet {     private static final long serialVersionUID = 1L;     protected Logger logger = LoggerFactory.getLogger(getClass());     /**     * @see Servlet#init(ServletConfig)     */    public void init(ServletConfig config) throws ServletException {        try {            PropertyUtil.init();            ServletContext servletContext = config.getServletContext();            setParameterToServerContext(servletContext);;            logger.info("++++ 初始化[classpath下面的属性配置文件]完成 ++++");        } catch (IOException e) {            logger.error("初始化classpath下的属性文件失败", e);        }    }     @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        doPost(req, resp);    }     @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        String action = StringUtils.defaultString(req.getParameter("action"));        resp.setContentType("text/plain;charset=UTF-8");        if ("reload".equals(action)) { // 重载            try {                PropertyUtil.init();                setParameterToServerContext(req.getSession().getServletContext());                logger.info("++++ 重新初始化[classpath下面的属性配置文件]完成 ++++,{IP={}}", req.getRemoteAddr());                resp.getWriter().print("<b>属性文件重载成功!</b>");//                writeProperties(resp);            } catch (IOException e) {                logger.error("重新初始化classpath下的属性文件失败", e);            }        } else if ("getprop".equals(action)) { // 获取属性            String key = StringUtils.defaultString(req.getParameter("key"));            resp.getWriter().print(key + "=" + PropertyUtil.get(key));        } else if ("list".equals(action)) { // 获取属性列表//            writeProperties(resp);        }    }     private void setParameterToServerContext(ServletContext servletContext) {        servletContext.setAttribute("prop", PropertyUtil.getKeyValueMap());    } }

2、PropertiesServlet 配置:

<!-- 配置文件 --><servlet><servlet-name>PropertiesServlet</servlet-name><servlet-class>servlet.PropertiesServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>PropertiesServlet</servlet-name><url-pattern>/servlet/properties</url-pattern></servlet-mapping>


(四)启动项目,使用tomcat-maven-plugin插件

1、启动方式:tomcat:run 和 tomcat:run -Dmaven.tomcat.port=8880(指定端口)

2、项目启动:

1)tomcat:run 默认运行dev环境的配置。





2)tomcat:run -Pproduct ,指定移动 product 的profile(运行product 的环境)。(这边的-P,即指的就是profile)。





0 0
原创粉丝点击