零基础学Java——第十章:Java Web开发入门(上)

第十章:Java Web开发入门(上)

在前面的章节中,我们已经学习了Java的基础知识、面向对象编程、高级特性、文件IO、多线程、网络编程和数据库操作。现在,我们将进入Java应用的一个重要领域:Web开发。本章将介绍Java Web开发的基础知识,帮助你理解Web应用的工作原理并开始构建自己的Web应用。

1. Web开发概述

1.1 什么是Web应用

Web应用是一种可以通过Web浏览器访问的应用程序。与传统的桌面应用不同,Web应用不需要安装在用户的计算机上,用户只需要一个浏览器就可以使用它。

想象一下,你使用的网上购物平台(如淘宝、京东)、社交媒体(如微博、微信网页版)、在线银行等,这些都是Web应用的例子。

1.2 Web应用的工作原理

Web应用的工作原理基于客户端-服务器模型:

  1. 客户端:通常是Web浏览器(如Chrome、Firefox、Safari等)
  2. 服务器:运行Web应用的计算机,处理客户端的请求并返回响应

基本工作流程如下:

  1. 用户在浏览器中输入网址(URL)或点击链接
  2. 浏览器向服务器发送HTTP请求
  3. 服务器处理请求(可能涉及数据库操作、业务逻辑处理等)
  4. 服务器返回HTTP响应(通常包含HTML、CSS、JavaScript等)
  5. 浏览器解析响应并渲染页面
  6. 用户与页面交互,可能触发新的请求

这就像你去餐厅点餐:

  • 你(客户端)向服务员(服务器)点餐(发送请求)
  • 服务员将订单传递给厨房处理(服务器处理请求)
  • 厨房准备好食物后,服务员将食物送到你的桌子(服务器返回响应)
  • 你享用食物(浏览器渲染页面)

1.3 Web开发的核心技术

前端技术(客户端)
  • HTML:定义网页的结构和内容
  • CSS:控制网页的样式和布局
  • JavaScript:实现网页的交互功能
后端技术(服务器端)
  • 服务器:如Tomcat、Jetty、Undertow等
  • Java Web技术:Servlet、JSP、Spring MVC、Spring Boot等
  • 数据库:MySQL、Oracle、PostgreSQL等

1.4 Java Web开发的优势

  • 跨平台:Java的"一次编写,到处运行"特性使得Web应用可以在不同的操作系统上运行
  • 安全性:Java提供了强大的安全机制
  • 丰富的生态系统:大量的框架和库可供选择
  • 企业级支持:适合开发大型、复杂的企业级应用
  • 成熟的社区:大量的开发者和资源

2. Servlet基础

2.1 什么是Servlet

Servlet是Java Web开发的核心技术,它是运行在Web服务器上的Java程序,用于处理客户端的请求并生成响应。

简单来说,Servlet就像是餐厅里的服务员,负责接收客户的点餐(请求),将订单传递给厨房(业务逻辑),然后将准备好的食物(响应)送回给客户。

2.2 Servlet的生命周期

Servlet的生命周期包括以下阶段:

  1. 加载和实例化:服务器启动时或首次请求时,Servlet容器创建Servlet的实例
  2. 初始化:调用init()方法,进行必要的初始化工作
  3. 服务:调用service()方法处理客户端请求
  4. 销毁:调用destroy()方法释放资源,通常在服务器关闭时

这就像餐厅服务员的一天:上班前准备工作(初始化),接待客人(服务),下班后整理(销毁)。

2.3 创建第一个Servlet

要创建一个Servlet,我们需要:

  1. 创建一个Java类,继承HttpServlet
  2. 重写doGet()和/或doPost()方法
  3. 在web.xml中配置Servlet或使用注解配置

下面是一个简单的Servlet示例:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello Servlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>你好,这是我的第一个Servlet!</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

2.4 Servlet的请求和响应

HttpServletRequest

HttpServletRequest对象表示客户端的请求,通过它可以获取:

  • 请求参数(如表单数据)
  • 请求头信息
  • Cookie
  • Session信息
  • 请求路径等
// 获取请求参数
String username = request.getParameter("username");

// 获取所有参数名
Enumeration<String> paramNames = request.getParameterNames();

// 获取请求头
String userAgent = request.getHeader("User-Agent");

// 获取Session
HttpSession session = request.getSession();
HttpServletResponse

HttpServletResponse对象表示服务器的响应,通过它可以:

  • 设置响应内容类型
  • 设置响应头信息
  • 设置Cookie
  • 发送重定向
  • 输出响应内容等
// 设置内容类型
response.setContentType("text/html;charset=UTF-8");

// 设置响应头
response.setHeader("Cache-Control", "no-cache");

