1 cobertura-maven-plugin maven的测试覆盖率插件集成cobertura-maven-plugin
2 intelli J 配置VM参数

3 配置显示行号

mvn clean install 安装到本地的repo中

超级pom

默认的仓储为maven提供的,其id为central,可以覆盖,也可以用mirror覆盖

5、classifier:帮助定义构建输出的一些附属构件。
     附属构件与主构件对应,如上例中的主构件是pms-indexer-4.2.2.jar,该项目可能还会通过使用一些插件生成如pms-indexer-4.2.2-javadoc.jar,pms-indexer-4.2.2-sources.jar这样一些附属构件,其包含了Java文档和源代码。这时候,javadoc和sources就是这两个附属构件的classifier。
 
介绍了pom.xml文件的五个元素,其中,groupId / artifactId / version 是必须定义的,packaging是可选的(默认为jar),而classifier是不能直接定义的。
 
6 mvn 生命周期与插件的关系,
 
生命周期基本是固定的有init-->compile-->test-->package-->integrationTest-->deply
mvn只是定义了声明周期,其内部是和插件绑定的,如编译由maven-compiler-plugin完成,测试由maven-surefire-plugin完成。
需要时,可以将plugin绑定到某个生命周期上。
 

一、Maven的生命周期

Maven的生命周期就是对所有的构建过程进行抽象和统一。包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有的构建步骤。

Maven的生命周期是抽象的,即生命周期不做任何实际的工作,实际任务由插件完成,类似于设计模式中的模板方法。

二、三套生命周期

Maven有三套相互独立的生命周期,分别是clean、default和site。每个生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。

1、clean生命周期:清理项目,包含三个phase。

1)pre-clean:执行清理前需要完成的工作

2)clean:清理上一次构建生成的文件

3)post-clean:执行清理后需要完成的工作

2、default生命周期:构建项目,重要的phase如下。

1)validate:验证工程是否正确,所有需要的资源是否可用。
2)compile:编译项目的源代码。  
3)test:使用合适的单元测试框架来测试已编译的源代码。这些测试不需要已打包和布署。
4)Package:把已编译的代码打包成可发布的格式,比如jar。
5)integration-test:如有需要,将包处理和发布到一个能够进行集成测试的环境。
6)verify:运行所有检查,验证包是否有效且达到质量标准。
7)install:把包安装到maven本地仓库,可以被其他工程作为依赖来使用。
8)Deploy:在集成或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。

3、site生命周期:建立和发布项目站点,phase如下

1)pre-site:生成项目站点之前需要完成的工作

2)site:生成项目站点文档

3)post-site:生成项目站点之后需要完成的工作

4)site-deploy:将项目站点发布到服务器

三、命令行和生命周期

各个生命周期相互独立,一个生命周期的阶段前后依赖。

举例如下:

1、mvn clean

调用clean生命周期的clean阶段,实际执行pre-clean和clean阶段

2、mvn test

调用default生命周期的test阶段,实际执行test以及之前所有阶段

3、mvn clean install

调用clean生命周期的clean阶段和default的install阶段,实际执行pre-clean和clean,install以及之前所有阶段

mvn clean,删除target目录构建的东西,

mvn package 打包,如jar包,放在target目录下,

mvn install  将包安装到本地repo

mvn deploy 将包push到远程repo

maven 插件和目标(plugins  and  goals)

插件和目标(plugins and  goals )的大小关系:

一个maven插件是由一个或者多个目标集合组成的。
 
一个目标是一个明确的任务,它可以作为单独的目标运行,或者作为一个大的构建的一部分和其它目标一起运行。一个目标是Maven中的一个“工作单元(unit of work)”。目标的例子包括Compiler插件中的compile目标,它用来编译项目中的所有源文件,或者Surefire插件中的test目标,用来运行单元测试。
 
 
 
注意:
当提到一个插件目标的时候,我们常常用速记符号:pluginId:goalId。例如,当提到Archetype插件的create目标的时候,我们写成archetype:create。
 
