Servlet学习
本篇文章记录学习Servlet技术的内容。
什么是Servlet
- Servlet是JavaEE的一个接口,是JavaWeb的三大组件之一。三大组件分别是:Servlet、Filter过滤器、Listener监听器。
- 处理请求和发送响应的过程是由Servlet程序来完成的,并且Servlet是为了解决实现动态页面而衍生的东西。
- Servlet是运行在服务器上的一个java程序,它可以接收客户端发送过来的请求,并发送响应数据给客户端。
Tomcat和Servlet的关系
- Tomcat是Web应用服务器,是一个Servlet/JSP容器。Tomcat作为Servlet容器,负责处理客户端发送的请求,将请求传给Servlet,并将Servlet的响应传回给客户端。
- 从http协议中的请求和响应可以知道,浏览器发出的请求是一个请求文本,浏览器接收到的也是一个响应文本。
从上图可以看出是如何请求和响应的。
①:Tomcat接收客户端的http请求文本并解析,然后封装成HttpServletRequest类型的request对象,所有的http头数据都可以通过request对象调用对应方法查到。
②:Tomcat同时会将响应的信息封装成HttpServletResponse类型的response对象,通过设置response的属性可以控制输出到浏览器中的内容,然后将response交给Tomcat,Tomcat会将其变成响应文本的格式发送给浏览器。
Java Servlet API是Servlet容器(Tomcat)和Servlet之间的接口,它定义了Servlet的各种方法,还定义了Tomcat传送给Servlet的对象类,其中最重要的是ServletRequest和ServletResponse。在编写Servlet程序时,需要实现Servlet接口,实现里面的方法。
实现Servlet
- 编写一个类去实现Servlet接口
- 实现service方法,处理请求,并响应数据。
- 在web.xml中配置servlet程序的访问地址。需要让浏览器知道发出的请求到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用。
实现的servlet类
1 | public class HelloServlet implements Servlet{ |
web.xml中需要配置以下四个信息。
1 | <servlet> |
url地址到Servlet程序的访问
Servlet的生命周期
- 执行Servlet构造器方法
- 执行init初始化方法
前两步是在第一次访问时创建Servlet程序时调用。
3.执行service方法(这一步每次访问都会调用)。
4.执行destroy销毁方法。(在web工程停止时调用)。
load-on-startup作用
- load-on-startup 元素标记容器是否应该在web应用程序启动的时候就加载这个servlet,(实例化并调用其init()方法)。
- 它的值必须是一个整数,表示servlet被加载的先后顺序。
- 如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
- 如果值为正整数或者0时,表示容器在应用启动时就加载并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
1 | 写在<servlet></servlet>中 |
通过继承HttpServlet实现Servlet程序
一般不会直接实现Servlet类实现Servlet程序,而是去继承HttpServlet类。在HttpServlet继承类中,只需要根据自己的需要去重写doGet和doPost方法既可。
查看HttpServlet类的继承结构,发现它继承于GenericServlet类。而GenericServlet类实现了Servlet类,对很多方法做了空实现。并且持有一个ServletConfig类的引用,对ServletConfig的使用定义了一些方法。
Servlet接口内容
可以看到,接口内有Servlet生命周期的三个关键方法,init、service、destroy,还有一个重要的getServletConfig方法来获取ServletConfig对象,ServletConfig对象可以获取到Servlet的信息,ServletName、ServletContext、InitParameter、InitParameterNames,通过查看ServletConfig这个接口就可以知道。
ServletConfig接口又可以获取ServletContext对象,具体内容下面讲解。
GenericServlet类内容
这个类实现了Servlet和ServletConfig的9个方法。其中init方法有两个,一个是带参数ServletConfig的,一个是无参的方法。
1 | private transient ServletConfig config; |
通过这几个方法一起看,首先看init(ServletConfig config)方法,因为只有init(ServletConfig config)中带有ServletConfig对象,为了方便能够在其他地方也能直接使用ServletConfig对象,而不仅仅局限在init(ServletConfig config)方法中,所以创建一个私有的成员变量config,在init(ServletConfig config)方法中就将其赋值给config,然后通过getServletConfig()方法就能够获取ServletConfig对象了。而当想在init方法中做一些别的事情,就需要重写init(ServletConfig config)方法,这样的话在重写的方法中必须调用父类的init(ServletConfig config)方法,即super.init(ServletConfig config),否则GenericServlet类中的成员变量config会一直是null值,无法再得到ServletConfig对象。增加一个init()方法,那么需要在init内初始化别的数据时,就只需要重写init()方法,不需要覆盖init(ServletConfig config)了,仍然可以得到config对象。
1 | public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; |
这是GenericServlet类中的service方法,是一个抽象方法,那么也就是还有一个子类继承它,即HttpServlet类。这个类实现了service方法的各种细节,通过类名也可知道和http协议有关系了。
HttpServlet类内容
包含各种常量,比如GET和POST请求,还有各种请求的处理方法。
service(ServletRequest req, ServletResponse res)方法
1 | public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { |
该方法只是把ServletRequest和ServletResponse这两个对象强转为HttpServletRequest和HttpServletResponse对象。之后,在调用service(HttpServletRequest req, HttpServletResponse resp)方法,这个方法就是判断浏览器过来的请求方式是哪种,每种的处理方式不一样,我们常用的就是get,post,并且,我们处理的方式可能有很多的内容,所以,在该方法内会将get,post等其他5种请求方式提取出来,变成单个的方法,然后我们需要编写servlet时,就可以直接重写doGet或者doPost方法就行了,而不是重写service方法,更加有针对性。
所以,以后编写servlet程序时,只需要继承于HttpServlet类,只要重写两个方法,doGet()和doPost()。
ServletConfig类
是servlet程序的配置信息类,由Tomcat负责创建,为每一个Servlet程序都创建一个ServletConfig对象。
三大作用
- 可以获取Servlet程序的别名servlet-name的值。(getServletName())
- 获取初始化参数init-param(只是该Servlet下的初始化参数)。(getInitParameter())
- 获取ServletContext对象。(getServletContext())
1 | <servlet> |
1 |
|
ServletContext类
- ServletContext 是一个接口,它表示 Servlet 上下文对象
- 一个 web 工程,只有一个 ServletContext 对象实例。
- ServletContext 对象是一个域对象。
- ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。
什么是域对象?
域对象,是可以像 Map 一样存取数据的对象,叫域对象。
这里的域指的是存取数据的操作范围,整个 web 工程。
四大作用
- 获取 web.xml 中配置的上下文参数 context-param.全局初始化参数,每个Servlet都可以得到该值(getServletContext())
- 获取当前的工程路径,格式: /工程路径。(getContextPath())
- 获取工程部署后在服务器硬盘上的绝对路径。(getRealPath())
- 存取数据。(setAttribute(),getAttribute())
1 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
HttpServletRequest类
每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的 信息。
常用api
1 |
|
获取请求参数
1 | <body> |
1 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
post请求中同样,但是会出现中文乱码,需要设置请求体的字符集为utf8.
1 | request.setCharacterEncoding("utf-8"); |
请求转发
请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源的操作叫请求转发。
- 浏览器地址栏没有发生变化
- 是同一次请求
- 共享Request域中的数据
- 可以转发到WEB-INF下
- 不可以访问工程以外的资源
1 | //servlet1中的get方法 |
base标签
可以设置当前页面的相对路径工作时,参照哪个相对路径进行跳转。
1 | <base href="http://localhost:8080/07_servlet/a/b/"> |
Web中”/“的意义
- 如果被浏览器解析,得到的地址是:http://ip:port/
- 如果被服务器解析,得到的地址是:http://ip:port/工程路径
- 特殊情况:response.sendRediect(“/“) 会把”/“发给浏览器解析,得到http://ip:port/
HttpServletResponse类
HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传 递给 Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息, 我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置。
两个输出流
字节流:getOutputStream()
字符流:getWriter()
两个流同时只能使用一个。
向客户端回传数据
1 |
|
请求重定向
是指客户端给服务器发请求,然后服务器告诉客户端说,我给你一些地址。你去新地址访问。叫请求 重定向(因为之前的地址可能已经被废弃)。
浏览器地址栏会发生变化
两次请求
不能共享request域中的数据
不能访问到WEB-INF下的资源
可以访问工程外的资源,比如百度
1 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
1 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |