Servlet 生命周期 ServletContext HttpServletRequest ServletContext Servlet线程安全

简单了解 Servlet 相关特性

Servlet 生命周期

什么是Servlet生命周期

容器创建Servlet对象, 为Servlet对象分配资源, 调用Servlet对象方法来处理请求, 以及销毁Servlet对象的整个过程。

生命周期的四个阶段

阶段一: 实例化
  • 什么是实例化
    容器调用Servlet构造器,创建一个Servlet对象
  • 什么时候实例化
    • 情形一:
      开始容器里面没有Servlet对象,只有收到请求后才会创建Servlet对象
    • 情形二:
      容器在启动之后就会立即创建相应的实例
阶段二: 初始化
//	什么是初始化
		-容器在创建好Servlet对象之后,会立即调用此对象的init()方法
		-一般情况下,我们不用写init()方法,因为GenericServlet已经提供了init()方法的实现(将容器传递过来的ServletConfig对象保存起来,并且提供了getServletConfig()方法来获取ServletConfig对象)
		-init()方法只会执行一次
//	Servlet的初始化参数如何设置
		<servlet>
			<servlet-name> </servlet-name>
			<servlet-class> </servlet-class>
			<init-param>
			<param-name>company </param-name>
			<param-value>hello </param-value>
			</url-param>
		</servlet>
//	如何读取Servlet初始化参数
	String name = servletConfig.getInitParameter("company");
阶段三: 就绪
 -容器收到请求之后调用Servlet对象的service()方法来处理请求
阶段四: 销毁
 -容器会依据自身的算法删除Servlet对象,删除前会调用destroy()方法
 -只会执行一次
 -可以重写destroy()方法来实现自己的处理逻辑
 -应用程序在卸载时一定会调用destroy()方法

Servlet 核心接口和类

ServletConfig接口:

用于获取Servlet初始化参数和ServletContext对象

ServletContext接口:

代表当前Servlet运行环境,Servlet可以通过ServletContext对象来访问Servlet容器中的各种资源

HttpServletRequest接口:

用于封装Http请求信息

HTTPServletResponse接口:

用于封装Http响应消息

ServletConfig 类:

获取ServletConfig对象:

使用初始化方法获得一个ServletConfig对象
通过继承父类(GenericServlet)的方法得到一个ServletConfig对象:

ServletConfig config = this.getServletConfig();
  • getServletName();
    获取servlet的名称,也就是我们在web.xml中配置的servlet-name
  • getServletContext();
    获取ServletContext对象,该对象的作用看下面讲解
  • getInitParameter(String);
    获取在servlet中初始化参数的值。这里注意与全局初始化参数的区分。这个获取的只是在该servlet下的初始化参数:
  • getInitParameterNames();
    获取在Servlet中所有初始化参数的名字,也就是key值,可以通过key值,来找到各个初始化参数的value值。注意返回的是枚举类型:

ServletContext类:

获取ServletContext对象

1)getServletContext();
2)getServletConfig().getServletContext();

这两种获取方式的区别就跟上面的解释一样,第一种是直接拿,在GenericServlet 中已经帮我们用 getServletConfig().getServletContext();拿到了ServletContext。
作用:

1)web项目中共享数据
在一定范围内(当前应用),使多个Servlet共享数据
	1.1setAttribute(String name, Object obj) 在web项目范围内存放内容,以便让在web项目中所有的servlet都能访问到
	1.2getAttribute(String name) 通过指定名称获得内容
	1.3removeAttribute(String name) 通过指定名称移除内容
2)获取全局配置信息
整个web项目初始化参数 (这个就是全局初始化参数,每个Servlet中都能获取到该初始化值)
	2.1getInitPatameter(String name)  //通过指定名称获取初始化值
	2.2getInitParameterNames()  //获得枚举类型
3)获取web项目资源
	3.1)获取web项目下指定资源的路径:getServletContext().getRealPath("/WEB-INF/web.xml")
    	String  getRealPath(String path);//根据资源名称得到资源的绝对路径
	3.2)获取web项目下指定资源的内容,返回的是字节输入流。
			InputStream getResourceAsStream(java.lang.String path)
	3.3getResourcePaths(java.lang.String path) // 指定路径下的所有内容。
	3.4)实现servlet的转发
    RequestDispatcher  getRequestDispatcher(String path) ;//参数表示要跳转到哪去

HttpServletRequest类:

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

request就是将请求文本封装而成的对象,所以通过request能获得请求文本中的所有内容,请求头、请求体、请求行

  • 请求行
    例:Get http://localhost:8080/day09/servlet/req1?username=zs
    http/1.1
