servlet是一个接口,servlet的实现类就可以被前端访问,继而处理一些前端请求
servlet一共有5个方法:
1、init:初始化方法
2、getServletConfig:获取servletConfig对象的
3、service:提供服务的方法
4、getServletInfo:获取servlet的一些信息、版本、作者等等…
5、destroy:销毁方法
servlet的实现类必须要重写这5个方法
public interface Servlet {
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
1、init:初始化方法 ------只执行一次
2、service:提供服务的方法--------提供服务(可以执行多次)
*每一次访问servlet时,service方法都会被调用一次
3、destroy:销毁方法-------服务器正常关闭被销毁(执行一次)
1、创建一个servlet的实现类Demo01Servlet
public class Demo01Servlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//处理前端请求的逻辑代码
System.out.println("servlet来咯");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
2、配置servlet
2.1、在web.xml中配置
注意:servlet-class 标签中定义的是类的全限定类名(包名+类名),
如Demo01Servlet的全限定类名为cn.itCate.web.servlet.Demo01Servlet
<servlet>
<servlet-name>demo1</servlet-name>
<servlet-class>cn.itCate.web.servlet.Demo01Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
2.2、注解配置
servlet3.0支持注解配置,注解配置比在web.xml文件这种配置方便多了只需在类上加入一个注解
即可
@WebServlet("/demo01")//添加一个注解,就可以不用在web.xml中进行配置了
public class Demo01Servlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//处理前端请求的逻辑代码
System.out.println("servlet来咯");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
当一个请求来请求Demo01Servlet时,服务器主要做以下两件事情:
一、通过访问路径中 /demo01找到全限定类名cn.itCate.web.servlet.Demo01Servlet
具体步骤:
1、通过访问路径/demo01找到 servlet-mapping中的 url-pattern
2、servlet-mapping中的servlet-name 找到servlet标签中的servlet-name
3、找到servlet-class的全限定类名cn.itCate.web.servlet.Demo01Servlet
二、通过反射创建Demo01Servlet对象,并且执行service方法
具体步骤:
1、通过全限定类名找到对应的Demo01Servlet字节码文件(也就是Demo01Servlet.class文件)
2、JVM将Demo01Servlet字节码文件加载到内存中,并创建一个对应的class类对象
3、通过操作class类对象创建一个Demo01Servlet对象
4、通过Demo01Servlet对象执行service方法
每次写一个servlet的实现类都必须重写这5个方法,实在是太麻烦了,因此GenericServlet抽象类继承了Servlet,并且实现了其他4个方法,只剩一个抽象方法service
public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable
{
public void destroy() {
}
public ServletConfig getServletConfig() {
return config;
}
public String getServletInfo() {
return "";
}
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
//service方法仍然是抽象方法,因此子类需要重写此方法
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
}
创建一个GenericServlet的子类demo02Servlet
@WebServlet("/demo2")//使用注解配置
public class demo02Servlet extends GenericServlet {
//只需重写service方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//处理前端请求的逻辑代码
System.out.println("genderricservlet来了");
}
}
这里配置使用了注解配置,当然也可以在web.xml文件中配置,看个人喜好
<servlet>
<servlet-name>demo2</servlet-name>
<servlet-class>cn.itCate.web.servlet.Demo02Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo2</servlet-name>
<url-pattern>/demo2</url-pattern>
</servlet-mapping>
GenericServlet的运行过程和Servlet的运行过程一样,当有请求来请求Demo02Servlet时服务器会:
通过反射创建Demo02Servlet对象,并且执行service方法
继承了GenericServlet的抽象类(开发常用),HttpServlet是专门用来处理http请求的一个抽象类,下面来看一些它的主要方法
public abstract class HttpServlet extends GenericServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(405, msg);
} else {
resp.sendError(400, msg);
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(405, msg);
} else {
resp.sendError(400, msg);
}
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{
method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest)req;
response = (HttpServletResponse)res;
} catch (ClassCastException var6) {
throw new ServletException(lStrings.getString("http.non_http"));
}
this.service(request, response);
}
}
HttpServlet四个主要方法:
1、service(ServletRequest req, ServletResponse res) , 此方法是重写父类GenericServlet的service方法
2、service(HttpServletRequest req, HttpServletResponse resp),此方法是重载上一个方法,这两个方法的参数不同
3、doPost(HttpServletRequest req, HttpServletResponse resp),处理post请求
4、doGet(HttpServletRequest req, HttpServletResponse resp),处理get请求
1、service(ServletRequest req, ServletResponse res)方法
首先,先来查看service(ServletRequest req, ServletResponse res)方法
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest)req;//ServletRequest --> HttpServletRequest
response = (HttpServletResponse)res;//ServletResponse --> HttpServletResponse
} catch (ClassCastException var6) {
throw new ServletException(lStrings.getString("http.non_http"));
}
this.service(request, response);//跳转到service(HttpServletRequest req, HttpServletResponse resp)方法
}
此方法主要是将参数ServletRequest req 和 ServletResponse res强制转换成 HttpServletRequest request 和 HttpServletResponse response,之后就跳转到service(HttpServletRequest req, HttpServletResponse resp)方法。
注意:HttpServletRequest继承自ServletRequest,HttpServletResponse继承自ServletResponse,它们都是接口。HttpServletRequest相比较于ServletRequest多了一些关于http协议的方法,强制转换的原因也是为了使用这些http协议的方法
2、service(HttpServletRequest req, HttpServletResponse resp)
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();//获取请求的方式
long lastModified;
if (method.equals("GET")) {
//如果请求方式为get,则跳转到doGet方法
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{
method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
此方法主要是获取请求的方式,并执行对应的方法。
String method = req.getMethod();
getMethod()就是HttpServletRequest独有的方法,此方法是获取请求的方式。
若请求方式为GET,则执行doGet(req, resp)方法:
this.doGet(req, resp);
若请求方式为POST,则执行doPost(req, resp)方法:
this.doPost(req, resp);
HttpServlet实现了service(ServletRequest req, ServletResponse res)方法,因此HttpServlet的子类就不必再去重写service方法了,只需要重写doget和dopost方法,在方法内编写对应的代码即可。
创建一个HttpServlet的实现类demo03servlet方法,使用注解进行配置
@WebServlet(value = "/demo3")//注解配置
public class demo03servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理get请求逻辑代码
System.out.println("doget..");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理post请求逻辑代码
System.out.println("dopost...");
}
}
1、当有一个请求来请求demo03servlet时我们都知道服务器会通过反射创建一个demo03servlet对象
2、创建的demo03servlet对象会调用service(ServletRequest req, ServletResponse res)方法,也就是demo03servlet对象.service(ServletRequest req, ServletResponse res)
3、demo03servlet类中并没有service(ServletRequest req, ServletResponse res)方法,于是就会去调用父类也就是HttpServlet中的service(ServletRequest req, ServletResponse res)方法
4、service(ServletRequest req, ServletResponse res)方法主要是将参数ServletRequest req 和 ServletResponse res强制转换成 HttpServletRequest request 和 HttpServletResponse response , 转换完成后,执行service(HttpServletRequest req, HttpServletResponse resp)方法
5、在service(HttpServletRequest req, HttpServletResponse resp)方法中,先是获取了请求方式:String method = req.getMethod();
若请求方式为GET,则执行doGet(req, resp)方法:
this.doGet(req, resp);
若请求方式为POST,则执行doPost(req, resp)方法:
this.doPost(req, resp);
注意这里的 this 关键字指的是demo03servlet对象,因为是它调用了service方法。因此在执行 this.doGet(req, resp) 或者 this.doPost(req, resp) 时,执行的是我们在demo03servlet类中定义 doGet 和 doPost 方法,当 this 调用demo03servlet类中没有定义的方法时,才会去父类中寻找。