[Java Web]Java Servlet基础

一、Servlet对象到底是啥?

Servlet对象其实就是一个"处理用户请求的小帮手"。当你用浏览器访问一个网站时,背后其实是有一个服务器在处理你发的请求,这个服务器通过Servlet对象来"理解"你的请求,然后给你一个合适的回复。


二、Servlet对象的作用:

  1. 接收请求:比如你填了一个表单,点击提交,表单里的数据就通过HTTP请求发到服务器。这时,Servlet对象就会接收到这些请求内容。

  2. 生成响应:它会根据你发过来的请求生成响应内容。比如,显示一个页面,或者返回一些数据(比如JSON格式的返回),然后再发送给你。

  3. 与用户交互:Servlet可以根据用户的输入做很多事情,比如查询数据库、处理登录信息、判断你是不是登录了,等等。

  4. 管理会话 :比如你登录了一个网站,接下来的每次请求,服务器都要知道你已经登录了。Servlet对象可以通过Session来记住这些信息,让你不需要每次都重新登录。


三、Servlet对象是怎么工作的?

  1. 初始化 :第一次访问这个Servlet时,容器(比如Tomcat)会帮你创建这个Servlet对象,并调用它的init()方法来做一些准备工作。

  2. 处理请求 :当你发送请求时,Servlet会处理它。它根据请求的类型(比如你是用GET请求还是POST请求)来调用不同的方法(比如doGet()或者doPost())。

  3. 销毁 :当服务器不需要再用这个Servlet时,Servlet对象会被销毁,调用它的destroy()方法来释放资源。

  4. 举个简单的例子:

假设你访问一个叫做/greeting的页面,URL是/greeting?name=John,Servlet对象就会:

  • 获取你传来的name参数(比如你传了John),

  • 然后根据这个信息给你返回一段话:"Hello, John!"


四、doGet()doPost()

1. 什么是 doGet()doPost()

doGet()doPost()HttpServlet 类的两个方法,它们用来处理 HTTP请求 。HTTP请求有很多类型,其中最常见的就是 GET请求POST请求

  • GET请求:用于获取数据,通常是从服务器获取信息。

  • POST请求:用于提交数据,通常是向服务器发送数据,比如提交表单、上传文件等。

2. 这两个方法分别干什么?

  • doGet() :用于处理 GET请求。通常用于获取数据。比如,访问网页、获取某些信息等。

  • doPost() :用于处理 POST请求。通常用于提交数据,比如提交表单信息、上传文件等。

3. 代码

我们来看看这个例子:

java 复制代码
@WebServlet("/example")
public class ExampleServlet extends HttpServlet {
    
    // 处理GET请求
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().println("GET request received");
    }
    
    // 处理POST请求
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().println("POST request received");
    }
}

3.1 代码解析:

  1. @WebServlet("/example") :这个注解是用来配置Servlet的,告诉服务器,当访问 /example 这个路径时,应该调用 ExampleServlet 类来处理请求。

  2. doGet() 方法

    • 这个方法会处理所有到 /example 路径的 GET请求

    • response.getWriter().println("GET request received"); 这行代码告诉服务器,返回"GET request received"给客户端(浏览器)。也就是浏览器发起 GET 请求后,页面会显示 "GET request received"。

  3. doPost() 方法

    • 这个方法会处理所有到 /example 路径的 POST请求

    • response.getWriter().println("POST request received"); 这行代码告诉服务器,返回"POST request received"给客户端。

3.2 举个例子:

假设你有一个网页,这个网页可以发送两种类型的请求:

  • GET请求 :浏览器打开这个网页时,发送的是 GET请求,通常是获取网页内容。

  • POST请求 :当用户提交表单时,通常会发送 POST请求,用于提交表单数据到服务器。

3.2.1 GET请求的情况

用户在浏览器中访问:http://localhost:8080/example

  • 浏览器会发送一个 GET请求/example 路径。

  • 服务器接收到 GET请求 后,会调用 doGet() 方法,并返回"GET request received"。

  • 浏览器页面显示:GET request received

3.2.2 POST请求的情况

用户提交了一个表单(例如,一个名字字段)到服务器:

html 复制代码
<form action="example" method="POST">
    <input type="text" name="name" placeholder="Enter your name" />
    <input type="submit" value="Submit" />
</form>
  • 当用户点击提交按钮时,表单数据通过 POST请求 发送到 /example

  • 服务器接收到 POST请求 后,会调用 doPost() 方法,并返回"POST request received"。

  • 浏览器页面显示:POST request received

4. 关键区别:

  • GET请求:常用于获取数据,如在浏览器中访问网页。

  • POST请求:常用于提交数据,如提交表单、上传文件等。

5. 为什么要区分 doGet()doPost()

因为这两种请求处理的逻辑通常不同:

  • GET请求通常用于获取内容,不会改变服务器的数据。

  • POST请求通常用于提交数据,可能会改变服务器的数据(比如存储用户提交的信息)。

6. 综上:

  • doGet() :处理从浏览器发送的 GET请求(获取数据)。

  • doPost() :处理从浏览器发送的 POST请求(提交数据)。


五、如何使用Servlet对象?