// 设置Cookie
Cookie cookie = new Cookie("username", "john");
cookie.setMaxAge(3600); // 1小时
response.addCookie(cookie);

// 重定向
response.sendRedirect("/welcome.jsp");

// 输出内容
PrintWriter out = response.getWriter();
out.println("Hello, World!");

2.5 Servlet的配置

有两种方式配置Servlet:

使用注解(推荐,Java EE 6及以上)
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    // Servlet代码
}
使用web.xml配置
<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.example.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

2.6 Servlet的应用场景

Servlet适用于各种Web应用场景,例如:

  • 处理表单提交
  • 实现RESTful API
  • 文件上传和下载
  • 会话管理
  • 权限控制等

2.7 实战:简单的用户登录Servlet

下面是一个简单的用户登录Servlet示例:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    // 模拟用户数据库
    private static final String VALID_USERNAME = "admin";
    private static final String VALID_PASSWORD = "password";
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // 显示登录表单
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>登录页面</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h2>用户登录</h2>");
        out.println("<form method='post' action='login'>");
        out.println("用户名: <input type='text' name='username'><br>");
        out.println("密码: <input type='password' name='password'><br>");
        out.println("<input type='submit' value='登录'>");
        out.println("</form>");
        out.println("</body>");
        out.println("</html>");
    }
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // 处理登录请求
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        // 验证用户名和密码
        if (VALID_USERNAME.equals(username) && VALID_PASSWORD.equals(password)) {
            // 登录成功,创建会话
            HttpSession session = request.getSession();
            session.setAttribute("username", username);
            
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>登录成功</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h2>登录成功!</h2>");
            out.println("<p>欢迎, " + username + "!</p>");
            out.println("<a href='logout'>退出登录</a>");
            out.println("</body>");
            out.println("</html>");
        } else {
            // 登录失败
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>登录失败</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h2>登录失败!</h2>");
            out.println("<p>用户名或密码错误。</p>");
            out.println("<a href='login'>返回登录页面</a>");
            out.println("</body>");
            out.println("</html>");
        }
    }
}

配套的登出Servlet:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // 获取会话并使其无效(登出)
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }
        
        // 重定向到登录页面
        response.sendRedirect("login");
    }
}

在上一部分中,我们学习了Web开发的基本概念和Servlet技术。本部分将介绍JSP(JavaServer Pages)技术,这是Java Web开发中另一个重要的组成部分,它使得开发动态网页变得更加简单和直观。

3. JSP概述

3.1 什么是JSP

JSP(JavaServer Pages)是一种基于Java技术的网页开发技术,它允许开发者在HTML页面中嵌入Java代码,从而创建动态的Web内容。JSP页面在首次被访问时会被编译成Servlet,然后执行生成HTML响应返回给客户端。

想象一下,如果你经营一家在线书店,每天的畅销书榜单都会变化。使用静态HTML页面,你需要每天手动更新页面内容;而使用JSP,你可以编写一段代码,自动从数据库获取最新的畅销书信息并显示在页面上。

3.2 JSP与Servlet的关系

JSP和Servlet是紧密相关的技术:

  • 本质上是一样的:JSP页面最终会被转换成Servlet执行
  • 侧重点不同
    • Servlet侧重于处理业务逻辑
    • JSP侧重于展示数据和页面设计
  • 开发方式不同
    • Servlet是纯Java代码
    • JSP是HTML和Java代码的混合体

3.3 JSP的优势

  • 易于开发:对于熟悉HTML的开发者来说,学习曲线较低
  • 分离关注点:可以将表现层(HTML)和业务逻辑(Java)分开
  • 动态内容生成:能够根据用户请求动态生成内容
  • 可重用性:支持组件重用,如包含文件、标签库等

4. JSP基本语法

4.1 JSP页面结构

JSP页面通常包含以下元素:

  • HTML/CSS/JavaScript代码
  • JSP脚本元素(Java代码)
  • JSP指令
  • JSP动作
  • 表达式语言(EL)
  • 自定义标签

4.2 JSP脚本元素

JSP提供了三种在页面中嵌入Java代码的方式:

4.2.1 声明(Declaration)

声明用于定义变量和方法,语法为 <%! ... %>

<%! 
    int count = 0;
    public String getGreeting() {
        return "Hello, visitor #" + (++count);
    }
%>
4.2.2 脚本段(Scriptlet)

脚本段用于执行Java代码,语法为 <% ... %>

<% 
    String username = request.getParameter("username");
    if (username != null && !username.isEmpty()) {
%>
    <h2>欢迎, <%= username %>!</h2>
<% 
    } else {
%>
    <h2>欢迎访问我们的网站!</h2>
<% 
    }
%>
4.2.3 表达式(Expression)

