目录

1、mybatis框架概述

2、直接使用jdbc连接数据库带来的问题

3、mybatis连接池

3.1、mybatis连接池yml配置

3.2、mybatis连接池xml配置

4、一个简单的mybatis框架demo(XML配置)

4.1、maven项目目录结构如下:

4.2、代码

4.3、mybatis代码架构分析

5、一个简单的mybatis框架demo(annotation配置)

5.1、maven项目目录结构如下

5.2、mybatis注解使用

6、mybatis总结

7、参考资料


文章中所涉及的代码源码下载地址:https://gitee.com/wulinchun/ssm-learning.git

1、mybatis框架概述

mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。 mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行sql 并将结果映射为 java 对象并返回。 采用ORM思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。 为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来 学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。

2、直接使用jdbc连接数据库带来的问题

  1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
  2. Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
  3. 使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
  4. 对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记 录封装成 pojo 对象解析比较方便。

(projo对象就是简单的java对象,可以理解为实体类与数据库中表一一映射的对象,可以参考https://blog.csdn.net/kobexiaol/article/details/78195856

3、mybatis连接池

连接池就是用于存储连接对象的一个容器。而容器就是一个集合,且必须是线程安全的,即两个线程不能拿到同一个连接对象。同时还要具备队列的特性:先进先出原则。

   使用连接池的好处:避免频繁创建和关闭数据库连接造成的开销,节省系统资源。

3.1、mybatis连接池yml配置

server:
port: 8080
spring:
datasource:
name: erp
url: jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Hongkong
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径
type-aliases-package: com.mybatis_demo.domain # 注意:对应实体类的路径jetbrains://idea/navigate/reference?project=DataBase_conn&fqn=com.example.demo.Entity

3.2、mybatis连接池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">
<!-- mybatis的主配置文件 -->
<configuration> <properties url="file:///C:/Users/Administrator/Desktop/ssm框架/mybatis_demo/src/main/resources/jdbcConfig.properties">
</properties>
<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.mybatis_demo.domain"></package>
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments> <!-- 配置映射文件位置 -->
<mappers>
<package name="com.mybatis_demo.dao"></package>
</mappers>
</configuration>

4、一个简单的mybatis框架demo(XML配置)

建立一个maven工程

eclipse配置maven可参考 https://blog.csdn.net/wcc27857285/article/details/81812304

eclipse建立maven工程可参考 https://jingyan.baidu.com/article/2fb0ba40a2b22b00f2ec5faf.html

4.1、maven项目目录结构如下:

4.2、代码

IUserDao.java

package com.mybatis_demo.dao;

import com.mybatis_demo.domain.User;

import java.util.List;

/**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:13
*/ public interface IUserDao {
/**
*查询所有
* @return
*/
List<User> findAll(); /**
* 根据id查询
* @param id
* @return
*/
List<User> findByUid(Integer uid); /**
* 根据name模糊查询
* @param userName
* @return
*/
List<User> findByName(String userName); /**
* 根据id删除
* @param id
* @return
*/
int deleteUser(Integer uid); /**
* 添加
* @param user
* @return
*/
int saveUser(User user); /**
* 修改
* @param user
* @return
*/
int updateUser(User user);
}

User.java

package com.mybatis_demo.domain;

import java.io.Serializable;
import java.sql.Date; /**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:08
*/ public class User implements Serializable {
private Integer uid;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress; public User() {
} public User(Integer uid, String userName, Date userBirthday, String userSex, String userAddress) {
this.uid = uid;
this.userName = userName;
this.userBirthday = userBirthday;
this.userSex = userSex;
this.userAddress = userAddress;
} public Integer getUid() {
return uid;
} public void setUid(Integer uid) {
this.uid = uid;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public Date getUserBirthday() {
return userBirthday;
} public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
} public String getUserSex() {
return userSex;
} public void setUserSex(String userSex) {
this.userSex = userSex;
} public String getUserAddress() {
return userAddress;
} public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
} @Override
public String toString() {
return "User{" +
"uid=" + uid +
", userName='" + userName + '\'' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + '\'' +
", userAddress='" + userAddress + '\'' +
'}';
}
}

