Servlet原理解析及作用2

注:再看本文章前,请先看我前面写的《Servlet原理解析及作用1》。

一、Servlet中的线程安全问题

  *首先我们要明白web应用是并发应用

   当用户多次刷新页面,就会请求一次服务端,这个时候就会出现该同一个请求service被两个对象调用现象,存在数据不安全。

解决方案:
      (1)在Servlet中定义变量,除非特殊要求,尽量使用局部变量。
      (2)如果有需要实例变量时,应做同步处理,且同步代码块尽量包围少的代码。

                     

implements SingleThreadModel接口就可以保证安全这个时候servlet就可能实行两种方式进行加锁:

(1)每次进来一个的访问serlet对象就进行加锁,指导用完后,才给下一个访问加锁。

(2)给每一个访问一个servlet对象(相对繁琐了,而且违背了servlet单独一个对象在内存中的原则)但是安全还是无     法成立。

二、Servlet的配置对象:
ServletConfig:(读取下列数据咋内存中创建该对象(由容器来创建))
作用:代表了Servlet配置中的参数信息。
比如在web.xml中的参数配置如下:
   

<servlet>
    <servlet-name>ServletDom2</servlet-name>
    <servlet-class>com.dp.java.servlet.ServletDom2</servlet-class>
    <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>

      问题来了!!怎么调用方法呢?用 init(ServletConfig config)周期方法

public class ServletDom2 extends HttpServlet {
	private ServletConfig config;
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test1();//去配置固定值
		test2();//取配置所有init的值
		test3();//取配置servlet-name
	}
	private void test3() {
		//得到servlet元素文本
		String s_name=config.getServletName();
		System.out.println("servlet-name: "+s_name);
	}
	private void test2() {
		//得到所有init元素标签,并打印所有映射的value值
		Enumeration enu=config.getInitParameterNames();
		while(enu.hasMoreElements()){
			String parmname=(String)enu.nextElement();
			System.out.println("init-param的name值: "+parmname+"  " +
					"  init-param的value值: "+config.getInitParameter(parmname));
		}
	}

	private void test1() {
		//得到init的AAA所映射的value值
		String AAA_value=config.getInitParameter("AAA");
		System.out.println(AAA_value);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
	
	@Override
	//组件创建对象
	public void init(ServletConfig config) throws ServletException {
		this.config=config;
	}

}
结果:

                 


三、ServletContext详解

                 

        1、在应用被服务器加载时就创建ServletContext对象的实例。每一个JavaWeb应用都有唯一的一个                                 ServletContext对象它就代表着当前的应用。
2、如何得到ServletContext对象:ServletConfig.getServletContext();

       (1)第一种,写一个ServletContext对象来调用

	private ServletConfig config;
	//一个web应用只有一个servletcontext对象
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
			config.getServletContext();

	}

	public void init(ServletConfig config) throws ServletException {
		this.config=config;
	}
    (2)第二种直接调用,因为在HttpServlet的父类关系中写得有。

ServletContext sc=getServletContext();

3、有什么用呢?

最重要的一个作用实现Servlet对象之间可以通过ServletContext(就因为它可以得到类对象名)对象来实现通讯,           所以ServletContext对象也被称为Context域对象。

              3.1ServletContext对象是一个域对象(域对象就是说其内部维护了一个Map<String,Object>)
       Object getAttribute(String name):根据名称获取绑定的对象
Enumeration getAttributeNames() :获取ServletContext域中的所有名称
void removeAttribute(String name):根据名称移除对象
void setAttribute(String name,Object value):添加或修改对象。


3.2实现多个Servlet之间的数据共享

                这个举一个例子:

在ServletContext对象中放入数据   

	//	ServletContext的练习
public class ServletDom3 extends HttpServlet {
	private ServletConfig config;
	//一个web应用只有一个servletcontext对象
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
			ServletContext sc=config.getServletContext();
			sc.setAttribute("P", "放了一个p对象");
			response.getOutputStream().write("已经放了".getBytes());
	}

	public void init(ServletConfig config) throws ServletException {
		this.config=config;
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
在ServletContext对象中放入数据   


public class ServletDom4 extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		    ServletContext sc=getServletContext();
		    String obj=(String)sc.getAttribute("p");
		    response.getOutputStream().write(obj.getBytes());
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

3.3获取WEB应用的初始化参数(应用的全局参数)
在web.xml的根元素下配置一下信息:
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
这些参数就属于整个应用的全局参数,使用ServletContext来读取。  可以直接进行得到全局value。

3.4读取资源文件的三种方式:
利用ServletContext.getRealPath():
特点:读取应用中任何文件。只能在Web环境下用
利用ResourceBundle读取配置文件
特点:可以用在非web环境下。但是只能读取类路径中的properties文件
利用类加载器读取配置文件(专业)
特点:可以用在非web环境下。可以读取类路径下的任何文件。

举一个例子:

package com.dp.java.servlet;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 读取资源,并下载资源
 *
 */
public class ServletDom6_file extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		  test2(response);
	}
	/**
	 *最简单的文件下载
	 */
	private void test2(HttpServletResponse response)
			throws FileNotFoundException, IOException {
		//得到要下载的文件
		ServletContext sc=getServletContext();
		String path=sc.getRealPath("/1.jpg");//根目录下的真实照片文件路径,必须通过它
		System.out.println(path);//打印路径
		//截取文件名
		String filename=path.substring(path.lastIndexOf("\\")+1);
		System.out.println(filename);
		  //构建输入流
		InputStream in=new FileInputStream(path);
		  //通知客户端的形式打开
		response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename, "UTF-8"));
		response.setHeader("Content-Type", "application/octet-stream");
		  //得到输出流
		OutputStream out=response.getOutputStream();
		int len=-1;
		byte b[]=new byte[1024];
		while((len=in.read(b))!=-1){
			out.write(b, 0, len);
		}
	}

	private String URLEncoder(String filename, String string) {
		// TODO Auto-generated method stub
		return null;
	}
	/**
	 *最简单的文件下载
	 */
	private void test1(HttpServletResponse response)
			throws FileNotFoundException, IOException {
		//得到要下载的文件
		ServletContext sc=getServletContext();
		String path=sc.getRealPath("/1.jpg");//根目录下的照片
		System.out.println(path);//打印路径
		  //构建输入流
		InputStream in=new FileInputStream(path);
		  //通知客户端的形式打开
		response.setHeader("Content-Disposition", "attachment;filename=1.jpg");
		response.setHeader("Content-Type", "application/octet-stream");
		  //得到输出流
		OutputStream out=response.getOutputStream();
		int len=-1;
		byte b[]=new byte[1024];
		while((len=in.read(b))!=-1){
			out.write(b, 0, len);
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值