一、doGet()与doPost()
我们在TestServlet类中重写doGet()、doPost()、service()。
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{
public TestServlet() {}; @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doPost");
} @Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("sevice");
} @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet");
}
}
同时在WebContent创建一个Test.html文件
<!DOCTYPE html>
<!-- http://localhost:8080/TestServlet/Test.html -->
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!--表单提交调用servlet -->
<!-- http://localhost:8080/TestServlet/TestServlet.html -->
<form name = f1 action = "/TestServlet/TestServlet.html" method = "get">
username:<input type = "text" name = "username"></input>
pwd:<input type = "password" name = "pwd"></input>
<input type = "submit" value = "提交">
</form> </body>
</html>
我们点击提交按钮会发现控制台输出sevice,说明调用的service()方法。
我们看下API中关于service()方法的介绍:接收标准的HTTP请求,并将其
发送到此类中定义的doXXX方法,不需要重写这个方法。
也就是说请求会先传递到service()中,在由其发送给doXXX方法。
只要service()被重写了,请求就会一直传递给service().
我们将service()方法注释
再来提交信息,看下会执行那个方法。
可以看4到此时执行的是doGet,这时因为在form中设置了method=“get”,
代表提交方式为get,请求先提交给service(),然后再由其转发给对应的doXXX方法。
<form name = f1 action = "/TestServlet/TestServlet.html" method = "get">
由于设置了提交方式为get,所以是执行给doGet()。
doGet调用时我会发现在地址栏显示传递给servlet的数据:
这样是不安全的,而且采用get方式传递的数据有大小限制,后面跟随的信息字节不能超过1.3k。
我们来看下API中对doGet()的叙述:
由服务器调用,以允许servlet处理get请求,重写此方法时,读取请求数据、
写入响应头、获取响应的写入器或输出流对象,最后写入响应数据。
如果将"get"设置为“post”,则会执行doPost()方法。
采用post传递数据不会在URL上显示出来,有一定的安全性。
而且post可以传递的数据理论上是无限大的。
二、Servlet生命周期
2.1实例化一个Servlet
创建一个servlet实例
2..2调用Init()
调用一次。
2.3调用service方法(doGet、doPost)
被调用多次,每次请求调用。
2.4调用destory方法。
调用一次销毁Servlet
我们创建一个TestServlet类,继承HTTPServlet。
重写里面的intI()、doget() doPost() destroy() 并添加一个无参构造器。
HTML采用上述代码。
import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{
public TestServlet() {
System.out.println("TestServlet");
}; @Override
public void init() throws ServletException {
System.out.println("Init");
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doPost");
} @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet");
} @Override
public void destroy() {
System.out.println("destroy");
}
}
然后将项目添加到Tomcat上。
点击提交我们会发现控制台中打印的信息:
一开始首先实例化一个Servlet,然后初始化,我们提交数据时调用对应的servlet方法(doGet或doPost)。
我们继续刷新会发现控制台继续打印doGet,但实例化和初始化只调用一次,有请求是调用则调用doGet方法。
最后我们将Tomcat停止运行,会发现控制会输出destroy,此时servlet被销毁了。
三、获取初始化参数
首先在web.xml文件中配置初始化参数。
初始化参数分为:局部初始化,只有当前Servlet可以获取其参数。
全局初始化:所有Servlet都可以获取其参数。
我们首先要在web.xml中设置初始参数信息。
<context-param> <!-- 设置全局参数 -->
<param-name>context-param</param-name>
<param-value>localhost:3306/mydatabase</param-value>
</context-param> <servlet>
<servlet-name>firstServlet</servlet-name>
<servlet-class>com.servlet.firstServlet.TestServlet</servlet-class> <init-param> <!-- 设置局部初始化参数 -->
<param-name>initParam</param-name> <!-- 设置参数名称和值 -->
<param-value>initParam</param-value> <!-- 该初始化参数是设置在当前这个Servlet下的-->
</init-param> <!-- 所以也只有当前Servlet可以获取到-->
</servlet>
<servlet-mapping>
<servlet-name>firstServlet</servlet-name>
<url-pattern>/TestServlet.html</url-pattern>
</servlet-mapping>
设置好了参数,我们来获取参数。
import java.io.IOException; import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class TestParam extends HttpServlet{ private String initParam = null;
private String contextParam = null; @Override
public void init() throws ServletException {
//获取初始化参数,和全局参数
this.initParam = this.getInitParameter("initParam");
this.contextParam = this.getServletContext().getInitParameter("context-param");
} @Override //在doGet中输出参数。
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("initparam:"+initParam);
System.out.println("contextParam:"+contextParam);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);//调用doGet方法
}
}
初始化之后我们提交数据就会调用doGet方法,将获取到的初始化参数打印出来。
四、页面跳转
4.1请求重定向
请求重定向,即进行页面跳转。
需要用到void sendRedirect(java.lang.String location)
当location是带有/的话,将被解释为容器的根,
即此时的地址会被解释为localhost:8080+location。
例如localtion为"/fail.htm",此时跳转的地址位localhost:8080/fail.html
当没有‘/’时,将解释为相对于当前请求的URL地址。
例如localtion为"fail.htm",此时跳转的是localhost:8080/项目名/fail.html
使用指定的重定向URL向客户端发送临时重定向响应。
获取表达数据采用getParameter(Stringz name),
import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{
private String initParam = null;
private String contextParam = null; @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取HTML中设置了 name = "username" 标签的数据
String name = req.getParameter("username");//获取表单提交的数据,
//如果输入框的内容等于百度则跳转到百度,其他跳转到fail.html
if("baidu".equals(name))
//跳转到百度
resp.sendRedirect("http://www.baidu.com");
else
//跳转到当前工程WebContext目录下的fail.html
resp.sendRedirect("fail.html");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
采用重定向的跳转方法,不共享request的信息。
当username输入框的为百度时则跳转到百度首页,
其他的输入跳转到当前项目WebContent下的fail.html
重定向时地址栏会显示重定向资源的路径。
4.2请求转发:将当前请求转发到另一个资源处理。
请求转发时我们需要用到一个接口 RequestDispatcher。
TequestDispatcher:接收客户端请求,并将请求发送到服务器上的其他资源(如servlet、html文件或jsp文件)。
主要方法:
void forward(ServletRequest request, ServletResponse response)
将请求转发到服务器上另一资源,request为客户端对Servlet的请求的request对象,
response为表示servlet返回到客户端的响应的servletResponse对象
那么要想调用转发,我们必须向获取一个实现了RequestDispatcher接口的对象。
这时可以request下的RequestDispatcher getRequestDispatcher(java.lang.String path)方法
该方法获取一个RequestDispathcher对象,path为指定资源的路径名,可以为相对路径,
当为相对路径时必须是相对当前Servlet而言的。
请求转发只能在本应用资源下,不能先请求重定向那样跨应用(重定向到百度)。
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{
private PrintStream out = System.out;
private String initParam = null;
private String contextParam = null; @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("servlet..");
//设置资源路径
RequestDispatcher rd = req.getRequestDispatcher("fail.html");
//转发,由于是携带req、resp转发的,所以转发后的资源可以获取其数据。
rd.forward(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
但提交表单,进入doGet()方法后,会转发请求到指定的资源。
我们会发现请求转发并没有像重定向那样将URL变为fail.html,这时因为此时转发的是请求。
而且当前servlet输出的信息(“servlet..”)也没有打印出来,
转发就相当于将事情交给另外一个人去处理。自己不插手了。
4.3请求包含:将其他资源的响应结果包含到当前Servlet中。
请求包含和请求转发都是RequestDispatcher中定义的方法。
所以都是首先获取RequestDispatcher对象,然后调用对应方法。
请求包含是调用的是void include(ServletRequest request, ServletResponse response)
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter; import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet{
// private PrintStream out = System.out;
private String initParam = null;
private String contextParam = null; @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println("servlet");
//设置资源路径
RequestDispatcher rd = req.getRequestDispatcher("/fail.html");
//转发,由于是携带req、resp转发的servlet..,所以转发后的资源可以获取其数据。
rd.include(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
请求包含的url也不会发生变化,并且包含了fail.htm界面。
如果没有servlet,界面上会显示html所代表的内容,即Fail。
但当前界面将fail.htm的代码包含进来了,破坏了html的结构,
所以显示的是servlet+html代码。
包含是当前Servlet将另外一个资源及其处理流程包含进来。
转发时当前Servlet将事情交给另外一个资源去完成。
请求转发与请求包含的区别可参阅:https://blog.csdn.net/u013425438/article/details/81606248