IUserDao.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">
<mapper namespace="com.mybatis_demo.dao.IUserDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
<resultMap id="userMap" type="com.mybatis_demo.domain.User">
<!--property是实体类中的字段,column是数据库表中相应列名 -->
<!-- 主键字段的对应 -->
<id property="uid" column="id"></id>
<!--非主键字段的对应 -->
<result property="userName" column="username"></result>
<result property="userAddress" column="address"></result>
<result property="userSex" column="sex"></result>
<result property="userBirthday" column="birthday"></result>
</resultMap>
<!--配置查询所有 -->
<!-- <select id="findAll" resultType="com.mybatis_demo.domain.User"> select
* from user </select> -->
<select id="findAll" resultMap="userMap">
select id ,username ,address ,sex ,birthday from user;
/*select * from user*/
</select> <!-- 保存用户 -->
<insert id="saveUser" parameterType="user">
insert into
user(id,username,address,sex,birthday)values(#{uid},#{userName},#{userAddress},#{userSex},#{userBirthday})
</insert> <!--删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{uid}
</delete> <!--根据uid查询用户 -->
<select id="findByUid" parameterType="java.lang.Integer"
resultMap="userMap">
select * from user where id=#{uid}
</select> <!--根据userName模糊查询 -->
<select id="findByName" parameterType="String"
resultMap="userMap">
select * from user where username like #{userName}
</select> <update id="updateUser"
parameterType="user">
update user set username=#{userName},address=#{userAddress},sex=#{userSex},birthday=#{userBirthday} where id=#{uid}
</update>
</mapper>

IUserDao.xml中的映射配置需要注意!!!

jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
#mysql5.7以下版本,则可以直接这样写
#jdbc.url=jdbc:mysql://localhost:3306/ssm
#注意url这里,如果是mysql5.7及以上的要在后面设置useUnicode=true&characterEncoding=UTF-8
#否则会出现中文显示?
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456

SqlMapConfig.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">
<!-- mybatis的主配置文件 -->
<configuration>
<!-- 配置properties
可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
resource属性: 常用的
用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
url属性:
是要求按照Url的写法来写地址
URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
它的写法:
http://localhost:8080/mybatisserver/demo1Servlet
协议 主机 端口 URI URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
--> <properties url="file:///C:/Users/Administrator/Desktop/ssm框架/mybatis_demo/src/main/resources/jdbcConfig.properties">
</properties>
<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.mybatis_demo.domain"></package>
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments> <!-- 配置映射文件位置 -->
<mappers>
<package name="com.mybatis_demo.dao"></package>
</mappers>
</configuration>

MybatisTest.java

package com.mybatis_demo.test;

import com.mybatis_demo.dao.IUserDao;
import com.mybatis_demo.domain.User;
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.After;
import org.junit.Before;
import org.junit.Test; import java.io.InputStream;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List; /**
* @description:
* @author: wu linchun
* @time: 2020/12/30 22:25
*/ public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); @Before//用于在测试方法执行之前执行
public void init() throws Exception {
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession();
//4.获取dao的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
} @After//用于在测试方法执行之后执行
public void destroy() throws Exception {
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
} /**
* 测试查询所有
*/
@Test
public void testFindAll(){
List<User> userList = userDao.findAll();
for(User user : userList){
System.out.println(user);
}
} /**
* 测试添加用户
* @throws ParseException
*/
@Test
public void testSaveUser() throws ParseException {
java.util.Date bir=sdf.parse("2020-01-04");
java.sql.Date bir_sql=new java.sql.Date(bir.getTime());
User user=new User(11,"test11", bir_sql,"男","testAddress");
userDao.saveUser(user);
} /**
* 测试删除用户
*/
@Test
public void testDeleteUser(){
userDao.deleteUser(7);
} /**
* 测试根据uid查找
*/
@Test
public void testFindByUid(){
List<User> userList = userDao.findByUid(6);
for(User user : userList){
System.out.println(user);
} } /**
* 测试根据userName模糊查询
*/
@Test
public void testFindByName(){
List<User> userList=userDao.findByName("%t%");
for(User user : userList){
System.out.println(user);
}
} /**
* 测试修改
* @throws ParseException
*/
@Test
public void testUpdateUser() throws ParseException {
java.util.Date bir=sdf.parse("2020-01-04");
java.sql.Date bir_sql=new java.sql.Date(bir.getTime());
User user=new User(5,"test5",bir_sql,"男","testAddress");
userDao.updateUser(user);
} /**
* 入门案例
* @param args
*/
/*public static void main(String[] args) throws Exception {
//1.读取配置文件D:\学习资料\后端\ssm代码\mybatis_demo\src\main\resources\SqlMapConfig.xml
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}*/
}

