13、JavaEE核心技术 - Servlet与JSP

二、JavaEE核心技术 - Servlet与JSP

一、Servlet

Servlet(服务器端小程序)是JavaEE中用于处理HTTP请求的核心组件。它是一个Java类,运行在Web服务器上,负责接收和响应HTTP请求。

1. Servlet的生命周期

Servlet的生命周期由以下几个阶段组成:

  1. 初始化阶段(Initialization):
    • 触发: 当Servlet容器(如Tomcat)启动时,或者当第一次请求访问Servlet时,容器会创建Servlet的实例。
    • 方法: 调用Servlet的init()方法。
    • 作用: 初始化资源,读取配置参数,为后续的请求处理做准备。
  2. 服务阶段(Service):
    • 触发: 当客户端发送HTTP请求,并且请求映射到该Servlet时。
    • 方法: 调用Servlet的service()方法。
    • 作用: 处理HTTP请求,根据请求类型(GET、POST等)调用相应的doGet()doPost()方法,生成响应。
  3. 销毁阶段(Destruction):
    • 触发: 当Servlet容器关闭,或者Servlet被移除时。
    • 方法: 调用Servlet的destroy()方法。
    • 作用: 释放资源,关闭数据库连接,清理临时数据。

2. Servlet的配置

Servlet可以通过以下两种方式配置:

  1. 基于XML配置(web.xml):

    • web.xml文件中,通过<servlet><servlet-mapping>元素配置Servlet。

    • 示例:

      xml 复制代码
      <servlet>  
          <servlet-name>MyServlet</servlet-name>  
          <servlet-class>com.example.MyServlet</servlet-class>  
          <init-param>  
              <param-name> ParamName </param-name>  
              <param-value> ParamValue </param-value>  
          </init-param>  
      </servlet>  
      <servlet-mapping>  
          <servlet-name>MyServlet</servlet-name>  
          <url-pattern>/myServlet</url-pattern>  
      </servlet-mapping>  
  2. 基于注解配置:

    • 使用@WebServlet注解直接在Servlet类上配置。

    • 示例:

      java 复制代码
      @WebServlet(name = "MyServlet", urlPatterns = "/myServlet")  
      public class MyServlet extends HttpServlet {  
          // Servlet实现  
      }  

3. Servlet的基本实现

以下是一个基本的Servlet实现示例:

java 复制代码
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import java.io.IOException;  

public class MyServlet extends HttpServlet {  
    
    @Override  
    public void init() throws ServletException {  
        // 初始化代码  
        System.out.println("Servlet initialized");  
    }  

    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        // 处理GET请求  
        resp.setContentType("text/html");  
        resp.getWriter().println("<h1>Hello, World!</h1>");  
    }  

    @Override  
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        // 处理POST请求  
        String username = req.getParameter("username");  
        resp.setContentType("text/html");  
        resp.getWriter().println("<h1>Hello, " + username + "!</h1>");  
    }  

    @Override  
    public void destroy() {  
        // 销毁资源  
        System.out.println("Servlet destroyed");  
    }  
}  
二、JSP

JavaServer Pages(JSP)是一种动态网页技术,允许开发者在HTML页面中嵌入Java代码,以生成动态内容。

1. JSP的语法

JSP的语法包括以下几种元素:

  1. 表达式:

    • 用于在页面中输出Java表达式的值。
    • 语法:<%= 表达式 %>

    示例:

    jsp 复制代码
    <h2>当前时间:<%= new java.util.Date() %></h2>  
  2. 指令:

    • 用于提供指示,告诉JSP引擎如何处理页面。
    • 常见指令:<%@ page %><%@ include %><%@ taglib %>

    示例:

    jsp 复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" %>  
  3. 动作标签:

    • 用于在JSP页面中执行某些操作,如转发请求、包含其他页面等。
    • 示例:<jsp:forward><jsp:include>

    示例:

    jsp 复制代码
    <jsp:include page="header.jsp" />  
  4. 声明:

    • 用于在页面中定义Java代码块。
    • 语法:<% 声明 %>

    示例:

    jsp 复制代码
    <%!  
        private int counter = 0;  
    %>  
  5. 脚本лет:

    • 用于在页面中嵌入Java代码。
    • 语法:<% 代码 %>

    **示例: <% for(int i=0; i<10; i++) { %> <p>Loop: <%= i %></p> <% } %>

2. 动态内容生成

JSP可以通过以下方式生成动态内容:

  1. 使用JavaBeans:

    • 定义JavaBean:

      java 复制代码
      public class User {  
          private String name;  
          // Getters and setters  
      }  
    • 在JSP中使用JavaBeans:

      jsp 复制代码
      <jsp:useBean id="user" class="com.example.User" scope="request"/>  
      <jsp:getProperty name="user" property="name"/>  
  2. 使用Expression Language (EL):

    • 示例:

      jsp 复制代码
      <h2>Hello, ${user.name}</h2>  
  3. 使用JSP Standard Tag Library (JSTL):

    • 导入JSTL标签库:

      jsp 复制代码
      <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
    • 使用JSTL标签:

      jsp 复制代码
      <c:forEach var="item" items="${items}">  
          <p>${item}</p>  
      </c:forEach>  

三、Servlet与JSP的联动开发

Servlet和JSP的结合是JavaEE Web开发的核心模式。Servlet负责处理业务逻辑,JSP负责生成视图。

1. 分离Concerns(关注点分离)

  • Servlet: 处理业务逻辑,接收请求,调用模型(如JavaBeans)执行业务操作。
  • JSP: 生成动态的HTML页面,展示数据。

2. 请求转发与共享数据

  • 请求转发: 使用RequestDispatcher将请求从Servlet转发到JSP。

    java 复制代码
    RequestDispatcher dispatcher = req.getRequestDispatcher("result.jsp");  
    dispatcher.forward(req, resp);  
  • 共享数据: 将数据存储在HttpServletRequest对象中,供JSP访问。

    java 复制代码
    req.setAttribute("message", "Hello, JSP!");  

    在JSP中访问数据:

    jsp 复制代码
    <h2>${message}</h2>  

3. 用户登录案例

以下是一个简单的用户登录案例,展示了Servlet与JSP的联动开发:

  1. 登录页面(login.jsp):

    jsp 复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" %>  
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
    
    <html>  
    <head>  
        <title>用户登录</title>  
    </head>  
    <body>  
        <h2>用户登录</h2>  
        <form action="/loginServlet" method="post">  
            <p>用户名:<input type="text" name="username" /></p>  
            <p>密码:<input type="password" name="password" /></p>  
            <p><input type="submit" value="登录" /></p>  
        </form>  
    </body>  
    </html>  
  2. 登录处理Servlet(LoginServlet.java):

    java 复制代码
    import javax.servlet.ServletException;  
    import javax.servlet.http.HttpServlet;  
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletResponse;  
    import java.io.IOException;  
    
    public class LoginServlet extends HttpServlet {  
        @Override  
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            String username = req.getParameter("username");  
            String password = req.getParameter("password");  
            
            // 假设这是一个简单的验证逻辑  
            if (username.equals("admin") && password.equals("admin")) {  
                req.setAttribute("message", "登录成功,欢迎您," + username + "!");  
                req.getRequestDispatcher("/welcome.jsp").forward(req, resp);  
            } else {  
                req.setAttribute("message", "用户名或密码错误!");  
                req.getRequestDispatcher("/login.jsp").forward(req, resp);  
            }  
        }  
    }  
  3. 欢迎页面(welcome.jsp):

    jsp 复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" %>  
    
    <html>  
    <head>  
        <title>欢迎页面</title>  
    </head>  
    <body>  
        <h2>${message}</h2>  
        <p><a href="/login.jsp">退出</a></p>  
    </body>  
    </html>  

四、实践:用户登录与注册功能

在本节中,我们将通过一个完整的用户登录和注册功能来实践Servlet和JSP的联动开发。

1. 功能需求

  • 用户登录:
    • 用户输入用户名和密码,提交登录请求。
    • 系统验证用户信息,成功则跳转到欢迎页面,失败则显示错误信息。
  • 用户注册:
    • 用户填写用户名、密码、邮箱等信息,提交注册请求。
    • 系统验证用户输入,成功则跳转到登录页面,失败则显示错误信息。

2. 项目结构

以下是一个典型的JavaEE Web项目结构:

