Servlet不再是烦恼
Servlet
一、什么是Servlet?
Servlet是在服务器上运行的小程序,也就是一个Java类,但比较特殊,不需要new,自动就可以运行。也有创建、垃圾回收和销毁过程。Servlet是JavaWeb的三大组件之一(Servlet、Filter、Listener),它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
- 接收请求数据;
- 处理请求;
- 完成响应。
例如客户端发出登录请求,或者输出注册请求,这些请求都应该由Servlet来完成处理。Servlet需要我们自己来编写,每个Servlet必须实现javax.servlet.Servlet接口。Servlet对象驻留在服务器内存中。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
1、编写一个Servlet程序
写一个java类,实现Servlet接口,实现了该接口,该类就不是普通的类了。
package servletdemo; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException; @WebServlet("/servlet") public class servletDemo implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("Hello Servlet"); } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
部署应用到tomcat服务器。
测试:http://localhost:8080/MyMavenHome_war/servlet 在IDEA控制台输出 hello servlet,初体验成功!
二、Servlet的生命周期
实例化-->初始化-->服务->销毁
出生:(实例化-->初始化)第一次访问Servlet就出生了(默认情况下)。(说明我可以改变它的出生时机,比如让servlet在服务器启动时就创建)
活着:(服务)应用活着,servlet就活着。(Servlet是单实例,其中的service()方法是多线程的。)
死亡:(销毁)应用被卸载了,servlet就销毁了。
package servletdemo; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException; @WebServlet("/servlet") public class servletDemo implements Servlet { //Servlet生命周期的方法:实例化方法(new 对象,无参构造) //在servlet第一次被访问时调用 public servletDemo() { System.out.println("*******servletDemo执行了"); } //Servlet生命周期的方法:初始化方法 //在servlet第一次被访问时调用 @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("*********init执行了"); } @Override public ServletConfig getServletConfig() { return null; } //Servlet生命周期的方法:服务方法 //每次访问时都会被调用 @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("*******service执行了"); } @Override public String getServletInfo() { return null; } //Servlet生命周期的方法:销毁方法 //当应用被卸载时调用 @Override public void destroy() { System.out.println("*******destroy执行了"); } }
三、实现Servlet的方式
实现Servlet有三种方式:
- 实现javax.servlet.Servlet接口;
- 继承javax.servlet.GenericServlet类;
- 继承javax.servlet.http.HttpServlet类;
自定义Servlet类的继承结构,如下图:
1、实现javax.servlet.Servlet接口(参见:编写一个servlet程序)
2、继承javax.servlet.GenericServlet类(抽象类)(适配器模式)
GenericServlet类(抽象类)已经实现了Servlet接口,我们用哪个方法就调用哪方法,不用再去全部实现了,哪怕是全部的空实现。
3、继承javax.servlet.http.HttpServlet类(抽象类)(模板方法设计模式)
模板是HttpServlet类中的私有service()方法(开发中常用方式) HttpServlet类(抽象类)继承了GenericServlet类(抽象类)package servletdemo; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/servlet1") public class servlet extends HttpServlet { //具体实现1 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("******MydoGet*******"); System.out.println(req.getRemoteAddr()); } //具体实现2 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("*******MydoPost******"); } }
注意: 不要重写父类Httpservlet中的service()方法,因为该方法会调用Httpservlet中私有的service()方法,
而该私有的service()方法会根据不同的提交表单的方式,会调用相应的doGet()、doPost()、doHead()等方法。我们去重写这些不同的表单提交的方法即可。
Servlet(接口) --> GenericServlet(抽象类/适配器) --> HttpServlet(功能抽象类/模板) --> (继承HttpServlet,具体实现类,重写其功能)四、Servlet的线程安全
整个生命周期是单实例,但每次访问时为多线程。
一:单实例变成多实例,但过时了,因为耗费资源多,服务器压力大。
二:加线程锁,但数据会重复出现(没有同步机制),且运行效率低。
三:解决线程安全问题的最佳办法:不要写全局变量,而写局部变量(即改变变量的作用域)。五、ServletContext对象(重要)
ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。单实例。
作用:
1、作为域对象使用:即在一定范围内(当前应用),使多个Servlet通过ServletContext对象实现数据共享。因为当前应用中会有很多java类,很多Servlet。
常用方法:
public void setAttribute(String name, Object value) // 向ServletContext对象的map集合中添加数据
public Object getAttribute(String name) // 从ServletContext对象的map集合中取出数据
public void rmoveAttribute(String name) // 根据name移除数据
2、获取全局配置信息:
方法:public String getInitParamenter(String name) // 根据配置文件中的key得到value
3、读取简单的资源文件(即只包含key=value的形式):
方法:public String getRealPath(String path)// 根据资源名称得到资源的绝对路径,可以得到当前应用任何位置的任何资源。
4、实现Servlet的请求转发:
方法:public RequestDispatcher getRequestDispatcher(String path) //参数表示要跳转到哪去
5、依赖和关联
如果是通过参数传过来的对象,就叫依赖。
通过方法得到的对象,就叫关联。