4.3、mybatis代码架构分析

5、一个简单的mybatis框架demo(annotation配置)

5.1、maven项目目录结构如下

5.2、mybatis注解使用

IUserDao.java

package com.mybatis_demo_ann.dao;

import com.mybatis_demo_ann.domain.User;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import java.util.List; /**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:08
*/
public interface IUserDao { /**
* 查询所有操作
*
* @return
*/
@Select("select * from user")
//映射转换,将实体类中的字段与数据库表的列名一一对应起来
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
List<User> findAll(); /**
* 插入操作
* @param user
* @return
*/
@Insert("insert into user (id,username,birthday,sex,address) values (#{uid},#{userName},#{userBirthday},#{userSex},#{userAddress})")
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
int saveUser(User user); /**
* 更新操作
* @param user
* @return
*/
@Update("update user set username=#{userName},birthday=#{userBirthday},sex=#{userSex},address=#{userAddress} where id=#{uid}")
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
int updateUser(User user); /**
* 模糊查询
* @param username
* @return
*/
@Select("select * from user where username like #{username}")
List<User> findByName(String username); /**
* 删除用户
* @param id
* @return
*/
@Delete("delete from user where id=#{id}")
int deleteUser(int id);
}

注意!!!使用注解开发时,要求实体类数据中属性必须和 mysql 中的属性名一致(除非你进行映射转换的配置),可以忽略大小写。

可参考文章:https://blog.csdn.net/guan_sir/article/details/104561362       https://blog.csdn.net/weixin_44149454/article/details/90373036

6、mybatis总结

7、参考资料

  1. https://www.bilibili.com/video/BV1mE411X7yp?from=search
  2. https://blog.csdn.net/IT_CREATE/article/details/86564305
  3. https://www.cnblogs.com/arrows/p/10531808.html
  4. https://blog.csdn.net/dwenxue/article/details/82351120
  5. https://blog.csdn.net/writedew/article/details/94459863
  6. https://blog.csdn.net/although1/article/details/103719383
  7. https://www.cnblogs.com/king0207/p/13578912.html
  8. https://blog.csdn.net/weixin_44149454/article/details/90373036
  9. https://blog.csdn.net/guan_sir/article/details/104561362
  10. https://blog.csdn.net/chpllp/article/details/81945600
  11. https://www.cnblogs.com/jpfss/p/7681420.html
  12. https://blog.csdn.net/sinat_24230393/article/details/97006106
  13. https://www.cnblogs.com/jtlgb/p/8780594.html
  14. https://bbs.csdn.net/topics/380189849
  15. https://blog.csdn.net/qq_34902437/article/details/105041210
  16. https://jingyan.baidu.com/article/2fb0ba40a2b22b00f2ec5faf.html
  17. https://blog.csdn.net/zj420964597/article/details/84564440
  18. https://bbs.csdn.net/topics/391027203?list=lz
  19. https://blog.csdn.net/cc41798520101/article/details/52411401
  20. https://blog.csdn.net/qq_40645822/article/details/101844675
  21. https://developer.aliyun.com/article/619693
  22. https://blog.csdn.net/weixin_33716557/article/details/92423934
  23. https://www.cnblogs.com/softidea/p/5773191.html
  24. https://blog.csdn.net/csdn1428208016/article/details/85243863
  25. https://blog.csdn.net/u013412772/article/details/73648537
  26. https://www.itdaan.com/blog/2008/08/20/8aa0deb865221baa90f4259603ad2f64.html
  27. https://www.cnblogs.com/chongaizhen/p/11170595.html

