一、Mybatis是什么

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,mybatis是支持普通sql查询,存储过程和高级映射的优秀的、轻量级的持久层框架

二、Mybatis的作用

1. mybatis支持普通sql查询,存储过程和高级映射。

2. mybatis消除了几乎所有的jdbc代码和参数的手工设置以及结果集的检索。

3. mybatis使用简单的xml或注解用于配置和原始映射,将简单javabean映射成数据库中的对象。

三、为什么要学习Mybatis

1. 我们先来看使用jdbc操作数据库的过程

 package com.study.spring.mybatistest;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; /**
* jdbc操作数据库
* @author THINKPAD
*
*/
public class JdbcTest {
public static void main(String[] args) { // 数据库连接
Connection connection = null;
// 预编译的Statement,使用预编译的Statement提高数据库性能
PreparedStatement preparedStatement = null;
// 结果 集
ResultSet resultSet = null; try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver"); // 通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/study?characterEncoding=utf-8",
"root", "root");
// 定义sql语句 ?表示占位符
String sql = "select * from t_order where order_no = ?";
// 获取预处理statement
preparedStatement = connection.prepareStatement(sql);
// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "123");
// 向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
// 遍历查询结果集
while (resultSet.next()) {
System.out.println(resultSet.getString("id") + " " + resultSet.getString("orderinfo"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
} } }
}

使用jdbc操作数据库存在如下的问题:

1.1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。

Mybatis解决方案:使用数据库连接池管理数据库连接。

1.2、将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。

Mybatis解决方案:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。

1.3、向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。

Mybatis解决方案:将sql语句及占位符号和参数全部配置在xml中。

1.4、从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护。

 Mybatis解决方案:将查询的结果集,自动映射成java对象。

四、Mybatis架构图

架构图的说明:

1、mybatis配置

1.1 SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

1.2 mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2、通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

五、Mybatis入门程序

1. 需求:创建一个用户表,用户名有用户名称,生日,性别,地址字段,对用户表进行CRUD操作

2. 环境:JDK1.8,eclipse,Mysql5.6,maven

3. 创建一个名为MybatisTest的工程,目录结构如下:

4. 在数据库里面创建用户表,并插入数据

 SET FOREIGN_KEY_CHECKS=0;

 -- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(2) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES ('1', 'a', '2017-10-12', '2', '深圳');
INSERT INTO `t_user` VALUES ('2', 'b', '2017-10-12', '2', '深圳');
INSERT INTO `t_user` VALUES ('3', 'c', '2017-10-12', '1', '深圳');
INSERT INTO `t_user` VALUES ('4', 'd', '2017-10-12', '2', '深圳');

5. 在工程里面创建用户表的实体类UserModel.java

 package com.study.mybatis.model;

 import java.util.Date;

 /**
* 用户model 和数据库的表t_user对应
*
* @author THINKPAD
*
*/
public class UserModel {
// 属性名称和数据库字段名称保持一致
private Integer id;
// 姓名
private String username;
// 性别
private String sex;
// 地址
private String address;
// 生日
private Date birthday; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} public Date getBirthday() {
return birthday;
} public void setBirthday(Date birthday) {
this.birthday = birthday;
} @Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", address=" + address + ", birthday="
+ birthday + "]";
} }

