目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

JDBC

JDBC

  • 全称 Java DataBase Connectivity, 是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口
  • 提供了一种接口基准,可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序
  • 应用程序代码一般不能直接访问数据库,需要通过相应的数据库驱动程序才行,
  • 数据库驱动就是数据库厂商对JDBC接口的实现

JDBC

JDBC连接MySQL相关概念

  • 数据库驱动:不同数据库开发商(比如oracle mysql等)为了某一种开发语言能够实现统一的数据库调用而开发的一个程序, 作用相当于一个翻译人员, 将某个语言(比如java)中对数据库的调用通过这个翻译成各个种类的数据库 自己的数据库语言
  • Connection连接:特定数据库的连接(会话),在连接上下文中执行sql语句并返回结果
  • Statement 语句: 创建执行SQL语句的statement, 有好几种实现类,用于执行对应的sql
  • ResultSet结果集:SQL查询返回的结果信息

使用Java连接Mysql的步骤

  • 加载JDBC驱动程序
  • 建立数据库连接Connection
  • 创建执行SQL的语句Statement
  • 处理执行结果ResultSet
  • 释放连接资源

驱动包导入和数据库准备

https://abc1024.oss-cn-shanghai.aliyuncs.com/Picture/Javaweb/mysql-connector-java-5.1.46.jar

数据库表

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `phone` varchar(32) DEFAULT NULL,
  `pwd` varchar(128) DEFAULT NULL,
  `sex` int(2) DEFAULT NULL,
  `img` varchar(128) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `role` int(11) DEFAULT NULL COMMENT '1是普通用户,2是管理员',
  `username` varchar(128) DEFAULT NULL,
  `wechat` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


INSERT INTO `user` (`id`, `phone`, `pwd`, `sex`, `img`, `create_time`, `role`, `username`,`wechat`)
VALUES
    (1,'123','666',1,'xdclass.net','2021-09-09 00:00:00',1,'jack','xdclass6'),
    (2,'2323432','794666918',1,'wwwww','2020-05-20 04:54:01',1,'小滴Anna姐姐','xdclass-anna'),
    (3,'2323432','xdclass-lw',1,'wwwww','2020-05-20 04:54:42',1,'二当家小D','xdclass1'),
    (4,'2323432','3232323',1,'wwwww','2020-05-20 04:55:07',1,'老王','xdclass-lw');

编写一个JDBC程序

public class JDBCTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        //建立数据库连接Connection
        String name = "root";
        String password = "123456";
            //协议:子协议://ip:端口/数据库名称?参数1=值1&参数2=值2
        String url = "jdbc:mysql://192.168.31.101:50000/test?useUnicode=true&characterEncoding=utf-8&useSSL=false";
        Connection connection = DriverManager.getConnection(url, name, password);

        //创建执行SQL的语句Statement
        Statement statement = connection.createStatement();

        //处理执行结果ResultSet
        ResultSet resultSet = statement.executeQuery("select * from user");
        while (resultSet.next()) {
            System.out.println("用户名称 name="+ resultSet.getString("username") +
                    "  联系方式 wechat="+ resultSet.getString("wechat"));
        }

        //释放连接
        resultSet.close();
        statement.close();
        connection.close();
    }
}

SQL注入攻击和Statement预编译语句

  • 什么是SQL注入攻击

    • 可以执行恶意SQL语句,将任意SQL代码插入数据库查询,使用SQL注入来添加,修改和删除数据库中的记录
  • PrepareStatement

    • 字面可译为预声明,内部包含一个预编译的sql语句,参数采用占位符 ? 进行填充
    • 为啥可以防注入
      • 第一次操作数据库之前,SQL语句已经被数据库分析和编译,对应的执行计划也会缓存下来,之后数据库就会以参数化的形式进行查询
      • 传入的值始终都是会作为一个值,而不是sql指令
  • 好处:维护性好、提高sql效率、增加安全性

public class JDBCTest {


    public static void main(String [] args) throws Exception{

         //加载JDBC驱动程序
//         Class.forName("com.mysql.jdbc.Driver");
//
//         //建立数据库连接Connection
//        String username = "root";
//        String password = "xdclass.net";
//        //协议:子协议://ip:端口/数据库名称?参数1=值1&参数2=值2
//        String url = "jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false";
//
//        Connection connection = DriverManager.getConnection(url,username,password);
//
//         //创建执行SQL的语句Statement
//        Statement statement  = connection.createStatement();
//
//         //处理执行结果ResultSet
//        ResultSet resultSet = statement.executeQuery("select * from user");
//
//
//
//        while (resultSet.next()){
//
//            System.out.println("用户名称 name="+ resultSet.getString("username") + "  联系方式 wechat="+ resultSet.getString("wechat"));
//        }
//
//        //释放连接资源
//        statement.close();
//        connection.close();

        testInjectSQL();


    }




