42道JavaWeb高频题整理(附答案背诵版)
1、说一说Servlet的生命周期?
Servlet的生命周期主要由以下三个阶段组成:初始化,服务和销毁。
-
初始化(Initialization): 当一个Servlet被载入到内存中时(例如,第一次访问或者服务器启动并且在web.xml中配置了load-on-startup),Servlet容器(例如Tomcat)就会调用Servlet的
init()
方法进行初始化。此方法在Servlet的生命周期中只被调用一次。 -
服务(Servicing): 一旦Servlet被初始化,对其的每一次请求(例如HTTP请求)Servlet容器都会根据请求类型调用相应的方法(例如
doGet()
,doPost()
等)。这个阶段会重复执行,每次有新的请求时都会被调用。 -
销毁(Destruction): 当Servlet容器需要从内存中移除Servlet实例时(例如服务器关闭或者手动卸载Servlet),就会调用Servlet的
destroy()
方法。它也只在Servlet的生命周期中被调用一次。
举一个应用场景的例子,假设我们有一个用于处理用户登录请求的LoginServlet
。当服务器第一次启动或者第一次收到登录请求时,LoginServlet
会被初始化,调用init()
方法。然后,每当有用户发送登录请求时,LoginServlet
就会调用 doPost()
方法处理这个请求。最后,当服务器关闭或者我们不再需要LoginServlet
时,就会调用destroy()
方法,销毁这个Servlet。
2、Servlet API中forward()与redirect()的区别?
forward()
和 redirect()
都是用于在服务器端处理请求后,将请求/响应转发或重定向到另一个资源(例如另一个 Servlet,或者是一个 HTML 页面等)的方法。但是,它们的工作方式和使用场景有些不同。
1. forward():
forward()
方法是在服务器端进行的,客户端(浏览器)并不知道发生了转发,所以浏览器的 URL 地址栏不会改变。- 转发是在服务器内部进行的,所以它更快,且不需要服务器和客户端之间的额外通信。
- 当使用
forward()
方法时,请求对象和响应对象可以在资源之间共享,这意味着你可以在请求的属性中设置数据,然后在被转发的资源中获取这些数据。
2. redirect():
redirect()
方法是通过向客户端(浏览器)发送一个带有新 URL 的响应来工作的,然后客户端会向这个新 URL 发送一个新的请求。所以,浏览器的URL地址栏会显示新的地址。- 重定向需要服务器和客户端之间的额外通信,所以它比转发稍慢一些。
- 由于
redirect()
会导致新的请求,所以原始请求对象中的数据不会被保留。
举个例子,假设有一个电子商务网站,用户在浏览商品的时候,如果他们未登录,我们可能会使用 forward()
方法将请求转发到登录页面,因为我们需要保留用户原来的请求(即他们浏览的商品),以便在他们登录后可以继续处理。然而,如果用户完成了购物,我们可能会使用 redirect()
方法将他们重定向到一个确认页面,因为我们希望这个确认页面在浏览器的历史记录中有一个单独的条目,这样用户就可以使用浏览器的后退按钮返回到购物页面,而不会再次提交购物请求。
3、request.getAttribute()和 request.getParameter()有何区别?
request.getAttribute()
和 request.getParameter()
是 Java Web 编程中常见的两种方法,它们在 HTTP 请求处理中有着不同的用途和含义。
-
request.getParameter():这个方法是用来获取客户端(通常是一个网页表单)发送的参数。这些参数是通过 GET 或 POST 请求发送的。例如,如果您有一个登录表单,其中包含用户名和密码字段,那么您可以使用
request.getParameter("username")
和request.getParameter("password")
来获取这些字段的值。 -
request.getAttribute():这个方法是用来从请求范围(request scope)获取对象的。当您在处理一个请求时,可以在请求范围内设置对象,然后在稍后的处理阶段或者在 JSP 页面中获取这些对象。例如,一个 Servlet 可以通过
request.setAttribute("data", data)
来设置一个名为 "data" 的属性,然后在 JSP 页面中可以通过${data}
来获取和显示这个对象。
所以,主要的区别在于,getParameter()
是用来获取客户端发送的参数,而 getAttribute()
是用来在服务器端的请求处理过程中共享对象。
举个例子,假设您有一个用来处理用户登录的 Servlet。用户会从一个 HTML 表单中输入他们的用户名和密码,然后这些信息会通过 POST 请求发送到您的 Servlet。在您的 Servlet 中,您可以使用 request.getParameter("username")
和 request.getParameter("password")
来获取这些信息。然后,您可能会验证这些信息,并根据验证结果,将一些信息(如用户对象或错误消息)放入请求范围,以便在转发到不同的 JSP 页面时使用。这就是 request.setAttribute()
和 request.getAttribute()
的用途。
4、jsp静态包含和动态包含的区别
在 JSP 中,包含操作可以是静态的(也被称为编译时包含)或动态的(也被称为运行时包含)。它们的主要区别在于包含操作发生的时间和方式。
-
静态包含:静态包含使用 JSP 指令
<%@ include file="file.jsp" %>
来实现。这种包含在 JSP 页面编译时发生。换句话说,被包含的 JSP 页面的内容在编译时就被插入到主 JSP 页面中,然后作为一个整体一起编译。因此,如果被包含的页面在包含后发生更改,这些更改将不会反映在主页面上,除非主页面重新编译。 -
动态包含:动态包含使用 JSP 动作
<jsp:include page="file.jsp" />
来实现。这种包含在请求处理期间,也就是运行时发生。每次请求主 JSP 页面时,都会执行包含操作,并执行被包含的 JSP 页面的代码。因此,如果被包含的页面在包含后发生更改,这些更改将会在下次请求主页面时反映出来。
举个例子,假设我们有一个网站的头部和尾部是在所有页面上都一样的,我们可以用静态包含将它们包含在每个页面中。但是,如果我们有一个天气小部件,它需要根据当前的天气实时更新,那么我们可能会选择使用动态包含,以确保每次请求页面时都能获取最新的天气信息。
5、MVC的各个部分都有那些技术来实现?如何实现?
MVC(Model-View-Controller)是一种设计模式,用于分离应用程序的数据访问、用户界面和业务逻辑,主要用于简化应用程序的组织和实现。在 Java Web 开发中,通常使用以下技术来实现 MVC 设计模式:
-
Model(模型):模型代表应用程序的数据和业务逻辑。它通常包含与数据库交互的代码,以及处理数据的算法和逻辑。在 Java Web 应用程序中,模型通常由 POJO (Plain Old Java Object) 类来实现,这些类通常与数据库表一一对应。另外,数据访问对象(DAO)和服务层也可以被看作是模型的一部分,用于封装具体的数据库操作和业务逻辑。
在 Java 中,我们可以使用各种 ORM 框架(如 Hibernate、MyBatis 等)来实现与数据库的交互。
-
View(视图):视图负责将模型的数据展示给用户。在 Java Web 开发中,视图通常由 JSP 或 Thymeleaf 这样的模板引擎来实现。
例如,一个 JSP 页面可能会使用 EL (Expression Language) 和 JSTL (JSP Standard Tag Library) 来访问模型数据并将其呈现给用户。
-
Controller(控制器):控制器处理用户的请求,调用模型的逻辑,并更新视图。在 Java Web 开发中,控制器通常由 Servlet 或 Spring MVC 的 Controller 类来实现。
例如,一个 Servlet 可以接收用户的请求,从请求中获取参数,然后调用模型的方法来处理这些参数。处理完成后,Servlet 可以将结果存储在请求或会话范围的属性中,然后转发或重定向到一个 JSP 页面,该页面将使用这些结果来生成响应给用户。
以下是一个简单的示例,展示了如何使用 Servlet、JSP 和 POJO 类来实现 MVC 设计模式:
// Model
public class User {
private String name;
// getters and setters...
}
// Controller (Servlet)
@WebServlet("/user")
public class UserController extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = new User();
user.setName("John");
request.setAttribute("user", user);
request.getRequestDispatcher("/user.jsp").forward(request, response);
}
}
// View (JSP)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<body>
User name: ${user.name}
</body>
</html>
在这个例子中,当用户访问 "/user" URL 时,UserController
Servlet 会被执行。在 Servlet 中,我们创建了一个 User
对象,并将其设置为请求范围的属性。然后,我们将请求转发到 "user.jsp" 页面,该页面使用 EL 来访问 "user" 属性并将其显示给用户。
6、jsp有哪些内置对象?作用分别是什么?
-
JSP 中有 9 个预定义的(内置的)对象,你可以在 JSP 页面中直接使用它们,无需声明。以下是这些对象以及它们的作用:
-
request:这是一个
HttpServletRequest
对象。这个对象包含了客户端发送给服务器的请求信息,例如参数、头信息、请求的 URL 等。 -
response:这是一个
HttpServletResponse
对象。使用这个对象,你可以控制发送给客户端的响应,例如设置响应头、设置响应状态码等。 -
pageContext:这是一个
PageContext
对象。这个对象提供了对其他几个内置对象的访问,同时提供了一些有用的页面范围的方法,例如用于获取、设置和删除属性的方法。 -
session:这是一个
HttpSession
对象。这个对象用于在用户的整个会话期间保存状态信息。 -
application:这是一个
ServletContext
对象。这个对象允许你在整个应用程序范围内共享数据。 -
out:这是一个
JspWriter
对象。这个对象用于输出 HTML 到客户端。 -
config:这是一个
ServletConfig
对象。这个对象包含了 Servlet 的初始化参数。 -
page:这是一个
Object
对象,代表了当前的 Servlet 实例。 -
exception:这是一个
Throwable
对象。这个对象只在使用 isErrorPage="true" 的错误页面中可用,它包含了在当前页面中抛出的异常。
这些内置对象为你在处理 HTTP 请求时提供了很大的便利。例如,你可以使用
request
对象来获取客户端发送的参数,使用session
对象来跟踪用户的会话状态,使用out
对象来发送 HTML 响应到客户端,等等。 -
7、jsp 和 servlet 有什么区别?
JSP (Java Server Pages) 和 Servlet 都是 Java Web 开发中常用的技术,它们都可以用于生成动态的 Web 内容。然而,它们在语法和用途上有一些重要的区别:
-
语法和易用性:JSP 是基于 HTML 的,它允许你在 HTML 代码中嵌入 Java 代码,这使得JSP 页面非常适合于生成和展示视图。JSP 支持表达式语言 (EL) 和 JSTL 标签库,这些功能使得在 JSP 页面中访问数据和执行常见操作变得非常简单。另一方面,Servlet 是纯 Java 的,你需要在 Servlet 中写出完整的 Java 代码来生成 HTML,这通常比在 JSP 中编写代码更为复杂和冗长。
-
编译方式:Servlet 在服务器启动时或在接收到第一次请求时编译,而且只编译一次。但是,JSP 在接收到第一次请求时编译,并且如果 JSP 文件被修改了,服务器会再次编译它。这意味着你可以更新 JSP 文件并立即看到更改,而无需重新启动服务器。
-
用途:由于上述的语法和易用性的差异,JSP 和 Servlet 通常被用于不同的目的。JSP 更适合于生成和展示视图,也就是用户看到的 HTML。Servlet 更适合于处理业务逻辑,例如处理表单提交、执行数据库查询等。
在实际开发中,JSP 和 Servlet 通常会一起使用,以实现 MVC (Model-View-Controller) 设计模式。在这种模式中,Servlet 作为控制器,处理用户的请求并执行业务逻辑;模型是由 POJO (Plain Old Java Object) 类来实现的,它们代表了应用程序的数据;JSP 作为视图,显示模型的数据给用户。
8、session 和 cookie 有什么区别?
Session 和 Cookie 都是用于存储用户的状态信息,但它们在许多方面都有所不同。以下是它们的主要区别:
-
存储位置:Session 数据存储在服务器端,每个用户都有一个独立的 Session。而 Cookie 存储在客户端(浏览器),服务器通过设置响应头部信息将 Cookie 发送给客户端。
-
存储容量:由于 Cookie 数据存储在客户端,因此其存储容量相对较小,通常不超过 4KB。而 Session 存储在服务器端,理论上其存储容量没有限制,但过多的 Session 数据会占用服务器的内存资源。
-
存储类型:Cookie 只能存储字符串类型的数据,并且需要对特殊字符进行编码。而 Session 可以存储任何类型的数据,包括字符串、数字、对象等。
-
生命周期:Cookie 有一个明确的过期时间,过期后 Cookie 数据将会被浏览器删除。如果没有设置过期时间,那么 Cookie 仅在当前浏览器会话期间有效,关闭浏览器后 Cookie 就会被删除。而 Session 的生命周期通常由服务器设置,当用户在一段时间内没有活动(如没有发送新的请求)时,服务器会自动销毁该用户的 Session。
-
安全性:由于 Cookie 数据存储在客户端,因此其安全性相对较低,可能会被恶意用户修改或窃取。而 Session 存储在服务器端,用户无法直接访问,因此更安全。
总的来说,选择使用 Session 还是 Cookie 主要取决于你的需求。如果你需要在客户端存储大量的数据,并且对安全性要求较高,那么应该使用 Session。而如果你只需要存储少量的数据,并且希望即使在用户关闭浏览器后也能保持这些数据,那么可以使用 Cookie。
9、Cookie的过期和Session的超时有什么区别?
Cookie
和 Session
都是在 Web 开发中常用的会话技术,它们都可以用于在用户的多次请求之间保存某些状态信息。然而,Cookie
的过期和 Session
的超时代表的是两种不同的概念:
-
Cookie 过期:
Cookie
是存储在客户端的一小段数据。当我们创建一个Cookie
时,我们可以设置一个Max-Age
或者一个Expires
属性,来指定这个Cookie
的生命周期。当这个Cookie
的生命周期结束时,这个Cookie
就会过期,浏览器会将其删除。- 例如,如果我们创建了一个
Max-Age
为 3600 秒(1 小时)的Cookie
,那么这个Cookie
将在创建后的 1 小时后过期。无论用户在这个 1 小时内做了什么(无论是浏览其他页面,还是关闭浏览器),只要这个 1 小时结束,这个Cookie
就会过期。
-
Session 超时:
Session
是存储在服务器端的一组数据,每个用户都有一个与之对应的Session
。Session
的超时,也就是Session
的生命周期结束,通常是由于用户在一段时间内没有活动(例如,用户没有发送新的请求)。- 例如,如果我们设置了
Session
的超时时间为 30 分钟,那么如果用户在 30 分钟内没有发送新的请求,这个Session
就会超时。一旦用户发送了新的请求,Session
的生命周期就会重置。
总的来说,Cookie
的过期是由 Cookie
的创建时间和 Max-Age
或 Expires
属性决定的,而 Session
的超时是由用户的最后一次活动和 Session 的超时设置决定的。
10、如何解决分布式 Session 问题?
在分布式系统中,Session 管理可能会成为一个挑战,因为用户的请求可能会被路由到不同的服务器上,而这些服务器需要共享 Session 信息。以下是解决分布式 Session 问题的一些常见策略:
-
Session 复制:在这种方法中,每个服务器都有所有 Session 的副本。这意味着,无论请求被路由到哪个服务器,都能找到该 Session 的信息。这种方法的优点是,如果某个服务器出现故障,其他服务器仍可以处理请求。但是,这种方法可能会消耗大量的内存,并且在服务器之间同步 Session 信息也可能成为性能瓶颈。
-
Session 粘性:在这种方法中,一旦用户的请求被路由到某个服务器,后续的所有请求都将被路由到同一台服务器。这样,只有这台服务器需要保存 Session 信息。这种方法的优点是简单且效率高,但是,如果这台服务器出现故障,用户的 Session 信息将丢失。
-
集中 Session 存储:在这种方法中,所有的 Session 信息都存储在一个集中的数据存储(例如,数据库或者缓存服务器如 Redis)中。无论请求被路由到哪个服务器,都可以从这个集中的数据存储中获取 Session 信息。这种方法的优点是,可以很好地处理服务器的故障,但是,如果集中的数据存储出现故障,所有的 Session 信息都可能丢失。
-
JWT(JSON Web Tokens):JWT 是一种无状态的解决方案,每次用户请求都会携带一个签名的 JSON 对象,该对象包含所有必要的信息。服务器验证 JWT 的签名,如果验证通过,则处理请求。这种方法的优点是无需在服务器端存储 Session 信息,可以很好地处理服务器的故障,但是,JWT 的大小通常比 Session ID 大,如果 JWT 包含了大量的数据,可能会影响网络性能。
选择哪种策略取决于具体的应用需求和环境,例如系统的可用性需求、系统的规模、网络条件等。
11、在单点登录中,如果 cookie 被禁用了怎么办?
单点登录(Single Sign-On,SSO)是一种让用户只需登录一次就可以访问所有相关的系统或服务的方法。通常,这种方法依赖于 Cookie 来跟踪用户的登录状态。然而,如果 Cookie 被禁用了,我们可以考虑以下的替代方案:
-
URL 重写:在每个 URL 后面附加一个 Session ID。这样,即使 Cookie 被禁用,服务器仍然可以通过 URL 中的 Session ID 来识别用户。但是,这种方法可能会引发安全问题,因为 Session ID 可能会被截获或者泄露,同时也可能破坏 URL 的美观。
-
隐藏表单字段:在每个表单中添加一个隐藏的字段,用于存储 Session ID。当用户提交表单时,服务器可以从表单字段中获取 Session ID。这种方法只适用于那些通过表单进行交互的应用。
-
使用 localStorage 或 sessionStorage:如果应用是基于 HTML5 的,那么可以使用 Web Storage API 中的 localStorage 或 sessionStorage 来存储 Session ID。这两者都是在客户端存储数据的方法,和 Cookie 不同的是,它们不会随着每次请求自动发送到服务器,而需要通过 JavaScript 明确地读取和发送。
-
使用其他认证方法:例如,可以使用基于令牌的认证方法,如 JWT(JSON Web Tokens)。在这种方法中,服务器生成一个包含用户身份信息的令牌,并将其发送给客户端。客户端将此令牌存储起来,并在每次请求时将其包含在请求头中。服务器通过验证此令牌来识别用户。
以上这些方法都有其优点和缺点,选择哪种方法取决于具体的应用需求和环境。例如,如果应用需要高安全性,那么可能需要避免使用 URL 重写;如果应用是基于 HTML5 的,那么可能可以考虑使用 localStorage 或 sessionStorage。
12、session何时被删除?
在 Web 开发中,一个 Session 对象何时被删除(或称为 Session 失效)主要取决于以下几个因素:
-
Session 超时:大多数 Web 应用框架都允许你设置一个 Session 的超时时间。如果在这个时间段内,服务器没有收到来自特定 Session 的任何请求,那么这个 Session 就会被自动删除。在 Java Servlet 中,你可以在
web.xml
配置文件中通过<session-config>
元素来设置 Session 的超时时间。 -
手动删除:你的应用程序代码可以显式地删除一个 Session。例如,在 Java Servlet 中,你可以调用
HttpSession.invalidate()
方法来立即删除一个 Session。 -
服务器重启:如果你的 Web 服务器或应用服务器重启,那么存储在内存中的所有 Session 通常都会被删除。然而,一些服务器可以配置为在重启时将 Session 信息保存到磁盘,并在重启后从磁盘重新载入 Session 信息。
-
浏览器关闭:如果 Session 是基于 Cookie 实现的(这是最常见的实现方式),那么当用户关闭浏览器时,与 Session 关联的 Cookie 通常会被删除(除非你将 Cookie 设置为持久化 Cookie)。然而,这并不会直接导致 Session 在服务器端被删除,除非服务器设置了 Session 超时。
注意,Session 的管理是 Web 应用服务器的责任,不同的服务器可能会有不同的 Session 管理策略。例如,一些服务器可能会定期检查并删除超时的 Session,而其他服务器可能会在收到新请求时检查 Session 的超时状态。
13、tomcat容器是如何创建servlet类实例?用到了什么原理?
Tomcat 是一个实现了 Servlet 规范的 Web 容器。它负责创建和管理 Servlet 的生命周期,包括实例化 Servlet、调用其初始化方法和服务方法,以及调用其销毁方法。
以下是 Tomcat 创建 Servlet 实例的过程:
-
加载 Servlet 类:当 Tomcat 收到一个请求并确定需要使用某个特定的 Servlet 来处理请求时,它会使用类加载器(ClassLoader)来加载对应的 Servlet 类。如果这个 Servlet 类已经被加载过,那么就会跳过这个步骤。
-
实例化 Servlet 类:Tomcat 使用 Java 的
newInstance
方法来创建 Servlet 类的一个新实例。这个方法调用了 Servlet 类的无参构造函数。如果 Servlet 类没有无参构造函数,或者构造函数不可访问(例如,构造函数是私有的),那么newInstance
方法会抛出一个异常。 -
初始化 Servlet 实例:Tomcat 调用了 Servlet 实例的
init
方法来初始化这个 Servlet。init
方法接收一个ServletConfig
对象作为参数,这个对象包含了 Servlet 的初始化参数。 -
调用服务方法:在 Servlet 初始化完成后,Tomcat 会调用 Servlet 的
service
方法来处理请求。service
方法接收两个参数:一个HttpServletRequest
对象和一个HttpServletResponse
对象。这两个对象分别代表了客户端的请求和服务器的响应。
以上步骤中提到的 newInstance
方法,是 Java 反射(Reflection)的一部分。Java 反射允许程序在运行时访问和操作类和对象的内部信息,包括类的字段、方法和构造函数。在这个场景下,反射使得 Tomcat 能够在不知道 Servlet 类的具体类型的情况下,创建 Servlet 类的实例。
需要注意的是,Servlet 是单例的,即对于每个 Servlet 类,Tomcat 只会创建一个实例。这个实例会被多个线程共享,每个线程代表一个客户端的请求。因此,Servlet 必须是线程安全的。
14、如何避免 sql 注入?
SQL注入是一种常见的网络攻击方式,攻击者通过在查询语句中插入恶意的SQL代码,以获取敏感信息或对数据库进行操作。为了避免SQL注入,通常有以下几种方法:
- 预编译语句(Prepared Statements):这种方法是在执行SQL语句之前,先确定好SQL的执行格式,然后再把参数传入。由于参数不会被解释为SQL指令,因此可以防止SQL注入。在Java中,可以使用
PreparedStatement
对象来实现预编译语句。
String selectSQL = "SELECT * FROM Users WHERE username = ? AND password = ?";
PreparedStatement preparedStatement = connection.prepareStatement(selectSQL);
preparedStatement.setString(1, "user");
preparedStatement.setString(2, "password");
ResultSet resultSet = preparedStatement.executeQuery();
-
参数化查询(Parameterized Queries):参数化查询与预编译语句类似,也是先确定SQL语句的格式,然后再传入参数。这种方法也可以有效防止SQL注入。
-
过滤用户输入(Input Validation):在处理用户输入的信息之前,检查并过滤其中可能存在的恶意内容。例如,可以限制用户名只能由字母和数字组成。
-
最小权限原则(Principle of Least Privilege):对数据库的操作权限进行严格的控制,让每个用户只拥有其需要的最小权限,这样即使发生SQL注入,攻击者也无法执行非法的操作。
请注意,以上方法最好同时使用,以提供更强的安全保护。
15、什么是 XSS 攻击,如何避免?
XSS(Cross-Site Scripting)攻击是一种在网页上注入恶意脚本,使之在其他用户的浏览器上运行的攻击方式。当用户浏览这个含有恶意脚本的网页时,恶意脚本就会在用户的浏览器上执行,从而进行各种恶意操作,如窃取用户信息,篡改网页内容等。
以下是几种常用的防止XSS攻击的方法:
-
转义用户输入:对所有用户输入的数据进行转义处理(escaping),使得这些内容被浏览器解析为纯文本,而不是脚本代码。例如,可以把字符
<
和>
转义为<
和>
,这样就可以防止恶意用户提交含有脚本的内容。 -
内容安全策略(Content Security Policy, CSP):CSP是一种浏览器安全机制,可以限制网页加载和执行的资源。例如,可以设置CSP只允许加载和执行来自于当前域名的脚本,这样就可以有效防止XSS攻击。
-
输入验证:对所有用户输入的数据进行验证,检查是否含有可能引发XSS攻击的字符或字符串,如
<script>
等,如果有,就拒绝接受。 -
使用HTTP-only Cookies:将敏感的会话cookie设置为HTTP-only,这样JavaScript就无法读取到cookie。即便XSS攻击发生,攻击者也无法窃取这些cookie。
-
避免使用不安全的API:部分JavaScript API,如
eval
,document.write
,innerHTML
,outerHTML
等,可能会导致XSS攻击,应尽量避免使用。
请注意,以上方法最好同时使用,以提供更强的安全保护。
由于内容太多,更多内容以链接形势给大家,点击进去就是答案了
21. execute,executeQuery,executeUpdate的区别是什么?
22. JDBC的DriverManager是用来做什么的?
24. 说说preparedStatement和Statement的区别
27. JDBC的脏读是什么?哪种数据库隔离级别能防止脏读?
28. JDBC的DriverManager是用来做什么的?