Servlet

一、Servlet的生命周期
	
	生命周期:Servlet被实例化后,容器运行其init方法,当请求到达时运行其service方法,当服务器决定将实例销毁的时候调用其destroy方法。
	
	1、Servlet实例化对象和初始化方法,默认情况下,只有第一次访问时才执行,且只执行一次。
		
		重要:在内存中一个Servlet只有一个实例。针对不同的用户请求,容器采用多线程的机制调用service方法的。

		希望在应用被Tomcat加载完毕后(此时还没有任何人访问),就实例化并完成初始化Servlet的工作?
		<servlet>
			<servlet-name>FirstServlet</servlet-name>
			<servlet-class>com.jxn.servlet.FirstServlet</servlet-class>
			<load-on-startup>2</load-on-startup>
		</servlet>	
		
	注:<load-on-startup>n</load-on-startup>表示servlet加载的时机和顺序。
		1)当值为0或者大于0时:表示容器启动的时候该servlet就被加载(实例化并调用其init()方法)了。
			说明:
				[1]正数的值越小,启动该servlet的优先级越高。
				[2]org.apache.catalina.servlets.DefaultServlet中<load-on-startup>1</load-on-startup>,1已经被占用了,故如果想让该servlet在容器启动的时候就被加载,则从2开始取(注;实际上从1开始取也可以)
		2)当值为负数或者没有指定时:表示该servlet第一次被访问时才会被容器加载。

	
	2、Servlet接口中的常用方法:
		public void init(ServletConfig config):初始化。Servlet类被实例化后就执行,且执行一次。由容器进行调用
		public void destroy():销毁Servlet对象。由容器进行调用
	
	3、如果设计与HTTP协议有关的Servlet,一般选择集成javax.servlet.http.HttpServlet.

		容器最终要调用service方法为客户进行服务:
		
		HttpServlet覆盖了其父类GenericServlet的public abstract void service(ServletRequest req, ServletResponse res)方法,
		然后在覆盖的service方法中调用了自己的protected void service(HttpServletRequest req, HttpServletResponse resp)方法,
		在自己的service方法中调用了自己的doXXX方法。
		
		故自己写的Servlet不应该覆盖HttpServlet的service方法,而应该去覆盖掉它的doXXX方法。

			
二、Servlet的线程安全问题

	在内存中一个Servlet只有一个实例。针对不同的用户请求,容器采用多线程的机制调用service方法的。
	在Servlet中定义变量,除非特殊要求,尽量使用局部变量。
	如果有需要实例变量时,应做同步处理,且同步代码块尽量包围少的代码。

