简介:“Sun标准的JEE示例JEEDemo”提供了一个Java企业版(JEE)应用的实例,它利用JSP、Servlet、Filter、JDBC和CRUD操作等核心JEE技术来构建高效能、可扩展的Web应用程序。本项目不仅展示了这些技术的综合应用,还包括了模块化设计、异常处理、事务管理等良好编程实践,是开发者学习和提升JEE应用开发技能的重要资源。
1. JEE应用实例介绍与学习
1.1 什么是JEE应用
Java Platform, Enterprise Edition(JEE),是用于开发和运行大规模、多层、可伸缩、可靠和安全网络应用程序的Java平台。其最广泛的应用是在企业级环境,用于构建复杂的业务应用程序。JEE定义了一组丰富的服务和API,包括事务管理、安全性、可伸缩性和可移植性。
1.2 JEE应用的核心技术
JEE应用的核心技术包括EJB(企业Java Beans),Servlets,JSP(Java Server Pages),JDBC(Java Database Connectivity)等。这些技术构成了开发企业应用的基础,能够处理业务逻辑、数据库操作、网络通信等各个方面的问题。
1.3 JEE应用的学习路径
对于初学者来说,学习JEE应用的最佳路径是从理解基础的Java编程开始,逐步过渡到学习JEE的核心技术。理解并掌握Servlet和JSP是构建动态Web应用的基础,随后深入学习EJB,JDBC和JMS(Java Message Service)等。实践中,可以创建简单的MVC(Model-View-Controller)应用来整合这些技术,并理解它们在企业环境中的应用。
通过本章的介绍,我们将对JEE应用有一个初步的认识,并为学习后续章节打下坚实的基础。
2. JSP视图层技术应用
JSP (JavaServer Pages) 是一种基于 Java 的动态网页技术,用于创建可嵌入 Java 代码的 HTML 页面。它允许开发者将 Java 代码块嵌入到 HTML 文件中,这样就可以使用 Java 来生成动态内容。本章我们将深入探讨 JSP 的各种应用,包括其基本结构、语法、与 JavaBean 的交互、以及标签库的使用。
2.1 JSP页面的基本结构和语法
2.1.1 JSP页面的基本结构
JSP页面的主要结构由以下部分组成:
- 声明(Declarations):这些代码段定义了JSP页面中可用的变量和方法,声明以
<%!
开始,以%>
结束。 - 脚本片段(Scriptlets):这些是嵌入在页面中的Java代码片段,执行时会转换成servlet的_jspService方法内的代码。
- 表达式(Expressions):用于输出Java代码执行的结果到HTML页面中,表达式以
<%=
开始,以%>
结束。 - HTML标记:与普通HTML页面无异,可以内嵌Java代码。
一个简单的JSP页面示例如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>我的JSP页面</title>
</head>
<body>
<%!
// 声明变量和方法
private String message = "Hello, JSP!";
%>
<%
// 脚本片段执行
String name = request.getParameter("name");
out.println("<h1>Welcome, " + name + "!</h1>");
out.println("<p>" + message + "</p>");
%>
</body>
</html>
2.1.2 JSP语法和内置对象
JSP的语法提供了一种简单的途径来处理页面的逻辑和生成动态内容。JSP内置对象如request, response, out, session等在JSP页面中可以直接使用,无需声明。下面是对这些内置对象的简要介绍:
- request: 表示客户端的请求。
- response: 用于创建对客户端的响应。
- session: 表示用户会话。
- out: 用于向客户端发送输出。
- application: 表示整个web应用的环境信息。
这些对象在JSP页面中非常重要,用于处理客户端和服务器之间的交互。
2.2 JSP与JavaBean的交互
JavaBean是一种可重复使用的Java组件,可以用来封装数据、业务逻辑或者业务流程。在JSP中,JavaBean可以用来简化复杂数据的处理和页面逻辑。
2.2.1 JavaBean的创建和使用
创建一个JavaBean涉及到定义一个类,并将数据封装到私有成员变量中,通过公共的getter和setter方法提供对这些变量的访问。
例如,创建一个名为 User
的JavaBean:
public class User {
private String name;
private int age;
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
要在JSP页面中使用JavaBean,需要使用 <jsp:useBean>
标签来创建或获取一个Bean实例。然后,使用 <jsp:getProperty>
和 <jsp:setProperty>
标签与Bean的属性交互。
2.2.2 JSP与JavaBean的数据交换
以下示例展示了如何在JSP页面中使用JavaBean:
<jsp:useBean id="user" class="User" scope="request"/>
<jsp:setProperty name="user" property="*" />
<%-- 等价于:user.setName(request.getParameter("name"));
user.setAge(Integer.parseInt(request.getParameter("age"))) --%>
<html>
<head>
<title>JavaBean 使用示例</title>
</head>
<body>
<h2>用户信息</h2>
<p>姓名: ${user.name}</p>
<p>年龄: ${user.age}</p>
</body>
</html>
在这个例子中,我们首先声明了一个id为“user”的User对象,然后从请求中自动获取并设置其属性。之后,我们通过表达式来输出用户的名称和年龄。
2.3 JSP的标签库使用
JSP提供了标签库(Tag Libraries)来实现更高级的自定义功能。标签库包含标签处理器(Tag Handlers)和自定义标签(Custom Tags)。
2.3.1 JSTL标签库的使用
JavaServer Pages Standard Tag Library (JSTL) 是一个JSP标签库,用于处理常见的任务,如条件判断和循环处理,以及国际化和数据库访问等。
JSTL标签库需要先在JSP页面中引入:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
之后,就可以使用JSTL标签,比如 <c:if>
和 <c:forEach>
:
<c:forEach var="i" begin="1" end="10" step="1">
<p>${i}</p>
</c:forEach>
上述代码段演示了如何使用JSTL的forEach标签来生成一个从1到10的数字列表。
2.3.2 自定义标签库的创建和应用
除了JSTL标签库外,JSP允许开发者创建自己的自定义标签库。这需要以下几个步骤:
- 创建标签处理类(Tag Handler Class),必须继承自TagSupport或BodyTagSupport类。
- 定义TLD(Tag Library Descriptor)文件,用来描述标签库和标签信息。
- 在JSP页面中引入自定义标签库。
- 使用自定义标签。
例如,创建一个自定义标签来打印一个警告消息:
public class WarningTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
getJspContext().getOut().write("警告: 这是一个自定义的警告消息!");
}
}
TLD文件示例:
<taglib>
<tlib-version>1.0</tlib-version>
<short-name>warn</short-name>
<uri>http://mytags.org</uri>
<tag>
<name>warning</name>
<tag-class>com.example.tags.WarningTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
在JSP页面中使用自定义标签:
<%@ taglib prefix="warn" uri="http://mytags.org" %>
<warn:warning />
以上内容,我们成功介绍了JSP页面的基本结构和语法,阐述了如何在JSP中使用JavaBean以及如何运用JSP标签库。这些基础内容对于深入理解JSP技术至关重要,也是任何想要在JEE应用中使用JSP进行视图层开发的开发者的必备知识。
3. Servlet服务器端组件应用
3.1 Servlet的生命周期和工作原理
3.1.1 Servlet的生命周期
Servlet技术是Java EE(现在称为Jakarta EE)的核心组件之一,用于处理客户端的请求和生成响应。一个Servlet的生命周期包括初始化、处理请求、销毁三个阶段。
- 初始化 :当Servlet对象首次被加载到服务器上时,Servlet容器(例如Tomcat)会创建Servlet实例并调用其
init()
方法进行初始化。在这个方法中,通常会进行一些资源的加载和配置,比如初始化数据库连接,设置默认参数等。 - 处理请求 :在
service()
方法中,Servlet处理客户端的请求。每一次HTTP请求都会触发一次service()
调用。而实际响应客户端的是doGet()
,doPost()
等方法,这些方法会根据请求的类型(GET、POST等)被service()
方法调用。 - 销毁 :当服务器停止或重新部署应用时,Servlet容器会销毁Servlet实例,此时会调用
destroy()
方法。这个方法通常用于释放资源,如关闭数据库连接或文件流等。
下面的代码块展示了Servlet生命周期中三个主要方法的简单实现:
public class MyServlet extends HttpServlet {
@Override
public void init() throws ServletException {
//Servlet初始化代码
super.init();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理GET请求
//例如:response.getWriter().write("This is GET request");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理POST请求
//例如:response.getWriter().write("This is POST request");
}
@Override
public void destroy() {
//Servlet销毁前的清理工作
super.destroy();
}
}
3.1.2 Servlet的工作原理
Servlet的工作原理涉及到客户端的请求和服务器端的响应。当客户端(如浏览器)向Servlet发送一个请求时,请求首先到达Servlet容器。Servlet容器负责管理Servlet的生命周期,包括初始化、请求转发、响应处理等。
- 请求接收 :客户端的请求通过HTTP协议发送给服务器,服务器接收到请求后将其转发给对应的Servlet容器。
- 请求处理 :Servlet容器根据请求类型调用相应的Servlet方法(
doGet
,doPost
,doPut
,doDelete
等)。 - 响应生成 :Servlet生成响应内容,通常是HTML、JSON、XML等格式的数据。
- 响应返回 :Servlet容器将响应数据通过HTTP协议返回给客户端。
sequenceDiagram
Client->>Server: HTTP Request
Server->>Servlet Container: Request
Servlet Container->>Servlet: init(), service(), doGet/doPost, etc.
Servlet->>Servlet Container: Response
Servlet Container->>Server: Response
Server->>Client: HTTP Response
Servlet容器还负责线程管理,为了提高性能,Servlet容器通常使用线程池来处理请求。这意味着,当一个请求被处理时,Servlet不必为每个请求创建新的线程。相反,Servlet容器会从池中分配一个线程,处理完成后,线程被回收到池中供其他请求使用。
3.2 Servlet的请求和响应处理
3.2.1 Servlet的请求处理
Servlet处理请求主要通过 service()
方法,以及 doGet
, doPost
, doPut
, doDelete
等方法。其中, service()
方法会检查HTTP请求的类型,并调用相应的 doGet
, doPost
等方法。
在处理请求时,Servlet可以使用 HttpServletRequest
对象来获取客户端请求的数据,如查询参数、表单数据、上传的文件等。 HttpServletResponse
对象用于向客户端发送响应,比如设置响应头、发送文本或二进制数据等。
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
if (method.equals("GET")) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// 没有设置最后修改时间
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
// 客户端未过期
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
// 客户端已过期
resp.sendError(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals("POST")) {
doPost(req, resp);
}
// ... 其他请求类型处理
}
3.2.2 Servlet的响应处理
在Servlet中,响应处理主要是将数据和信息发送回客户端。 HttpServletResponse
对象提供了多种方法来完成这一过程,如发送状态码、设置响应头、写入响应体等。
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println("<h1>Hello, World!</h1>");
}
在这个例子中, resp.setContentType("text/html")
设置了响应的内容类型为HTML。然后通过 resp.getWriter()
获取了一个 PrintWriter
对象,最后使用该对象的 println
方法写入了简单的HTML内容。
3.3 Servlet的会话跟踪技术
3.3.1 Cookie的使用
Cookie是服务器发送到用户浏览器并保存在本地的一小块数据。它通常用于跟踪用户状态或记住用户的偏好设置。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("user", "username");
cookie.setMaxAge(30 * 24 * 60 * 60); // 设置Cookie有效期为30天
response.addCookie(cookie);
// 也可以使用response对象直接设置响应头来创建Cookie
response.setHeader("Set-Cookie", "username=JohnDoe; Max-Age=30; Path=/");
}
在上述示例中,我们创建了一个名为 user
的Cookie,并将其值设置为 username
。同时设置了Cookie的有效期为30天。然后将此Cookie添加到HTTP响应中,发送给客户端浏览器。之后,每次客户端发送请求时,都会携带这个Cookie。
3.3.2 Session的使用
Session是一种在服务器端保存用户状态的机制,当用户首次访问应用程序时,服务器会创建一个新的Session对象。此后,用户的每一次请求都会携带一个唯一的Session ID,服务器根据这个ID找到对应的Session对象。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(true); // 获取Session对象
session.setAttribute("user", "JohnDoe"); // 在Session中存储用户信息
// 获取存储在Session中的用户信息
String user = (String) session.getAttribute("user");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>Welcome " + user + "!</h1>");
}
在这个例子中,通过调用 request.getSession(true)
方法获取当前的Session对象。如果用户尚未拥有Session,方法会创建一个新的Session。然后,通过 setAttribute
方法将用户信息存储到Session中。在下一次请求时,可以通过 getAttribute
方法从Session中检索用户信息。
根据以上的描述,您应该能够理解Servlet的工作原理和生命周期,掌握如何处理请求和响应,以及如何使用会话跟踪技术如Cookie和Session。这些知识对于开发基于Java EE的Web应用程序是至关重要的基础。
4. Filter组件的请求/响应处理
4.1 Filter组件的基本概念和作用
4.1.1 Filter组件的基本概念
在Java EE(JEE)中,Filter是一种特殊的Servlet,用于在客户端请求到达Servlet之前或从Servlet返回到客户端之前,拦截和处理请求和响应。Filter的主要功能是预处理请求、过滤响应内容、日志记录、请求数据的转换等。Filter可以动态地拦截请求与响应,以实现一些通用的处理,如身份验证、请求和响应的加密解密、日志记录等。
4.1.2 Filter组件的作用
Filter在Web应用中扮演了非常重要的角色,它可以应用在多种场景,比如:
- 身份验证 :在用户访问受保护的资源之前,Filter可以验证用户身份。
- 数据压缩 :过滤器可以压缩发送给客户端的响应数据,减少网络传输的负载。
- 日志记录 :Filter可以记录请求和响应信息,用于系统调试和监控。
- 图片转换 :在发送图片之前,Filter可以转换图片的格式或改变图片的大小。
- 字符编码 :可以确保Web应用中使用统一的字符编码。
- 内容格式转换 :将特定的文本格式转换为HTML或其他格式。
4.2 Filter的生命周期和配置方法
4.2.1 Filter的生命周期
Filter的生命周期包括以下几个阶段:
- 实例化 :Web容器负责创建Filter实例。
- 初始化 :通过
init
方法进行初始化。在web.xml
中或者使用注解配置Filter时,容器会加载并初始化Filter。 - 请求处理 :对每一个到达目标资源的请求,Filter都会执行
doFilter
方法。 - 销毁 :当Web容器停止时,Filter会被销毁,此时会调用
destroy
方法。
4.2.2 Filter的配置方法
Filter可以通过以下两种方式配置:
- 部署描述符 :在
web.xml
文件中配置Filter及其映射。 - 注解 :使用
@WebFilter
注解直接在Java类中声明。
4.2.2.1 使用web.xml配置Filter
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.example.MyFilter</filter-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.2.2.2 使用注解配置Filter
@WebFilter("/example/*")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代码
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 处理请求的代码
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 销毁前的清理代码
}
}
4.3 Filter的请求和响应处理
4.3.1 Filter的请求处理
在 doFilter
方法中,Filter可以对请求进行预处理。下面是一个简单的Filter处理请求的代码示例:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 日志记录请求的URL和参数
String url = httpRequest.getRequestURL().toString();
Enumeration<String> parameterNames = httpRequest.getParameterNames();
while (parameterNames.hasMoreElements()) {
String parameterName = parameterNames.nextElement();
String parameterValue = httpRequest.getParameter(parameterName);
System.out.println("Parameter name: " + parameterName + " = " + parameterValue);
}
// 调用目标资源
chain.doFilter(request, response);
}
4.3.2 Filter的响应处理
在Filter中,同样可以对响应进行处理。例如,可以修改或添加响应头:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 处理请求
chain.doFilter(request, response);
// 在响应返回给客户端之前修改响应头
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("X-My-Header", "MyValue");
}
Filter的请求和响应处理是Web应用中实现中间件逻辑的一个重要手段,它使得开发者能够重用代码、维护和修改更加灵活。
通过本章节的介绍,我们深入探讨了Filter组件在JEE应用中的角色、生命周期和配置方法,以及如何处理请求和响应。Filter为Web应用提供了一种灵活的处理机制,使得开发者可以在请求达到Servlet之前和响应返回客户端之后进行自定义处理,增加了Web应用的可扩展性和维护性。
5. JDBC数据库连接与操作
JDBC(Java Database Connectivity)是Java语言中用来连接和操作数据库的应用程序接口。它定义了Java程序如何与数据库进行交互,并且可以支持任何类型的SQL数据库。本章节将详细介绍JDBC的基本概念、数据库连接和操作、以及CRUD操作的细节。
5.1 JDBC的基本概念和作用
5.1.1 JDBC的基本概念
JDBC提供了一套Java API,这些API允许Java程序执行SQL语句。它是Java SE标准的一部分,让Java程序可以使用统一的接口与数据库进行交互。JDBC API主要包含两部分:JDBC驱动管理器(DriverManager)和JDBC API接口。
5.1.2 JDBC的作用
JDBC的主要作用是作为一个中间层,使得Java程序能够通过标准API与数据库通信。它使得开发者可以使用Java编写数据库应用程序,而不需要关心底层数据库的具体实现和协议。
5.2 JDBC的连接和操作数据库
5.2.1 JDBC的连接数据库
JDBC连接数据库通常需要以下几个步骤:
- 加载并注册JDBC驱动。
- 创建数据库连接。
- 执行SQL语句。
- 处理查询结果。
- 关闭连接。
下面是一个简单的示例代码,演示如何使用JDBC连接MySQL数据库:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
public static void main(String[] args) {
// 加载MySQL JDBC驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
return;
}
// 创建数据库连接
String url = "jdbc:mysql://localhost:3306/yourDatabaseName";
String user = "yourUsername";
String password = "yourPassword";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
if (conn != null) {
System.out.println("Connected to the database!");
}
// 之后可以进行数据库操作,例如执行SQL语句等
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5.2.2 JDBC的操作数据库
在建立了数据库连接之后,可以使用 Statement
或者 PreparedStatement
对象来执行SQL语句。 PreparedStatement
相比于 Statement
的优势在于它能够防止SQL注入攻击,并且可以重复使用预编译的SQL语句。
5.3 JDBC的CRUD操作
CRUD指的是数据库中的基本操作:创建(Create)、读取(Read)、更新(Update)和删除(Delete)。
5.3.1 JDBC的创建操作
创建操作通常对应于SQL中的INSERT语句。以下是一个简单的示例:
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "Alice");
pstmt.setString(2, "alice@example.com");
int affectedRows = pstmt.executeUpdate();
if (affectedRows > 0) {
System.out.println("New record created successfully.");
}
} catch (SQLException e) {
e.printStackTrace();
}
5.3.2 JDBC的读取操作
读取操作对应于SQL中的SELECT语句。以下是一个简单的示例:
String sql = "SELECT * FROM users WHERE name = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "Alice");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println("Name: " + name + ", Email: " + email);
}
}
5.3.3 JDBC的更新操作
更新操作对应于SQL中的UPDATE语句。以下是一个简单的示例:
String sql = "UPDATE users SET email = ? WHERE name = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "newAlice@example.com");
pstmt.setString(2, "Alice");
int affectedRows = pstmt.executeUpdate();
if (affectedRows > 0) {
System.out.println("Record updated successfully.");
}
}
5.3.4 JDBC的删除操作
删除操作对应于SQL中的DELETE语句。以下是一个简单的示例:
String sql = "DELETE FROM users WHERE name = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "Alice");
int affectedRows = pstmt.executeUpdate();
if (affectedRows > 0) {
System.out.println("Record deleted successfully.");
}
}
通过以上示例,可以看到JDBC为数据库操作提供了强大的工具。不过,需要注意的是,数据库操作通常涉及异常处理,因此合理的异常捕获与处理是必不可少的。在实际开发中,代码应该更加健壮,能够处理各种可能的异常情况。
以上内容仅作为JDBC在实际应用中的一些基础知识和示例,由于篇幅限制,并不能涵盖所有JDBC的高级用法,但应该足以让读者对JDBC有一个初步的了解和认识。在后续的章节中,我们将探讨更多关于JEE应用的模块化、异常处理和事务管理的实践。
简介:“Sun标准的JEE示例JEEDemo”提供了一个Java企业版(JEE)应用的实例,它利用JSP、Servlet、Filter、JDBC和CRUD操作等核心JEE技术来构建高效能、可扩展的Web应用程序。本项目不仅展示了这些技术的综合应用,还包括了模块化设计、异常处理、事务管理等良好编程实践,是开发者学习和提升JEE应用开发技能的重要资源。