6. 定义实体类在mybatis里面的映射文件mapper-user.xml

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace命名空间,作用就是对sql进行分类化的管理,理解为sql隔离
注意:使用mapper代理开发时,namespace有特殊作用
-->
<mapper namespace="test">
<!-- 在映射文件中配置很多sql语句 -->
<!-- 需求:通过Id查询用户表的记录 -->
<!-- 通过SELECT执行数据库查询
id:标识映射文件中的sql,称为statement的id;
将sql语句封装在mapperStatement的对象中,所以Id称为Statement的id;
parameterType:指定输入参数的类型,这里指定int型
#{}:表示一个占位符;
#{id}:其中Id表示接收输入的参数,参数名称就是Id,如果输入参数是简单类型,#{}中的参数名可以任意,可以是value或者其它名称;
resultType:指定sql输出结果所映射的java对象类型,select指定resultType表示将单条记录映射成java对象。
-->
<select id="findUserById" parameterType="int" resultType="com.study.mybatis.model.UserModel" >
select * from t_user where id=#{id}
</select>
<!-- 根据用户名称模糊查询用户信息,可能返回多条数据
resultType:指定的就是单条记录所映射的java类型;
${}:表示拼接sql字符串,将接收到的参数内容不加任何修饰拼接在sql中.
使用${}拼接sql,可能会引起sql注入
${value}:接收输入参数的内容,如果传入的是简单类型,${}中只能使用value
-->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.study.mybatis.model.UserModel" >
select * from t_user where username LIKE '%${value}%'
</select>
<!-- 添加用户
parameterType:指定输入的参数类型是pojo(包括用户信息);
#{}中指定pojo的属性名称,接收到pojo对象的属性值 ,mybatis通过OGNL(类似struts2的OGNL)获取对象的属性值
-->
<insert id="insertUser" parameterType="com.study.mybatis.model.UserModel" >
<!--
将insert插入的数据的主键返回到User对象中;
select last_insert_id():得到刚insert进去记录的主键值,只适用于自增主键;
keyProperty:将查询到的主键值,设置到parameterType指定的对象的那个属性
order:select last_insert_id()执行顺序,相对于insert语句来说它的执行顺序。
resultType:指定select last_insert_id()的结果类型;
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select last_insert_id()
</selectKey>
<!--
使用mysql的uuid(),实现非自增主键的返回。
执行过程:通过uuid()得到主键,将主键设置到user对象的Id的属性中,其次,在insert执行时,从user对象中取出Id属性值;
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
select uuid()
</selectKey>
insert into t_user (id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
-->
insert into t_user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 删除用户
根据ID删除用户,需要输入Id值
-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from t_user where id=#{id}
</delete>
<!-- 更新用户
需要传入用户的Id和用户的更新信息
parameterType:指定User对象,包括Id和用户的更新信息,注意:Id是必须存在的
#{id}:从输入的User对象中获取Id的属性值
-->
<update id="updateUser" parameterType="com.study.mybatis.model.UserModel">
update t_user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update> </mapper>

7. 定义mybatis的主配置文件SqlMapConfig.xml,在里面引入数据库配置文件db.properties和实体映射文件mapper-user.xml

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引用db.properties配置文件 -->
<properties resource="db.properties" /> <!-- development : 开发模式 work : 工作模式,和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理 -->
<dataSource type="POOLED">
<!-- value属性值引用db.properties配置文件中配置的值 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${name}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="sqlmapper/mapper-user.xml" />
</mappers>
</configuration>

8. db.properties

 driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.152.1:3306/study?characterEncoding=utf-8
name=root
password=123456

9. 编写mybatis的测试类

 package com.study.mybatis.mybatistest;

 import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test; import com.study.mybatis.model.UserModel; /**
* Mybatis 测试
*
* @author THINKPAD
*
*/
public class MybatisTest {
// 根据Id查询用户信息,得到一条记录结果
@Test
public void findUserByIdTest() {
// mybatis的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = null;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream(resource);
// 1.创建会话工场,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 2.通过工厂得到SqlSession
sqlSession = sqlSessionFactory.openSession(); // 3.通过sqlSession操作数据库
// 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
// sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
// selectOne:查询一条结果
UserModel user = sqlSession.selectOne("test.findUserById", 1);
System.out.println(user.toString()); } catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} // 根据姓名模糊查询用户信息,得到一条或多条记录结果
@Test
public void findUserByNameTest() {
// mybatis的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = null;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream(resource);
// 1.创建会话工场,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 2.通过工厂得到SqlSession
sqlSession = sqlSessionFactory.openSession(); // 3.通过sqlSession操作数据库
// 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
// sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
// list中的user和resultType类型一致
List<UserModel> list = sqlSession.selectList("test.findUserByName", "a");
System.out.println(list); } catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} // 添加用户
@Test
public void insertUserTest() {
// mybatis的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = null;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream(resource);
// 1.创建会话工场,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.通过工厂得到SqlSession
sqlSession = sqlSessionFactory.openSession();
// 插入用户的对象
UserModel user = new UserModel();
user.setUsername("d");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("上海");
// 3.通过sqlSession操作数据库
// 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
// sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
sqlSession.insert("test.insertUser", user);
// 执行提交事务
sqlSession.commit(); // 项目中经常需要 获取新增的用户的主键
System.out.println(user.getId()); } catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} // 根据Id删除用户
@Test
public void deleteUserTest() {
// mybatis的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = null;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream(resource);
// 1.创建会话工场,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.通过工厂得到SqlSession
sqlSession = sqlSessionFactory.openSession();
// 3.通过sqlSession操作数据库
// 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
// sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
// 传入Id,删除用户
sqlSession.delete("test.deleteUser", 7);
// 执行提交事务
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} // 根据Id更新用户信息
@Test
public void updateUserTest() {
// mybatis的配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = null;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream(resource);
// 1.创建会话工场,传入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.通过工厂得到SqlSession
sqlSession = sqlSessionFactory.openSession();
// 更新用户的信息
UserModel user = new UserModel();
user.setId(2);
user.setUsername("e");
user.setBirthday(new Date());
user.setSex("2");
user.setAddress("上海");
// 3.通过sqlSession操作数据库
// 第一个参数:映射文件中的statement的Id,等于namespace + "." + statement的id;
// 第二个参数:指定和映射文件中所匹配的parameterType类型的参数;
// sqlSession.selectOne结果是与映射文件所匹配的resultType类型的对象;
// 更具Id更新用户
sqlSession.update("test.updateUser", user);
// 执行提交事务
sqlSession.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} public static void main(String[] args) {
// new MybatisTest().findUserByIdTest();
// new MybatisTest().findUserByNameTest();
// new MybatisTest().insertUserTest();
// new MybatisTest().deleteUserTest();
new MybatisTest().updateUserTest();
}
}

六、mybatis和Hibernate的本质区别与应用场景

mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。

应用场景

适用与需求变化较多的项目,比如:互联网项目。

hibernate:是一个标准ORM框架(对象关系映射),入门门槛较高的,不需要程序写sql,sql语句自动生成了,对sql语句进行优化、修改比较困难的。

应用场景

适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。

七、小结

1. parameterType和resultType

  parameterType:在映射文件中通过parameterType指定输入参数的类型。

  resultType:在映射文件中通过resultType指定输出结果的类型

2.#{}和${}

#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap;

如果接收简单类型,#{}中可以写成value或其它名称;

#{}接收pojo对象值,通过OGNL读取对象中的属性值,和struts的OGNL类似。

${}表示一个拼接符号,会引用sql注入,所以不建议使用{};

${}接收输入参数,类型可以是简单类型,pojo、hashmap;

如果接收简单类型,${}中只能写成value;

${}接收pojo对象值,通过OGNL读取对象中的属性值,和struts的OGNL类似。

3.selectOne()和selectList()

  selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。

  selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。

  如果使用selectOne报错: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

参考文章:http://www.cnblogs.com/selene/p/4604605.html

Mybatis系列(一):Mybatis入门的更多相关文章

  1. 深入浅出Mybatis系列一-Mybatis入门

    注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 最近两年 springmvc + mybatis 的在这种搭配还是蛮火的,楼主我呢, ...

  2. 深入迁出mybatis系列

    本系列教程均源于南柯梦,经好库文摘转发,感谢南柯梦的辛苦整理. 深入迁出mybatis系列 深入浅出Mybatis系列(一)---Mybatis入门 深入浅出Mybatis系列(二)---配置简介(m ...

  3. MyBatis学习总结-MyBatis快速入门的系列教程

    MyBatis学习总结-MyBatis快速入门的系列教程 [MyBatis]MyBatis 使用教程 [MyBatis]MyBatis XML配置 [MyBatis]MyBatis XML映射文件 [ ...

  4. Mybatis系列(一)入门

    Mybatis系列(一)入门 mybatis简介 MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结 ...

  5. 深入浅出Mybatis系列(一)---Mybatis入门

    最近两年 springmvc + mybatis 的在这种搭配还是蛮火的,楼主我呢,也从来没真正去接触过mybatis, 趁近日得闲, 就去学习一下mybatis吧. 本次拟根据自己的学习进度,做一次 ...

  6. 【mybatis深度历险系列】mybatis的框架原理+入门程序解析

    在前面的博文中,小编介绍了springmvc的相关知识点,在今天这篇博文中,小编将介绍一下mybatis的框架原理,以及mybatis的入门程序,实现用户的增删改查,她有什么优缺点以及mybatis和 ...

  7. MyBatis系列:一、入门

    MyBatis无需我介绍,本系列文章是纯干货,没有一点废话. 1.创建一个maven项目,引入mysql的驱动和mybatis的maven引用 <dependency> <group ...

  8. 深入浅出Mybatis系列(一)---Mybatis入门[转]

    最近两年 springmvc + mybatis 的在这种搭配还是蛮火的,楼主我呢,也从来没真正去接触过mybatis, 趁近日得闲, 就去学习一下mybatis吧. 本次拟根据自己的学习进度,做一次 ...

  9. 深入浅出Mybatis系列(二)---Mybatis入门

    一.Mybatis环境搭建及简单实例 1. 新建web项目, 添加依赖包:mybatis包.数据库驱动包(我使用的是mysql).日志包(我使用的是log4j), 由于我的是maven项目, 那么添加 ...

随机推荐

  1. CORS跨域、Cookie传递SessionID实现单点登录后的权限认证的移动端兼容性测试报告

    简述 本文仅记录如标题所述场景的测试所得,由于场景有些特殊,且并不需兼容所有浏览器,所以本文的内容对读者也许并无作用,仅为记录. 场景.与实现 需在移动端单点登录 需在移动端跨域访问我们的服务 基于历 ...

  2. 使用Maven对JAVA程序打包-带主类、带依赖【转】

    很多时候,我们需要对编写的程序进行打包,这个时候,我们可以借助一些项目构建工具,如maven, sbt, ant等,这里我使用的是maven. 打包成可执行有主类的jar包(jar包中无依赖) 以下是 ...

  3. 采用alluxio提升MR job和Spark job性能的注意点

    1. 介绍 2. 实验说明 2.1 实验环境 2.2 实验方法 2.3 实验负载 3. MapReduce on alluxio 3.1 读取10G文件(1G split) 3.2 读取20G文件(1 ...

  4. 【Linux技术】BusyBox详解

    BusyBox 是很多标准 Linux® 工具的一个单个可执行实现.BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大.更复杂的工具,例如 grep.find.moun ...

  5. CentOS6.5 安装Nexus配置Maven私服

    1.下载Nexus的tar包,链接地址.注意,3.x版本需要JDK版本1.8及以上版本. 2.创建安装包存放目录 命令:mkdir -p /usr/local/src/installs 3.rz或者f ...

  6. Netty高性能之Reactor线程模型

    Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用 ...

  7. Lintcode: Interleaving Positive and Negative Numbers 解题报告

    Interleaving Positive and Negative Numbers 原题链接 : http://lintcode.com/zh-cn/problem/interleaving-pos ...

  8. java多线程17:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

  9. linux输入子系统

    linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(InputCore)和输入子系统设备驱 ...

  10. php中文语义分析

    最近公司有个需求要做文章关键词提取,发现有个波森语义分析,还不错,把其http接口封装了一下, 发布到packagist上了. 简介 简单的封装了BosonNLP中文语义识别的api. 安装 comp ...