点击链接跳转到Servlet对象的使用https://blog.csdn.net/2302_80281315/article/details/156022906?fromshare=blogdetail&sharetype=blogdetail&sharerId=156022906&sharerefer=PC&sharesource=2302_80281315&sharefrom=from_linkhttps://blog.csdn.net/2302_80281315/article/details/156022906?fromshare=blogdetail&sharetype=blogdetail&sharerId=156022906&sharerefer=PC&sharesource=2302_80281315&sharefrom=from_linkhttps://blog.csdn.net/2302_80281315/article/details/156022906?fromshare=blogdetail&sharetype=blogdetail&sharerId=156022906&sharerefer=PC&sharesource=2302_80281315&sharefrom=from_link

1、写Servlet类

首先,你要写一个Servlet类 ,这个类需要继承自HttpServlet(或者实现Servlet接口)。这是你实现逻辑的地方。

我们从简单的Servlet类开始。比如说,创建一个简单的Servlet,它会处理一个/greeting的请求,输出一段欢迎文字。

java 复制代码
@WebServlet("/greeting")  // 这行注解说明这个Servlet会处理/greeting这个路径的请求
public class GreetingServlet extends HttpServlet {
    // 处理GET请求
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取用户请求的参数,这里假设用户访问的URL是/greeting?name=John
        String name = request.getParameter("name");

        // 设置响应内容类型
        response.setContentType("text/html");

        // 返回欢迎消息,假设用户传入的参数是John
        response.getWriter().println("<h1>Hello, " + name + "!</h1>");
    }
}

这个代码的意思是:

  • name = request.getParameter("name"); :这一行会从用户的请求中获取name参数的值,比如如果用户访问/greeting?name=John,那么name的值就是John。如果用户没有提供name参数,name的值会是null

  • response.setContentType("text/html"); :这行代码设置响应的内容类型为text/html,表示服务器将返回HTML格式的响应。

  • response.getWriter().println("<h1>Hello, " + name + "!</h1>"); :这行代码会根据获取到的name值生成HTML内容。如果用户提供了name=John,它就会显示"Hello, John!"。

2、配置Servlet

你可以通过两种方式配置Servlet,让服务器知道它是什么、怎么处理请求。

2.1 步骤 2:配置Servlet

2.1.1 什么是配置Servlet?

配置Servlet指的是告诉Web服务器(如Tomcat)如何找到和使用你的Servlet,并指定该Servlet处理哪些URL请求。Servlet本身是一个Java类,它需要通过配置来告诉服务器在何时、如何调用它。

Servlet配置的目的就是让服务器知道:

  • 这个Servlet类是什么?

  • 当访问某个URL时,应该调用哪个Servlet类来处理请求?

2.1.2 配置Servlet的方式

在Java Web应用中,配置Servlet有两种常见的方式:

1. 使用注解配置Servlet(推荐方式)

从Servlet 3.0版本开始,Java引入了注解,可以通过注解直接在Servlet类中配置Servlet,这种方式简单且不需要修改web.xml配置文件。

例如:

java 复制代码
@WebServlet("/greeting")
public class GreetingServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        response.setContentType("text/html");
        response.getWriter().println("<h1>Hello, " + name + "!</h1>");
    }
}

在这个例子中,@WebServlet("/greeting")是注解,它的作用是告诉Servlet容器,当访问URL路径/greeting时,就调用GreetingServlet这个Servlet类来处理请求。

优点 :不需要修改web.xml文件,配置更加简洁。

2. 使用web.xml配置(传统方式)

在没有注解时,配置Servlet是通过在web.xml文件中进行配置的。web.xml是Web应用的配置文件,位于WEB-INF文件夹下。

例如,配置Servlet时,可以在web.xml文件中指定Servlet类及其对应的URL模式:

XML 复制代码
<web-app>
    <!-- 配置Servlet -->
    <servlet>
        <servlet-name>GreetingServlet</servlet-name>
        <servlet-class>com.example.GreetingServlet</servlet-class>
    </servlet>

    <!-- 配置Servlet的URL映射 -->
    <servlet-mapping>
        <servlet-name>GreetingServlet</servlet-name>
        <url-pattern>/greeting</url-pattern>
    </servlet-mapping>
</web-app>

这段配置的意思是:

  • <servlet-name> :指定Servlet的名字,GreetingServlet是名字。

  • <servlet-class> :指定Servlet的类名,即com.example.GreetingServlet

  • <url-pattern> :指定访问该Servlet的URL路径,这里是/greeting

优点:这种方式更加灵活,适合需要更复杂配置的场景。

2.1.3 什么时候用配置Servlet?

你需要配置Servlet的时候通常是:

  1. 处理特定请求 :例如你想处理/login/register等路径的请求,Servlet可以指定这些路径,Servlet就会处理这些路径的请求。

  2. 定义Servlet行为:你可以通过配置不同的Servlet,来让它们处理不同的功能模块,比如一个Servlet处理用户登录,另一个处理数据查询等。

总的来说,配置Servlet 就是告诉服务器如何找到并使用Servlet类来处理特定的请求,可以通过注解(简单方便)或者在web.xml文件中进行配置(更加灵活)。

