一、Servlet对象到底是啥?
Servlet对象其实就是一个"处理用户请求的小帮手"。当你用浏览器访问一个网站时,背后其实是有一个服务器在处理你发的请求,这个服务器通过Servlet对象来"理解"你的请求,然后给你一个合适的回复。
二、Servlet对象的作用:
-
接收请求:比如你填了一个表单,点击提交,表单里的数据就通过HTTP请求发到服务器。这时,Servlet对象就会接收到这些请求内容。
-
生成响应:它会根据你发过来的请求生成响应内容。比如,显示一个页面,或者返回一些数据(比如JSON格式的返回),然后再发送给你。
-
与用户交互:Servlet可以根据用户的输入做很多事情,比如查询数据库、处理登录信息、判断你是不是登录了,等等。
-
管理会话 :比如你登录了一个网站,接下来的每次请求,服务器都要知道你已经登录了。Servlet对象可以通过Session来记住这些信息,让你不需要每次都重新登录。
三、Servlet对象是怎么工作的?
-
初始化 :第一次访问这个Servlet时,容器(比如Tomcat)会帮你创建这个Servlet对象,并调用它的
init()方法来做一些准备工作。 -
处理请求 :当你发送请求时,Servlet会处理它。它根据请求的类型(比如你是用GET请求还是POST请求)来调用不同的方法(比如
doGet()或者doPost())。 -
销毁 :当服务器不需要再用这个Servlet时,Servlet对象会被销毁,调用它的
destroy()方法来释放资源。 -
举个简单的例子:
假设你访问一个叫做/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 代码解析:
-
@WebServlet("/example"):这个注解是用来配置Servlet的,告诉服务器,当访问/example这个路径时,应该调用ExampleServlet类来处理请求。 -
doGet()方法:-
这个方法会处理所有到
/example路径的 GET请求。 -
response.getWriter().println("GET request received");这行代码告诉服务器,返回"GET request received"给客户端(浏览器)。也就是浏览器发起 GET 请求后,页面会显示 "GET request received"。
-
-
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的时候通常是:
-
处理特定请求 :例如你想处理
/login、/register等路径的请求,Servlet可以指定这些路径,Servlet就会处理这些路径的请求。 -
定义Servlet行为:你可以通过配置不同的Servlet,来让它们处理不同的功能模块,比如一个Servlet处理用户登录,另一个处理数据查询等。
总的来说,配置Servlet 就是告诉服务器如何找到并使用Servlet类来处理特定的请求,可以通过注解(简单方便)或者在web.xml文件中进行配置(更加灵活)。
2.2.3 步骤 3:访问Servlet
-
启动服务器:启动你的Web服务器(比如Tomcat)。
-
访问Servlet:在浏览器中输入:
http://localhost:8080/your-web-app/greeting?name=John这时,你就能看到"Hello, John!"的欢迎信息。
3、处理请求
在Servlet类里,你要定义方法,来处理用户发来的不同请求(如GET请求、POST请求)。
3.1 步骤 4:处理不同请求
在Java Servlet中,当浏览器发起不同类型的请求时,Servlet需要根据请求的类型(比如GET或POST)来做出响应。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);
}
-
@Override:这个注解是告诉Java编译器,我们重写了父类(HttpServlet)的doPost()方法。也就是说,我们告诉服务器:如果收到POST请求,应该执行这个方法。 -
protected void doPost(HttpServletRequest request, HttpServletResponse response):这是一个方法定义。doPost()方法专门用来处理客户端(比如浏览器)发来的POST请求。-
HttpServletRequest request:request是一个对象,它包含了客户端发来的请求数据,包括表单数据、URL参数等。 -
HttpServletResponse response:response是一个对象,我们用它来设置服务器要返回给客户端的数据。
-
-
String message = request.getParameter("message");:这里我们从客户端的请求中获取message这个参数。假设浏览器通过POST请求发送了一个表单,表单中有一个字段叫message,这行代码就把message字段的值提取出来并存储在message变量中。 -
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:整个流程
-
用户打开表单页面(HTML页面),看到一个输入框,提示他们输入消息。
-
用户在输入框里输入一些文字(比如
Hello, Servlet!),然后点击"Submit"按钮。 -
用户提交表单后,浏览器会通过POST请求 将
message=Hello, Servlet!发送到服务器上的/myServlet路径。 -
服务器接收到请求后,调用
doPost()方法,获取请求中的message参数(就是用户输入的内容)。 -
Servlet将内容处理后,返回一个包含消息的HTML页面:
<h1>Message received: Hello, Servlet!</h1>,并显示给用户。
3.3 以上的流程可总结为:
-
用户填写表单并点击提交按钮,浏览器将数据通过POST请求发送给服务器。
-
服务器接收到请求后,通过
request.getParameter("message")获取用户输入的数据。 -
服务器返回一段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 场景:
-
用户点击了"结账"按钮。
-
服务器需要检查用户是否已登录。
-
如果用户未登录,服务器会执行
response.sendRedirect("login.jsp");,将用户重定向到登录页面。 -
浏览器的地址栏会显示新的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 过程:
-
用户访问
/checkout页面。 -
服务器检查用户是否登录,如果没有登录,执行
response.sendRedirect("login.jsp");。 -
浏览器重新发送请求到
login.jsp,并加载登录页面。 -
浏览器的地址栏变为
login.jsp,用户看到的是登录页面。
注意 :response.sendRedirect() 会导致浏览器发出新的请求,地址栏会发生变化,浏览器重新加载新的页面。它适合用来跳转到完全不同的页面。
2. 转发(Forward)
转发则与重定向不同,它是完全在服务器端处理的,浏览器的地址栏并不会发生变化。也就是说,浏览器并没有重新发请求,而是服务器告诉浏览器,"继续处理这个请求,但是交给别的资源来做。"
-
工作原理 :当你调用
RequestDispatcher.forward()时,服务器会把请求转交给另一个资源(可能是另一个Servlet或JSP页面),但浏览器并不会感知到这个过程。浏览器的URL依旧不变。 -
结果:浏览器的地址栏不变,仍然显示最初的请求URL。
2.1 举个例子:
假设你有一个用户个人信息页面,用户访问 /userInfo 页面时,服务器需要检查用户是否登录。如果没有登录,服务器会转发请求到一个错误页面(errorPage.jsp)。用户仍然会看到原来访问的 /userInfo 页面,浏览器的URL不变。
2.1.1 场景:
-
用户访问
/userInfo页面。 -
服务器检查用户是否已登录。
-
如果未登录,服务器执行
RequestDispatcher.forward(request, response);,将请求转发到errorPage.jsp页面。 -
浏览器的地址栏仍然是
/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 过程:
-
用户访问
/userInfo页面。 -
服务器检查用户是否登录,如果没有登录,执行
RequestDispatcher.forward(request, response);,将请求转发到errorPage.jsp。 -
浏览器的地址栏不会变化,依然是
/userInfo,但是用户看到的是errorPage.jsp页面,告诉他们需要登录才能查看个人信息。
注意 :RequestDispatcher.forward() 会让服务器内部将请求转发到另一个页面,而不会更改浏览器的地址栏。适用于需要在服务器内部处理多个资源的场景,比如验证、处理、显示等。
3. 重定向与转发的区别对比
| 特点 | 重定向 (sendRedirect) | 转发 (forward) |
|---|---|---|
| 发生位置 | 客户端(浏览器)发起新的请求 | 服务器内部操作 |
| 浏览器地址栏变化 | 是,浏览器会重新加载新的URL | 否,浏览器地址栏不变 |
| 请求是否重新发送 | 是,浏览器会发送一个新的请求 | 否,服务器直接处理请求 |
| 用途 | 适用于需要改变URL或者引导用户到其他页面的场景,比如登录验证后跳转到主页。 | 适用于服务器内部的处理,不需要改变URL的跳转,比如从一个Servlet转发到另一个JSP页面。 |
八、登录验证实践
在很多Web应用中,用户需要登录才能访问某些页面。登录验证通常需要使用重定向和转发来控制页面的跳转。
场景设定
假设你正在开发一个在线商店网站,在这个网站上,只有登录的用户才能访问"结账页面"和"用户主页"。如果用户未登录,访问这些页面时需要转到登录页面;如果已经登录,用户应该被重定向到他们的主页。
1. 用户未登录:转发到登录页面
当用户访问需要登录才能访问的页面(比如结账页面或用户主页),如果他们没有登录,你需要将他们转发到登录页面。
- 使用转发的原因:当用户没有登录时,你可以将他们转发到登录页面,告诉他们需要登录。这个过程不改变浏览器的地址栏,用户看到的还是原始的请求URL。
1.1 具体步骤:
-
用户尝试访问结账页面(比如
/checkout)。 -
服务器检查用户是否已经登录。
-
如果用户未登录,服务器将请求转发到
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 具体步骤:
-
用户成功登录。
-
服务器通过
response.sendRedirect()将用户重定向到用户主页(比如userHome.jsp)。 -
浏览器的地址栏会显示
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 登录流程:
-
用户访问结账页面
/checkout。 -
如果用户没有登录,服务器会将请求转发 到登录页面
login.jsp。 -
用户填写用户名和密码,点击登录按钮。
-
服务器检查登录信息,如果正确,重定向 到用户主页
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. 实现步骤:
-
用户登录:用户提交登录表单,Servlet会验证用户名和密码。
-
使用Session:如果登录成功,用户信息会存储到Session中。
-
访问受保护页面:如果用户未登录,访问受保护页面时会被重定向到登录页面。
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. 完整流程说明:
-
用户访问登录页面 :
用户打开
login.jsp页面,输入用户名和密码提交表单。 -
用户登录验证 :
LoginServlet接收提交的用户名和密码,如果正确,将用户名保存到 Session 中,重定向到userHome.jsp。 -
检查用户是否已登录 :
访问受保护的页面(比如结账页面或用户主页)时,
CheckLoginServlet会检查 Session 是否包含有效的用户信息。如果没有,重定向到登录页面。如果已登录,允许访问。 -
用户登出 :
用户点击登出按钮,
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)。
示例:
假设有一个用户信息的应用:
-
Model :
User类,封装用户数据。 -
View:一个JSP页面,显示用户的信息。
-
Controller:一个Servlet,负责处理用户请求,获取用户数据,然后转发到JSP页面显示。
javapublic 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>
十一、四则运算实践
假设你想做一个计算器,通过网页来接收两个数字和操作符(加、减、乘、除),然后返回结果。
场景说明
我们需要实现一个可以进行加、减、乘、除运算的计算器,用户输入两个数字和一个运算符(如加、减、乘、除),计算器根据用户的输入进行运算,并返回结果。
步骤:
-
创建一个 HTML 表单,用户可以在其中输入两个数字和选择运算符。
-
创建一个 Servlet 来处理用户输入的数据,进行计算,并返回结果。
-
显示结果到用户的浏览器页面。
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>
解释:
-
num1 和 num2 是用户输入的两个数字。
-
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>");
}
}
解释:
-
获取数据:
-
request.getParameter("num1")和request.getParameter("num2")获取用户输入的两个数字。 -
request.getParameter("operation")获取用户选择的运算符。
-
-
计算结果:
-
我们使用 switch-case 语句来判断用户选择的运算符。
-
根据选择的操作符,执行相应的四则运算。
-
-
返回结果:
-
response.getWriter().println("<h2>Result: " + result + "</h2>");用来将结果打印在页面上。 -
如果除法操作中 除数为零,我们会返回一个错误信息:"Error: Cannot divide by zero."
-
3. 如何工作:
-
用户访问
calculator.html页面,填写两个数字并选择运算符(如加法)。 -
用户点击"Calculate"按钮,表单提交会发送 POST 请求 到
/calculate。 -
CalculatorServlet会接收到请求,解析出两个数字和操作符。 -
根据用户选择的操作符,执行相应的四则运算。
-
计算结果通过
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中,通过读取用户输入的参数(如
num1、num2和operation),然后根据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应用,需要实现如下功能:
-
用户通过HTML表单输入数字和选择运算符。
-
当用户点击"提交"时,表单数据会通过POST请求发送到一个Servlet。
-
Servlet接收数据,进行四则运算(加、减、乘、除),并返回计算结果。
-
如果用户未登录,访问某些页面时,可以使用 转发 将他们引导到登录页面;如果用户登录后,通过 重定向 跳转到用户主页。
-
使用 Session 来保持用户登录状态,确保用户登录后访问受保护的页面。