Web基础之与Servlet的邂逅
一、Servlet简介:
Servlet全名为Server applet,即服务端小应用。
Setvlet的API文档描述:(看不懂的直接略过)
二、如何创建Servlet以及Servlet的生命周期
通过文档描述,我们可以三种方式创建Servlet
实现Servlet接口
继承GenericServlet抽象类
继承HttpServlet普通类
API中提到Servlet生命周期的三个阶段,刚好对应三个接口方法:
init :构造Servlet时调用的方法;
service:处理request时调用的方法;
destroy:销毁Servlet时调用的方法
三、创建我们的第一个Servlet
1、打开JavaEE,新建一个Dynamic项目;取名为Servlet01;在src目录下新建一个名为FirstServlet.java类;
整个项目结构如下图:
编辑我们的第一个Servlet
package com.hx.serverlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
//通过实现Servlet接口创建我们的第一个Servlet,注意不要导错包 import javax.servlet.Servlet;
public class FirstServlet implements Servlet{
//初始化参数
private String str=null;
//构造函数
public FirstServlet() {
System.out.println("do my constucter......");
}
// 初始化方法
public void init(ServletConfig config) throws ServletException {
str=config.getInitParameter("str");
System.out.println("do my init .......");
}
//service方法
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
// 设置响应输出的文本类型;这里设置为html文本输出;字符编码为UTF-8
res.setContentType("text/html;charset=UTF-8");
// 输出响应正文
res.getWriter().print(""
+ "<!DOCTYPE html><head><body><p>"+str+"</p></body></head>");
}
//销毁方法,一般太快,捕捉不到
public void destroy() {
System.out.println("do my destory......");
}
//后面这两个方法放到后面讲
public ServletConfig getServletConfig() {
return null;
}
public String getServletInfo() {
return null;
}
}
编辑好以后,打开web.xml配置文件,加入如下配置信息
关于web.xml配置文件的解释:
<servlet>
<servlet-name>firstServlet</servlet-name>
<servlet-class>com.hx.serverlet.FirstServlet</servlet-class>
<init-param>
<param-name>str</param-name>
<param-value>Hello World!</param-value>
</init-param>
</servlet>
并且初始化了一个名为str的变量,变量中的内容为Hello World!
<servlet-mapping>
<servlet-name>firstServlet</servlet-name>
<url-pattern>/first</url-pattern>
</servlet-mapping>
这里的配置代表当访问/first路径时,要交给firstServlet对象处理;也就是执行上面我们写的Java代码;根据Servlet的生命周期,会一次调用init()方法,service()方法;当关闭程序是,执行destory()方法;
好了,保存我们上面写的代码和配置文件,将该工程发布到Tomcat服务器下并启动Tomcat服务器(不知道发布的请看我前面的博客)
启动后,在浏览器中输入http://localhost:8080/Seervlet01/first访问,会看到如下界面;
如上,我们的第一Servlet就创建好了;
看下控制台的打印信息:(destory没有抓取到,可以再次理解下Servlet生命周期)
Servlet中的其他方法:
public String getServletInfo()
获取Servlet信息,用处不大,可以返回当前Servlet的作者,版本号等。
public ServletConfig getServletConfig()
在init方法中有一个ServletConfig入参,我们将其保存到一个Field中,当使用 getServletConfig方法时,可以返回该ServletConfig 对象。
四、设计我们自己的Servlet抽象类和HttpServlet类
现在,我们可以思考这样一个问题,基本所有的Servlet都会调用init()方法和destory()方法,还有
getServletInfo()
方法,
getServletConfig()
方法,但我们真正处理业务逻辑的方法是service()方法;所以,我们可以设计一个抽象类,让这个抽象类实现Servlet接口以及除service()方法外的四个方法的具体实现;而
service()则交给真正需要处理业务逻辑的类实现该方法;
由于Servlet中获取ServletConfig的各种信息需要通过getServletConfig().getXX()间接获取,为了让Servlet中直接有getServletName(),所以我们这里也实现了ServletConfig接口,就相当于进一步包装;
我们自己的抽象Servlet类
package com.hx.serverlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
//让我们自己的抽象类是实现Servlet接口和ServletConfig接口
public abstract class RzGenericServlet implements Servlet,ServletConfig{
// 保存init(ServletConfig config)的config参数
private ServletConfig config;
// 构造方法
public RzGenericServlet() {
System.out.println("do my super constructer once......");
}
//具体实现init()方法
public void init(ServletConfig config) throws ServletException {
this.config=config;
System.out.println("do my super init......");
// 这里为什么还要写一个init()方法呢?这是Java中的一种叫Hook(钩子)的设计方法
// 方便真正的类做初始化,比如获取参数等
this.init();
}
// 如果该子类没有重写init()方法,则会调到父类的Init()方法
public void init(){
}
//getServletName()的具体实现
public String getServletName() {
return config.getServletName();
}
//getServletContext()的具体实现
public ServletContext getServletContext() {
return config.getServletContext();
}
//
public String getInitParameter(String name) {
return config.getInitParameter(name);
}
public Enumeration<String> getInitParameterNames() {
return this.config.getInitParameterNames();
}
public ServletConfig getServletConfig() {
return this.config;
}
// 子类可以重写该方法
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
}
public String getServletInfo() {
return null;
}
public void destroy() {
}
}
接下来,我们创建Servlet就不要像前面那样该复杂了,只要继承上面的抽象类,并重写service()方法就可以了;
package com.hx.serverlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
//继承RzGenericServlet抽象类
public class FirstRzServlet extends RzGenericServlet{
// 保存参数
private String info=null;
// 这个init()方法已经不是Servlet生命中的init()方法了,这里通过我们自己的init()方法获取web.xml中配置的参数
public void init() {
info=super.getInitParameter("str1");
System.out.println("str1:"+info);
}
// 重写servce()方法像客户端输出
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
res.getWriter().write("<!DOCTYPE html><html><head><body><p>"+info+"</p></body></head></html>");
}
}
不要忘记去web.xml中配置一下我们新的Servlet信息;这里就不在累赘解释了;看/my路径匹配
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>com.hx.serverlet.FirstRzServlet</servlet-class>
<init-param>
<param-name>str1</param-name>
<param-value>This is my Servlet!</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/my</url-pattern>
</servlet-mapping>
打开浏览器,访问http://localhost:8080/Servlet01/my (注意重启服务器,这里还是同一个工程下)
看下我们控制台的打印信息:
接下来我们更近一步的优化;即对service()方法进行进一步的优化;我们客户端发起的请求一般是http请求,而http请求中最常见的是GET请求和POST请求;
我们自己的HttpServlet抽象类
package com.hx.serverlet;
import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//实现系统的抽象类(当然也可以实现我们自己的抽象类)
public class MyHttpServlet extends GenericServlet{
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
// 类型强转为HTTP请求
HttpServletRequest httpreq=(HttpServletRequest)req;
HttpServletResponse httpres=(HttpServletResponse)res;
String method=httpreq.getMethod();
// 获取请求方式(在浏览器输入地址,敲回车都是GET请求,POST请求一般是form表单的请求)
if("GET".equalsIgnoreCase(method)){
doGet(httpreq,httpres);
}
if("POST".equalsIgnoreCase(method)){
doPost(httpreq,httpres);
}
}
// 让子类重写的方法,如果子类没有重写,则抛出异常
public void doGet(HttpServletRequest httpreq,HttpServletResponse httpres)
throws ServletException, IOException {
throw new RuntimeException("不支持的请求方式");
}
// 让子类重写的方法,如果子类没有重写,则抛出异常
public void doPost(HttpServletRequest httpreq,HttpServletResponse httpres)
throws ServletException, IOException {
throw new RuntimeException("不支持的请求方式");
}
}
继承我们自己的HttpServlet类
package com.hx.serverlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyFirstHttpServlet extends MyHttpServlet{
private static final long serialVersionUID = 1L;
private String str1=null;
// 注意这是我们自己的init()方法
public void init() throws ServletException {
str1=super.getInitParameter("str2");
}
// 处理GET请求
public void doGet(HttpServletRequest httpreq,HttpServletResponse httpres)
throws ServletException, IOException {
httpres.getWriter().write("<!DOCTYPE html><html><head><body><p>"+str1+"</p></body></head></html>");
}
}
web.xml中配置我们的Servlet
<servlet>
<servlet-name>myFirstHttpServlet</servlet-name>
<servlet-class>com.hx.serverlet.MyFirstHttpServlet</servlet-class>
<init-param>
<param-name>str2</param-name>
<param-value>This is my First HttpServlet Example!</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>myFirstHttpServlet</servlet-name>
<url-pattern>/myfirst</url-pattern>
</servlet-mapping>
打开浏览器,访问http://localhost:8080/Servlet01/myfirst (这里还是同一个工程下)
在客户端浏览器地址栏中输入地址敲回车都是GET请求,POST请求多用于form表单中;后面我们会见识到;
至此,我们自己的抽象类和HttpServlet类就实现了;其实,这里我们自己实现一遍的可以让我们更好的理解其中的原理;以后我们写Servlet,只需要继承HttpServlet类就可以 了;然后重写init()方法。doGet(),doPost()方法就可以了;
整个工程目录如下:LoginServlet请忽略;
五、总结
了解Servlet的生命周期;init,service,destory;
了解系统抽象类和HttpServlet的设计原理;
写完了Servlet千万要记得配置哟;
还是自己敲一遍收获大;一起努力奋斗!
共勉!