getMethod();     //获得请求方式
getRequestURL();   // 返回客户端发出请求时的完整URL。
getRequestURI();    //返回请求行中的资源名部分。
getContextPath();   // 当前应用的虚拟目录
getQueryString() ;    //返回请求行中的参数部分。
  • 请求头
String getHeader(String name) //根据头名称得到头信息值
long getDateHeader(java.lang.String name) //获得指定头内容Date
int getIntHeader(java.lang.String name)  //获得指定头内容int
Enumeration getHeaderNames()// 得到所有头信息name
Enumeration getHeaders(String name) /根据头名称得到相同名称头信息值
  • 请求体(请求正文)

1)与表单获取相关的方法

String getParameter(name) 根据表单中name属性的名,获取value属性的值方法
String[] getParameterValues(String name)专为复选框取取提供的方法
getParameterNames()  得到表单提交的所有name的方法
Map<String,String[]> getParameterMap()得到表单提交的所有值的方法 //做框架用,非常实用
getInputStream   以字节流的方式得到所有表单数据

2)与操作非表单数据相关的方法(request也是一个域对象)

void setAttribute(String name, Object value);
Object getAttribute(String name);
Void removeAttribute(String name);

3)与请求转发相关的方法

 //得到请求转发或请求包含的协助对象
RequestDispatcher getRequestDispatcher(String path) //获取转发器
forward(ServletRequest request, ServletResponse response) //转发的方法
include(ServletRequest request, ServletResponse response) //请求包含

4)与编码相关的方法

//解决post方式编码
request.setCharacterEncoding("UTF-8"); //告诉服务器客户端什么编码,只能处理post请求方式
//解决get方式编码
String name = new String(name.getBytes(“iso-8859-1),”UTF-8);

HttpServletResponse类:

  • 响应头:
Accept:	指示HTTP响应可以接收的文档类型集
Accept-Charset:	告知客户可以接收的字符集
Accept-Encoding:	所有响应的字符编码集 
Content-Type:	响应体的MIME类型
Content-Language:	响应体的语言类型
Content-Length:	响应体的长度和字节数
Expires:	通知客户端过期时间,防止客户浏览器使用本地缓存副本
Cookie:	包含保存到客户端的Cookie集
Redirect:	提供指定重定向,可以不向浏览器输出响应内容,而是直接重新请求到另一个URL地址,实现重定向响应,即是一种自动定向。
setHeader(String name, String value) //设置响应头信息
  • 响应正文:
getWrite(); 字符输出流
getOutputStream(); 字节输出流
setCharacterEncoding(String charset) 告知服务器使用什么编码
setContentType(String type)

在这里插入图片描述

ServletContext (Select上下文)

什么是Servlet上下文
  • 容器启动之后会为每一个web应用创建唯一的一个符合ServletContext接口要求的对象,这个对象就是Servlet上下文
  • 特点:
    1)唯一性(一个web应用对应一个ServletContext)
    2)一直存在(只要容器不关闭,应用没有被卸载,ServletContext就一直存在)
如何获得servlet上下文
  • 方式一:
    通过 GenericServlet 提供的 getServletContext() 方法
  • 方式二:
    通过 ServletConfig 提供的 getServletContext() 方法
  • 方式三:
    通过 HttpSession 提供的 getServletContext() 方法
  • 方式四:
    通过 FilterConfig 提供的 getServletContext() 方法
Servlet上下文的作用及特点
作用:
	1)使用setAttribute绑定数据
	2)使用removeAttribute移除绑定数据
	3)使用getAttribute获取绑定数据
特点:
	Servlet上下文绑定的数据可以被整个应用上的所有组件共享,并且一直可以访问

Servlet线程安全问题

为什么会有线程安全问题

  • 容器在收到请求之后会去启动一个线程来进行相应的处理,默认情况下,容器只会为每个Servlet创建一个实例对象,如果同时有多个请求访问同一个Servlet,则肯定会有多个线程访问这个Servlet实例,如果这些线程要修改Servlet实例的某个属性,就有可能发生线程安全问题

如何保证线程安全

使用synchronized对代码加锁即可
例如:
	synchronized(this){
	count--;
	}
  • 请求之后会去启动一个线程来进行相应的处理,默认情况下,容器只会为每个Servlet创建一个实例对象,如果同时有多个请求访问同一个Servlet,则肯定会有多个线程访问这个Servlet实例,如果这些线程要修改Servlet实例的某个属性,就有可能发生线程安全问题

版权声明:本文为weixin_44603464原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。