  //攻击的例子

//    private static  void  testInjectSQL()throws Exception{
//        //加载JDBC驱动程序
//        Class.forName("com.mysql.jdbc.Driver");
//
//        //建立数据库连接Connection
//        String username = "root";
//        String password = "xdclass.net";
//        //协议:子协议://ip:端口/数据库名称?参数1=值1&参数2=值2
//        String url = "jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false";
//
//        Connection connection = DriverManager.getConnection(url,username,password);
//
//        //创建执行SQL的语句Statement
//        Statement statement  = connection.createStatement();
//
//        String name = "jack";
//
//        String pwd = "666' or 1=1 or'";
//
//        String sql = "select * from user where username='"+name +"' and pwd='"+pwd +"'";
//
//        System.out.println(sql);
//
//        //处理执行结果ResultSet
//        ResultSet resultSet = statement.executeQuery(sql);
//
//
//        while (resultSet.next()){
//
//            System.out.println("用户名称 name="+ resultSet.getString("username") + "  联系方式 wechat="+ resultSet.getString("wechat"));
//        }
//
//        //释放连接资源
//        statement.close();
//        connection.close();
//    }


    /**
     * 防止攻击的例子
     * @throws Exception
     */
    private static  void  testInjectSQL()throws Exception{
        //加载JDBC驱动程序
        Class.forName("com.mysql.jdbc.Driver");

        //建立数据库连接Connection
        String username = "root";
        String password = "xdclass.net";
        //协议:子协议://ip:端口/数据库名称?参数1=值1&参数2=值2
        String url = "jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false";

        Connection connection = DriverManager.getConnection(url,username,password);

        String name = "jack";

        String pwd = "666 or 1=1 ";

        //创建执行SQL的语句Statement
        PreparedStatement preparedStatement  = connection.prepareStatement("select * from user where username=? and pwd=?");

        preparedStatement.setString(1,name);
        preparedStatement.setString(2,pwd);


        //处理执行结果ResultSet
        ResultSet resultSet = preparedStatement.executeQuery();

        while (resultSet.next()){

            System.out.println("用户名称 name="+ resultSet.getString("username") + "  联系方式 wechat="+ resultSet.getString("wechat"));
        }

        //释放连接资源
        preparedStatement.close();
        connection.close();
    }


    }

增删功能

private static void testAdd() throws Exception {
        //加载JDBC驱动程序
        Class.forName("com.mysql.jdbc.Driver");

        //建立数据库连接Connection
        String username = "root";
        String password = "xdclass.net";
        //协议:子协议://ip:端口/数据库名称?参数1=值1&参数2=值2
        String url = "jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false";

        Connection connection = DriverManager.getConnection(url, username, password);

        PreparedStatement preparedStatement = connection.prepareStatement("insert into  user(username, pwd,sex,role,create_time) values(?,?,?,?,?) ");

        preparedStatement.setString(1,"二当家小D");
        preparedStatement.setString(2,"123456");
        preparedStatement.setInt(3,1);
        preparedStatement.setInt(4,2);
        preparedStatement.setTimestamp(5,new Timestamp(System.currentTimeMillis()));

        //执行
        preparedStatement.execute();

        preparedStatement.close();
        connection.close();




    }


    private static void testDelete() throws Exception {
        //加载JDBC驱动程序
        Class.forName("com.mysql.jdbc.Driver");

        //建立数据库连接Connection
        String username = "root";
        String password = "xdclass.net";
        //协议:子协议://ip:端口/数据库名称?参数1=值1&参数2=值2
        String url = "jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false";

        Connection connection = DriverManager.getConnection(url, username, password);

        PreparedStatement preparedStatement = connection.prepareStatement("delete  from user where  id=?");

        preparedStatement.setInt(1,2);

        //执行
        preparedStatement.execute();

        preparedStatement.close();
        connection.close();


    }

JDBC控制Mysql事务

  • 事务:

    • 一个最小的不可再分的工作单元,通常一个事务对应一个完整的业务
    • 例如银行账户转账业务,该业务就是一个最小的工作单元
  • 四大特性

    • 原子性(A):事务是最小单位,不可再分
    • 一致性(C):事务要求所有的DML语句操作的时候,必须保证同时成功或者同时失败
    • 隔离性(I):事务A和事务B之间具有隔离性
    • 持久性(D):是事务的保证,事务终结的标志(内存的数据持久到硬盘文件中)
  • 事务的一些术语

    • 开启事务:Start Transaction
    • 事务结束:End Transaction
    • 提交事务:Commit Transaction
    • 回滚事务:Rollback Transaction
  • JDBC事务控制实操

