GenericServlet
(1)GenericServlet概述
GenericServlet是Servlet接口的实现类,我们可以通过继承GenericServlet来编写自己的Servlet
ServletConfig是什么?
<servlet>这是一个配置信息,它与ServletConfig对象对应。这个信息最终会被加载进内存,也就是说web.xml文件会由其解析器解析后加载进内存。这个文件中的name和class信息会加到ServletConfig对象中,这个对象是对本Servlet的配置:即 一个Servlet对象,对应一段web.xml中Servlet的配置信息
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
(2)查看API文档中ServletConfig接口中定义的方法:接口中提供的方法如果不是由自己来实现,那么就由Tomcat来实现。
String getServletName()
方法获取的是<servlet-name>
中的内容,这个方法使用的很少;- 没有获取
<servlet-class>
信息的方法,因为获取这个信息是不安全的; ServletContext getServletContext()
方法获取的是Servlet上下文对象,这个对象后面会提到;这个方法使用的多String getInitParameter(String name)
方法获取初始化参数Enumeration getInitParameterNames()
方法获取的是一个集合,里面装的是初始化参数的名称
下面这段代码也是属于<servlet>
中的
<init-param>
<param-name>p1</param-name>
<param-value>v1</param-value>
</init-param>
<init-param>
<param-name>p2</param-name>
<param-value>v2</param-value>
</init-param>
通过String getInitParameter(String name)
方法,传入p1就可以得到v1的值
方法演示:
自定义方法
public class HelloWorld implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
/*
获取初始化参数
*/
System.out.println(servletConfig.getInitParameter("p1"));
System.out.println(servletConfig.getInitParameter("p2"));
/*
获取所有初始化参数的名称
*/
Enumeration e = servletConfig.getInitParameterNames();
while(e.hasMoreElements()){
System.out.println(e.nextElement());
}
}
可以看到,在调用init()方法后,显示出了相应的初始化参数和其对应的值
(2)Servlet相关类之ServletRequest和ServletResponse对象的介绍
void service(ServletRequest req, ServletResponse res)
形参中包含了两个对象:请求和响应。
- Servlet把请求数据拿过来,然后处理请求,最后对客户端响应。所有的请求数据都被Tomcat封装到ServletRequest对象当中,调用对象的方法就能把请求信息拿出来,http协议中请求的所有信息都在其中。
- 而ServletResponse对象,例如服务端返回一个302,那么这个302的值还有Location就可以调用对象相应的set方法来发送,甚至可以使用其对象来发送html的代码,这时浏览器就会收到这个对象发送回来的信息
(3)GenericServlet
GenericServlet是Servlet接口的实现类,可以通过继承GenericServlet来编写自己的Servlet
以下是自己写的一个Servlet实现:Servlet每次被访问的时候,Tomcat传递给它一个ServletConfig对象。在所有的方法第一个被调用的是init()。
import javax.servlet.*;
import java.io.IOException;
/*
* 模拟GenericServlet抽象类
*/
public class BServlet implements Servlet {
private ServletConfig servletConfig;
//前期自己写的时候总会写这个成员
@Override
/*
由Tomcat来调用,并且只调用一次
它是这些方法中第一个被调用的,它会在构造器之后马上被调用
*/
public void init(ServletConfig servletConfig) throws ServletException {
//把Tomcat传递的ServletConfig值赋给本类的一个成员,其实就是把它保存起来,方便在其他方法中使用
this.servletConfig = servletConfig;
}
@Override
public ServletConfig getServletConfig() {
return this.servletConfig;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("每次处理请求都会被调用!");
}
@Override
/*
这个方法用的很少,所以不写了
*/
public String getServletInfo() {
return "我是一个快乐的Servlet";
}
@Override
public void destroy() {
System.out.println("啊,我要死了!");
}
}
下面来看GenericServlet抽象类的常用方法:
ServletConfig getServletConfig()
方法返回this.servletConfig对象;ServletContext getServletContext()
方法用的是this.getServletContext();- 其他的一些方法就可以使用ServletConfig对象的方法来实现;
一个小技巧:上面代码是自己实现的Servlet,如果再写一个类CServlet继承上面的这个类,对于初始化方法想重新写,那么就可以这样写
//父类中的初始化方法
public void init(ServletConfig servletConfig) throws ServletException {
this.servletConfig = servletConfig;
init();
//组合的方式
}
public init(){}
//子类中的初始化方法
public init(){
System.out.println("这是我自己的初始化方法!");
}
以下是GenericServlet的源码:关于源码的一些解释和技巧看上面自己实现的BServlet
import java.io.IOException;
import java.util.Enumeration;
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config;
public GenericServlet() {
}
@Override
public void destroy() {
//可写可不写
}
@Override
//参考上面解释
public String getInitParameter(String name) {
return getServletConfig().getInitParameter(name);
}
@Override
//参考上面解释
public Enumeration<String> getInitParameterNames() {
return getServletConfig().getInitParameterNames();
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public ServletContext getServletContext() {
return getServletConfig().getServletContext();
}
@Override
//这个方法不常用
public String getServletInfo() {
return "";
}
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
//参考小技巧
this.init();
}
public void init() throws ServletException {
//不是生命周期方法(生命周期方法只有三个)不由Tomcat直接调用,这个方法的创建是为了其子类再定义初始化方法使用的,具体参考小技巧
}
public void log(String msg) {
getServletContext().log(getServletName() + ": " + msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
@Override
//这个是抽象方法,强迫各位程序猿必须去写
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
@Override
public String getServletName() {
return config.getServletName();
}
}
自己调皮的继承了GenericServlet抽象类,并简单演示了如何继承:
import javax.servlet.*;
import java.io.IOException;
public class DServlet extends GenericServlet {
//小技巧的使用
public void init(){
System.out.println("哈哈哈,我来了!");
}
@Override
//这个方法必须写
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello World!");
}
@Override
//可写可不写
public void destroy() {
System.out.println("哎,我走了!");
}
}
把web.xml文件中的name,class,url-pattern修改一下,使得能够访问DServlet。可以看到自定义的东西:
访问六次以后
关闭服务:
HttpServlet
(1)HttpServlet所在的包与Servlet和GenericServlet的包有所不同,类名前缀说明HttpServlet总是与http协议相关。http请求最常见的两种方式:get和post,这个类就提供了相应的方法来获取。
现在重点看一下几个方法
void doGet(HttpServletRequest req, HttpServletResponse resp)
方法void service(HttpServletRequest req, HttpServletResponse resp)
和void service(ServletRequest req, ServletResponse res)
是service方法的重载,前者是跟协议相关的。Tomcat会很智能的根据协议来创建对象。协议是基于http但是方法却与协议无关,所以在HttpServlet后者中对传入其中的对象做一个强转,然后再去调用http的方法,这样就可以让生命周期方法来调用前者
(2)这里的doGet()和doPost()是需要覆盖的,如果没有覆盖并且他们被调用了,那么就会出现405表示不支持这种请求方式(资源找到了,但是不支持客户端这样的请求方式)
过程时序图示:
首先覆盖一下doGet方法而不覆盖doPost方法
public class EServlet extends HttpServlet {
//这个类是抽象类,但是所有方法都实现了
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("deGet()...");
}
}
在地址里输入地址,localhost:8080/JavaWeb/EServlet这就是get的请求方式,就可以看到:
当只覆盖doPost方法时:由于使用默认使用的是get请求方式,所以会出现下面的情况
此时写一个html文件,请求方式为post。上传表单到EServlet
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form action="/JavaWeb/EServlet" method="post">
<input type="submit" value="sub"/>
</form>
</body>
</html>
这时候就可以看到正常的页面了:
HttpServlet的关键就是调用流程,也就是上面的时序图
本人是菜鸟一枚,当做学习笔记写博客。谢谢各路大咖驻足审阅