ssm——mybatis整理的更多相关文章

  1. ssm知识点整理

    第1章 resultType和resultMap的区别是什么?  MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType ...

  2. SSM Mybatis将新增数据写入数据库时出现的500状态码:Error updating database.的可能

    关于maven下ssm整合的项目推荐这篇博客:https://www.cnblogs.com/yiye/p/5969157.html 今日在ssm下的将新增数据写回数据库时遇到不少的问题,现作记录 如 ...

  3. Mybatis整理_01

    Mybatis专题 Mybaits介绍 Mybatis是一个持久化框架,它有不同语言的版本,比如.NET和Java都有Mybatis对应的类库:它有大多数ORM框架都具有的功能,比如自定义的SQL语句 ...

  4. [原] MyBatis 整理

    花了一上午的时间,先整理一个脑图.

  5. Mybatis整理系列(01)————传入参数方式以及#{}与${}的区别

    一.在MyBatis的select.insert.update.delete这些元素中都提到了parameterType这个属性.MyBatis现在可以使用的parameterType有基本数据类型和 ...

  6. SSM - Mybatis SQL映射文件

    MyBatis 真正的力量是在映射语句中.和对等功能的jdbc来比价,映射文件节省很多的代码量.MyBatis的构建就是聚焦于sql的. sql映射文件有如下几个顶级元素:(按顺序) cache配置给 ...

  7. mybatis整理笔记

    以下是idea2018辑编器 新建 Maven工程 1  file ->new ->project 新建后编程器在右下角加载插件.,这个时候需要会儿,  加载好后,软件目录会多一个ja包 ...

  8. SSM+MyBatis框架详解

  9. 【Mybatis架构】 延迟加载

    在上一篇博客中,我们提到过有关于Mybatis输出映射中resultMap能够实现延迟加载的事,然而真的是所有的resultMap都能实现延迟加载还是咋地啊?现在我们就来对那一句话做一下阐述和实例说明 ...

  10. 【Mybatis框架】查询缓存(二级缓存)

    继上一篇博客,我们讲述了mybatis的一级缓存,接下来,我们来学习一下mybatis的二级缓存 博客链接地址: http://blog.csdn.NET/liweizhong193516/artic ...

随机推荐

  1. Es 学习笔记 (1)

    目录 前言 什么是es? es数据组织类比 应用场景 核心概念 集群 节点(node) 索引(Index) 文档类型(Type) 文档(Document) Mapping 核心简单域类型 分片(sha ...

  2. Java8新特性之Stream流(含具体案例)

    一.概述   Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选.排序.聚合等.元素 ...

  3. 通过 Github Action 实现定时推送天气预报

    偶然间,看到 GitHub Actions 教程:定时发送天气邮件 - 阮一峰的网络日志 这篇文章,没错,这个正好能打发自己的折腾之心,也能通过代码给生活引入一些变化. 还是在这里简单记录一下实现过程 ...

  4. MasaFramework -- 缓存入门与规则配置

    概念 什么是缓存,在项目中,为了提高数据的读取速度,我们会对不经常变更但访问频繁的数据做缓存处理,我们常用的缓存有: 本地缓存 内存缓存:IMemoryCache 分布式缓存 Redis: Stack ...

  5. Linux系统命令基础

    Linux系统命令基础 前面咱们已经成功安装了Linux系统--centos7,那么现在奔向Linux命令行的世界. Linux命令格式 1.一般情况下,[参数]是可选的,一些情况下[文件或路径]也是 ...

  6. FHE学习笔记 #2 多项式环

    https://en.wikipedia.org/wiki/Polynomial_ring https://zhuanlan.zhihu.com/p/419266064 这篇知乎文章讲的比较透彻,但是 ...

  7. C语言指针重点

    指针 指针与一维数组 万能公式 p[i] = *(p+i) = (i+p) = i[p] &p[i] == &((p+i))== p+i 指针与二维数组 二维数组万能公式: ((p+i ...

  8. [CS61A] Lecture 4. Higher-Order Functions & Project 1: The Game of Hog

    [CS61A] Lecture 4. Higher-Order Functions & Project 1: The Game of Hog Lecture Lecture 4. Higher ...

  9. Ajax基础(中)

    这节主要在上节的基础上学会如何使用Ajax 源码下载: 链接:https://pan.baidu.com/s/1kG-vACFxneAZqONdo97XrQ 提取码:k21y 在WebStorm中打开 ...

  10. perl之grep函数的用法

    转载至 perl中grep的详细用法 grep有2种表达方式: 1 grep BLOCK LIST 2 grep EXPR, LIST BLOCK表示一个code块,通常用{}表示:EXPR表示一个表 ...