Servlet

概述

Servlet—Server let:运行在服务器端,必须有一个运行环境(Servlet容器-Tomcat)

Servlet的生命周期

Servlet在默认情况下,是在第一次处理请求时,由容器实例化,且只会实例化一次,紧接着会调用init方法,由service方法处理请求,在容器正常关闭时调用destory

  1. 实例化:只有servlet第一次处理请求时由容器实例化一次,任何时候都不推荐重写servlet的构造函数
  2. 初始化:只有servlet第一次处理请求时调用一次init方法,init方法有两个分别为init(ServletConfig config)和init(),调用带参的init方法时会将参数config赋给this.config,然后调用无参的init方法,所以一般不建议重写带参的init方法
  3. 处理请求每次浏览器发送请求时调用service方法,对于service方法,一般是不用重写的,因为在HttpServlet中已经将service方法有了很好的实现,它会根据请求的方法名调用doGet、doPost、doXXX等等方法
  4. 摧毁容器:在容器正常关闭时调用,如手动关闭容器,重启容器,但停电等程序异常终止的情况不会调用

代码示例

@WebServlet("/servlet1")
public class Servlet1 extends HttpServlet{
	
	public Servlet1() {
		System.out.println("servlet1实例化");
	}


	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		System.out.println("service()");
	}


	@Override
	public void destroy() {
		System.out.println("destory");
	}

	@Override
	public void init() throws ServletException {
		System.out.println("init无参");
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init带参");
	}
	
	
	
}

结果

在这里插入图片描述

@WebServlet注解常用属性(属性详解)

  1. urlPatterns:该servlet的URL匹配模式
  2. value:作用等同于urlPattern,为了编程方便,但是两个属性不能同时用
  3. loadOnStartup:指定服务器启动时加载servlet,指定加载顺序(实例化顺序),正数有效,数值越大优先级越低,
  4. initParam:指定一组 Servlet 初始化参数

一般写单个属性时使用value,写多个属性时使用urlPatterns

初始化参数的配置

在@WebServlet注解中使用initParams,他的值时@WebInitParam注解的数组,注解配置的初始化参数只针对该注解下的唯一一个servlet,一般注解不会用来配置初始化参数而是采用xml方式

loadOnStartup代码演示

servlet1

@WebServlet(urlPatterns="/servlet1",loadOnStartup=2)
public class Servlet1 extends HttpServlet{
	
	public Servlet1() {
		System.out.println("servlet1实例化");
	}


	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		System.out.println("service()");
	}


	@Override
	public void destroy() {
		System.out.println("destory");
	}

	@Override
	public void init() throws ServletException {
		System.out.println("init无参");
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init带参");
	}
	
	
	
}

servlet2

@WebServlet(urlPatterns="/servlet2",loadOnStartup=1)
public class Servlet2 extends HttpServlet{

	public Servlet2() {
		System.out.println("servlet2实例化");
	}
	
}

结果

在这里插入图片描述

Servlet源码分析

Servlet是一个接口类型的实例,该接口就叫Servlet(如HttpServlet是它的子类)
源码文件中有javax和org两个包,其中javax是servlet接口规范,org是tomcat对serlvet的实现,不同的容器对servlet的实现都遵守该接口规范

servlet

  1. servlet是一个在web服务器端运行的程序,它通常是通过http协议从客户端接受请求和作出响应
  2. 实现servlet接口的方式:可以写一个继承自javax.servlet.GenericServlet的generic servlet或者写一个继承自javax.servlet.HttpServlet的http servlet
  3. servlet接口定义了一些方法作用于servlet的初始化(init方法)、处理请求(service方法,servlet中的service方法参数为servletRequest和servletRReusponse)、从容器移除servlet(destory方法);这些方法以下列顺序调用:实例化与初始化—>处理请求—>从容器中移除servlet—>垃圾回收和结束
  4. 除了生命周期方法之外,servlet接口还提供了getServletConfig方法用于获得任何请求时的信息;以及一个getServletInfo的方法用于获取servlet的自身信息(如作者、版本、版权)

HttpServlet

  1. 提供了一个抽象类来创建一个适合web站点的http servlet子类,这个子类必须实现至少一个方法,通常是:
    (1). doGet:在servlet支持HTTP GET请求时
    (2). doPost:用于HTTP POST请求
    (3). doPut:用于HTTP PUT请求
    (4). doDelete:用于HTTP DELETE请求
    (5). init和destory:用于管理资源和支持生命周期
    (6). getServletInfo:获取servlet自身信息
  2. 通常没有情况会要去重写service方法,因为service方法通过分发请求到每一个http请求类型的方法(doXXX方法)
  3. 也没有情况需要重写doOptions和doTrace方法
  4. servlet通常运行在多线程服务器里面,所以要小心servlet必须处理并发请求并且要小心的同步访问共享资源(servlet是单实例多线程的)。如:
    (1). 实例变量(对象所拥有的,非静态成员变量)和类变量(类拥有的,静态成员变量)
    (2). 外部的对象,如文件、数据库连接、网络连接

service方法

ServletRequest

  1. 定义了一个对象,提供客户端请求信息到servlet,servlet容器会创建一个ServletRequest对象并传给service方法作为参数
  2. ServiceRequest提供的数据包括参数键值对、属性、输入流。继承于ServletRequest接口的子类可以提供额外的与对应的协议相关的数据,如HttpServletRequest提供HTTP数据

在HttpServlet中,有两个service方法,其中参数为ServletRequest和ServletResponse的service方法才是重写自父类的方法,而参数为HttpServeltRequest和HttpServletResponse的方法是新方法

当浏览器发送http请求时,会找自写的servlet中的service方法,因为没有重写会找到父类即HttpServlet中的service方法,在该方法中会将ServletRequest和ServletResponse向下转型为HttpServeltRequest和HttpServletResponse对象,然后调用新的service方法,在新的service方法中,通过request.getMethod()来获得请求类型,然后调用对应的请求方法,如果编写的子类中重写的对应的doMethod,则会调用子类的doMethod方法;如果编写的子类没有重写对应的doMethod,就会调用父类HttpServlet的doMethod方法,HttpServlet中的doMethod方法会抛出异常(模板方法设计模式)

模板方法设计模式代码演示
class Test1{
	public void test1() {
		System.out.println("test1");
	}
	public void test2() {
		test1();
	}
}
class Test2 extends Test1{

	@Override
	public void test1() {
		System.out.println("this test1");
	}
	
}
public class Test {

	public static void main(String args[]) {
		new Test2().test2();
	}
}

在这里插入图片描述

当子类中重写了test1,但没有重写test2,调用test2时会找到父类的test2,然后父类的test2在调用test1时又从子类开始找,这里子类重写了test1,所以调用子类的test1

class Test1{
	public void test1() {
		System.out.println("test1");
	}
	public void test2() {
		test1();
	}
}
class Test2 extends Test1{

	
}
public class Test {

	public static void main(String args[]) {
		new Test2().test2();
	}
}

在这里插入图片描述

这里子类没有重写test1和test2,在子类对象调用test2方法时会找到父类的test2调用,然后父类的test2调用test1方法时在子类又没找到,于是调用父类的test1方法

为什么不推荐重写service方法

对于部分资源,如js、css浏览器会直接下载到本地,再次访问时响应码为304,即从本地获取资源,原有的service就会做出这个判断,响应304,如果自己重写service方法,可能忽略这个判断,每次都从服务器端获得资源

会话跟踪

  1. Session:作用域比request作用域大,在首次访问资源时创建session,直到不操作30分钟后失效(可以通过配置文件修改时长)
  2. 获取Session:使用request的getSession()方法,得到的是HttpSession接口类型的实例
  3. Session的产生依赖于Cookie,当客户端第一次访问Web应用时,请求头中没有Cookie信息,服务器端会产生一个Cookie到客户端。后续再去发送请求时,将第一次产生的Cookie带到服务器端,这样服务器端能区分是不是同一个用户(同一个客户端)。在Cookie不能使用的情况下,可以使用隐藏表单域—将数据存在隐藏的表单中,URL重写(rewrite)
  4. 如果要配置session的存活时间,在web.xml中配置session-config session-timeout值,单位是分钟

欢迎页面

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>

当访问地址没有指向具体的资源,而只是指向目录时,servlet会自动找到该目录下的欢迎页面,依次查找

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值