archetype 是插件
create 是目标
 
 
 
 
pom.xml中module标签中指的是聚合,parent标签以及dependencyManagment/pluginManagment指的是继承
 
1.继承
(1)标签:<parent>
(2)举例
  1. <parent>
  2. <groupId>com.tiantian.mavenTest</groupId>
  3. <artifactId>projectA</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. </parent>
2. 聚合
(1)标签:<modules>
(2)举例
  1. <modules>
  2. <module>../projectB</module>
  3. </modules>

在使用mvn package进行编译、打包时,Maven会执行src/test/java中的JUnit测试用例,有时为了跳过测试,会使用参数-DskipTests和-Dmaven.test.skip=true,这两个参数的主要区别是:

-DskipTests,不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下。

-Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类。

mvn test -Dtest=ATest, BTest,CTest , 只执行ATest, BTest, CTest, 不执行其他测试用例。

 

背景

项目构建的时候,需要根据不同的场景来改变项目中的属性资源,最为常见的莫过于数据库连接配置了,试想有生产环境、测试缓存、发布环境等,需要为不同的场景下来动态的改变数据库的连接配置。而使用maven就可以帮我们解决这些问题。下面就来分享一下maven中的profile和filtering的属性。

为了便于测试一下功能,需要搭建maven的web项目,具体配置请详见如何用maven创建web项目

filtering功能

 

主要用来替换项目中的资源文件(*.xml、*.properties)当中的${...},比如${db.url},那么如果配置了db.url=aaa的话,在项目编译的时候,就会自动的把${db.url}替换为aaa,下面以实例来讲解一下

采取参照博客中创建完maven的web项目后,会看到src/main/sources的目录,在此目录下面创建个“test.properties”,里面随便来上一行,例如Hello ${user.name},好了,接下来修改我们的pom文件,来启动filtering功能

  1. <span style="font-family:Comic Sans MS;font-size:18px;"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>testwebProject</groupId>
  5. <artifactId>com.test.web.test</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>war</packaging>
  8. <build>
  9. <!--第一种方式,两种方式都需要指定需要编译的目录 -->
  10. <resources>
  11. <resource>
  12. <directory>src/main/resources</directory>
  13. <!--可以在此配置过滤文件  -->
  14. <includes>
  15. <include>**/*.xsd</include>
  16. <include>**/*.properties</include>
  17. </includes>
  18. <!--开启filtering功能  -->
  19. <filtering>true</filtering>
  20. </resource>
  21. </resources>
  22. <plugins>
  23. <plugin>
  24. <artifactId>maven-war-plugin</artifactId>
  25. <configuration>
  26. <version>2.5</version>
  27. </configuration>
  28. </plugin>
  29. </plugins>
  30. </build>
  31. </project></span>

然后编译我们的maven项目

$mvn clean compile -Duser.name=tom

编译完后,查看输出文件 target/classes/test.properties 的内容,可见原先的 “Hello {user.name}” 已经变成 “Hello Tom”。

 

上面如果麻烦的话,也可以把filtering用到的变量写在项目得属性段里面,如下面的方式

 

  1. <span style="font-family:Comic Sans MS;font-size:18px;"><!--也可以配置到外部属性里面 -->
  2. <properties>
  3. <user.name>Lucky</user.name>
  4. <user.age>50</user.age>
  5. </properties></span>

进行编译,$mvn clean compile,在此查看的话,就会看到属性被替换的效果

当然了,如果属性比较多的话,那么此时可以把属性单独抽取出来一个*.properties文件来保存,例如我们在pom.xml的同级目录下面创建一个project.properties,里面指明我们的内容

user.name=Lucky

紧接着在修改我们的pom文件,如下

  1. <span style="font-family:Comic Sans MS;font-size:18px;"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>testwebProject</groupId>
  5. <artifactId>com.test.web.test</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>war</packaging>
  8. <build>
  9. <!--第一种方式,两种方式都需要指定需要编译的目录 -->
  10. <resources>
  11. <resource>
  12. <directory>src/main/resources</directory>
  13. <!--可以在此配置过滤文件 -->
  14. <includes>
  15. <include>**/*.xsd</include>
  16. <include>**/*.properties</include>
  17. </includes>
  18. <!--开启filtering功能 -->
  19. <filtering>true</filtering>
  20. </resource>
  21. </resources>
  22. <filters>
  23. <!-- 是以该pom文件路径作为参考 -->
  24. <filter>project.properties</filter>
  25. </filters>
  26. <plugins>
  27. <plugin>
  28. <artifactId>maven-war-plugin</artifactId>
  29. <configuration>
  30. <version>2.5</version>
  31. </configuration>
  32. </plugin>
  33. </plugins>
  34. </build>
  35. </project></span>

再次执行编译命令的话,就会看到效果

profile功能

允许在项目文件(pom.xml)里面定义若干个profile段,然后在编译时选择其中的一个用于覆盖项目文件原先的定义。接着上一个例子,如果我们需要为开发环境和生产环境定义不同的 user.name 属性值,则我们在项目目录里创建两个属性文件分别是pre.properties和dev.properties,然后再每个文件里分别写入user.name=lucky和user.name=wangwang,然后在此修改我们的pom文件,修改后如下所示

  1. <span style="font-family:Comic Sans MS;font-size:18px;"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>testwebProject</groupId>
  5. <artifactId>com.test.web.test</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>war</packaging>
  8. <build>
  9. <!--第一种方式,两种方式都需要指定需要编译的目录 -->
  10. <resources>
  11. <resource>
  12. <directory>src/main/resources</directory>
  13. <!--可以在此配置过滤文件 -->
  14. <includes>
  15. <include>**/*.xsd</include>
  16. <include>**/*.properties</include>
  17. </includes>
  18. <!--开启filtering功能 -->
  19. <filtering>true</filtering>
  20. </resource>
  21. </resources>
  22. <profiles>
  23. <profile>
  24. <id>dev</id>
  25. <activation>
  26. <!--默认的编译选项  -->
  27. <activeByDefault>true</activeByDefault>
  28. </activation>
  29. <build>
  30. <filters>
  31. <filter>pre.properties</filter>
  32. </filters>
  33. </build>
  34. </profile>
  35. <profile>
  36. <id>pre</id>
  37. <build>
  38. <filters>
  39. <filter>dev.properties</filter>
  40. </filters>
  41. </build>
  42. </profile>
  43. </profiles>
  44. <plugins>
  45. <plugin>
  46. <artifactId>maven-war-plugin</artifactId>
  47. <configuration>
  48. <version>2.5</version>
  49. </configuration>
  50. </plugin>
  51. </plugins>
  52. </build>
  53. </project></span>

在编译项目时,可以使用 -P 参数指定需要使用的 profile 的 id,比如下面命令将会使用 dev profile

$mvn clean compile -Pdev

如果想使用pre,只需要改为以下即可

$mvn clean compile -Ppre

假如不指定 -P 参数的话,则会使用 activeByDefault=true 的一项(即 pre)。

spring bean 注解分为两类:

1、一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

2、一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

 

 jar -tvf ABC-1.0.0-SNAPSHOT.jar  查看jar包的内容

tar -zvf ABC.jar 可以直接解压

首先,来看下MAVENx项目标准的目录结构:

一般情况下,我们用到的资源文件(各种xml,properites,xsd文件等)都放在src/main/resources下面,利用maven打包时,maven能把这些资源文件打包到相应的jar或者war里。

  • src/main/resources,负责管理项目主体的资源。在使用Maven2执行compile之后,这个目录中的所有文件及子目录,会复制到target/classes目录中,为以后的打包提供了方便。
  • src/test/resources,负责管理项目测试的资源。在使用Maven2执行test-compile之后,这个目录中的所有文件及子目录,会复制到target/test-classes目录中,为后续的测试做好了准备。

流程: resouce路径copy到target/class中,然后打包,将resource总的文件打入到jar包中。

所有resource目录下的东西都会打入到jar包中,供jar包使用,这样jar可以读取到配置文件了。

ABC.jar 包含完整的class文件、配置文件、资源文件以及相关的依赖库(在lib目录中)。

ABC-source.jar 中包含的是源文(java文件),配置文件,资源文件,不包含依赖库。

logback 配置:

    1. 设置loger
      用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<loger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。
      name:用来指定受此loger约束的某一个包或者具体的某一个类。
      level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。
      addtivity:是否向上级loger传递打印信息。默认是true。

      <loger>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger。

    2. 设置root
      也是<loger>元素,但是它是根loger。只有一个level属性,应为已经被命名为"root".
      level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。默认是DEBUG。

      <root>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger。

 
root logger是所有logger的parent。
对于某一个logger来说,name可以控制包或者类,一个logger可以添加多个appender
 
 
 

http://www.cnblogs.com/panxuejun/p/5847774.html

可以理解成tomcat和spring本身是解耦的,spring实现了一套自己的servelet,从而简化了web编程。

spring在从web.xml 中启动,注册了一大推bean,并 通过component-scan来扫描java程序的bean,从而实现注入(auto-wire,resource等。)

大牛请绕过,此文仅针对自己小白水平,对web程序的启动流程做个清晰的回顾。

一.使用spring等框架的web程序在Tomcat下的启动流程

1)Tomcat是根据web.xml来启动的。首先到web.xml

2)web.xml中负责启动spring和spring mvc。对应的启动配置文件分别是

启动spring mvc,并进行所有资源路径映射

<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/cfg/springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

启动spring,通过ContextLoaderListener

1
2
3
4
5
6
7
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/cfg/spring.xml</param-value>
</context-param>

3)spring中对一些orm框架的启动,包括Mybatis/hibernate。orm框架的启动基本都是通过sqlsessionFactory bean来启动的。

并配置各种bean到ioc容器中。包括datasource等。

4)web应用程序中,spring相当于程序运行的平台,spring对整个程序提高供ioc支持和aop支持。

spring提供注解如@service @repository @component将各种类注册到ioc容器中。通过设置scan package的方式,spring在启动时候会扫描包下的所有注解,并将它们注册到ioc容器中。并针对@autowired @resource,将一些bean从ioc容器中获取填充到bean的构造属性中。

spring会自动扫描如下包中的注解:

<context:component-scan base-package=”pagkage1[,pagkage2,…,pagkageN]”/>

以上可以看出spring所有的bean注入都是在spring.xml中配置的,所有的bean注入都在spring.xml中配置的。

@autowired @resource只针对于类的成员变量,不针对方法里的局部变量。

注:正是spring的ioc支持了controller层注入service,service注入dao。打通了各层之间的桥梁,省去了原来的new service(),new Dao()的方法。

问答

1.使用spring ioc有什么好处?

答:网上有很多介绍使用Spring IOC容器的好处的文章,我看到的主要有两点, 
1.方便测试,当需要测试的类依赖其他的类时,可以为依赖的类做个mock,然后注入进来。 
2.方便维护及升级,当某个类需要修改实现时,只要接口没变,则无需修改源代码,重写一个实现类,修改下配置即可。

3.默认下,IOC容器管理的bean都是单例的,不会被gc掉。

4.spring提倡面向接口开发,因此在servcie里面的dao直接是接口就可以了。这样有助于解耦。(测试等等)。。

如果不用spring,要么自己new daoimpl,就面向具体了,如果还想抽象,就必须自己写工厂——其实spring就是一个工厂IOC。实现类似的作用。

其实,面向抽象是实现和接口分离,对于多数的项目,实现大量变化的机会不是很大,因此直接面向具体(省略掉dao接口等)是我个人推荐的做法。

spring工厂对其中的对象的生命周期,作用范围都有很明确的定义,很容易使用,如果自己做这么一套,只怕没这么好。

