MyBatis《2》
1.properties 属性
mysql.driver = com.mysql.jdbc.Driver
mysql.url = jdbc:mysql://localhost:3306/test
mysql.username = root
mysql.password = lizhiwei
oracle.driver=oracle.jdbc.driver.OracleDriver
oracle.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
oracle.username=
oracle.password=
<properties resource="config.properties">
<property name="property_0" value="value_1" />
<property name="property_2" value="value_2" />
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}" />
<property name="url" value="${mysql.url}" />
<property name="username" value="${mysql.username}" />
<property name="password" value="${mysql.password}" />
</dataSource>
</environment>
</environments>
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);
- 在 properties元素体内指定的属性首先被读取。
- 然后根据properties元素中的resource属性读取类路径下属性文件或根据url属性指定的路径读取属性文件,并覆盖已读取的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。
2.settings 设置
设置参数 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 | true | false | false |
aggressiveLazyLoading | 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 | true | false | true |
multipleResultSetsEnabled | 是否允许单一语句返回多结果集(需要兼容驱动)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | Any positive integer | Not Set (null) |
defaultFetchSize | Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting. | Any positive integer | Not Set (null) |
safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。 | true | false | False |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成的默认语言。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 | true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | Any String | Not set |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 or above) |
vfsImpl | Specifies VFS implementations | Fully qualified class names of custom VFS implementation separated by commas. | Not set |
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25" />
<setting name="defaultFetchSize" value="100" />
<setting name="safeRowBoundsEnabled" value="false" />
<setting name="mapUnderscoreToCamelCase" value="false" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="OTHER" />
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
</settings>
3.typeAliases 类型命名
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author" />
<typeAlias alias="Blog" type="domain.blog.Blog" />
<typeAlias alias="Comment" type="domain.blog.Comment" />
<typeAlias alias="Section" type="domain.blog.Section" />
</typeAliases>
<typeAliases>
<package name="domain.blog" />
</typeAliases>
@Alias("author")
public class Author {
...
}
别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator
4.typeHandlers 类型处理器
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
BooleanTypeHandler | java.lang.Boolean, boolean | 数据库兼容的 BOOLEAN |
ByteTypeHandler | java.lang.Byte, byte | 数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler | java.lang.Short, short | 数据库兼容的 NUMERIC 或 SHORT INTEGER |
IntegerTypeHandler | java.lang.Integer, int | 数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler | java.lang.Long, long | 数据库兼容的 NUMERIC 或 LONG INTEGER |
FloatTypeHandler | java.lang.Float, float | 数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler | java.lang.Double, double | 数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler | java.lang.String | CHAR, VARCHAR |
ClobTypeHandler | java.lang.String | CLOB, LONGVARCHAR |
NStringTypeHandler | java.lang.String | NVARCHAR, NCHAR |
NClobTypeHandler | java.lang.String | NCLOB |
ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB, LONGVARBINARY |
DateTypeHandler | java.util.Date | TIMESTAMP |
DateOnlyTypeHandler | java.util.Date | DATE |
TimeOnlyTypeHandler | java.util.Date | TIME |
SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
SqlDateTypeHandler | java.sql.Date | DATE |
SqlTimeTypeHandler | java.sql.Time | TIME |
ObjectTypeHandler | Any | OTHER 或未指定类型 |
EnumTypeHandler | Enumeration Type | VARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引) |
EnumOrdinalTypeHandler | Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称)。 |
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ExampleTypeHandler extends BaseTypeHandler<String>
{
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException
{
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException
{
return rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException
{
return rs.getString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException
{
return cs.getString(columnIndex);
}
}
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler" />
</typeHandlers>
<typeHandlers>
<package name="org.mybatis.example" />
</typeHandlers>
- 在类型处理器的配置元素(typeHandler element)上增加一个 javaType 属性(比如:javaType="String")
- 在类型处理器的类上(TypeHandler class)增加一个 @MappedTypes 注解来指定与其关联的 Java 类型列表。 如果在 javaType 属性中也同时指定,则注解方式将被忽略。
- 在类型处理器的配置元素上增加一个 javaType 属性(比如:javaType="VARCHAR")
- 在类型处理器的类上(TypeHandler class)增加一个 @MappedJdbcTypes 注解来指定与其关联的 JDBC 类型列表。 如果在 javaType 属性中也同时指定,则注解方式将被忽略。
public class GenericTypeHandler<E extends MyObject> extends BaseTypeHandler<E> {
private Class<E> type;
public GenericTypeHandler(Class<E> type) {
if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
this.type = type;
}
...
<!-- mybatis-config.xml -->
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode" />
</typeHandlers>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.apache.ibatis.submitted.rounding.Mapper">
<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="funkyNumber" property="funkyNumber"/>
<result column="roundingMode" property="roundingMode"/>
</resultMap>
<select id="getUser" resultMap="usermap">
select * from users
</select>
<insert id="insert">
insert into users (id, name, funkyNumber, roundingMode) values (
#{id}, #{name}, #{funkyNumber}, #{roundingMode}
)
</insert>
<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="funkyNumber" property="funkyNumber"/>
<result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
</resultMap>
<select id="getUser2" resultMap="usermap2">
select * from users2
</select>
<insert id="insert2">
insert into users2 (id, name, funkyNumber, roundingMode) values (
#{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
)
</insert>
</mapper>
6.objectFactory 对象工厂
// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory
{
public Object create(Class type)
{
return super.create(type);
}
public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs)
{
return super.create(type, constructorArgTypes, constructorArgs);
}
public void setProperties(Properties properties)
{
super.setProperties(properties);
}
public <T> boolean isCollection(Class<T> type)
{
return Collection.class.isAssignableFrom(type);
}
}
<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
<property name="someProperty" value="100"/>
</objectFactory>
7.plugins 插件
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
// ExamplePlugin.java
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class ExamplePlugin implements Interceptor
{
public Object intercept(Invocation invocation) throws Throwable
{
return invocation.proceed();
}
public Object plugin(Object target)
{
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties)
{
}
}
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.ExamplePlugin">
<property name="someProperty" value="100" />
</plugin>
</plugins>
8.environments 环境
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader);
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties);
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..." />
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
- 默认的环境 ID(比如:default="development")。
- 每个 environment 元素定义的环境 ID(比如:id="development")。
- 事务管理器的配置(比如:type="JDBC")。
- 数据源的配置(比如:type="POOLED")。
- JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务范围。
- MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false" />
</transactionManager
public interface TransactionFactory
{
void setProperties(Properties props);
Transaction newTransaction(Connection conn);
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
public interface Transaction
{
Connection getConnection() throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
void close() throws SQLException;
}
- driver – 这是 JDBC 驱动的 Java 类的完全限定名(并不是JDBC驱动中可能包含的数据源类)。
- url – 这是数据库的 JDBC URL 地址。
- username – 登录数据库的用户名。
- password – 登录数据库的密码。
- defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
- poolMaximumActiveConnections – 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10
- poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
- poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
- poolTimeToWait – 这是一个底层设置,如果获取连接花费的相当长的时间,它会给连接池打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。
- poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否处在正常工作秩序中并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。
- poolPingEnabled – 是否启用侦测查询。若开启,也必须使用一个可执行的 SQL 语句设置 poolPingQuery 属性(最好是一个非常快的 SQL),默认值:false。
- poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的使用频度。这可以被设置成匹配具体的数据库连接超时时间,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。
- initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么 data_source 属性将会直接从 InitialContext 中寻找。
- data_source – 这是引用数据源实例位置的上下文的路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
public interface DataSourceFactory
{
void setProperties(Properties props);
DataSource getDataSource();
}
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory
{
public C3P0DataSourceFactory()
{
this.dataSource = new ComboPooledDataSource();
}
}
<dataSource type="org.myproject.C3P0DataSourceFactory">
<property name="driver" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql:mydb" />
<property name="username" value="postgres" />
<property name="password" value="root" />
</dataSource>
9.databaseIdProvider 数据库厂商标识
<databaseIdProvider type="DB_VENDOR" />
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver" />
<property name="DB2" value="db2" />
<property name="Oracle" value="oracle" />
</databaseIdProvider>
public interface DatabaseIdProvider
{
void setProperties(Properties p);
String getDatabaseId(DataSource dataSource) throws SQLException;
}
10.mappers 映射器
<!-- Using classpath relative resources -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml" />
<mapper resource="org/mybatis/builder/BlogMapper.xml" />
<mapper resource="org/mybatis/builder/PostMapper.xml" />
</mappers>
<!-- Using url fully qualified paths -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml" />
<mapper url="file:///var/mappers/BlogMapper.xml" />
<mapper url="file:///var/mappers/PostMapper.xml" />
</mappers>
<!-- Using mapper interface classes -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper" />
<mapper class="org.mybatis.builder.BlogMapper" />
<mapper class="org.mybatis.builder.PostMapper" />
</mappers>
<!-- Register all interfaces in a package as mappers -->
<mappers>
<package name="org.mybatis.builder" />
</mappers>
-------------------------------------------------------------------------------------------------------------------------------
MyBatis《2》的更多相关文章
- 如何使用mybatis《三》
在前边阐述了单独使用mybatis的方法,在实际开发过程中mybatis经常和spring一起使用,即mybatis和spring进行集成,现在我们来看如何集成. mybatis和spring进行集成 ...
- 如何使用mybatis《二》
前边阐述了如何在java项目中使用mybatis,我们使用的是映射文件的方式,在获得具体的数据操作方法时需要传入映射文件中namespace+“.”方法名称,这种方式有时候会感觉很不爽,很麻烦.我们在 ...
- 如何使用mybatis《一》
mybatis作为ORM轻量级框架一出现就吸引了无数人的眼球,比hibernate要简单且入门较容易,下面开始我的第一个mybatis程序. 一.下载mybatis的包 我们知道任何一个框架都会有其包 ...
- MyBatis《1》
MyBatis入参考文档:http://mybatis.org/mybatis-3/zh/ 1.使用MyBatis前的准备 1.增加Maven依赖 <dependency> <g ...
- MyBatis基础入门《十七》动态SQL
MyBatis基础入门<十七>动态SQL 描述: >> 完成多条件查询等逻辑实现 >> 用于实现动态SQL的元素主要有: > if > trim > ...
- MyBatis基础入门《十三》批量新增数据
MyBatis基础入门<十三>批量新增数据 批量新增数据方式1:(数据小于一万) xml文件 接口: 测试方法: 测试结果: =============================== ...
- MyBatis基础入门《十》添加数据
MyBatis基础入门<十>添加数据 描述: 修改了实体类:TblClient.java,将其字段:cbirthday 由String类型改成了Date类型. TblClient.java ...
- MyBatis基础入门《九》ResultMap自动匹配
MyBatis基础入门<九>ResultMap自动匹配 描述: Mybatis执行select查询后,使用ResultMap接收查询的数据结果. 实体类:TblClient.java 接口 ...
- MyBatis基础入门《八》查询参数传入Map
MyBatis基础入门<八>查询参数传入Map 描述: 在执行select查询数据的时候,方法传入的参数是java.util.Map类型. 接口方法: xml文件 注意: 书写SQL语句的 ...
随机推荐
- 运维&网络知识(一)
1. DNS 域名系统(Domain Name System),因特网上作为域名和IP地址映射的一个分布式数据库.
- flume自定义Source(taildirSource),自定义Sink(数据库),开发完整步骤
一.flume简单了解推荐网站(简介包括简单案例部署): http://www.aboutyun.com/thread-8917-1-1.html 二.我的需求是实现从ftp目录下采集数据,目录下文件 ...
- Django(二)
QuerySet与惰性机制: 所谓惰性机制:Publisher.objects.all()或者所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个Que ...
- 如何快速部署 Prometheus?- 每天5分钟玩转 Docker 容器技术(85)
上一节介绍了 Prometheus 的核心,多维数据模型.本节演示如何快速搭建 Prometheus 监控系统. 环境说明 我们将通过 Prometheus 监控两台 Docker Host:192. ...
- 安利一波那个叫做 hutool 的通用工具类库
摘自3.1.1版本作者发布原话,当时看到有点说不上的情绪,为作者的坚持.热爱点个赞. 已经想不起来是怎样结识 Hutool 的,但 Hutool 伴随几个项目的推进,获得了同事一致好评. 没经过实践和 ...
- Unix/Linux僵尸进程
1. 僵尸进程的产生: 一个进程调用exit命令结束自己生命的时候,其实它并没有真正的被销毁,而是留下一个称为“僵尸进程”的数据结构.这时它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度 ...
- codeblocks无法编译的问题
(题外话:网上垃圾资源太多,良心推荐下载 codeblocks的码农们,别TM用DevC++,百度搜索100个不用devc++的理由加上我自己亲身经历!!!) https://jingyan.baid ...
- FastDFS与Nginx的配置说明
1.简介 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适合以文件为载 ...
- Java基础笔记13
1.集合与对象数组的区别 集合与对象数组共同点:都是存放对象的容器: 区别在于:①集合是没有长度限制的:②集合容器中没有类型的限制. 2.集合(都在Java.util包下) 常用的集合:Collect ...
- AngularJS学习篇(二)
AngularJS 指令 AngularJS 通过被称为 指令 的新属性来扩展 HTML. AngularJS 通过内置的指令来为应用添加功能. AngularJS 允许你自定义指令. Angular ...