2.2.3 步骤 3:访问Servlet

  1. 启动服务器:启动你的Web服务器(比如Tomcat)。

  2. 访问Servlet:在浏览器中输入:

    http://localhost:8080/your-web-app/greeting?name=John

    这时,你就能看到"Hello, John!"的欢迎信息。

3、处理请求

在Servlet类里,你要定义方法,来处理用户发来的不同请求(如GET请求、POST请求)。

3.1 步骤 4:处理不同请求

在Java Servlet中,当浏览器发起不同类型的请求时,Servlet需要根据请求的类型(比如GETPOST)来做出响应。doGet()方法处理的是GET请求,doPost()方法处理的是POST请求。

具体的代码解析:

java 复制代码
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 获取POST请求的数据
    String message = request.getParameter("message");

    // 处理这个消息
    response.getWriter().println("Message received: " + message);
}
  1. @Override :这个注解是告诉Java编译器,我们重写了父类(HttpServlet)的doPost()方法。也就是说,我们告诉服务器:如果收到POST请求,应该执行这个方法。

  2. protected void doPost(HttpServletRequest request, HttpServletResponse response) :这是一个方法定义。doPost()方法专门用来处理客户端(比如浏览器)发来的POST请求。

    • HttpServletRequest requestrequest是一个对象,它包含了客户端发来的请求数据,包括表单数据、URL参数等。

    • HttpServletResponse responseresponse是一个对象,我们用它来设置服务器要返回给客户端的数据。

  3. String message = request.getParameter("message"); :这里我们从客户端的请求中获取message这个参数。假设浏览器通过POST请求发送了一个表单,表单中有一个字段叫message,这行代码就把message字段的值提取出来并存储在message变量中。

  4. response.getWriter().println("Message received: " + message); :这一行代码将message的值返回给客户端。在浏览器中,服务器会显示"Message received: [你提交的消息]"。

3.2 举个更详细的例子

假设我们现在有一个简单的Web应用,用户可以在页面上输入一个消息,点击提交按钮,服务器处理这个消息后,再将处理结果显示给用户。

3.2.1 步骤 1:HTML页面(前端)

我们创建一个HTML表单,让用户输入消息并提交给服务器。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Message Form</title>
</head>
<body>
    <h1>Enter your message</h1>
    <form action="/myServlet" method="POST">
        <!-- 用户输入的消息 -->
        <input type="text" name="message" placeholder="Type your message here" required/>
        <input type="submit" value="Submit" />
    </form>
</body>
</html>
  • <form action="/myServlet" method="POST"> :这个表单将会通过POST方法提交数据到/myServlet路径(也就是你的Servlet的路径)。

  • <input type="text" name="message" /> :这个输入框让用户填写消息,name="message"会将这个字段的数据作为message参数提交。

  • <input type="submit" value="Submit" />:点击这个按钮会提交表单。

3.2.2 步骤 2:Servlet(后端)

服务器端处理用户的请求并返回响应。我们在Servlet中处理POST请求,获取用户填写的消息,然后将处理后的内容返回给用户。

java 复制代码
@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取用户通过POST提交的消息
        String message = request.getParameter("message");
        
        // 设置响应内容类型
        response.setContentType("text/html");

        // 将接收到的消息返回给客户端
        response.getWriter().println("<h1>Message received: " + message + "</h1>");
    }
}
  • request.getParameter("message") :这行代码从用户提交的表单中获取message字段的内容(就是用户输入的消息)。

  • response.getWriter().println("<h1>Message received: " + message + "</h1>"); :这行代码将用户输入的消息显示出来,response.getWriter()是用来将响应数据写回客户端的。

3.2.3 步骤 3:整个流程
  1. 用户打开表单页面(HTML页面),看到一个输入框,提示他们输入消息。

  2. 用户在输入框里输入一些文字(比如Hello, Servlet!),然后点击"Submit"按钮。

  3. 用户提交表单后,浏览器会通过POST请求message=Hello, Servlet!发送到服务器上的/myServlet路径。

  4. 服务器接收到请求后,调用doPost()方法,获取请求中的message参数(就是用户输入的内容)。

  5. Servlet将内容处理后,返回一个包含消息的HTML页面:<h1>Message received: Hello, Servlet!</h1>,并显示给用户。

3.3 以上的流程可总结为:

  1. 用户填写表单并点击提交按钮,浏览器将数据通过POST请求发送给服务器。

  2. 服务器接收到请求后,通过request.getParameter("message")获取用户输入的数据。

  3. 服务器返回一段HTML内容给浏览器,告诉用户他们的消息已被接收。

3.4 最终效果:

当用户提交表单后,浏览器页面显示:

html 复制代码
<h1>Message received: Hello, Servlet!</h1>

这个过程就是POST请求和Servlet处理过程的一个完整示例,通过这种方式,浏览器和服务器就可以进行交互,用户输入的内容被传递到服务器并返回处理后的结果。

4. 使用Servlet类的总的流程:

  • 写Servlet类 :继承HttpServlet并重写doGet()doPost()来处理请求。

  • 配置Servlet :你可以通过注解(推荐)或者web.xml来配置。

  • 访问Servlet:通过浏览器或者其他HTTP客户端访问Servlet,服务器会调用相应的方法来处理。

Servlet对象基本就这些,核心是:它就是用来接收请求、处理逻辑并生成响应的。