表达式用于输出变量或方法的值,语法为 <%= ... %>

<p>当前时间是: <%= new java.util.Date() %></p>
<p><%= getGreeting() %></p>

4.3 JSP指令

JSP指令用于设置整个JSP页面相关的属性,语法为 <%@ directive attribute="value" %>

4.3.1 page指令

设置页面的属性,如语言、内容类型、错误页面等。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.util.Date, java.text.SimpleDateFormat" %>
<%@ page errorPage="error.jsp" %>
4.3.2 include指令

在编译时包含其他文件的内容。

<%@ include file="header.jsp" %>
<!-- 页面主体内容 -->
<%@ include file="footer.jsp" %>
4.3.3 taglib指令

引入自定义标签库。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

4.4 JSP动作

JSP动作使用XML语法,用于执行各种操作,如包含文件、转发请求等。

4.4.1 jsp:include

在运行时包含其他资源的输出。

<jsp:include page="header.jsp" />
4.4.2 jsp:forward

将请求转发到另一个资源。

<jsp:forward page="result.jsp">
    <jsp:param name="status" value="success" />
</jsp:forward>
4.4.3 jsp:useBean

创建或查找JavaBean实例。

<jsp:useBean id="user" class="com.example.User" scope="session" />
<jsp:setProperty name="user" property="username" value="张三" />
用户名: <jsp:getProperty name="user" property="username" />

5. JSP内置对象

JSP提供了9个内置对象,可以直接在页面中使用,无需创建:

  • request:HttpServletRequest对象,包含客户端请求信息
  • response:HttpServletResponse对象,用于向客户端发送响应
  • session:HttpSession对象,表示客户端会话
  • application:ServletContext对象,表示整个Web应用
  • out:JspWriter对象,用于向客户端输出内容
  • pageContext:PageContext对象,提供对所有JSP组件的访问
  • config:ServletConfig对象,包含Servlet的配置信息
  • page:代表当前JSP页面的实例(相当于this)
  • exception:Exception对象,仅在错误页面中可用

5.1 内置对象的使用示例

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>JSP内置对象示例</title>
</head>
<body>
    <h1>JSP内置对象示例</h1>
    
    <h2>Request对象</h2>
    <p>客户端IP地址: <%= request.getRemoteAddr() %></p>
    <p>请求方法: <%= request.getMethod() %></p>
    
    <h2>Session对象</h2>
    <% 
        // 获取会话ID
        String sessionId = session.getId();
        // 设置会话属性
        session.setAttribute("lastVisit", new java.util.Date());
    %>
    <p>会话ID: <%= sessionId %></p>
    <p>会话创建时间: <%= new java.util.Date(session.getCreationTime()) %></p>
    
    <h2>Application对象</h2>
    <% 
        // 获取应用属性或设置应用属性
        Integer visitorCount = (Integer)application.getAttribute("visitorCount");
        if (visitorCount == null) {
            visitorCount = 1;
        } else {
            visitorCount++;
        }
        application.setAttribute("visitorCount", visitorCount);
    %>
    <p>网站访问次数: <%= visitorCount %></p>
</body>
</html>

6. JSP实战:简单留言板

下面我们将创建一个简单的留言板应用,用户可以提交留言,并查看所有留言。

6.1 创建留言实体类

首先,创建一个Message.java类来表示留言:

package com.example.model;

import java.util.Date;

public class Message {
    private String author;
    private String content;
    private Date createTime;
    
    public Message(String author, String content) {
        this.author = author;
        this.content = content;
        this.createTime = new Date();
    }
    
    // Getters and setters
    public String getAuthor() { return author; }
    public void setAuthor(String author) { this.author = author; }
    
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
    
    public Date getCreateTime() { return createTime; }
    public void setCreateTime(Date createTime) { this.createTime = createTime; }
}

6.2 创建留言处理Servlet

接下来,创建一个MessageServlet.java来处理留言的提交:

package com.example.servlet;

import java.io.IOException;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.example.model.Message;

@WebServlet("/message")
public class MessageServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // 设置请求和响应的字符编码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        
        // 获取表单数据
        String author = request.getParameter("author");
        String content = request.getParameter("content");
        
        // 创建新留言
        Message message = new Message(author, content);
        
        // 获取应用范围内的留言列表,如果不存在则创建新列表
        List<Message> messages = (List<Message>) getServletContext().getAttribute("messages");
        if (messages == null) {
            messages = new ArrayList<>();
            getServletContext().setAttribute("messages", messages);
        }
        
        // 添加新留言到列表
        messages.add(message);
        
        // 重定向到留言列表页面
        response.sendRedirect("messageboard.jsp");
    }
}

6.3 创建留言板JSP页面