css 复制代码
MyWebProject/  
├── src/  
│   ├── main/  
│   │   ├── java/  
│   │   │   └── com/  
│   │   │       └── example/  
│   │   │           ├── controller/  
│   │   │           │   ├── LoginServlet.java  
│   │   │           │   └── RegisterServlet.java  
│   │   │           └── model/  
│   │   │               └── User.java  
│   │   ├── resources/  
│   │   │   └── META-INF/  
│   │   │       └── persistence.xml  
│   │   └── webapp/  
│   │       ├── WEB-INF/  
│   │       │   └── web.xml  
│   │       ├── login.jsp  
│   │       ├── register.jsp  
│   │       └── welcome.jsp  
├── pom.xml  
└── README.md  

3. 实现步骤

  1. 创建项目:

    • 使用Eclipse或IntelliJ IDEA创建一个新的JavaEE Web项目。
    • 配置项目结构,确保包含上述文件夹和文件。
  2. 设计数据库:

    • 创建一个users表,包含idusernamepasswordemail字段。
    • 使用JDBC或JPA技术与数据库交互。
  3. 实现JavaBeans:

    • 创建User JavaBean,用于封装用户数据。

      java 复制代码
      public class User {  
          private int id;  
          private String username;  
          private String password;  
          private String email;  
          // Getters and setters  
      }  
  4. 实现Servlet:

    • LoginServlet: 处理登录请求,验证用户信息。
    • RegisterServlet: 处理注册请求,保存用户信息到数据库。
  5. 实现JSP页面:

    • login.jsp: 提供登录表单。
    • register.jsp: 提供注册表单。
    • welcome.jsp: 显示登录成功的欢迎信息。
  6. 配置安全性:

    • 添加输入验证,防止SQL注入和XSS攻击。
    • 使用HTTPS加密通信。
  7. 部署和测试:

    • 将项目部署到Tomcat服务器。
    • 测试登录和注册功能,确保所有场景都能正常处理。

4. 代码示例

以下是部分代码示例:

  1. LoginServlet.java:

    java 复制代码
    import javax.servlet.ServletException;  
    import javax.servlet.http.HttpServlet;  
    import javax.servlet.http.HttpServletRequest;  
    import javax.servlet.http.HttpServletResponse;  
    import java.io.IOException;  
    import java.sql.Connection;  
    import java.sql.PreparedStatement;  
    import java.sql.ResultSet;  
    
    public class LoginServlet extends HttpServlet {  
        @Override  
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            String username = req.getParameter("username");  
            String password = req.getParameter("password");  
            
            try {  
                // 验证用户信息  
                if (isValidUser(username, password)) {  
                    req.getSession().setAttribute("user", username);  
                    req.getRequestDispatcher("/welcome.jsp").forward(req, resp);  
                } else {  
                    req.setAttribute("error", "用户名或密码错误!");  
                    req.getRequestDispatcher("/login.jsp").forward(req, resp);  
                }  
            } catch (Exception e) {  
                // 处理异常  
            }  
        }  
        
        private boolean isValidUser(String username, String password) throws Exception {  
            // 数据库验证逻辑  
            Connection conn = null;  
            PreparedStatement stmt = null;  
            ResultSet rs = null;  
            
            try {  
                conn = getConnection();  
                stmt = conn.prepareStatement("SELECT * FROM users WHERE username = ?");  
                stmt.setString(1, username);  
                
                rs = stmt.executeQuery();  
                if (rs.next()) {  
                    return rs.getString("password").equals(password);  
                }  
                return false;  
            } finally {  
                closeResources(conn, stmt, rs);  
            }  
        }  
    }  
  2. login.jsp:

    jsp 复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" %>  
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
    
    <html>  
    <head>  
        <title>用户登录</title>  
    </head>  
    <body>  
        <h2>用户登录</h2>  
        <form action="${pageContext.request.contextPath}/loginServlet" method="post">  
            <p>用户名:<input type="text" name="username" /></p>  
            <p>密码:<input type="password" name="password" /></p>  
            <p><input type="submit" value="登录" /></p>  
        </form>  
        <c:if test="${error != null}">  
            <p style="color: red;">${error}</p>  
        </c:if>  
    </body>  
    </html>  
  3. register.jsp:

    jsp 复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" %>  
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
    
    <html>  
    <head>  
        <title>用户注册</title>  
    </head>  
    <body>  
        <h2>用户注册</h2>  
        <form action="${pageContext.request.contextPath}/registerServlet" method="post">  
            <p>用户名:<input type="text" name="username" /></p>  
            <p>密码:<input type="password" name="password" /></p>  
            <p>邮箱:<input type="email" name="email" /></p>  
            <p><input type="submit" value="注册" /></p>  
        </form>  
        <c:if test="${error != null}">  
            <p style="color: red;">${error}</p>  
        </c:if>  
    </body>  
    </html>  
  4. welcome.jsp:

    jsp 复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" %>  
    
    <html>  
    <head>  
        <title>欢迎页面</title>  
    </head>  
    <body>  
        <h2>欢迎,${user}!</h2>  
        <p><a href="${pageContext.request.contextPath}/login.jsp">退出</a></p>  
    </body>  
    </html>  