六、Servlet的生命周期

Servlet的生命周期由Servlet容器管理,主要包括以下几个阶段:

  • 初始化阶段 :当Servlet被第一次加载时,容器调用Servlet的init()方法进行初始化。这个方法只会执行一次。

  • 服务阶段 :每次收到请求时,容器调用Servlet的service()方法,该方法根据请求类型(GET或POST)调用对应的doGet()doPost()方法。

  • 销毁阶段 :当Servlet被卸载或容器关闭时,容器调用Servlet的destroy()方法。这个方法通常用于释放资源。


七、重定向和转发

1. 重定向(Redirect)

重定向是当你想要让用户浏览器去访问一个新的地址时,用来实现的操作。就像你对浏览器说:"去这个新地址看看吧!"

  • 工作原理 :当你调用response.sendRedirect()时,服务器会告诉浏览器,"重新发一个请求,去访问另一个页面。"浏览器会重新向新地址发起请求。

  • 结果:浏览器的地址栏会显示新的URL,并且浏览器会重新发送一个请求。

1.1 举个例子:

假设你有一个在线商店,当用户点击"结账"按钮时,你需要确保用户已经登录。如果用户没有登录,你会将他们重定向到登录页面。

1.1.1 场景:
  1. 用户点击了"结账"按钮。

  2. 服务器需要检查用户是否已登录。

  3. 如果用户未登录,服务器会执行 response.sendRedirect("login.jsp");,将用户重定向到登录页面。

  4. 浏览器的地址栏会显示新的URL------login.jsp,然后浏览器会向服务器发出新的请求加载登录页面。

1.1.2 代码示例:
java 复制代码
@WebServlet("/checkout")
public class CheckoutServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 假设用户未登录
        boolean isLoggedIn = false;  // 模拟未登录的状态

        if (!isLoggedIn) {
            // 重定向到登录页面
            response.sendRedirect("login.jsp");
        } else {
            // 如果用户已登录,继续结账流程
            response.getWriter().println("Proceed to checkout...");
        }
    }
}
1.1.3 过程:
  1. 用户访问 /checkout 页面。

  2. 服务器检查用户是否登录,如果没有登录,执行 response.sendRedirect("login.jsp");

  3. 浏览器重新发送请求到 login.jsp,并加载登录页面。

  4. 浏览器的地址栏变为 login.jsp,用户看到的是登录页面。

注意response.sendRedirect() 会导致浏览器发出新的请求,地址栏会发生变化,浏览器重新加载新的页面。它适合用来跳转到完全不同的页面。

2. 转发(Forward)

转发则与重定向不同,它是完全在服务器端处理的,浏览器的地址栏并不会发生变化。也就是说,浏览器并没有重新发请求,而是服务器告诉浏览器,"继续处理这个请求,但是交给别的资源来做。"

  • 工作原理 :当你调用RequestDispatcher.forward()时,服务器会把请求转交给另一个资源(可能是另一个Servlet或JSP页面),但浏览器并不会感知到这个过程。浏览器的URL依旧不变。

  • 结果:浏览器的地址栏不变,仍然显示最初的请求URL。

2.1 举个例子:

假设你有一个用户个人信息页面,用户访问 /userInfo 页面时,服务器需要检查用户是否登录。如果没有登录,服务器会转发请求到一个错误页面(errorPage.jsp)。用户仍然会看到原来访问的 /userInfo 页面,浏览器的URL不变。

2.1.1 场景:
  1. 用户访问 /userInfo 页面。

  2. 服务器检查用户是否已登录。

  3. 如果未登录,服务器执行 RequestDispatcher.forward(request, response);,将请求转发到 errorPage.jsp 页面。

  4. 浏览器的地址栏仍然是 /userInfo,但显示的是 errorPage.jsp 页面。

2.1.2 代码示例:
java 复制代码
@WebServlet("/userInfo")
public class UserInfoServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 假设用户未登录
        boolean isLoggedIn = false;  // 模拟未登录的状态

        if (!isLoggedIn) {
            // 转发到错误页面
            RequestDispatcher dispatcher = request.getRequestDispatcher("errorPage.jsp");
            dispatcher.forward(request, response);
        } else {
            // 如果用户已登录,显示用户信息
            response.getWriter().println("Welcome to your profile!");
        }
    }
}
2.1.3 过程:
  1. 用户访问 /userInfo 页面。

  2. 服务器检查用户是否登录,如果没有登录,执行 RequestDispatcher.forward(request, response);,将请求转发到 errorPage.jsp

  3. 浏览器的地址栏不会变化,依然是 /userInfo,但是用户看到的是 errorPage.jsp 页面,告诉他们需要登录才能查看个人信息。

注意RequestDispatcher.forward() 会让服务器内部将请求转发到另一个页面,而不会更改浏览器的地址栏。适用于需要在服务器内部处理多个资源的场景,比如验证、处理、显示等。

3. 重定向与转发的区别对比

特点 重定向 (sendRedirect) 转发 (forward)
发生位置 客户端(浏览器)发起新的请求 服务器内部操作
浏览器地址栏变化 是,浏览器会重新加载新的URL 否,浏览器地址栏不变
请求是否重新发送 是,浏览器会发送一个新的请求 否,服务器直接处理请求
用途 适用于需要改变URL或者引导用户到其他页面的场景,比如登录验证后跳转到主页。 适用于服务器内部的处理,不需要改变URL的跳转,比如从一个Servlet转发到另一个JSP页面。