最后,创建messageboard.jsp页面来显示留言表单和留言列表:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="java.util.List, com.example.model.Message, java.text.SimpleDateFormat" %>
<!DOCTYPE html>
<html>
<head>
    <title>简易留言板</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 0; padding: 20px; }
        .container { max-width: 800px; margin: 0 auto; }
        .form-group { margin-bottom: 15px; }
        label { display: block; margin-bottom: 5px; }
        input, textarea { width: 100%; padding: 8px; box-sizing: border-box; }
        button { padding: 10px 15px; background-color: #4CAF50; color: white; border: none; cursor: pointer; }
        .message { border: 1px solid #ddd; padding: 15px; margin-bottom: 15px; border-radius: 5px; }
        .message-header { display: flex; justify-content: space-between; margin-bottom: 10px; }
        .message-content { line-height: 1.5; }
    </style>
</head>
<body>
    <div class="container">
        <h1>简易留言板</h1>
        
        <!-- 留言表单 -->
        <div>
            <h2>发表留言</h2>
            <form action="message" method="post">
                <div class="form-group">
                    <label for="author">您的名字:</label>
                    <input type="text" id="author" name="author" required>
                </div>
                <div class="form-group">
                    <label for="content">留言内容:</label>
                    <textarea id="content" name="content" rows="5" required></textarea>
                </div>
                <button type="submit">提交留言</button>
            </form>
        </div>
        
        <!-- 留言列表 -->
        <div>
            <h2>留言列表</h2>
            <% 
                List<Message> messages = (List<Message>) application.getAttribute("messages");
                if (messages != null && !messages.isEmpty()) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    for (int i = messages.size() - 1; i >= 0; i--) {
                        Message message = messages.get(i);
            %>
                        <div class="message">
                            <div class="message-header">
                                <strong><%= message.getAuthor() %></strong>
                                <span><%= sdf.format(message.getCreateTime()) %></span>
                            </div>
                            <div class="message-content">
                                <%= message.getContent().replace("\n", "<br>") %>
                            </div>
                        </div>
            <% 
                    }
                } else {
            %>
                    <p>暂无留言</p>
            <% 
                }
            %>
        </div>
    </div>
</body>
</html>

7. JSP最佳实践

7.1 MVC模式与JSP

MVC(Model-View-Controller)是一种常用的设计模式,在Java Web开发中:

  • Model(模型):JavaBean,表示数据和业务逻辑
  • View(视图):JSP页面,负责展示数据
  • Controller(控制器):Servlet,处理用户请求并协调模型和视图

使用MVC模式可以使代码更加清晰、易于维护和扩展。

7.2 避免在JSP中编写复杂的Java代码

JSP主要用于展示数据,应避免在JSP中编写复杂的业务逻辑:

  • 将业务逻辑放在JavaBean或Servlet中
  • 在JSP中只进行简单的数据展示和格式化
  • 使用JSTL和EL表达式代替Java脚本

7.3 使用JSTL和EL表达式

JSTL(JSP标准标签库)和EL(表达式语言)可以简化JSP页面的开发:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!-- 使用EL表达式访问属性 -->
<p>欢迎, ${user.name}!</p>

<!-- 使用JSTL标签遍历集合 -->
<c:forEach var="item" items="${itemList}">
    <p>${item.name}: ${item.price}</p>
</c:forEach>

<!-- 使用JSTL条件标签 -->
<c:if test="${user.role == 'admin'}">
    <p>您有管理员权限</p>
</c:if>

总结

在本章的第一部分,我们介绍了Web开发的基本概念和Servlet技术。我们了解了Web应用的工作原理、Java Web开发的优势,以及如何创建和配置Servlet。通过实战示例,我们学习了如何处理HTTP请求和响应,以及如何实现简单的用户登录功能。

在本章中第二部分,我们学习了JSP的基本概念、语法和使用方法。JSP作为Java Web开发中的重要技术,为开发动态网页提供了便捷的方式。我们了解了JSP脚本元素、指令、动作和内置对象,并通过一个简单的留言板应用实践了JSP的使用。

虽然在现代Java Web开发中,前后端分离的架构越来越流行,但JSP仍然是学习Java Web开发的重要基础,也是理解MVC模式的良好起点。

在下一部分,我们将学习Spring框架和SpringBoot,它们是现代Java Web开发中不可或缺的技术。

练习

  1. 创建一个简单的Servlet,显示当前时间和访问计数器。
  2. 实现一个简单的在线留言板,使用Servlet处理留言的提交和显示。
  3. 扩展登录示例,添加用户注册功能。
  4. 创建一个文件上传Servlet,允许用户上传图片并显示上传后的图片。
  5. 实现一个简单的购物车功能,使用Session存储购物车信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值