`
chenzehe
  • 浏览: 532811 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JDBC 快速入门

阅读更多

一、JDBC分类

JDBC驱动程序按照工作方式分为四类:
    1、JDBC-ODBC bridge + ODBC 驱动
       JDBC-ODBC bridge桥驱动将JDBC调用翻译成ODBC调用,再由ODBC驱动翻译成访问数据库命令。
       优点:可以利用现存的ODBC数据源来访问数据库。
       缺点:从效率和安全性的角度来说的比较差。不适合用于实际项目。
    2、基于本地API的部分Java驱动
       我们应用程序通过本地协议跟数据库打交道。然后将数据库执行的结果通过驱动程序中的Java部分返回给客户端程序。
       优点:效率较高。
       缺点:安全性较差。
    3、纯Java的网络驱动
       (中间协议)            (本地协议)
       app    JDBC     纯Java                 中间服务器               DB
       缺点:两段通信,效率比较差
       优点:安全性较好
    4、纯Java本地协议:通过本地协议用纯Java直接访问数据库。
       特点:效率高,安全性好。

 

二、JDBC 编程的步骤

1、加载和注册数据库驱动Driver

1.1 使用Class.forName(driverName)自动注册,需要把驱动的jar包导进来,需处理异常,driverName为各数据库厂商驱动名,如:

String driverName = "com.mysql.jdbc.Driver";//MySQL的
String driverName = "oracle.jdbc.driver.OracleDriver";//Oracle的

 1.2 实例化具体的Driver驱动:

Driver driver = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver); 

 这种写法一般不用,不能参数化驱动名,不够灵活,一般使用上面第一种方式。每个数据库厂商会实现Driver接口,并会调用DriverManager的静态registerDriver方法,如MySQL实现的:

	static {
		try {
			java.sql.DriverManager.registerDriver(new Driver());
		} catch (SQLException E) {
			throw new RuntimeException("Can't register driver!");
		}
	}

  2、连接数据库
        conn = DriverManager.getConnection(url, username, password);//需处理异常
        //Connection返回数据库连接,如:“com.mysql.jdbc.Connection@1ffb8dc”;连接不成功则返回 null
 3、创建Statement对象
        stmt = conn.createStatement();//需处理异常,返回其生成结果的对象
        /*为了类型安全和批量更新的效率,建议用PreparedStatement
         String sql = "insert into tableName values(?,?)"; // "?"占位符
         stmt = conn.prepareStatement(sql); */
4、操作数据库,执行SQL语句
        String sql = "select * from tableName";
        rs = stmt.executeQuery(sql); //executeQuery(sqlString) 查询 返回查询结果集
        String sql = "insert into tableName values(?,?)"; // "?"占位符
        int number = stmt.executeUpdate(sql);//更新,再返回int(更新、修改影响的条数)
        //executeUpdate(sql) 执行给定 SQL 语句,如 INSERT、UPDATE 或 DELETE 等不返回任何内容的语句
        //用PreparedStatement时,已经有语句: rs = stmt.executeQuery();
    5.处理数据(游标)

        StringBuffer sb = new StringBuffer();
        ResultSetMetaData md = rs.getMetaData(); //ResultSetMetaData可获取列的类型和属性信息
        int col = md.getColumnCount(); //获取列的数目
        while(rs.next()){ //rs.next()使游标下移一位,返回boolean,没有下一个结果则返回false
            for(int i=1; i<=col;i++){ // index(JDBC 的下标从1开始)
                sb.append(md.getColumnName(i)+"="+rs.getString(i)+"  ");
            }
            sb.append("\n");
        }
       System.out.println(sb);

    游标的初始位置在第一条记录的前面,使第一次调用next()后,刚好拿到第一个结果。
    游标的最终位置在最后一条记录的后面(结果集的前面和后面留空,真正存在)
6、释放资源,断开与数据库的连接
      先判断是否有引用资源,再释放,释放空资源会抛异常:       

		if (rs != null) {
			try {
				rs.close();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}

注意顺序,要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,因为 ResultSet需要Statement和Connection连接时才可以用的;Statement也需要Connection才可用;结束 Statement之后有可能其它的Statement还需要连接,因此不能先关闭Connection,ResultSet同理。

JDBC访问数据库例子:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class JdbcTest {
	public static void main(String[] args) {
		String driverName = "com.mysql.jdbc.Driver";
		String url = "jdbc:mysql://192.168.0.248:3306/test?characterEncoding=UTF-8";
		String username = "huisou";
		String password = "huisou";
		Connection con = null;
		PreparedStatement stmt = null;
		try {
			Class.forName(driverName);
			con = DriverManager.getConnection(url, username, password);
			String query = "insert into student(age,name) values (?,?)";
			stmt = con.prepareStatement(query);
			stmt.setInt(1, 25);
			stmt.setString(2, "lilei");
			stmt.executeUpdate();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			if (stmt != null)
				try {
					stmt.close();
				}
				catch (Exception e) {
					e.printStackTrace();
				}
			if (con != null)
				try {
					con.close();
				}
				catch (Exception e) {
					e.printStackTrace();
				}
		}
	}
}

 
三、java.sql和javax.sql

JDBC中包括了两个包:java.sql和javax.sql

1、java.sql 这个包中的类和接口主要针对基本的数据库编程服务,如生成连接、执行语句以及准备语句和运行批处理查询等。同时也有一些高级的处理,比如批处理更新、事务隔离和可滚动结果集等。

2、javax.sql 主要为数据库方面的高级操作提供了接口和类。如为连接管理、分布式事务和旧有的连接提供了更好的抽象,它引入了容器管理的连接池、分布式事务和行集等。

 

四、JDBC对象解释

1、Connection 数据库连接对象,与特定数据库的连接(会话),能够通过getMetaData方法获得数据库提供的信息、所支持的SQL语法、存储过程和此连接的功能等信息。

2、Driver 每个驱动程序类必需实现的接口,每个数据库驱动程序也都应该提供一个实现Driver接口的类。

3、DriverManager 工具类,管理一组JDBC驱动程序的基本服务。作为初始化的一部分,此接口会尝试加在”jdbc.drivers”系统属性中引用的驱动程序。只是一个辅助类。

4、Statement 用于执行静态SQL语句并返回其生成结果的对象,在向数据库发送相应的SQL语句时,都需要创建Statement接口或 PreparedStatement接口。在具体应用中,Statement主要用于操作不带参数(可以直接运行)的SQL语句,比如删除语句、添加或更 新。

5、PreparedStatement 继承Statement接口,表示预编译的SQL语句的对象,SQL语句被预编译并且存储在PreparedStatement对象中。使用PreparedStatement有下面三步:

 一:通过连接获得PreparedStatement对象,用带占位符(?)的sql语句构造。
            PreparedStatement  pstm = con.preparedStatement(“insert into student(age,name) values (?,?)”);
 二:设置参数
           stmt.setInt(1, 25);
           stmt.setString(2, "lilei");
三:执行sql语句
            Rs  =  pstm.excuteQuery();

       Statement发送完整的Sql语句到数据库不是直接执行而是由数据库先编译,再运行。每次都需要编译。而PreparedStatement是先发送带参数的Sql语句,由数据库先编译,再发送一组组参数值(同构时不需重复编译)。

同构:两个Sql语句可编译部分是相同的,只有参数值不同;
异构:整个sql语句的格式是不同的;
       如果是同构的sql语句,PreparedStatement的效率要比statement高。而对于异构的sql则两者效率差不多。一般都用 PreparedStatement代替Statement,因为它是类型安全的。Statement对参数类型不作检查,故不够安全。使用时注意下面几 点:

    1、使用预编译的Statement编译多条Sql语句一次执行
    2、可以跨数据库使用,编写通用程序
    3、能用预编译时尽量用预编译
    4、如果第二个SQL语句与前一个是异构的,需要再次编译“ps = con.prepareStatement(sql);“

6、CallableStatement 用来访问数据库中的存储过程,它提供了一些方法来指定语句所使用的输入/输出参数。

7、ResultSet 查询结果集接口,它对返回的结果集进行处理。

8、 ResultSetMetaData 对元数据进行操作的接口,可以实现很多高级功能,Hibernate运行数据库的操作,大部分都是通过此接口。可以认为,此接口是SQL查询语言的一种反 射机制。ResultSetMetaData接口可以通过数组的形式,遍历数据库的各个字段的属性。

       JDBC通过元数据(MetaData)来获得具体的表的相关信息,例如,可以查询数据库中有哪些表,表有哪些字段,以及字段的属性等。MetaData中通过一系列getXXX将这些信息返回给我们。

JDBC通过元数据(MetaData)来获得具体的表的相关信息,例如,可以查询数据库中有哪些表,表有哪些字段,以及字段的
       数据库元数据 Database MetaData 用connection.getMetaData()获得;包含了关于数据库整体元数据信息。
       结果集元数据 ResultSet MetaData 用resultSet.getMetaData()获得;比较重要的是获得表的列名,列数等信息。
       结果集元数据对象:ResultSetMetaData meta = rs.getMetaData();
                字段个数:meta.getColomnCount();
                字段名字:meta.getColumnName();
                字段JDBC类型:meta.getColumnType();
                字段数据库类型:meta.getColumnTypeName();
       数据库元数据对象:DatabaseMetaData dbmd = con.getMetaData();
                数据库名:dbmd.getDatabaseProductName();
                数据库版本号:dbmd.getDatabaseProductVersion();
                数据库驱动名:dbmd.getDriverName();
                数据库驱动版本号:dbmd.getDriverVersion();
                数据库Url:dbmd.getURL();
                该连接的登陆名:dbmd.getUserName();

 五、JDBC中的事务编程

    1、事务是具备以下特征(ACID)的工作单元:
        原子性(Atomicity)—— 如果因故障而中断,则所有结果均被撤消;
        一致性(Consistency)—— 事务的结果保留不变;
        孤立性(Isolation)—— 中间状态对其它事务是不可见的;
        持久性(Durability)—— 已完成的事务结果上持久的。
        原子操作,也就是不可分割的操作,必须一起成功一起失败。
     2、事务处理三步曲:(事务是一个边界)
        ① connection.setAutoCommit(false); //把自动提交关闭;在创建Statement对象之前。
        ② 正常的DB操作                       //若有一条SQL语句失败了,自动回滚
        ③ connection.commit()              //主动提交
        和 connection.rollback()            //主动回滚,一般写在catch语句里,而前三个都写在try语句里

try{
    con.setAutoCommit(false);   //step① 把自动提交关闭
    Statement stm = con.createStatement();    //step② 正常的DB操作
    stm.executeUpdate("insert into person(id, name, age) values(520, 'X-Man', 18)");
    stm.executeUpdate("insert into Person(id, name, age) values(521, 'Super', 19)");
    con.commit();               //step③ 成功主动提交
} catch(SQLException e){
    try{con.rollback();        //如果中途发生异常,则roolback;这语句也会抛异常
    }catch(Exception e){e.printStackTrace();}    //step③ 失败则主动回滚
}

      3、JDBC事务并发产生的问题和事务隔离级别
     JDBC事务并发产生的问题:
        ① 脏读(Dirty Reads) 一个事务读取了另一个并行事务还未提交的数据。(产生原因:读-写)
        ② 不可重复读(UnPrpeatable Read)一个事务前后两次读取数据时,得到的数据不一致,被另一个已提交的事务修改。
        ③ 幻读(Phantom Read) 一个事务再次查询,记录中的量变化了。(仅对统计有影响)
     为了避免以上三种情况的出现,则采用事务隔离级别:
        TRANSACTION_NONE                不使用事务(不可能用,只是理论的)
        TRANSACTION_READ_UNCOMMITTED    可以读取未提交数据(允许脏读,也不可能)
        TRANSACTION_READ_COMMITTED      只读提交的数据:可防止脏读;大部分数据库的默认隔离级别
        TRANSACTION_REPEATABLE_READ     重复读取;只可以避免脏读
        TRANSACTION_SERIALIZABLE        事务串行化:可以避免脏读,重复读取和幻读,但会降低数据库效率(最常用)
     以上的五个事务隔离级别都是在Connection类中定义的静态常量。隔离级别越高,数据越安全,并发能力越差。
     使用setTransactionIsolation(int level) 方法可以设置事务隔离级别。
     比如:con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);

 

六、Scrollability 结果集可滚动

        可双向支持绝对与相对滚动,对结果集可进行多次迭代。
        Con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
        //上句的 SCROLL 再到 CONCUR;不可以写反,编译器无法检测到,因为他们都是int类型的。
        TYPE_FORWARD_ONLY:(单向,一般不用)该常量指示指针只能向前移动的 ResultSet 对象的类型。
        TYPE_SCROOL_INSENSITIVE:(双向、不敏感)可滚动但不受其他更改影响的 ResultSet 对象的类型。
        TYPE_SCROLL_SENSITIVE:(双向、敏感)该常量指示可滚动并且通常受其他的更改影响的 ResultSet 对象的类型。
        CONCUR_READ_ONLY:(只读)该常量指示只可以读取的 ResultSet 对象的并发模式。
        CONCUR_UPDATABLE:(可更新)该常量指示可以更新的 ResultSet 对象的并发模式。
        绝对定位:boolean absolute(int row)将游标移动到指定位置。(row指记录的序号,没有这位置则返回false)
                void afterLast() 将游标指向最后一条记录的后一位(有这位置,但记录为空)。
                void beforeFirst()将游标指向最前一条记录的前一位。
                boolean first()将游标移动到结果集最前。
                boolean last()将游标移动到结果集末尾。
        相对定位:boolean next()指向下一个。
                boolean previous()指向前一个。
                boolean relative(int) 向next()方向移动 int 位(int 可负)。
        判位函数:boolean isAfterLast() 是否在最后一条的后一位。
                boolean isBeforeFirst() 是否最前一条记录的前一位。
                boolean isFirst() 是否最前位置。
                boolean isLast() 是否最后位置。

 七、Updatability结果集可更新

        rs.updateString(“name”,”Tony”);//前面一个是字段的名字或者序号
        rs.updateInt(1,”122323”);修改
        rs.deleteRow();删除
        rs.updateRow();

        只有在必要的时候(如桌面应用)才用结果集更新数据库,因为使用结果集更新数据库效率低下。可更新结果集还要看数据库驱动程序是否支持,如Oracle就 支持,MySql不支持。并且只能针对一张表做结果集更新(不能子查询),而且不能有join操作,必须有主健,必须把所有非空没有默认值的字段查出,处 理可更新结果集时不能用select *来查询语句,必须指出具体要查询的字段,不能使用通配符。

 

 八、Batch updates 批量更新

 将多组对数据库的更新操作发送到数据库统一执行(数据库支持并发执行操作),以提高效率。主要是通过减少数据(Sql语句或参数)在网络上传输的次数来节省时间。

1、对于Statement的批量更新处理:
            stm.addBatch(Sql);
            int[] ResultSet=stm.executeBatch();

2、对于PreparedStatement的批量更新处理

             pstm.setInt(1,12);pstm.setString(2,”gaga”);
             pstm.addBatch();
             int[] ResultSet=pstm.executeBatch();

       int[] 中每一个数表示该Sql语句影响到的记录条数,PreparedStatement的更新操作比Statement的更新操作多了一个设置参数的过程。

 

 九、JNDI 命名目录服务器

JNDI(Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。 JNDI的方法是在javax.naming包下,接口是Context实现类是InitialContext,是Java的命名目录服务器。而JDBC 是Java的数据库访问接口。

        bind(String name, Object obj) 将名称绑定到对象资源,建立指定的字符串和对象资源的关联
        lookup(String name) ,通过指定的字符串获得先前绑定的资源
JNDI与JDBC:
JNDI提供了一种统一的方式,可以用在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个纪录,同时返回数据库连接建立所必须的信息。
代码示例:

		try {
			Context cntxt = new InitialContext();
			DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");
		}
		catch (NamingException ne) {
			...
		}

 

 十、DataSourse 数据源

 

package javax.sql;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Wrapper;
public interface DataSource  extends CommonDataSource,Wrapper {
    Connection getConnection() throws SQLException; 
    Connection getConnection(String username, String password) throws SQLException;
}
 用于提供到此 DataSource 对象所表示的物理数据源的连接。作为 DriverManager 工具的替代项,DataSource 对象是获取连接的首选方法。实现 DataSource 接口的对象通常在基于 JavaTM Naming and Directory Interface (JNDI) API 的命名服务中注册。

 

<!-- Generated by javadoc (build 1.6.0-beta2) on Mon Mar 19 18:32:23 CST 2007 -->

<noscript></noscript>

DataSource 接口由驱动程序供应商实现。共有三种类型的实现:

    1. 基本实现 - 生成标准的 Connection 对象
    2. 连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
    3. 分布式事务实现 - 生成一个
Connection
      <!-- Generated by javadoc (build 1.6.0-beta2) on Mon Mar 19 18:32:23 CST 2007 -->
<noscript></noscript>
    对象,该对象可用于分布式事务,大多数情况下总是参与连接池。此实现与中间层事务管理器一起使用,大多数情况下总是与连接池管理器一起使用。

<!-- Generated by javadoc (build 1.6.0-beta2) on Mon Mar 19 18:32:23 CST 2007 -->

<noscript></noscript>

通过 DataSource 对象访问的驱动程序本身不会向 DriverManager 注册。通过查找操作获取 DataSource 对象,然后使用该对象创建 Connection 对象。使用基本的实现,通过 DataSource 对象获取的连接与通过 DriverManager 设施获取的连接相同。

        

1、包含了连接数据库所需的信息,可以通过数据源获得数据库连接,有时由于某些连接数据库的信息会变更,所以经常使用包含数据库连接信息的数据源。
        2、一个标准的数据库连接工厂,作为DriverManager的替代项,保存与数据库相关的信息, 可以将数据库的连接信息放在一个共享的空间进行提取,不用在本地安装。
           支持JNDI的绑定,支持连接池,支持分布式服务,用getConnection方法可获得与数据库的连接。 数据源应该由管理员创建(目的是为了保证数据库的安全)。所以数据源对象一般放在JNDI服务器中。

通过JNDI获得绑定的资源:

	public static Object lookup(String context) throws NamingException {
		Properties pro = new Properties();
		// Weblogic的JNDI服务器参数
		pro.put(InitialContext.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
		pro.put(InitialContext.PROVIDER_URL, "t3://localhost:7001");
		Context ctx = new InitialContext(pro);
		return ctx.lookup(context);// 查找;通过指定的字符串获得先前绑定的资源。
	}

 

 十一、连接池

在内存中用来保存一个个数据库连接的对象。
        访问数据库时,建立连接和拆连接需要花费较长时间,通过以连接池直连的方式获取连接,不需要注册驱动程序,可以大量的节省销毁和创建连接的资源消耗,提高 访问数据库的效率。通过连接池获得的Connection,当执行con.close()时,不是关闭连接,而是表示将连接释放回连接池。
         连接池是一个很复杂的算法,常见的连接池有C3P0、DBCP、BoneCP、Druid等。

 

十二、分布式的事务管理器JTA(Java Transaction API)

      分布式事务是通过多个异地数据库执行一组相关的操作,要保证原子操作的不可分,也不用再自己写commit,和rollback,全部都交给中间服务器(TM)来处理。

      如果计划用JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和
javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个
XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。

 

 

分享到:
评论

相关推荐

    jdbc快速入门.pdf

    JDBC 本质:其实是官方(sun 公司)定义的一套操作所有关系型数据 库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱 动 jar 包。我们可以使用这套接口(JDBC)编程,真正执行的代码是 驱动 jar 包中的...

    JDBC快速入门相关笔记

    JDBC 概念 java数据库连接,java语言操作数据库 使用统一的一套JAVA代码可以操作所有关系型数据库JDBC定义了一套所有关系型数据库的规则 每一种数据库 厂商都会提供自己的JDBC实现类 实现类:数据库驱动 本质 :由...

    《-JDBC快速入门-》

    是本篇文章的PDF格式,对关键部分的图片进行了补充

    muxin-4#muxin-note#01、JDBC快速入门1

    我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动 jar 包中的实现类什么是实现类Person 接口 Worker 类 Person p = new

    JDBC基础入门教程

    JDBC基础教程, 是JDBC的入门教程, 让你快速了解JDBC的用法.

    presto_jdbc

    presto jdbc 快速入门demo

    JDBC概述+快速入门+API详解+数据库连接池

    JDBC概述+快速入门+API详解+数据库连接池

    JSP快速入门教程

    JSP快速入门教程 6 实例:hello.jsp  创建一JSP快速入门教程 第一讲(参考《Java Web程序设计基础教程》第1章) 1 JSP 和 Java的关系  一般Java指的标注版 Java SE  另外两个版本:Java EE 和 Java ME  JSP属于...

    springJdbcDemo11_java_springjdbc_

    spring集成JDBC 入门源码,快速上手,快速理解spring

    Spring基础与快速入门

    其次针对框架而言,由于业务逻辑中没有Spring的API,所以业务逻辑也可以从Spring框架快速的移植到其他框架。 2 容器:Spring提供容器功能,容器可以管理对象的生命周期,对象与对象之间的依赖关系。你可以写一个...

    sqljdbc42.zip

    本部分提供使用 Microsoft JDBC Driver for SQL Server 与 SQL Server 数据库建立简单连接的快速入门指导。 在连接到 SQL Server 数据库之前,必须首先在本地计算机或服务器上安装 SQL Server,并且必须在本地计算机...

    JDBC使用教材-同济大学软件学院

    JDBC使用频率非常高故推荐上课时用的教材。帮助新手快速入门。

    JDBC学习笔记(java链接数据库的基础)

    java链接数据库的常用方法-- JDBC。 基本的JDBC知识介绍和使用。 可快速入门,也可当手册使用。 另外,最后还有一个JDBC工具类,以供使用。

    mybatis框架学习笔记--快速入门

    内容概要:mybatis学习笔记,适合刚接触mybatis的人能让你快速入门。 适用人群:大学生或者初基础mybatis的人 使用场景及目标:idea集成mybatis,简化jdbc

    javaWEb快速入门项目--选课系统

    学习javaWEB的快速入门项目,学生选课系统,使用jsp+servlet技术 数据库使用mysql数据库 采用jdbc+Dbutils组件;使用的db连接池是c3p0。

    jdbc基础

    JDBC基础-快速入门 &lt;br&gt;创建完整的JDBC应用程序

    Mybatis持久层框架快速入门(环境搭建、xml配置文件、注解).zip

    本资源包含mybatis快速入门案例(含sql) mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂...

    chapter6_jspjdbc_

    jdbc 连接mysql以及jdbc的简单使用,可以帮助初学者快速入门

    JDBC基础培训课件ppt

    JDBC基础培训课件ppt,很基础的一些知识,带你快速入门。

    JAVA WEB 新手入门笔记

    五、 JDBC 六、 JDBC连接池 七、 DBUtils 八、 Tomcat & Http 九、 Servlet & request & response 十、 JSP & EL 十一、 Cookie & Session 十二、 Listener 十三、 Filter 十四、 文件的上传和下载 十五、...

Global site tag (gtag.js) - Google Analytics