八、登录验证实践

在很多Web应用中,用户需要登录才能访问某些页面。登录验证通常需要使用重定向和转发来控制页面的跳转。

场景设定

假设你正在开发一个在线商店网站,在这个网站上,只有登录的用户才能访问"结账页面"和"用户主页"。如果用户未登录,访问这些页面时需要转到登录页面;如果已经登录,用户应该被重定向到他们的主页。

1. 用户未登录:转发到登录页面

当用户访问需要登录才能访问的页面(比如结账页面或用户主页),如果他们没有登录,你需要将他们转发到登录页面。

  • 使用转发的原因:当用户没有登录时,你可以将他们转发到登录页面,告诉他们需要登录。这个过程不改变浏览器的地址栏,用户看到的还是原始的请求URL。

1.1 具体步骤:

  1. 用户尝试访问结账页面(比如/checkout)。

  2. 服务器检查用户是否已经登录。

  3. 如果用户未登录,服务器将请求转发到login.jsp页面。

1.2 代码示例:

java 复制代码
@WebServlet("/checkout")
public class CheckoutServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 假设这里检查用户是否登录
        boolean isLoggedIn = false;  // 模拟用户未登录的情况
        
        if (!isLoggedIn) {
            // 用户未登录,转发到登录页面
            RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
            dispatcher.forward(request, response);
        } else {
            // 用户已登录,继续处理结账逻辑
            response.getWriter().println("Proceed to checkout...");
        }
    }
}

1.3 过程:

  • 用户访问 /checkout 路径。

  • 服务器发现用户未登录,执行 request.getRequestDispatcher("login.jsp").forward(request, response)

  • 服务器将请求转发到 login.jsp 页面。

  • 浏览器的地址栏不变 ,仍然是 /checkout,但显示的是 login.jsp 页面。

1.4 何时使用转发:

  • 用户未登录时,通过转发引导用户去登录页面,而浏览器地址栏仍然显示原始的请求地址。

  • 转发是服务器内部操作,因此用户不知道跳转的过程。


2. 用户已登录:重定向到用户主页

当用户登录成功后,应该引导他们访问个人主页或者其他页面,重定向 是此时的合适选择。重定向会告诉浏览器去访问一个新的URL,浏览器地址栏的URL会改变

2.1 具体步骤:

  1. 用户成功登录。

  2. 服务器通过response.sendRedirect()将用户重定向到用户主页(比如userHome.jsp)。

  3. 浏览器的地址栏会显示 userHome.jsp,然后浏览器会发起一个新的请求加载用户主页。

2.2 代码示例:

java 复制代码
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取用户登录信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 假设用户登录验证通过
        boolean isValidUser = true;  // 模拟登录验证成功

        if (isValidUser) {
            // 登录成功,重定向到用户主页
            response.sendRedirect("userHome.jsp");
        } else {
            // 登录失败,转发到错误页面或显示错误信息
            request.setAttribute("errorMessage", "Invalid credentials!");
            RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
            dispatcher.forward(request, response);
        }
    }
}

2.3 过程:

  • 用户通过POST请求提交登录信息。

  • 如果登录成功,response.sendRedirect("userHome.jsp"); 会让浏览器发起新的请求到 userHome.jsp

  • 浏览器的地址栏会变成 userHome.jsp,并加载用户主页。

2.4 何时使用重定向:

  • 用户登录成功后,你想让浏览器跳转到另一个页面(比如用户主页),并且浏览器的地址栏需要更新。

  • 重定向是客户端操作,因此浏览器会重新发起请求,地址栏的URL会改变。


3. 综合示例:一个完整的登录验证和页面跳转

让我们来看一个综合的例子,这个例子结合了转发和重定向。

3.1 登录流程:

  1. 用户访问结账页面 /checkout

  2. 如果用户没有登录,服务器会将请求转发 到登录页面 login.jsp

  3. 用户填写用户名和密码,点击登录按钮。

  4. 服务器检查登录信息,如果正确,重定向 到用户主页 userHome.jsp

3.2 代码实现:

java 复制代码
@WebServlet("/checkout")
public class CheckoutServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 假设检查用户登录状态
        boolean isLoggedIn = false;  // 用户未登录

        if (!isLoggedIn) {
            // 如果用户未登录,转发到登录页面
            RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
            dispatcher.forward(request, response);
        } else {
            // 如果用户已登录,继续处理结账
            response.getWriter().println("Proceed to checkout...");
        }
    }
}

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 假设这里进行登录验证
        boolean isValidUser = true;  // 用户验证通过

        if (isValidUser) {
            // 登录成功,重定向到用户主页
            response.sendRedirect("userHome.jsp");
        } else {
            // 登录失败,转发回登录页面并显示错误
            request.setAttribute("errorMessage", "Invalid credentials!");
            RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
            dispatcher.forward(request, response);
        }
    }
}