private static void testTransaction() throws Exception {
        //加载JDBC驱动程序
        Class.forName("com.mysql.jdbc.Driver");

        //建立数据库连接Connection
        String username = "root";
        String password = "xdclass.net";
        //协议:子协议://ip:端口/数据库名称?参数1=值1&参数2=值2
        String url = "jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false";

        Connection connection = DriverManager.getConnection(url, username, password);

            try (
                PreparedStatement ps1 = connection.prepareStatement("insert into  user(username, pwd) values(?,?) ");
                PreparedStatement ps2 = connection.prepareStatement("insert into  user(username, pwd) values(?,?) ")) {

            //JDBC中默认事务是自动提交的,false就不会自动提交
            connection.setAutoCommit(false);

            ps1.setString(1, "1111tranc ps 1二当家小D");
            ps1.setString(2, "123456");

            ps2.setString(1, "2222tranc ps 2二当家小D");
            ps2.setString(2, "123456");

            ps1.execute();

            //模拟异常
            int i = 1/0;

            ps2.execute();


        } catch (Exception e) {
            e.printStackTrace();

            //事务回滚
            connection.rollback();

        } finally {
                //事务提交
            connection.commit();


            connection.close();
        }

    }

封装DBUtils工具类

  • 优化JDBC操作,提高效率
  • javaweb项目中,使用jdbc需要添加mysql启动到tomcat里面

db.properties

url=jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false
username=root
password=xdclass.net
driver=com.mysql.jdbc.Driver

CustomDBUtil

public class CustomDBUtil {

    private static String url;

    private static String username;

    private static String password;

    private static String driver;
  
    static {
        try {
            Properties properties = new Properties();

            properties.load(CustomDBUtil.class.getClassLoader().getResourceAsStream("db.properties"));

            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            driver = properties.getProperty("driver");

            //加载JDBC驱动程序
            Class.forName(driver);

        }catch (Exception e){
            e.printStackTrace();
        }
    }
  
    /**
     * 获取连接
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception{

        Connection connection = DriverManager.getConnection(url,username,password);
        return connection;
    }

    /**
     * 关闭数据库资源
     * @param resultSet
     * @param ps
     * @param connection
     */
    public static void close(ResultSet resultSet, PreparedStatement ps, Connection connection){
        try{
            if(resultSet!=null){
                resultSet.close();
            }

            if(ps!=null){
                ps.close();
            }
            if(connection!=null){
                connection.close();
            }

        }catch (SQLException e){
            throw  new RuntimeException();
        }
    }
}

TestJDBCServlet

@WebServlet({"/jdbc"})
public class TestJDBCServlet extends HttpServlet {
    public TestJDBCServlet() {
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String idStr = req.getParameter("id");
        int id = Integer.parseInt(idStr);

        try {
            Connection connection = CustomDBUtil.getConnection();
            PreparedStatement ps = connection.prepareStatement("select  * from user where  id=?");
            ps.setInt(1, id);
            ResultSet resultSet = ps.executeQuery();

            while(resultSet.next()) {
                System.out.println("用户名称 name=" + resultSet.getString("username") + "  联系方式 wechat=" + resultSet.getString("wechat"));
            }

            CustomDBUtil.close(resultSet, ps, connection);
        } catch (Exception var8) {
            var8.printStackTrace();
        }

    }
}

池化思想

  • 为什么要用连接池

    • 数据库建立Connection比较耗时,频繁的创建和释放连接引起的大量性能开销
    • 如果数据库连接得到重用,避免这些开销,也提高了系统稳定
    • 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用,对于业务请求处理而言,直接利用现有可用连接,缩减了系统整体响应时间
    • 统一的连接管理,避免数据库连接泄漏、超时占用等问题
  • 同类对比其他池化思想

    • Java线程池
    • tomcat连接池
    • 对象池(SpringIOC容器)

主流DB工具类、数据库连接池

  • 数据库工具类 : Apache commens-dbutils

    • Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,能极大简化jdbc编码的工作量,同时也不会影响程序的性能
    • 地址:https://commons.apache.org/proper/commons-dbutils/
    • 导入
      • 添加到IDEA
      • 可以添加到web-inf的lib包(添加到tomcat效果是一样的)
  • 数据库连接池:c3p0、druid、dbcp

所有依赖包

commons-pool2-2.8.0 、commons-logging-1.2、commons-dbcp2-2.7.0、commons-dbutils-1.7、mysql-connector-java-5.1.46

https://abc1024.oss-cn-shanghai.aliyuncs.com/Picture/Javaweb/packages.rar

DBCP连接池、dbutils工具类

创建配置文件database.properties

driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/xd_web?useUnicode=true&characterEncoding=utf-8&useSSL=false
username = root
password = xdclass.net

initialSize=10              //连接池建立时创建的连接的数量
maxActive=30            //连接池同一时间内最多能够分配的活动连接的数量

数据库连接池工具类(用于返回DataSource,更方便使用dbutils工具类)

/**
 * 数据库连接池工具类
 */