第三,spring对ioc管理的对象,可以做很多增强,比如aop,代理等等。

5.感觉AOP最有用了。

2.spring是怎样支持面向接口编程的?

由于依赖于接口,可以通过依赖注入随时替换DAO接口的实现类,而应用程序完全不用了解接口与底层数据库操作细节。

应用程序----调用-----》DAO接口《---实现--DAO接口实现类----操作------》数据库

 

java 学习总结的更多相关文章

  1. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  2. 0035 Java学习笔记-注解

    什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...

  3. 分享篇——我的Java学习路线

    虽然之前我是开发出身,但是我学习的语言是Objective-c,这个语言使用起来范围比较窄,对于自动化学习来说也是无用武之地,所以我自己学习了Java,对于一个有开发经验的人来说学习一门新语言相对来说 ...

  4. Java学习笔记(04)

    Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...

  5. Java学习心得之 HttpClient的GET和POST请求

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Java学习心得之 HttpClient的GET和POST请求 1. 前言2. GET请求3 ...

  6. 0032 Java学习笔记-类加载机制-初步

    JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...

  7. 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用

    垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...

  8. 0028 Java学习笔记-面向对象-Lambda表达式

    匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...

  9. 0025 Java学习笔记-面向对象-final修饰符、不可变类

    final关键字可以用于何处 修饰类:该类不可被继承 修饰变量:该变量一经初始化就不能被重新赋值,即使该值跟初始化的值相同或者指向同一个对象,也不可以 类变量: 实例变量: 形参: 注意可以修饰形参 ...

  10. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

随机推荐

  1. NetworkManager概述

    NetworkManager服务是管理和监控网络设置的守护进程,CentOS7更加注重使用NetworkManager服务来实现网络的配置和管理,CentOS7以前是通过network服务管理网络,以 ...

  2. 【数据结构】 最小生成树(四)——利用kruskal算法搞定例题×3+变形+一道大水题

    在这一专辑(最小生成树)中的上一期讲到了prim算法,但是prim算法比较难懂,为了避免看不懂,就先用kruskal算法写题吧,下面将会将三道例题,加一道变形,以及一道大水题,水到不用高级数据结构,建 ...

  3. BZOJ 3343:教主的魔法(分块)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3343 [题目大意] 给出一个数列,有区间加法操作,询问区间大于等于c的数字个数 [题解 ...

  4. [AGC019E]Shuffle and Swap

    [AGC019E]Shuffle and Swap 题目大意: 给出两个长度为\(n(n\le10000)\)的\(01\)串\(A_{1\sim n}\)和\(B_{1\sim n}\).两个串均有 ...

  5. Perl读写文件&字符串操作

    Perl中读写文件的方法非常简单,可以使用open或sysopen函数来打开文件,linux下运行perl脚本只需 ./XX.pl 或 perl XX.pl. 读文件 open(文件句柄, " ...

  6. Problem B: 零起点学算法81——找出数组中最大元素的位置(下标值

    #include<stdio.h> int main(void) { ],i,max; while(scanf("%d",&n)!=EOF) { ;i<n ...

  7. 【OpenJudge9277】【递推】Logs Stacking堆木头

    Logs Stacking堆木头 总时间限制: 1000ms 内存限制: 131072kB [描述] Daxinganling produces a lot of timber. Before loa ...

  8. Hiho : 二分·二分查找之k小数

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很多船位,但船位再多也是有限的.Nettl ...

  9. UITabBarController 详解

    // UITabBarController 标签视图控制 // 主要管理没有层级关系的视图控制器 // 1. ViewControllers 所有被管理的视图控制器, 都在这个数组中 // 2. se ...

  10. [转]SSIS数据转换组件_派生列、审核、字符映射转换和条件性拆分转换

    本文转自:http://www.cnblogs.com/gudujianxiao/archive/2012/04/14/2446925.html 一 派生列 派生列转换通过对输入列进行类型转换或应用表 ...