3.3 说明:

  • 未登录用户 :访问 /checkout 时会被转发到 login.jsp,浏览器的地址栏不变。

  • 登录用户 :登录成功后,通过 response.sendRedirect("userHome.jsp") 重定向到用户主页,浏览器的地址栏变为 userHome.jsp

4. 总结:

  • 转发:用于将请求从一个资源(如Servlet)转交到另一个资源(如JSP),地址栏不变,通常用于用户未登录时跳转到登录页面。

  • 重定向:用于让浏览器重新发起请求,地址栏会发生变化,通常用于用户登录后跳转到主页。


九、Session(会话)

Session 是用来保存用户的会话数据的,像是"记录"用户的状态(比如登录状态)。它能让你在多个请求之间存储数据。

  • 获取Session :每次请求都会生成一个Session,可以通过 request.getSession() 获取。

  • 存储数据 :比如你想保存一个用户对象,可以用 session.setAttribute("user", userObject); 将它存到Session中。

  • 获取数据 :你可以通过 session.getAttribute("user") 获取存储的用户数据。

1. 具体场景

我们将实现一个简单的登录系统,用户输入用户名和密码后,系统会检查用户的登录状态并进行相应的跳转。

  • 用户未登录 :如果用户没有登录,我们通过 Session 保存登录状态,并跳转到欢迎页面。

  • 用户已登录 :如果用户已经登录,我们通过 Session 获取存储的用户信息,跳转到用户主页。

2. 实现步骤

  1. 用户登录:用户提交登录表单,Servlet会验证用户名和密码。

  2. 使用Session:如果登录成功,用户信息会存储到Session中。

  3. 访问受保护页面:如果用户未登录,访问受保护页面时会被重定向到登录页面。

3. 完整代码示例

3.1 登录页面 (login.jsp)

这是一个简单的登录表单,用户在此页面输入用户名和密码。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <h1>Login</h1>
    <form action="LoginServlet" method="POST">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required>
        <br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required>
        <br>
        <input type="submit" value="Login">
    </form>
    <p>${errorMessage}</p>
</body>
</html>

3.2 登录验证 Servlet (LoginServlet.java)

这个Servlet处理用户的登录请求,它会验证用户的用户名和密码,并在验证成功后将用户信息保存到Session中。

java 复制代码
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 假设用户名是admin,密码是1234
        if ("admin".equals(username) && "1234".equals(password)) {
            // 登录成功,将用户信息保存到Session
            HttpSession session = request.getSession();
            session.setAttribute("user", username);  // 保存用户名到Session中

            // 登录成功后,重定向到用户主页
            response.sendRedirect("userHome.jsp");
        } else {
            // 登录失败,设置错误信息并转发回登录页面
            request.setAttribute("errorMessage", "Invalid username or password!");
            RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
            dispatcher.forward(request, response);
        }
    }
}

3.3 用户主页 (userHome.jsp)

这是一个简单的用户主页,当用户登录成功后会被重定向到这里。主页会显示欢迎信息。

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User Home</title>
</head>
<body>
    <h1>Welcome, ${user}!</h1>
    <p>This is your home page.</p>
    <a href="logout.jsp">Logout</a>
</body>
</html>

3.4 检查登录状态 Servlet (CheckLoginServlet.java)

这个Servlet用于在每个受保护的页面访问时检查用户是否已登录。如果用户没有登录,它会重定向到登录页面。

java 复制代码
@WebServlet("/checkLogin")
public class CheckLoginServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取Session
        HttpSession session = request.getSession(false);

        if (session == null || session.getAttribute("user") == null) {
            // 用户未登录,重定向到登录页面
            response.sendRedirect("login.jsp");
        } else {
            // 用户已登录,继续处理
            response.getWriter().println("Welcome to the protected page!");
        }
    }
}

3.5 登出页面 (logout.jsp)

当用户点击"Logout"链接时,我们会销毁Session,退出登录。

java 复制代码
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取Session并销毁
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();  // 销毁Session
        }
        
        // 重定向回登录页面
        response.sendRedirect("login.jsp");
    }
}

4. 完整流程说明

  1. 用户访问登录页面

    用户打开 login.jsp 页面,输入用户名和密码提交表单。

  2. 用户登录验证
    LoginServlet 接收提交的用户名和密码,如果正确,将用户名保存到 Session 中,重定向到 userHome.jsp

  3. 检查用户是否已登录

    访问受保护的页面(比如结账页面或用户主页)时,CheckLoginServlet 会检查 Session 是否包含有效的用户信息。如果没有,重定向到登录页面。如果已登录,允许访问。

  4. 用户登出

    用户点击登出按钮,LogoutServlet 会销毁当前 Session 并重定向到登录页面。

5. 会话(Session)使用总结

  • 获取 Session :每个 HTTP 请求都会有一个 HttpSession 对象,可以通过 request.getSession() 获取。

  • 存储数据 :通过 session.setAttribute("key", value) 将数据保存到 Session 中(如保存用户名)。

  • 获取数据 :通过 session.getAttribute("key") 获取存储在 Session 中的数据(如获取用户名)。

  • 销毁 Session :通过 session.invalidate() 销毁 Session,用户登出时常用。

这样通过 Session 可以实现对用户登录状态的管理,在多次请求之间保持状态,确保只有已登录的用户能够访问某些受保护的页面。


