1. 简介
本文章基于:
- Eclipse 4.6(NEON)
- Servlet 3.0
- Tomcat 9.0
2. Servlet是什么?
Java Servlet是在Web或应用程序服务器上运行的程序,并充当Web浏览器或其他HTTP客户端发出的请求与HTTP服务器上的数据库或应用程序之间的中间层。使用Servlet,可以通过网页表单收集用户的输入,从数据库或其他来源显示记录,并动态创建网页。
3. Servlet生命周期
下图说明了Servlet的生命周期。 自创建以来,一直处理用户的请求,直到销毁为止。
Servlet生命周期共有5
个步骤:
- 第1步:加载Servlet类。
- 第2步:创建Servlet实例。
- 第3步:调用servlet
init()
方法。 - 第4步:调用servlets
service()
方法。 - 第5步:调用servlet
destroy()
方法。
最初加载Servlet时,第1、2和3步仅执行一次。默认情况下,只有在收到第一个请求后才加载servlet。不过,可以在容器启动时强制容器加载servlet。
第4步多次执行 - 对Servlet的每个HTTP请求一次都会执行第4步。当servlet容器销毁servlet时,执行第5步。
可以下图,以更好地了解Servlet的生命周期。
当用户请求Servlet时,Servlet将调用service()
方法来满足用户的需求,service()
将调用doGet()
或doPost()
。
因此,当用户请求Servlet时,Servlet将在第一次请求时创建,并同时调用servlet的init()
方法以对其进行初始化,而init()
方法仅被调用一次。 destroy()
方法用于销毁servlet,在删除Web应用程序的部署(取消部署)或停止Web服务器时,它将仅被调用一次。
4. 安装Tomcat Web服务器
要开始使用Servlet,需要下载Tomcat Web Server并在Eclipse中进行配置。参考以下网址:
5. 在Web项目中创建Servlet
打开Eclipse,选择:File/New/Other,创建一个动态Web项目,如下图所示:
输入项目名称:ServletTutorial,如下图所示:
点击下一步(Next>),如下图所示:
勾选生成web.xml
,点击完成(Finish),如下图所示:
项目创建成功后,目录结构如下所示:
接下来在WebContent
目录中创建一个HTML文件:index.html,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
6. 配置Eclipse在Tomcat上运行应用
到目前为止,我们只是创建了一个动态Web项目。接下来要对项目进行配置,以便它可以运行Web应用程序。
在Eclipse中,右键单击项目名称:ServletTutorial,选择Properties:
选择运行环境的版本,如下图所示:
填写服务器的名称,并选择运行服务器的安装路径,然后点击完成。如下图所示:
返回运行时界面,选择上面配置的服务器(Apache Tomcat v9),如下图所示:
右键单击项目ServletTutorial,选择“Run As / Run on Server”。如下图所示:
弹出选择服务器,这里选择Tomcat V9 Server,如下图所示:
选择发布项目,如下图所示:
网站已经在Eclipse浏览器上运行。如下图所示:
工作原理
当您访问以下URL时:
网站显示index.html
页面的内容,这是可以理解的。但是,如果访问URL:
上面URL中并没有指定要访问的页面,因此Web服务器将查找在web.xml中声明的<welcome-file>
标记中声明的默认页面以获取答案。
注意:
/ServletTutorial
称为上下文路径。每个网站都有一个上下文路径,可以为它配置另一个值或将其设置为空。如果为空,则可以通过以下方式访问网站:
- http://localhost:8080
- http://localhost:8080/index.html
当它在Tomcat中运行时,Context-Path
命名为项目名称(本示例为:ServletTutorial)。
过程如下图中所示:
7. 加入一些类
下面将向这个示例中加入一些Java类:
文件:Constants.java
package com.xntutor.tutorial.beans;
public class Constants {
public static final String ATTRIBUTE_USER_NAME_KEY = "ATTRIBUTE_USER_NAME_KEY";
public static final String SESSION_USER_KEY = "SESSION_USER_KEY";
public static final String CALLBACK_URL_KEY = "CALLBACK_URL_KEY";
}
文件:UserInfo.java
package com.xntutor.tutorial.beans;
public class UserInfo {
public String userName;
private int post;
private String country;
public UserInfo(String userName, String country, int post) {
this.userName = userName;
this.country = country;
this.post = post;
}
public int getPost() {
return post;
}
public void setPost(int post) {
this.post = post;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public void setUserName(String userName) {
this.userName = userName;
}
public UserInfo(String userName) {
this.userName = userName;
}
public String getUserName() {
return this.userName;
}
}
8. 创建一个Servlet
项目的目录结构如下所示:
文件:HelloServlet.java,完整代码如下:
package com.xntutor.tutorial.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HelloServlet() {
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
out.println("<html>");
out.println("<head><title>Hello Servlet</title></head>");
out.println("<body>");
out.println("<h3>Hello World</h3>");
out.println("This is my first Servlet");
out.println("</body>");
out.println("<html>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
如果已创建的HelloServlet
类代码提示有错误,可能是您还未加入Servlet库。在这里,因为使用Tomcat,因此需要对其进行声明。
在“项目”上单击鼠标右键,选择“属性”:
然后,选择服务器运行时,如下图所示:
选择对应的服务器版本,如下图所示:
现在HelloServlet
类代码应该没有错误提示了。
接下来,需要在Web.xml中声明HelloServlet
和访问它的路径。需要添加以下配置:
<!-- Define servlet, named helloServlet -->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.xntutor.tutorial.servlet.HelloServlet</servlet-class>
</servlet>
<!-- Defines the path to access this Servlet -->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
完整的web.xml文件中的代码如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>ServletTutorial</display-name>
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.xntutor.tutorial.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
右键单击项目(ServletTutorial),然后选择:Run As/Run on Server,如下图所示:
服务器启动完成后,使用浏览器访问以下URL:
可以根据下面的执行流程图示来了解Servlet的工作原理。
调用Servlet时,根据客户端的请求方法来调用doGet(..)
或doPost(..)
。在doGet()
或doPost()
中,可以检索ServletOutputStream
对象,这是将数据发送到用户浏览器的输出流。调用ServletOutputStream.println(..)
将数据写入流中。如下示例代码:
// The output stream to send data to user's browser
ServletOutputStream out = response.getOutputStream();
9. Servlet初始化参数
在web.xml中声明servlet时,可以为servlet设置初始化参数。参考以下Servlet实现代码。
文件:InitParamServlet.java
package com.xntutor.tutorial.servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class InitParamServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String emailSupport1;
public InitParamServlet() {
}
// This method is always called once after the Servlet object is created.
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
// Get the value of the initialization parameter of the Servlet.
// (According to the Configuration of this Servlet in web.xml).
this.emailSupport1 = config.getInitParameter("emailSupport1");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get the initialization parameter's value in a different way.
String emailSupport2 = this.getServletConfig().getInitParameter("emailSupport2");
ServletOutputStream out = response.getOutputStream();
out.println("<html>");
out.println("<head><title>Init Param</title></head>");
out.println("<body>");
out.println("<h3>Init Param</h3>");
out.println("<p>emailSupport1 = " + this.emailSupport1 + "</p>");
out.println("<p>emailSupport2 = " + emailSupport2 + "</p>");
out.println("</body>");
out.println("<html>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
接下来,向web.xml文件添加一些内容:
<servlet>
<servlet-name>initParamServlet</servlet-name>
<servlet-class>com.xntutor.tutorial.servlet.InitParamServlet</servlet-class>
<init-param>
<param-name>emailSupport1</param-name>
<param-value>support1@xntutor.com</param-value>
</init-param>
<init-param>
<param-name>emailSupport2</param-name>
<param-value>support2@xntutor.com</param-value>
</init-param>
</servlet>
完整的web.xml文件内容,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>ServletTutorial</display-name>
<!-- Define servlet, named helloServlet -->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.xntutor.tutorial.servlet.HelloServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>initParamServlet</servlet-name>
<servlet-class>com.xntutor.tutorial.servlet.InitParamServlet</servlet-class>
<init-param>
<param-name>emailSupport1</param-name>
<param-value>support1@xntutor.com</param-value>
</init-param>
<init-param>
<param-name>emailSupport2</param-name>
<param-value>support2@xntutor.com</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>initParamServlet</servlet-name>
<url-pattern>/initParam</url-pattern>
</servlet-mapping>
<!-- Defines the path to access this Servlet -->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
重新运行Web应用程序并访问以下URL:
应该会看到类似下面的结果:
10. 使用注释配置Servlet
在Servlet 3.0或更高版本中,可以使用Annotation
配置Servlet,在本项目中,我们使用Servlet 3.x版,以便可以使用Annotation进行配置。参考下面的一个例子。
文件:AnnotationExampleServlet.java
package com.xntutor.tutorial.servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// You can configure one or multiple 'URL Patterns' can access this Servlet.
@WebServlet(urlPatterns = { "/annotationExample", "/annExample" }, initParams = {
@WebInitParam(name = "emailSupport1", value = "support1@xntutor.com"),
@WebInitParam(name = "emailSupport2", value = "support2@xntutor.com") })
public class AnnotationExampleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String emailSupport1;
public AnnotationExampleServlet() {
}
// In any case, init() is guaranteed to be called
// before the Servlet handles its first request.
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
this.emailSupport1 = config.getInitParameter("emailSupport1");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String emailSupport2 = this.getServletConfig().getInitParameter("emailSupport2");
ServletOutputStream out = response.getOutputStream();
out.println("<html>");
out.println("<head><title>Init Param</title></head>");
out.println("<body>");
out.println("<h3>Servlet with Annotation configuration</h3>");
out.println("<p>emailSupport1 = " + this.emailSupport1 + "</p>");
out.println("<p>emailSupport2 = " + emailSupport2 + "</p>");
out.println("</body>");
out.println("<html>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
可以通过以下两个链接之一来访问此Servlet:
- http://localhost:8080/ServletTutorial/annExample
- http://localhost:8080/ServletTutorial/annotationExample
它们运行的结果相同:
上面Servlet不需要在web.xml文件中配置。
11. Servlet URL模式
有四种方法可以配置Servlet的路径:
第1种方式: /*
,示例如下:
http://example.com/contextPath
http://example.com/contextPath/status/abc
第2种方式: /status/abc/*
,示例如下:
http://example.com/contextPath/status/abc
http://example.com/contextPath/status/abc/mnp
http://example.com/contextPath/status/abc/mnp?date=today
第3种方式: *.map
,示例如下:
http://example.com/contextPath/status/abc.map
http://example.com/contextPath/status.map?date=today
第4种方式: /
,这是默认的Servlet。
当用户在浏览器上输入链接时,它将被发送到WebContainer
。 WebContainer
必须决定是否
Servlet将处理来自用户的请求。
下图说明了WebContainer
如何决定使用Servlet来响应来自客户端的请求。
例如,创建一个带有星号的Servlet url-pattern:
url-pattern = "/any/*";
文件:AsteriskServlet.java
package com.xntutor.tutorial.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = { "/any/*" })
public class AsteriskServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public AsteriskServlet() {
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
out.println("<html>");
out.println("<head><title>Asterisk</title></head>");
out.println("<body>");
out.println("<h3>Hi, your URL match /any/*</h3>");
out.println("</body>");
out.println("<html>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
以下URL由AsteriskServlet(/any/*
)提供服务:
http://localhost:8080/ServletTutorial/any/path1/a.html
http://localhost:8080/ServletTutorial/any/something
http://localhost:8080/ServletTutorial/any
访问上面URL,可以看到以下结果:
默认Servlet
作为默认Servlet,Servlet将用于处理路径与应用程序中声明的Servlet的url-pattern不匹配的请求。下面来看看默认servlet的示例:
文件:MyDefaultServlet.java
package com.xntutor.tutorial.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns = { "/" })
public class MyDefaultServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public MyDefaultServlet() {
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
out.println("<html>");
out.println("<head><title>Page not found</title></head>");
out.println("<body>");
out.println("<h3>Sorry! Page not found</h3>");
out.println("<h1>404</h1>");
out.println("Message from servlet: " + this.getClass().getName());
out.println("</body>");
out.println("<html>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
重新运行Web应用程序,并访问URL:
http://localhost:8080/ServletTutorial/news/someonewho
上面的链接servletPath = /news/tomAndJerry
,与声明的url模式不匹配。但是“默认Servlet”满足该请求。
12. 获取Servlet的基本信息
有时因为某种需要,想了解Servlet实例提供的时间有关的信息,这些信息包括:
- 来自客户端的信息请求。
- 服务器信息。
- 客户资料。
- 标头信息按要求发送。
- …
创建一个Servlet类文件:ExampleInfoServlet.java
package com.xntutor.tutorial.servlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/other/exampleInfo")
public class ExampleInfoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public ExampleInfoServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
out.println("<style> span {color:blue;} </style>");
String requestURL = request.getRequestURL().toString();
out.println("<br><span>requestURL:</span>");
out.println(requestURL);
String requestURI = request.getRequestURI();
out.println("<br><span>requestURI:</span>");
out.println(requestURI);
String contextPath = request.getContextPath();
out.println("<br><span>contextPath:</span>");
out.println(contextPath);
out.println("<br><span>servletPath:</span>");
String servletPath = request.getServletPath();
out.println(servletPath);
String queryString = request.getQueryString();
out.println("<br><span>queryString:</span>");
out.println(queryString);
String param1 = request.getParameter("text1");
out.println("<br><span>getParameter text1:</span>");
out.println(param1);
String param2 = request.getParameter("text2");
out.println("<br><span>getParameter text2:</span>");
out.println(param2);
// Server Infos
out.println("<br><br><b>Server info:</b>");
out.println("<br><span>serverName:</span>");
String serverName = request.getServerName();
out.println(serverName);
out.println("<br><span>serverPort:</span>");
int serverPort = request.getServerPort();
out.println(serverPort + "");
// Client Infos
out.println("<br><br><b>Client info:</b>");
out.println("<br><span>remoteAddr:</span>");
String remoteAddr = request.getRemoteAddr();
out.println(remoteAddr);
out.println("<br><span>remoteHost:</span>");
String remoteHost = request.getRemoteHost();
out.println(remoteHost);
out.println("<br><span>remoteHost:</span>");
int remotePort = request.getRemotePort();
out.println(remotePort + "");
out.println("<br><span>remoteUser:</span>");
String remoteUser = request.getRemoteUser();
out.println(remoteUser);
// Header Infos
out.println("<br><br><b>headers:</b>");
Enumeration<String> headers = request.getHeaderNames();
while (headers.hasMoreElements()) {
String header = headers.nextElement();
out.println("<br><span>" + header + "</span>: " + request.getHeader(header));
}
// Servlet Context info:
out.println("<br><br><b>Servlet Context info:</b>");
ServletContext servletContext = request.getServletContext();
// Location of web application in hard disk
out.println("<br><span>realPath:</span>");
String realPath = servletContext.getRealPath("");
out.println(realPath);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
请参阅下图以了解一些您感兴趣的信息:
重新运行Web应用程序并访问链接:
得到以下结果:
13. Servlet转发
转发(Forward):向Servlet发送请求时,它可以将请求转发到另一个页面(或另一个Servlet)。 用户浏览器上的地址仍然是第一页的链接,但是内容是由转发的页面创建的。
请求的页面被转发到位于Web应用程序上的页面(或servlet)。使用转发,可以使用request.setAttribute()
将数据从第1页传输到第2页。
创建一个Servlet类文件:ForwardDemoServlet.java
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xntutor.tutorial.beans.Constants;
@WebServlet("/other/forwardDemo")
public class ForwardDemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// Request:
// http://localhost:8080/ServletTutorial/other/forwardDemo?forward=true
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get value of parameter on URL.
String forward = request.getParameter("forward");
if ("true".equals(forward)) {
System.out.println("Forward to ShowMeServlet");
// Set data to attribute of the request.
request.setAttribute(Constants.ATTRIBUTE_USER_NAME_KEY, //
"Hi, I'm Tom come from Walt Disney !");
RequestDispatcher dispatcher //
= request.getServletContext().getRequestDispatcher("/showMe");
dispatcher.forward(request, response);
return;
}
ServletOutputStream out = response.getOutputStream();
out.println("<h3>Text of ForwardDemoServlet</h3>");
out.println("- servletPath=" + request.getServletPath());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
重新运行Web应用并分别访问以下2个URL:
- http://localhost:8080/ServletTutorial/other/forwardDemo
- http://localhost:8080/ServletTutorial/other/forwardDemo?forward=true
情况1: 没有转发,页面的数据由ForwardDemoServlet
生成。如下图所示:
情况2:向前转移到ShowMeServlet
。在这种情况下,页面上的URL不变,而页面的数据是由ShowMeServlet
生成的。如下图所示:
在某些情况下(例如,当用户请求Servlet-A
时)通常使用转发。但是,此页面必须先登录。Servlet-A
会检查用户的登录,如果尚未登录,它将移至Servlet-Login
。回到RequestDispatcher
,有两种获取RequestDispatcher
对象的方法。
request.getServletContext ().getRequestDispatcher(url)
返回RequestDispatcher
对象,它是位于相对于contextPath
(相对于网站根目录的位置)。
request.getRequestDispatcher(url)
返回RequestDispatcher
对象,它是相对于当前页面位置。
注意:
- 重定向允许导航到网站以外的页面。
- 转发仅允许移动到网站内的页面,并且可以通过
request.setAttribute
在两个页面之间传输数据。
14. Servlet重定向
重定向:当用户向Servlet(页面A)发出请求时,Servlet可以将请求重定向到另一个页面(页面B),并结束其任务。 页面被重定向到应用程序中的页面,也可以Web应用以外是任何页面。
不同与转发,使用重定向不能使用request.setAttribute(..)
将数据从页面A传输到页面B。
创建一个Servlet类文件:ShowMeServlet.java
package com.xntutor.tutorial.servlet.other;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xntutor.tutorial.beans.Constants;
@WebServlet("/showMe")
public class ShowMeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get value of an attribute of the request.
String value = (String) request.getAttribute(Constants.ATTRIBUTE_USER_NAME_KEY);
ServletOutputStream out = response.getOutputStream();
out.println("<h1>ShowMeServlet</h1>");
out.println(value);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
创建另一个Servlet类文件:RedirectDemoServlet.java
package com.xntutor.tutorial.servlet.other;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/other/redirectDemo")
public class RedirectDemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// Request:
// http://localhost:8080/ServletTutorial/other/redirectDemo?redirect=true
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get the value of parameter on the URL.
String redirect = request.getParameter("redirect");
if ("true".equals(redirect)) {
System.out.println("Redirect to ShowMeServlet");
// contextPath: Is an empty string "" or non-empty.
// If it is non-empty, it always starts with /
// and does not ends with /
String contextPath = request.getContextPath();
// ==> /ServletTutorial/showMe
response.sendRedirect(contextPath + "/showMe");
return;
}
ServletOutputStream out = response.getOutputStream();
out.println("<h3>Text of RedirectDemoServlet</h3>");
out.println("- servletPath=" + request.getServletPath());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
重新运行服务器并在浏览器中分别访问以下2个URL:
- http://localhost:8080/ServletTutorial/other/redirectDemo
- http://localhost:8080/ServletTutorial/other/redirectDemo?redirect=true
访问第一个URL显示内容如下:
访问第二个URL,请求将重定向到ShowMeServlet。在浏览器上看到的URL是Servlet ShowMeServlet的路径。显示内容如下:
15. Servlet会话
HttpSession
对象代表一个用户会话。 用户会话包含有关多个HTTP请求的用户信息。当用户首次进入网站时,Servlet会为用户提供唯一的ID来标识其会话依据。 此ID通常存储在cookie或请求参数中。
下面是访问会话对象的方式:
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
}
可以将值存储在会话对象中,并在以后检索(读取)它们。首先,让我们看看如何在会话对象中存储值:
// Get the HttpSession object.
HttpSession session = request.getSession();
// Suppose user has successfully logged.
UserInfo loginedInfo = new UserInfo("Maxsu", "China", 5);
// Store user information into a Session attribute.
// You can retrieve this information using the getAttribute method.
session.setAttribute(Constants.SESSION_USER_KEY, loginedInfo);
并检索(读取)存储在Session中特定页面的信息。
// Get the HttpSession object.
HttpSession session = request.getSession();
// Get the UserInfo object stored to the session
// after the user login successfully.
UserInfo loginedInfo
= (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
下面通过一个完整的示例,演示创建使用会话。
Servlet类文件:LoginServlet.java
package com.xntutor.tutorial.servlet.session;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;
import com.xntutor.tutorial.beans.Constants;
import com.xntutor.tutorial.beans.UserInfo;
@WebServlet(urlPatterns = { "/login" })
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
// Get HttpSession object
HttpSession session = request.getSession();
// Suppose a user has successfully logged.
UserInfo loginedInfo = new UserInfo("Maxsu", "China", 5);
// Storing user information in an attribute of Session.
session.setAttribute(Constants.SESSION_USER_KEY, loginedInfo);
out.println("<html>");
out.println("<head><title>Session example</title></head>");
out.println("<body>");
out.println("<h3>You are logined!, info stored in session</h3>");
out.println("<a href='userInfo'>View User Info</a>");
out.println("</body>");
out.println("<html>");
}
}
Servlet类文件:LoginServlet.java
package com.xntutor.tutorial.servlet.session;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;
import com.xntutor.tutorial.beans.Constants;
import com.xntutor.tutorial.beans.UserInfo;
@WebServlet(urlPatterns = { "/userInfo" })
public class UserInfoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public UserInfoServlet() {
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletOutputStream out = response.getOutputStream();
// Get HttpSession object.
HttpSession session = request.getSession();
// Get UserInfo object stored in session after user login successful.
UserInfo loginedInfo = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
// If not logined, redirect to login page (LoginServlet).
if (loginedInfo == null) {
// ==> /ServletTutorial/login
response.sendRedirect(this.getServletContext().getContextPath() + "/login");
return;
}
out.println("<html>");
out.println("<head><title>Session example</title></head>");
out.println("<body>");
out.println("<h3>User Info:</h3>");
out.println("<p>User Name:" + loginedInfo.getUserName() + "</p>");
out.println("<p>Country:" + loginedInfo.getCountry() + "</p>");
out.println("<p>Post:" + loginedInfo.getPost() + "</p>");
out.println("</body>");
out.println("<html>");
}
}
重新运行服务器并在浏览器中以下URL:
点击上面链接查看登录的用户信息,结果如下所示: