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

一、实现资源过滤

(一)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算法,为了保持原有顺序使用有序Map
		Properties 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)。

时间: 2024-10-15 21:42:20

Maven学习(五):maven的灵活构建的相关文章

Maven学习 五 Maven项目创建(1)jar项目

第一步:Maven项目的创建 File->new->Maven project. 点击下一步 上方的两个多选框选上,第一个是不使用archetype 原型模板,第二个是使用默认工作空间 点击next Group ID : 公司名.公司网址倒写 Artifact ID : 项目名 Version : 版本   0.0.1-SNAPSHOT快照版,也可以写成1.0之类的版本号,作用不是很大,只有在以后搭建私服时候有作用 Packaging: 项目的打包方式,也就是指定项目最终会打成什么包,有jar

Maven学习(1) - Maven入门

home index:http://maven.apache.org/ download:http://maven.apache.org/download.cgi install: http://maven.apache.org/download.cgi#Installation   一.Maven的基本概念 Maven(翻译为"专家","内行")是跨平台的项目管理工具.主要服务于基于Java平台的项目构建,依赖管理和项目信息管理. 1.1.项目构建 项目构建过程包

Maven学习笔记(十一):灵活的构建

典型的项目会有开发环境.测试环境和产品环境,这些环境的数据库配置不尽相同,那么项目构建的时候就需要能够识别所在的环境并使用正确的配置.还有一种情形是,项目开发了大量的集成测试,这些测试运行起来非常耗时,不适合在每次构建项目的时候都运行,因此需要一种手段能让我们在特定的时候才激活这些集成测试.Maven为了支持构建的灵活性,内置了三大特性,即属性.Profile和资源过滤.本章将介绍这些特性. Maven属性 Maven的六类属性: Maven一共有六类属性,分别是: 1.  内置属性:主要有两个

maven学习五 Eclipse下Tomcat常用设置

Eclipse下Tomcat常用设置 1,Eclipse建立Tomcat服务 1.1 新建Server 首先这里是指,jee版的Eclipse.Eclipse是没有像MyEclipse那样集成Tomcat的,需要我们自己设置. New -> Other -> Server ,然后选择Apache下的tomcat的版本. 注意:如果Next或Finish按钮都是灰的,那么需要到Windw- > Preferences -> Server -> Runtime Environme

maven 学习---使用Maven运行单元测试

要通过Maven运行单元测试,发出此命令: mvn test 这会在你的项目中运行整个单元测试. 案例学习 创建两个单元测试,并通过 Maven 的运行它.参见一个简单的 Java 测试类: package com.yiibai.core; public class App { public static void main(String[] args) { System.out.println(getHelloWorld()); } public static String getHelloW

【Maven学习】Maven打包生成普通jar包、可运行jar包、包含所有依赖的jar包

http://blog.csdn.net/u013177446/article/details/54134394 ****************************************************** 使用maven构建工具可以将工程打包生成普通的jar包.可运行的jar包,也可以将所有依赖一起打包生成jar: 一.普通的jar包 普通的jar包只包含工程源码编译出的class文件以及资源文件,而不包含任何依赖:同时还包括pom文件,说明该包的依赖信息: 在工程pom文件下

MAVEN学习(二) maven安装及集成Myeclipse

1.maven下载 : http://maven.apache.org/download.cgi 2.maven本地仓库配置:apache-maven-3.3.9\apache-maven\src\conf\settings.xml 的 <localRepository>属性, 输入本地jar包存放路径 3.打开myeclipse,window-preferences,搜索maven,在Users Settings存入上一步的文件路径

Maven学习——修改Maven的本地仓库路径

本文来自互联网,原文地址:http://aeritheve.iteye.com/blog/1709652 安装Maven后我们会在用户目录下发现.m2 文件夹.默认情况下,该文件夹下放置了Maven本地仓库.m2/repository.所有的Maven构件(artifact)都被存储到该仓库中, 以方便重用.但是windows用户的操作系统都安装在C盘,把Maven仓库放到C盘是很危险的,为此我们需要修改Maven的本地仓库路径. 修改方式如下: 手动创建本地仓库的存放路径,例如:D:\Java

maven学习笔记--maven项目创建

使用Maven命令和Eclipse的Maven插件,创建Maven项目 (1)maven命令生成项目         新建一个文件目录,dos进入该目录并执行下面命令: mvn archetype:create -DgroupId=com.learn -DartifactId=LearnNew -DarchetypeArtifactId=maven-archetype-webapp (2)使用Eclipse生成项目          Elipse中发布一个Maven项目到Tomcat:http:

Maven学习 七 Maven项目创建(2)war项目

一.web项目的目录结构 如果手动创建一个java  web项目,其基本的目录结构包括:METE-INF,WEB-INF,以及WEB-INF下必须包含一个web.xml文件 二.使用Maven创建war项目 (一) 创建maven project时选择packaging为war (二)在webapp文件夹下新建META-INF和WEB-INF/web.xml 刚创建的项目发现会报错,因为此时的项目没有web项目的目录结构,需要创建一些文件夹和文件,形成web的目录结构,在main/webapp下