十、MVC模式

MVC(Model-View-Controller)是一种设计模式,用来组织Web应用程序的代码,使其更清晰、易于维护。它把代码分成了三个部分:

  • Model:处理数据和业务逻辑(比如数据库操作)。

  • View:负责显示数据(比如网页的界面)。

  • Controller:接收请求,并决定如何处理这些请求(通常是调用Model和View)。

示例:

假设有一个用户信息的应用:

  • ModelUser 类,封装用户数据。

  • View:一个JSP页面,显示用户的信息。

  • Controller:一个Servlet,负责处理用户请求,获取用户数据,然后转发到JSP页面显示。

    java 复制代码
    public class UserServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 假设这里是从数据库获取用户数据
            User user = new User("John", "Doe");
    
            // 将用户数据存入请求中
            request.setAttribute("user", user);
    
            // 转发请求到JSP页面
            RequestDispatcher dispatcher = request.getRequestDispatcher("user.jsp");
            dispatcher.forward(request, response);
        }
    }

user.jsp 页面,你可以显示用户的信息:

javascript 复制代码
<h1>User: ${user.firstName} ${user.lastName}</h1>

十一、四则运算实践

假设你想做一个计算器,通过网页来接收两个数字和操作符(加、减、乘、除),然后返回结果。

场景说明

我们需要实现一个可以进行加、减、乘、除运算的计算器,用户输入两个数字和一个运算符(如加、减、乘、除),计算器根据用户的输入进行运算,并返回结果。

步骤

  1. 创建一个 HTML 表单,用户可以在其中输入两个数字和选择运算符。

  2. 创建一个 Servlet 来处理用户输入的数据,进行计算,并返回结果。

  3. 显示结果到用户的浏览器页面。


1. HTML 表单(calculator.html

这是一个简单的表单页面,用户可以输入两个数字并选择运算符。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Calculator</title>
</head>
<body>
    <h1>Simple Calculator</h1>
    <form action="calculate" method="POST">
        <label for="num1">Number 1:</label>
        <input type="text" id="num1" name="num1" required>
        <br><br>
        <label for="num2">Number 2:</label>
        <input type="text" id="num2" name="num2" required>
        <br><br>
        <label for="operation">Operation:</label>
        <select name="operation" id="operation" required>
            <option value="add">Add</option>
            <option value="subtract">Subtract</option>
            <option value="multiply">Multiply</option>
            <option value="divide">Divide</option>
        </select>
        <br><br>
        <input type="submit" value="Calculate">
    </form>
</body>
</html>
解释:
  • num1num2 是用户输入的两个数字。

  • operation 是一个下拉框,用户可以选择加、减、乘、除。

  • 表单提交时,数据会通过 POST 请求 发送到 /calculate,由我们接下来的 Servlet 来处理。


2. Servlet(CalculatorServlet.java

这个Servlet负责接收用户提交的数据,根据选择的操作符进行计算,并返回结果。

java 复制代码
@WebServlet("/calculate")
public class CalculatorServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取表单数据
        int num1 = Integer.parseInt(request.getParameter("num1"));  // 获取第一个数字
        int num2 = Integer.parseInt(request.getParameter("num2"));  // 获取第二个数字
        String operation = request.getParameter("operation");  // 获取操作符

        int result = 0;  // 存储计算结果
        
        // 根据操作符进行不同的计算
        switch(operation) {
            case "add":  // 加法
                result = num1 + num2;
                break;
            case "subtract":  // 减法
                result = num1 - num2;
                break;
            case "multiply":  // 乘法
                result = num1 * num2;
                break;
            case "divide":  // 除法
                if(num2 != 0) {  // 防止除以0的错误
                    result = num1 / num2;
                } else {
                    response.getWriter().println("Error: Cannot divide by zero.");
                    return;
                }
                break;
            default:
                response.getWriter().println("Invalid operation.");
                return;
        }

        // 返回计算结果给客户端
        response.setContentType("text/html");  // 设置响应类型为HTML
        response.getWriter().println("<h2>Result: " + result + "</h2>");
    }
}
解释:
  1. 获取数据

    • request.getParameter("num1")request.getParameter("num2") 获取用户输入的两个数字。

    • request.getParameter("operation") 获取用户选择的运算符。

  2. 计算结果

    • 我们使用 switch-case 语句来判断用户选择的运算符。

    • 根据选择的操作符,执行相应的四则运算。

  3. 返回结果

    • response.getWriter().println("<h2>Result: " + result + "</h2>"); 用来将结果打印在页面上。

    • 如果除法操作中 除数为零,我们会返回一个错误信息:"Error: Cannot divide by zero."


3. 如何工作:

  1. 用户访问 calculator.html 页面,填写两个数字并选择运算符(如加法)。

  2. 用户点击"Calculate"按钮,表单提交会发送 POST 请求/calculate

  3. CalculatorServlet 会接收到请求,解析出两个数字和操作符。

  4. 根据用户选择的操作符,执行相应的四则运算。

  5. 计算结果通过 response.getWriter() 返回到浏览器页面,显示出来。


4. 完整的文件结构:

假设我们有一个简单的项目结构,如下所示:

html 复制代码
WebApp/
│
├── WEB-INF/
│   └── web.xml          // 这里可以配置Servlet(也可以通过注解配置)
│
├── calculator.html      // 前端HTML表单
├── CalculatorServlet.java // 处理计算逻辑的Servlet
└── userHome.jsp         // 如果需要一个主页可以放在这里

5.结合总结:Web应用中的处理流程

HTML 表单与用户输入

  • 用户通过HTML表单输入数据并提交给服务器。这些数据可能包括用户的操作(如四则运算的数字和运算符)或者需要登录验证的用户信息。

  • 比如,一个计算器应用中,用户输入两个数字和选择一个操作符(加、减、乘、除)。这种数据会通过POST请求发送给服务器,供后台逻辑处理。

Servlet:处理用户输入与逻辑

  • Servlet 是Web应用中用来处理客户端请求的Java类。它接收来自用户的输入,执行相应的逻辑,然后将结果返回给浏览器。

  • 在四则运算的例子中,Servlet会从请求中获取用户输入的数字和运算符,使用 switch-case 语句进行运算,最后通过 response.getWriter() 返回运算结果给用户。

例如,用户输入 num1 = 10, num2 = 5, operation = "add",Servlet会计算出 num1 + num2,并返回结果 15
3.

四则运算:使用逻辑进行处理

  • 处理用户输入的数字和操作符,通常使用 switch-case 语句来根据用户选择的操作(加法、减法、乘法、除法)执行相应的运算。

  • 在Servlet中,通过读取用户输入的参数(如 num1num2operation),然后根据 operation 的值来执行不同的运算(加、减、乘、除)。

重定向与转发

  • 重定向 :如果用户需要被引导到一个新的页面(比如登录验证后跳转到用户主页),可以使用 重定向 。这种方式会让浏览器重新发送请求,并且地址栏的URL会发生变化。例如,用户登录成功后,通过 response.sendRedirect("userHome.jsp"); 重定向到用户主页。

  • 转发 :当你希望在服务器内部处理请求时,使用 转发 。这通常用于数据的传递和页面间的跳转,且浏览器的地址栏不会变化。例如,在用户未登录的情况下,服务器通过 request.getRequestDispatcher("login.jsp").forward(request, response); 将请求转发到登录页面,但浏览器的地址栏依旧显示最初的请求URL。

Session:保存和管理用户数据

  • Session 用来在多次请求之间存储和管理用户的数据。例如,在一个Web应用中,登录后的用户信息(如用户名)可以通过 Session 保持,确保用户在访问其他页面时仍然处于登录状态。

  • 在登录验证的场景中,用户登录后,登录信息(如用户名)会通过 session.setAttribute("user", username); 存储在Session中,然后用户访问其他需要登录的页面时,服务器通过 request.getSession().getAttribute("user") 获取这个信息来判断用户是否已登录。

MVC模式

  • MVC(Model-View-Controller) 是一种设计模式,用于将Web应用的逻辑分为三个主要部分:

    • Model(模型):负责处理数据和业务逻辑(比如四则运算的计算逻辑,或者从数据库读取用户数据)。

    • View(视图):负责显示数据给用户(比如HTML页面、JSP页面等)。

    • Controller(控制器):负责处理请求,协调Model和View(例如Servlet)。

MVC模式可以帮助你将代码的不同部分分离,使得应用更清晰、易于维护。比如,在一个计算器应用中:

  • Model 是进行四则运算的计算逻辑。

  • View 是HTML表单,显示用户输入和结果。

  • Controller 是Servlet,处理请求,执行计算并返回结果。


6. 如何在实际应用中结合这些技术:

假设你正在开发一个Web应用,需要实现如下功能:

  1. 用户通过HTML表单输入数字和选择运算符。

  2. 当用户点击"提交"时,表单数据会通过POST请求发送到一个Servlet。

  3. Servlet接收数据,进行四则运算(加、减、乘、除),并返回计算结果。

  4. 如果用户未登录,访问某些页面时,可以使用 转发 将他们引导到登录页面;如果用户登录后,通过 重定向 跳转到用户主页。

  5. 使用 Session 来保持用户登录状态,确保用户登录后访问受保护的页面。

相关推荐
遇印记8 小时前
java期末复习(构造方法和成员方法,重写和重载)
java·开发语言·学习
C雨后彩虹8 小时前
事件推送问题
java·数据结构·算法·华为·面试
玉木成琳8 小时前
Taro + React + @nutui/nutui-react-taro 时间选择器重写
前端·react.js·taro
lxh01139 小时前
2025/12/17总结
前端·webpack
芳草萋萋鹦鹉洲哦9 小时前
【elementUI】form表单rules没生效
前端·javascript·elementui
没有bug.的程序员9 小时前
SOA、微服务、分布式系统的区别与联系
java·jvm·微服务·架构·wpf·日志·gc
LYFlied9 小时前
【每日算法】LeetCode 560. 和为 K 的子数组
前端·数据结构·算法·leetcode·职场和发展
howcode9 小时前
年度总结——Git提交量戳破了我的副业窘境
前端·后端·程序员
素雪风华9 小时前
只使用Docker+Maven实现全自动化流程部署服务;Docker创建ffmpeg环境;
java·运维·后端·docker·容器·自动化·maven