1.什么是 Servlet
* 1、Servlet 是 JavaEE 规范之一。规范就是接口
* 2、Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
* 3、Servlet 是运行在服务器上的一个小的 java 程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
*
2.手动实现 Servlet 程序
* 1、编写一个类去实现 Servlet 接口
* 2、实现 service 方法,处理请求,并响应数据
* 3、到 web.xml 中去配置 servlet 程序的访问地址 【否则服务器是不知道你写的这个helloservlet程序的】
*
3.要用到的servlet包什么的都在Tomcat安装路径下的lib的
*
4. Servlet 的生命周期
* 1、执行 Servlet 构造器方法
* 2、执行 init 初始化方法
* 1和2创建 Servlet 程序会调用,只调用一次
* 3、执行 service 方法 第三步,每次访问都会调用。
* 4、执行 destroy 销毁方法 第四步,在 web 工程停止的时候调用。
5.ServletConfig 类:【如何理解下面的三点看下面第8点】
* * ServletConfig 类从类名上来看,就知道是 Servlet 程序的配置信息类。
* * Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。(****)
* * Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对 象(****)
* *
* * ServletConfig 类的三大作用
* * 1、可以获取 Servlet 程序的别名 servlet-name 的值
* * 2、获取初始化参数 init-param
* * 3、获取 ServletContext 对象
HelloServlet.java
1 public class HelloServlet implements Servlet {
2
3 public HelloServlet() {
4 System.out.println("1.执行servlet构造器方法");
5 }
6
7 @Override
8 public void init(ServletConfig servletConfig) throws ServletException {
9 System.out.println("2.init初始化方法");
10 //获取 Servlet 程序的别名 servlet-name 的值
11 System.out.println(servletConfig.getServletName());//他就会返回在web.xml中我们
配置的servlet-name
12 //获取初始化参数 init-param
13 System.out.println(servletConfig.getInitParameter("password"));//username
14 //获取 ServletContext 对象
15 System.out.println(servletConfig.getServletContext());
16 }
17
18 @Override
19 public ServletConfig getServletConfig() {
20 return null;
21 }
22
23 //直接实现Servlet接口,那么就要在service()方法中实现手动分发请求处理
24 @Override
25 public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
26 System.out.println("3.services 方法 hello,servlet");
27 //类型转换 子接口有getMethod方法
28 HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
29 //获取请求的方式
30 String method = httpServletRequest.getMethod();
31 if ("GET".equals(method)){
32 doGET();
33 }else if ("POST".equals(method)){
34 doPOST();
35 };
36 }
37
38 @Override
39 public String getServletInfo() {
40 return null;
41 }
42
43 @Override
44 public void destroy() {
45 System.out.println("4.执行 destroy 销毁方法");
46 }
47
48 public void doGET(){
49 System.out.println("GET 方式下的操作");
50 }
51
52 public void doPOST(){
53 System.out.println("POST 方式下的操作");
54 }
55 }
6.Servlet的继承体系
* Servlet(interface):只负责Servlet程序的访问规范
* --->GenericServlet(class):对Servlet中的规范做很多空实现,并持有一个ServletConfig类的引用。并对ServletConfig的使用做了一些方法
* --->HttpServlet(class):实现了service()方法,并实现了请求的分发处理(get/post),
* 也就是说他实现了String method= req.getMethod();if(method=get/post){doget/dopost}
* --->自己的类继承于HttpServlet,那么该类也会拥有service()方法,我们只需要在自己的类中重写
* doget和dopost方法,然后执行service()方法时就会调用重写好的doget和dopost方法。所以我们都继承于
* HTTPServlet,如果我们直接去实现Servlet接口,那么service()方法还得自己去写请求的分发处理代码
7.通过继承 HttpServlet 实现 Servlet 程序
* 一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。
* 步骤:
* 1、编写一个类去继承 HttpServlet 类
* 2、根据业务需要重写 doGet 或 doPost 方法
* 3、到 web.xml 中的配置 Servlet 程序的访问地址
这种方式与直接继承于Servlet接口的区别就是不用手动实现请求的分发处理代码
public class HelloServlet2 extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("初始化一些操作");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("httpservlet的doGet方法");
//首先,在servlet中,Tomcat会自动创建一个ServletConfig
//在HelloServlet中,我们是采用了实现Servlet接口的方式。那么需要重写init方法,【public interface Servlet {
// void init(ServletConfig var1) throws ServletException;】,在重写的方法中我们可以使用ServletConfig
//类,获取一些信息。
// 在我们直接继承于HttpServlet的类中,也就是本类,因为HttpServlet是继承于GenericServlet,而
//GenericServlet是实现了Servlet。
// 在GenericServlet中去重写了init方法,【public void init(ServletConfig config) throws ServletException {
// this.config = config;
// this.init();
// }
// 】
//所以在继承于HttpServlet的本类HelloServlet2中就不用再去重写init方法,因为他可以从GenericServlet类中继承到
//已经写好的init方法.
//如果你想在该HelloServlet2类中重写init方法,一定要在init方法中加上super.init(config);
//加上以后,看GenericServlet源码,它里面的init方法就会把Tomcat提供的ServletConfig赋值给config属性,因为
//init方法很早就会执行(servlet生命周期),所以现在config属性有了值,接下来
// ServletConfig servletConfig = getServletConfig();这个方法他会返回这个config属性的值,也就是Tomcat自动创建的
//confign.接下来才会去servletConfig.getServletName()、servletConfig.getInitParameter("username")等
//如果你要是不加上super.init(config);那么在该类中重写init方法后Tomcat自动创建提供的ServletConfig就没办法赋值给
//confign属性,那么你再去ServletConfig servletConfig = getServletConfig();这个方法是返回confign属性的值
//那就返回不到了,是null对象,然后你在用空对象去servletConfig.getServletName()、servletConfig.getServletContext()
//就会抛出来空指针异常
ServletConfig servletConfig = getServletConfig();
System.out.println(servletConfig.getServletName());
System.out.println(servletConfig.getInitParameter("username"));
System.out.println(servletConfig.getServletContext());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("httpservlet的doPost方法");
}
}
8.如上代码是用自定义类继承HttpServlet类,很显然大体上来看,我们只需要把不同请求的操作代码写在各自的函数中即可。
有一个细节关于servletConfig的:如果在类中你去重写init()方法:可能会出现空指针异常,原因是未在init方法中写上super.init(confign)
首先,在servlet中,Tomcat会自动创建一个ServletConfig
//在HelloServlet中,我们是采用了实现Servlet接口的方式。那么需要重写init方法,【public interface Servlet { // void init(ServletConfig var1) throws ServletException;】,在重写的方法中我们可以使用ServletConfig //类,获取一些信息。 // 在我们直接继承于HttpServlet的类中,也就是本类,因为HttpServlet是继承于GenericServlet,而 //GenericServlet是实现了Servlet。 // 在GenericServlet中去重写了init方法,【public void init(ServletConfig config) throws ServletException { // this.config = config; // this.init(); // } // 】 //所以在继承于HttpServlet的本类HelloServlet2中就不用再去重写init方法,因为他可以从GenericServlet类中继承到 //已经写好的init方法. //如果你想在该HelloServlet2类中重写init方法,一定要在init方法中加上super.init(config); //加上以后,看GenericServlet源码,它里面的init方法就会把Tomcat提供的ServletConfig赋值给config属性,因为 //init方法很早就会执行(servlet生命周期),所以现在config属性有了值,接下来 // ServletConfig servletConfig = getServletConfig();这个方法他会返回这个config属性的值,也就是Tomcat自动创建的 //confign.接下来才会去servletConfig.getServletName()、servletConfig.getInitParameter("username")等 //如果你要是不加上super.init(config);那么在该类中重写init方法后Tomcat自动创建提供的ServletConfig就没办法赋值给 //confign属性,那么你再去ServletConfig servletConfig = getServletConfig();这个方法是返回confign属性的值 //那就返回不到了,是null对象,然后你在用空对象去servletConfig.getServletName()、servletConfig.getServletContext() //就会抛出来空指针异常
9.如何生成一个servlet程序?
直接在src下的包名下生成Servlet程序(类),该类直接继承于HttpServlet,并且自动给我们重写了doPost和doGet方法,而且 * 还在web.xml 里面帮我们写好了<servlet></servlet>,我们只需要手动去写一个<servlet-mapping></servlet-mapping>。 操作方式:在src->包名->new->create new servlet ->起类名 ->包名不要变 ->起全类名(包名+起好的类名)->不要选下面的
* 对号,这是采用注解时用到的servlet 3.0版本以后 这样方便省事,省略了手动重写方法,手动在web.xml中配置
10.ServletContext 类
* 什么是 ServletContext? * 1、ServletContext 是一个接口,它表示 Servlet 上下文对象 * 2、一个 web 工程,只有一个 ServletContext 对象实例。[示例在contextServlet1,2里面。] * 3、ServletContext 对象是一个域对象。[示例在contextServlet1,2里面。] * 4、ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。【理解在contextServlet1,2里面。】
11.什么是域对象?
* 域对象,是可以像 Map 一样存取数据的对象,叫域对象。
* 这里的域指的是存取数据的操作范围,整个 web 工程。
*
* 存数据 取数据 删除数据
* Map put() get() remove()
* 域对象 setAttribute() getAttribute() removeAttribute();
* ServletContext 类的四个作用 【1,2,3是本例下】
* 1、获取 web.xml 中配置的上下文参数 context-param
* 2、获取当前的工程路径,格式: /工程路径
* 3、获取工程部署后在服务器硬盘上的绝对路径
* 4、像 Map 一样存取数据
*
* 怎样获取ServletContext对象?
* 通过ServletConfig类来获得
ContextServlet.java
public class ContextServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取 web.xml 中配置的上下文参数 context-param; getInitParameter()方法
ServletContext context = getServletConfig().getServletContext();
String username = context.getInitParameter("username");
System.out.println(username);
System.out.println(context.getInitParameter("password"));
// 2、获取当前的工程路径,格式: /工程路径 ;getContextPath()
System.out.println(context.getContextPath());//06_servlet
// 3、获取工程部署后在服务器硬盘上的绝对路径
/// 斜杠被服务器解析地址为:http://ip:port/工程名/ 通过一系列操作,映射到 IDEA 代码的 web 目录;如下解释
//所以最重要的就是你要记住工程部署后对应到的是web目录下 即 / ----> web目录位置【部署后的】 /css --->web/css
// 斜杠表示的是工程路径啊,也就是在本module下【06_servlet下】,那么他在电脑中存的位置是【E:\workspace_idea1\JavaWeb\06_servlet】
// 而工程部署后他在E:\workspace_idea1\JavaWeb\out\artifacts\06_servlet_war_exploded\,并且只有web目录下的内容
// 那src里的java代码去哪了?其实也在web/WEB_INF,它生成一个classes文件夹,来放java文件的.class文件。所以位置在06_servlet_war_exploded\WEB-INF\classes\com\atguigu\servlet
// 而我们需要知道他是怎么部署的。他先把工程拷贝到C:\Users\lenovo\AppData\Local\JetBrains\IntelliJIdea2020.2\tomcat\Unnamed_JavaWeb_3
// 然后在\conf\Catalina\localhost下生成一个06_servlet.xml,该.xml文件就是我们说的之前手动部署项目到Tomcat服务器的第二种方法
//该文件内容<Context path="/06_servlet" docBase="E:\workspace_idea1\JavaWeb\out\artifacts\06_servlet_war_exploded" />
///06_servlet正好就是我们的工程名,它代表的就是docBase里的地址,而docBase里的地址正好就是部署后的地址。我们之前说这种方式
//就是把文件名字写在path里,而真正的工程不用放在webapps下,可以放在任意位置。而docBase就是工程的位置,只需要用path的名字来引用即可
//而这就是Tomcat的部署过程,他帮我们做了这些事情。我们点击Tomcat服务器的执行按钮,在浏览器自动跳转过去的位置是
//http://localhost:8080/06_servlet/, 那么他实际上就去跳转到web工程部署后的位置也就是
// E:\workspace_idea1\JavaWeb\out\artifacts\06_servlet_war_exploded
System.out.println("工程部署后的路径是:"+context.getRealPath("/"));//E:\workspace_idea1\JavaWeb\out\artifacts\06_servlet_war_exploded\
System.out.println("工程下的css目录的绝对路径是:"+context.getRealPath("/css"));//E:\workspace_idea1\JavaWeb\out\artifacts\06_servlet_war_exploded\css
}
}
ServletContext的性质2,3,4理解:
*
* 2、一个 web 工程,只有一个 ServletContext 对象实例。【不管是ContextServlet1还是ContextServlet2程序,都共享一个ServletContext 对象】
* * [示例在contextServlet1,2里面。重新启动或者重新部署Tomcat,
* * 都会销毁这个servletContext对象。这个对象一个web工程只有一份,当启动了servlet服务器后,不论是你去跑contextServlet1程序
* * 还是跑contextServlet2程序,ServletContext 对象都只有一份,如下程序,一开始还没有给他的属性赋值时,key1的值就为null,
* * 当你附上值以后,你去执行contextServlet2程序(浏览器中只用把web.xml中映射的地址改一下,Tomcat服务器不用重新部署或重启)]
* * 他仍旧会保存key1的值,一旦给key1附上值以后,他就一直存在,也就是说,跑完contextServlet2程序,再去跑contextServlet1程序
* * 保存之前Context1获取key1的值就不为null了。 也可以再跑一次contextServlet1程序,那么赋值的值也会存在于key1中。
* 当然也可以去在contextServlet1,2都打印一下context的值,看看地址,都是一样的。
*
*所以这就叫做4.ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。
*
* 3、ServletContext 对象是一个域对象,域对象,是可以像 Map 一样存取数据的对象。域指的是整个web工程都可以操作存取数据
ContextServlet1.java
public class ContextServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得servletcontext对象
ServletContext context = getServletContext();
//保存之前Context1获取key1的值
System.out.println(context.getAttribute("key1"));
context.setAttribute("key1","value1");
System.out.println("Context1获取域数据key1的值是:"+context.getAttribute("key1"));
}
}
ContextServlet2.java
public class ContextServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = getServletContext();
System.out.println("Context1获取域数据key1的值是:"+context.getAttribute("key1"));
}
}