1.servlet
就Servlet是一个普通的JAVA类,但是能够处理http的请求与响应过程。
1 Servlet的基本架构
Servlet的自身就是一个接口,同时还有一个ServletConfig的接口。分别处理的不同事务。
- Servlet接口
//
// Source code recreated from a.class file by IntelliJ IDEA
// (powered by FernFlowerdecompiler)
//
package javax.servlet;
import java.io.IOException;
public interface Servlet {
//当前的对象初始化 ***
void init(ServletConfig var1)throws ServletException;
//获取到ServletConfig实例对象
ServletConfig getServletConfig();
//服务的提供方法 *****
void service(ServletRequestvar1, ServletResponse var2) throws ServletException, IOException;
//获取到Servlet信息
String getServletInfo();
//销毁服务 ***
void destroy();
}
- ServletConfig接口
该接口主要的功能就是实现配置加载
//
// Source code recreated from a.class file by IntelliJ IDEA
// (powered by FernFlowerdecompiler)
//
package javax.servlet;
import java.util.Enumeration;
public interface ServletConfig {
//获取到Servlet的名字
String getServletName();
//获取到Servlet的上下文
ServletContext getServletContext();
//获取到Servlet配置中的初始化参数
String getInitParameter(String var1);
//获取到Servlet配置中的所有的初始化参数
Enumeration<String> getInitParameterNames();
}
- GenericServlet
该类虽然实现了Servlet接口,但是更多的是对ServletConfig接口进行了实现,而把对应的Http请求方法Service,扔给了其子类HttpServlet。
//
// Source code recreated from a.class file by IntelliJ IDEA
// (powered by FernFlowerdecompiler)
//
package javax.servlet;
import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.ResourceBundle;
public abstract class GenericServlet implements Servlet,ServletConfig, Serializable {
private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.se
rvlet.LocalStrings");
private transientServletConfig config;
public GenericServlet() {}
public void destroy() {}
public String getInitParameter(String name) {
ServletConfig sc =this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_ini
tialized"));
} else {
return sc.getInitParameter(name);
}
}
public Enumeration<String> getInitParameterNames() {
ServletConfig sc =this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_ini
tialized"));
} else {
return sc.getInitParameterNames();
}
}
public ServletConfig getServletConfig() {
return this.config;
}
public ServletContext getServletContext() {
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_ini
tialized"));
} else {
return sc.getServletContext();
}
}
public String getServletInfo(){
return "";
}
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {}
public void log(String msg) {
this.getServletContext().log(this.getServletName() + ": " + msg);
}
public void log(String message, Throwable t) {
this.getServletContext().log(this.getServletName() + ": " +message, t);
}
//由子类实现对应请求服务响应
public abstract void service(ServletRequest var1,ServletResponse var2) throws
ServletException, IOException;
public String getServletName(){
ServletConfig sc = this.getServletConfig();
if (sc == null) {
throw new IllegalStateException(lStrings.getString("err.servlet_config_not_ini
tialized"));
} else {
return sc.getServletName();
}
}
}
- HttpServlet
该类主要就是完成用户的请求和响应。自定义的Servlet必须继承该类!
protected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {
//获取到请求方式
String method = req.getMethod();
long lastModified;
//根据不同的请求方式调用不同doXXX()方法
if (method.equals("GET")){
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req,resp);
} else {
long ifModifiedSince =req.getDateHeader("If-Modified-Since");
if(ifModifiedSince < lastModified) {
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);
}
}
- 自定义Servlet
声明一个类,继承自HttpServlet
package com.csi.eshop.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 步骤1:需要继承自HttpServlet
*
* 思考:自定义Servlet是一个单例的还是多例的?(面试题)
* Servlet是一个单例设计,同时能够支持多线程并发访问,所以可能会造成线程安全性问题。
*/
public class TestController extends HttpServlet {
//对象的创建
public TestController(){
System.out.println("当前的Servlet对象被创建了...");
}
//对象初始化
@Override
public void init()throws ServletException {
System.out.println("当前的Servlet被初始化了...");
}
//提供服务
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws
ServletException,IOException {
System.out.println("hello...");
System.out.println(this);
}
//销毁
@Override
public void destroy() {
System.out.println("我即将消失,不要对我留恋...");
System.out.println("我即将消失,不要对我留恋...");
System.out.println("我即将消失,不要对我留恋...");
}
}
- 配置部署Servlet
在web.xml中,配置Servlet的信息
<!--步骤1:先配置Servlet的位置-->
<servlet>
<!--定义Servlet的名字,供将来请求时能够找到该Servlet-->
<servlet-name>TestController</servlet-name>
<servlet-class>com.csi.eshop.controller.TestController</servlet-class>
<!--可以不写
<init-param>
<param-name>username</param-name>
<param-value>zhangsan</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>20</param-value>
</init-param>-->
</servlet>
<!--步骤2:配置什么样的请求要找到哪一个对应Servlet-->
<servlet-mapping>
<servlet-name>TestController</servlet-name>
<url-pattern>/TestController</url-pattern>
</servlet-mapping>
Servlet运行步骤:
1. 先去URL中找到对应的请求(url-partten)
2. 找到请求所对应的Servlet的名字(servlet-name)
以上两个部分都是在servlet-mapping中.
3. 根据名字找到Servlet配置节点中的Servlet的名字(servlet-name)
4. 再确定Servlet的class所在位置(servlet-class)
1.Servlet生命周期
- 实例化Servlet
首先由客户端发起请求,容器会解析请求的URL,找到对应Servlet配置中的"url-partten",紧跟着继续查找对应“servlet-name”,找到了“servlet-name”就会使用"servlet-class"实现类实例化。
- 调用init方法实现Servlet初始化
当容器执行自定义Servlet时,会自动调用init方法,实现Servlet的初始化。
Servlet是一个单例设计的类,能够提高多线程的访问能力。因此可能会存在线程安全性问题。
- 调用init方法实现Servlet初始化
当容器执行自定义Servlet时,会自动调用init方法,实现Servlet的初始化。
Servlet是一个单例设计的类,能够提高多线程的访问能力。因此可能会存在线程安全性问题。
- 调用Service方法提供服务
在HttpServlet中的Service方法,会根据用户提交的方式,选择调用doXXX方法,如果我们自己重写了Service方法,而没有调用doXXX具体的方法,可能在请求后,如果同时存在service以及对应doXXX方法时,只会调用service这一个方法。
- 调用destory方法实现销毁
当web容器销毁时,会调用每一个自定义Servlet中的destory实现对Servlet的销毁功能。
3. 在Servlet中获取request、session、application内置对象的方式
//获取request,在调用doXX方法和service方法时,会存在两个对应对象,其中一个就是request
doXXX(HttpServletRequest request,HttpServletResponse response)
service(HttpServletRequest request,HttpServletResponse repsonse)
//获取Session
HttpSession session = request.getSession() ;
//获取Application
ServletContext application = request.getServletContext() ;
4.request的一些其他方法
- getContextPath(): 获取到当前项目的上下文路径
- getMethod():获取到请求的方式
- getHeader(String str):获取到请求的头信息的内容
5.response的一些其他方法
- getWriter() :获取到PrintWriter对象,在内置对象中,代表out对象。
PrintWriter out = response.getWriter() ;
out.println() ;
- setContentType(String txt):设置当前页面响应的内容形式。
response.setContentType("application/json;charset=utf-8") ;
response.setContentType("img/jpeg")