Servlet的应用
1、重定向
HttpServletRequest接口提供的sendRedirect()方法用于生产302响应码和Location响应头,从而通知客户端去重新访问Location响应头中指定的URL。
Servlet01类:
package com.yyq.sendredirect; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by gao on 16-4-14. */ public class Servlet01 extends HttpServlet{ //处理HTTP GET请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } //处理HTTP POST请求 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //重新定向到servlet02 resp.sendRedirect("s02"); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 } }
Servlet02类:
package com.yyq.sendredirect; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Created by gao on 16-4-14. */ public class Servlet02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>Servlet06</head></title>"); out.println("<body>"); out.print("在Servlet02中获取请求参数name的值"); out.print(req.getParameter("name")); out.println("</body>"); out.println("</html>"); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 } }
web.xml注册:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>servlet01</servlet-name> <servlet-class>com.yyq.sendredirect.Servlet01</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet01</servlet-name> <url-pattern>/s01</url-pattern> </servlet-mapping> <servlet> <servlet-name>servlet02</servlet-name> <servlet-class>com.yyq.sendredirect.Servlet02</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet02</servlet-name> <url-pattern>/s02</url-pattern> </servlet-mapping> </web-app>
启动运行:http://localhost:8080/s01?name=test
浏览器的地址栏的URL已经被自动修改成s02了,而且在Servlet02类中获取请求参数name的值为null,这表明无法获取初始请求中的参数数据了。
2、请求分派
Servlet API中定义了一个RequestDispatcher接口,俗称请求分派器,有两个方法:forward()方法和include()方法。forward()方法用于将请求转发到RequestDispatcher实例封装的资源;include()方法用于将RequestDispatcher实例封装的资源作为当前响应内容的一部分包含进来。
Servlet03类:
package com.yyq.requestdispatcher; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by gao on 16-4-14. */ public class Servlet03 extends HttpServlet { //处理HTTP GET请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } //处理HTTP POST请求 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求分派器 RequestDispatcher dispatcher = req.getRequestDispatcher("servlet04"); //将请求转发至指定路径的资源 dispatcher.forward(req,resp); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 } }
Servlet04类:
package com.yyq.requestdispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Created by gao on 16-4-14. */ public class Servlet04 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>Servlet06</head></title>"); out.println("<body>"); out.print("在Servlet03中获取请求参数name的值"); out.print(req.getParameter("name")); out.println("</body>"); out.println("</html>"); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 } }
web.xml注册:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>servlet03</servlet-name> <servlet-class>com.yyq.requestdispatcher.Servlet03</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet03</servlet-name> <url-pattern>/servlet03</url-pattern> </servlet-mapping> <servlet> <servlet-name>servlet04</servlet-name> <servlet-class>com.yyq.requestdispatcher.Servlet04</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet04</servlet-name> <url-pattern>/servlet04</url-pattern> </servlet-mapping> </web-app>
启动Tomcat,输入:http://localhost:8080/servlet03?name=test
浏览器地址栏的URL不变,但是服务器却是用Servlet04来响应的,在Servlet04中也可以获取客户端请求Servlet03时发送的参数数据。
3、重定向和请求分派的比较
虽然HttpServletResponse的sendRedirect()方法和RequestDispatcher的forward()方法都可以让浏览器获得另一个URL所指向的资源所作出的响应,但两者的内部运行机制有着很大的区别。
1)请求分派只能将请求转发给同一个Web应用中的其他组件;而重定向不仅可以定向到当前应用程序中的其他资源,也可以重定向到其他站点的资源上。
2)重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而请求转发过程结束后,浏览器地址保持初始的URL地址不变。
3)请求分派的发起者和被调用者之间共享相同的request实例和response实例,它们属于同一个“请求/响应”过程;而重定向的发起者和被调用者使用各自的request实例和response,它们各自属于独立的“请求/响应”过程。
4、利用请求域属性传递对象数据
HttpServletRequest接口中提供了几个方法,用来操作请求实例中存储的对象。
- setAttribute(String name,Object o)方法:将数据作为request对象的一个属性存放到request对象中,例如:request.setAttribute("data", data);
- getAttribute(String name)方法:获取request对象的name属性的属性值,例如:request.getAttribute("data")
- removeAttribute(String name)方法:移除request对象的name属性,例如:request.removeAttribute("data")
- Enumeration getAttributeNames()方法,获取request对象的所有属性名,返回的是一个Enumeration 对象,例如:Enumeration<String> attrNames = request.getAttributeNames();
这种存储在HttpServlet中的对象称为请求域属性,属于同一请求过程的多个处理模块之间可以通过请求域属性来传递对象数据,如通过请求转发的两个Servlet之间就可以通过请求域属性来传递对象数据,但通过重定向的两个Servlet之间就不能通过请求域来传递对象数据。Servlet05类:package com.yyq.attributerequest; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by gao on 16-4-14. */ public class Servlet05 extends HttpServlet { //处理HTTP GET请求 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } //处理HTTP POST请求 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String str = "在Servlet05中存放请求域属性"; req.setAttribute("content",str); //获取请求分派器 RequestDispatcher dispatcher = req.getRequestDispatcher("servlet06"); //将请求转发至指定路径的资源 dispatcher.forward(req,resp); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 } }
Servlet06类:
package com.yyq.attributerequest; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Created by gao on 16-4-14. */ public class Servlet06 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>Servlet06</head></title>"); out.println("<body>"); String str = (String) req.getAttribute("content"); out.print("从Servlet05中获取请求域属性content的值为:" + str); out.println("</body>"); out.println("</html>"); } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 } }
web.xml注册:<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>servlet05</servlet-name> <servlet-class>com.yyq.attributerequest.Servlet05</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet05</servlet-name> <url-pattern>/servlet05</url-pattern> </servlet-mapping> <servlet> <servlet-name>servlet06</servlet-name> <servlet-class>com.yyq.attributerequest.Servlet06</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet06</servlet-name> <url-pattern>/servlet06</url-pattern> </servlet-mapping> </web-app>
启动Tomcat,输入:http://localhost:8080/servlet05
5、ServletConfig和ServletContext
1)ServletConfig
在web容器初始化Servlet实例时,都会为这个Servlet准备一个唯一的ServletConfig实例(俗称Servlet配置对象),Web容器会从部署描述文件中“读出”该Servlet类的初始化参数,并设置到ServletConfig实例中,然后再把这个ServletConfig实例传递给该Servlet实例的init()方法。
a、给Servlet类配置初始化参数
通过在web.xml文件中声明Servlet时添加<init-param>元素来配置。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>initparamservlet</servlet-name> <servlet-class>com.yyq.initparam.InitParamServlet</servlet-class> <!--定义一个Servlet初始化参数--> <init-param> <!--参数名--> <param-name>encoding</param-name> <!--参数值--> <param-value>utf-8</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>initparamservlet</servlet-name> <url-pattern>/initparamservlet</url-pattern> </servlet-mapping> </web-app>
b、在Servlet类中获取它的初始化参数值
一个Servlet类的实例初始化完毕之后,Web容器已经为它准备好了ServletConfig实例,在这个Servlet类中只需使用getServletConfig()方法就可以获取到这个实例。而ServletConfig接口中提供了getInitParameter(String name)方法来获取指定名称的初始化参数的字符串值。
package com.yyq.initparam; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Created by gao on 16-4-14. */ public class InitParamServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取ServletConfig实例 ServletConfig config = this.getServletConfig(); //获取指定名称的初始化参数的字符串值 String str = config.getInitParameter("encoding"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>initparamservlet</head></title>"); out.println("<body>"); out.print("获取InitParamServlet的初始化参数\"encoding\"的字符串值为:" + str); out.println("</body>"); out.println("</html>"); } @Override public void destroy() { super.destroy(); } @Override public void init() throws ServletException { super.init(); } }
Servlet的初始化参数只是针对当前这个Servlet类有效,在本Servlet类中只能获取自身的初始化参数,无法获取其他Servlet类的初始化参数。
c、启动Tomcat
2)ServletContext
如果在多个Servlet类要获取相同的初始化参数,就可以把参数配置成Web应用上下文初始化参数。Web容器部署某个Web应用程序后,会为每个Web应用程序创建一个ServletContext实例(俗称Web应用上下文对象)。通过这个ServletContext实例就可以获取到所有的Web应用上下文初始化参数的值。
ServletContext可以被认为是对于Web应用程序的一个整体性存储区域。每一个Web应用程序都只有一个ServletContext实例,存储在ServletContext之中的对象间一直被保留,直到它被删除。
a、配置web应用上下文初始化参数
通过在web.xml文件中添加<context-param>元素来配置。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>servletcontextservlet</servlet-name> <servlet-class>com.yyq.servletcontext.ServletContextServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletcontextservlet</servlet-name> <url-pattern>/servletcontextservlet</url-pattern> </servlet-mapping> <!--定义一个Web应用上下文初始化参数--> <context-param> <!--参数名--> <param-name>appName</param-name> <!--参数值--> <param-value>Servlet入门基础</param-value> </context-param> </web-app>
b、在Servlet类中获取Web应用上下文的初始化参数值
Web容器也为每个Web应用程序准备好了一个ServletContext实例,在这个实例中保存着本Web应用中的所有应用上下文初始化参数。在Servelt类中都可以使用getServletContext()方法来获取本应用的ServletContext实例,通过ServletContext接口提供的getInitParameter(String name)方法就可以获取指定名称的Web应用上下文初始化采纳数的值。
package com.yyq.servletcontext; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Created by gao on 16-4-14. */ public class ServletContextServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取ServletContext实例 ServletContext context = this.getServletContext(); //获取指定名称的web应用上下文初始参数的字符串值 String str = context.getInitParameter("appName"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>servletcontextservlet</head></title>"); out.println("<body>"); out.print("获取ServletContext的初始化参数\"appName\"的字符串值为:" + str); out.println("</body>"); out.println("</html>"); } @Override public void destroy() { super.destroy(); } @Override public void init() throws ServletException { super.init(); } }
c、启动Tomcat