三、Servlet的配置
	Servlet的配置对象ServletConfig:(容器来创建)
		作用:代表了Servlet配置中的参数信息。
		比如在web.xml中的参数配置如下:
			<servlet>
				<servlet-name>ServletDemo2</servlet-name>
				<servlet-class>cn.jxn.servlet.ServletDemo2</servlet-class>
				<!-- aaa=bbb -->
				<init-param>
					<param-name>aaa</param-name>
					<param-value>bbb</param-value>
				</init-param>
				<init-param>
					<param-name>xxx</param-name>
					<param-value>yyy</param-value>
				</init-param>
			</servlet>
			
		Servlet配置
		1、一个Servlet可以被映射到多个URL地址上
		2、URL地址映射还支持通配符*
			方式一:以*开头,以扩展名结尾。比如 <url-pattern>*.do</url-pattern>
			方式二:以/前缀开头,以*结尾。 比如<url-pattern>/action/*</url-pattern>
		3、多个Servlet使用通配符时,有可能有多
					以"/"开头(方式二)要比"*"开头(方式一)优先级高
					都以"/"开头,还是有多个匹配,找最匹配的
		4、如果一个Servlet的映射为一个"/",就称之为默认的Servlet,它负责处理没有映射路径的URL请求的响应。

四、ServletContext

	1、在应用被服务器加载时就创建ServletContext对象的实例。每一个JavaWeb应用都有唯一的一个ServletContext对象。它就代表着当前的应用。
	2、如何得到ServletContext对象:ServletConfig.getServletContext();
	3、作用:
		3.1ServletContext对象是一个域对象(域对象就是说其内部维护了一个Map<String,Object>)
			    Object getAttribute(String name):根据名称获取绑定的对象
				void setAttribute(String name,Object value):添加或修改对象。
				void removeAttribute(String name):根据名称移除对象
				Enumeration getAttributeNames() :获取ServletContext域中所有的值对应的名称
		3.2实现多个Servlet之间的数据共享
		3.3获取WEB应用的初始化参数(应用的全局参数)
			在web.xml下配置以下信息:
			<context-param>
				<param-name>encoding</param-name>
				<param-value>UTF-8</param-value>
			</context-param>
			这些参数就属于整个应用的全局参数,使用ServletContext来读取。
		3.4读取资源文件的三种方式:
			利用ServletContext.getRealPath():
					特点:读取应用中任何文件。只能在Web环境下用
			利用ResourceBundle读取配置文件
					特点:可以用在非web环境下。但是只能读取类路径中的properties文件
			利用类加载器读取配置文件(专业)
					特点:可以用在非web环境下。可以读取类路径下的任何文件。

五、HttpServletResponse详解
	5.1输出中文数据:
		字节流:
			注:String.getBytes()方法:使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
				String.getBytes("UTF-8")方法:使用UTF-8将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
		
			ServletOutputStream out = response.getOutputStream();
			out.write("中文".getBytes());无乱码
			无乱码的原因:平台默认的字符集和浏览器默认的字符集一样(在中国一般为GBK)
			
			ServletOutputStream out = response.getOutputStream();
			out.write("中文".getBytes("UTF-8"));有乱码
			解决办法:
				通知浏览器,使用的码表
				方式一:response.setHeader("Content-Type", "text/html;charset=UTF-8");
				方式二:response.getOutputStream().write("<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>".getBytes("UTF-8"));
				*方式三:response.setContentType("text/html;charset=UTF-8");//方式一、二、三都是一样的
				
		字符流:
			注:Servlet中的字符流默认查ISO-8859-1(SUN的Servlet规范要求的)
			PrintWriter out = response.getWriter();
			out.write(s);//字符输出流out默认查的是ISO-8859-1码表,即默认以ISO-8859-1编码的形式输出到浏览器
			解决办法:
				方式一:
					第一步:更改默认的编码:	response.setCharacterEncoding("UTF-8");
					第二步:通知浏览器的编码:	response.setHeader("Content-Type", "text/html;charset=UTF-8");
				方式二:
					response.setContentType("text/html;charset=UTF-8");
					在字符流输出中文数据时:response.setContentType("text/html;charset=UTF-8");有两个作用:
						(1)通知字符流以UTF-8编码输出
						(2)通知客户端以UTF-8解码显示

	5.2控制不要缓存
	
		response.setHeader("Pragma","no-cache");	// HTTP1.0  Pragma: 编译指示,标示,杂注
		response.setHeader("Cache-Control","no-cache"); // HTTP1.1
		response.setDateHeader("Expires", 0);

	5.3HttpServletResponse细节:
		字节流和字符流不能同时使用,互斥的。
		通过字符流或字节流输出的数据并不是直接打给浏览器的。而是把数据写到response对象的缓存中的。服务器从缓存中取出数据,按照HTTP协议的响应格式输出给浏览器。
		如果你调用的response的输出流没有主动关闭,服务器会替你关的。

六、HttpServletRequest详解
	HttpServletRequest代表着客户端的请求。要客户的信息只要找这个对象即可,该对象由容器创建。
	ServletRequest是一个域对象(内部维护了一个Map<String,Object>)
		Object getAttribute(Stirng name):
		void setAttribute(String name,Object value):
		void removeAttribute(String name):
	请求参数的编码:
		浏览器当前使用什么编码,就以什么编码提交请求参数。<meta http-equiv="content-type" content="text/html; charset=UTF-8">
		request.setCharacterEncoding(编码):通知程序,客户端提交的数据使用的编码。但是只对POST请求方式有效
		【重要】如果是get请求提交数据,编码就是ISO-8859-1
		
	请求转发、包含、重定向
	
	1、请求转发:(当前应用内转)
		请求转发借助于RequestDispatcher: RequestDispatcher.forward(request,response)
		如何得到RequestDispatcher对象:
			方式一:ServletContext.getRequestDispatcher(目标资源的URI);
			方式二:ServletRequest.getRequestDispatcher(目标资源的URI);
			区别:
				方式一中的目标资源的URI必须以"/"开头,否则报错,此"/"就表示的是当前应用(绝对路径表示法)
				方式二中的目标资源的URI如果以"/"开头,就表示的是当前应用(绝对路径表示法)。如果不以"/"开头,就表示相对路径。

		转发的细节:AServlet(源组件)--->BServlet(目标组件)
			注:Response对象是有缓存的。转发前,容器会清空response的缓存
			1>转发前会清空response的正文。容器会清空源组件输出的数据。因此,用户只会看到目标组件输出的页面结果。但是,源组件的响应头信息是不清空的。
			2>转发页面上只会输出目标组件的输出,源组件的任何页面输出都无效。
			原则:转发前,不要刷新或关闭response的输出流。
	
	2、包含:借助于RequestDispatcher: RequestDispatcher.include(request,response)
		AServlet(源组件)--->BServlet(目标组件):AServlet包含BServlet的输出内容

		包含的细节:
		由源组件包含到目标组件时,容器会清空目标组件的头。因此,只有源组件设置的头才有效。但是,目标组件的响应体信息是不清空的。
		编码原则:不要在目标组件中设置响应头。(做无用功)

	3、重定向:response.sendRedirect(String location)
	
	各种URL地址的写法
		相对路径:不是以"/"开头
		绝对路径:(建议的)
		原则:地址是不是给服务器用的,如果是,"/"就代表着当前应用。如果是给客户端用的绝对路径要加上应用名称。
		
		
		<link href=path/>                               要加/day07
		<script src=path/>								要加/day07
		<img src=path/>									要加/day07
		<a href=path/>									要加/day07
		<form action="path"/> 							要加/day07
		

		HttpServletResponse.sendRedirect(path)			要加/day07
		getRequestDispatcher(String path):  			不要加应用名称,"/"就代表着当前应用
		
		ServletContext.getRealPath(path)				不要加,"/"就代表着当前应用

		响应消息头:Refresh=2;URL=path      			要加/day06




	


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值