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:
点击上面链接查看登录的用户信息,结果如下所示:
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/264052.html