public class DataSourceUtil {

    //连接池
    private static DataSource dataSource;

    static {

        try{

            InputStream in = DataSourceUtil.class.getClassLoader().getResourceAsStream("database.properties");
            Properties p = new Properties();
            p.load(in);
	    //BasicDataSourceFactory用于创建连接池
            dataSource = BasicDataSourceFactory.createDataSource(p);

        }catch (Exception e){
            e.printStackTrace();
            throw new ExceptionInInitializerError("初始化DBPC失败");
        }
    }

    /**
     * 获取连接池
     * @return
     */
    public static DataSource getDataSource(){
        return dataSource;
    }

}

dbutils工具介绍

DbUtils 中的核心类/接口

  • QueryRunner

    • 查询执行器,提供对sql语句操作的API
    • update(String sql,Object...params) 可执行 增-INSERT、删-DELETE、改-UPDATE
    • query(String sql,ResultSetHandler rsh,Object...params) 可执行 查询-SELECT
  • ResultSetHandler

    • 结果集处理类,执行处理一个结果集对象,将数据转变并处理为任何一种形式
      • BeanHandler 结果集中的第一行数据封装到一个对应的JavaBean实例
      • BeanListHandler 结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里
      • MapHandler 结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值
      • MapListHandler 结果集中的每一行数据都封装到一个Map里,然后再存放到List
      • ScalarHandler 结果集中第一行数据指定列的值,常用来进行单值查询
public class UserDao {

    private QueryRunner queryRunner = new QueryRunner(DataSourceUtil.getDataSource());

    //开启驼峰映射
    private BeanProcessor bean = new GenerousBeanProcessor();
    private RowProcessor processor = new BasicRowProcessor(bean);

    /**
     * 新增
     * queryRunner.update(sql,params);
     * @param user
     * @return
     * @throws Exception
     */
    public int save(User user) throws Exception {

        String sql = "insert into user (phone,pwd,sex,img,create_time,role,username,wechat) values(?,?,?,?,?,?,?,?)";

        Object [] params = {
                user.getPhone(),
                user.getPwd(),
                user.getSex(),
                user.getImg(),
                user.getCreateTime(),
                user.getRole(),
                user.getUsername(),
                user.getWechat()
        };
//        String sql = "delete from user where id= ?";
//        Object [] params = { 1};

        int i = 0;
        try{

           i = queryRunner.update(sql,params);

        }catch (Exception e){
            e.printStackTrace();
            throw new Exception();
        }
        return i;
    }

    /**
     * BeanHandler 结果集中的第一行数据封装到一个对应的JavaBean实例
     * @param id
     * @return
     */
    public User findById(int id){
        String sql = "select * from user where id=?";
        User user = null;
        try {
            user  =  queryRunner.query(sql,new BeanHandler<>(User.class,processor),id);

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return user;
    }

    /**
     * BeanListHandler 结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里
     * @return
     */
    public List<User> list(){
        String sql = "select * from user";
       List<User> list = null;
        try {
            list  =  queryRunner.query(sql,new BeanListHandler<>(User.class,processor));

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 根据id找用户
     * MapHandler  结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值
     * @param id
     * @return
     */
    public Map<String,Object> findByIdWithMap(int id){
        String sql = "select * from user where id=?";
        Map<String,Object> map = null;
        try {
            map  =  queryRunner.query(sql,new MapHandler(),id);

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 小滴课堂jdbc实战 https://xdclass.net
     *
     * 查找全部用户
     * MapListHandler 果集中的每一行数据都封装到一个Map里,然后再存放到List
     * @return
     */

    public List<Map<String,Object>> listWithMap(){
        String sql = "select * from user";
        List<Map<String,Object>> list = null;
        try {
            list  =  queryRunner.query(sql,new MapListHandler());

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * ScalarHandler 结果集中第一行数据指定列的值,常用来进行单值查询
     * @return
     */
    public int countUser(){

        String sql = "select count(*) from user";

        Long count = null;

        try{

            count = (Long)queryRunner.query(sql,new ScalarHandler<>());

        }catch (Exception e){
            e.printStackTrace();
        }
        return count.intValue();
    }
}

Maven依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>net.xdclass</groupId>
  <artifactId>xd_forum</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>xd_forum Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>


    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>


    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.41</version>
    </dependency>

    <!-- JSP -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>provided</scope>
    </dependency>


    <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
    <dependency>
      <groupId>commons-dbutils</groupId>
      <artifactId>commons-dbutils</artifactId>
      <version>1.7</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>2.7.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
    <dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.9.4</version>
    </dependency>





    <!-- https://mvnrepository.com/artifact/taglibs/standard -->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>


    <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>


  </dependencies>

  <build>

    <!--专门用于打包配置文件到类路径-->
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
    </resources>



    <finalName>xd_forum</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>


作者:Soulboy