5. 使用Expression Language (EL) 和 JSTL

  • Expression Language (EL): 用于在JSP中访问JavaBean的属性。

    jsp 复制代码
    <h2>${user.username}</h2>  
  • JSTL: 用于在JSP中执行逻辑操作,如条件判断、循环等。

    jsp 复制代码
    <c:if test="${user.role == 'admin'}">  
        <p>您是管理员:</p>  
    </c:if>  

6. 依赖管理

在项目中,可以使用Maven或Gradle来管理依赖。以下是一个Maven pom.xml文件的示例:

xml 复制代码
<?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>com.example</groupId>  
    <artifactId>mywebapp</artifactId>  
    <version>1.0-SNAPSHOT</version>  
    <packaging>war</packaging>  
    
    <dependencies>  
        <dependency>  
            <groupId>javax.servlet</groupId>  
            <artifactId>javax.servlet-api</artifactId>  
            <version>4.0.1</version>  
            <scope>provided</scope>  
        </dependency>  
        <dependency>  
            <groupId>javax.servlet.jsp</groupId>  
            <artifactId>jsp-api</artifactId>  
            <version>2.3.1</version>  
            <scope>provided</scope>  
        </dependency>  
        <dependency>  
            <groupId>jstl</groupId>  
            <artifactId>jstl</artifactId>  
            <version>1.2</version>  
        </dependency>  
        <dependency>  
            <groupId>mysql</groupId>  
            <artifactId>mysql-connector-java</artifactId>  
            <version>8.0.21</version>  
        </dependency>  
    </dependencies>  
    
    <build>  
        <plugins>  
            <plugin>  
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-compiler-plugin</artifactId>  
                <version>3.8.1</version>  
                <configuration>  
                    <source>1.8</source>  
                    <target>1.8</target>  
                </configuration>  
            </plugin>  
            <plugin>  
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-war-plugin</artifactId>  
                <version>3.3.1</version>  
                <configuration>  
                    <warSourceDirectory>src/main/webapp</warSourceDirectory>  
                </configuration>  
            </plugin>  
        </plugins>  
    </build>  
</project>  
相关推荐
m0_7482475515 分钟前
数据库系统架构与DBMS功能探微:现代信息时代数据管理的关键
java·开发语言·数据库
计算机-秋大田31 分钟前
基于Spring Boot的企业车辆管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·spring·课程设计
汇匠源36 分钟前
Java Spring Boot 外卖系统,构建便捷的本地生活服务
java·spring boot·生活
曹天骄2 小时前
Spring Boot Gradle 项目中使用 @Slf4j 注解
java·spring boot·后端
虾球xz2 小时前
游戏引擎学习第133天
java·学习·游戏引擎
吉星9527ABC2 小时前
Linux下的c进程和java进程的通信-UnixSocket
java·linux·c语言·unixsocket通讯
浪九天2 小时前
Java常用正则表达式(身份证号、邮箱、手机号)格式校验
java·开发语言·正则表达式
鸿即为江边鸟2 小时前
Java TCP 通信:实现简单的 Echo 服务器与客户端
java·服务器·tcp/ip
会code的厨子2 小时前
leetcode5:最长回文子串
java·数据结构·算法
ALPH_2 小时前
用共线性分析的方法进行古基因组重构(具体步骤1)
java·开发语言·重构