ServletContext Response Request

ServletContext的功能:


【功能一:读取全局初始化参数】


配置全局初始化参数:
  <context-param>
  	<param-name>username</param-name>
  	<param-value>root</param-value>
  </context-param>
    <context-param>
  	<param-name>password</param-name>
  	<param-value>123</param-value>
  </context-param>

代码:
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String username = this.getServletContext().getInitParameter("username");
		String password = this.getServletContext().getInitParameter("password");
		
		System.out.println(username+"    "+password);
		
		Enumeration<String> e = this.getServletContext().getInitParameterNames();
		while(e.hasMoreElements()){
			String name = e.nextElement();
			String value = this.getServletContext().getInitParameter(name);
			System.out.println(name+"    "+value);
		}
	}

【功能二:获得文件的MIME的类型】

* 获得文件的MIME的类型.

代码实现:
	/**
	 * 获得文件的MIME的类型
	 */
	private void test2() {
		String type = this.getServletContext().getMimeType("1.html");
		System.out.println(type);

【功能三:作为域对象存取数据】

范围:整个web项目.而且全局的对象.

创建:服务器启动的时候,服务器为每个web项目创建一个单独的ServletContext对象.

销毁:服务器关闭的时候销毁ServletContext.

【功能四:读取web项目下的文件】

【演示传统方式读取WEB工程文件】
	/**
	 * 传统方式读取文件:
	 * * 使用的是相对路径,相对的JVM的路径.
	 * * 但是现在是一个web项目,相对于JVM的路径的.现在JVM已经交给tomcat管理.
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void test1() throws FileNotFoundException, IOException {
		InputStream is = new FileInputStream("src/db.properties");
		Properties properties = new Properties();
		properties.load(is);
		
		String driverClass = properties.getProperty("driverClass");
		String url = properties.getProperty("url");
		String username = properties.getProperty("username");
		String password = properties.getProperty("password");
		
		System.out.println(driverClass);
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}

【使用ServletContext对象读取WEB项目下的文件】


* InputStream getResourceAsStream(String path); --- 根据提供路径读取文件返回一个文件的输入流.


* String getRealPath(String path); --- 返回一个路径的磁盘绝对路径.

代码实现:
使用getResourceAsStream读取
	/**
	 * 使用ServletContext中的getResourceAsStream读取.
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void test2() throws FileNotFoundException, IOException {
	
		// 获得ServletContext:
		ServletContext context = this.getServletContext();
		InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
		Properties properties = new Properties();
		properties.load(is);
		
		String driverClass = properties.getProperty("driverClass");
		String url = properties.getProperty("url");
		String username = properties.getProperty("username");
		String password = properties.getProperty("password");
		
		System.out.println(driverClass);
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}
使用getRealPath读取文件:
/**
	 * 使用ServletContext中的getRealPath读取.
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private void test3() throws FileNotFoundException, IOException {
		// 获得ServletContext:
		ServletContext context = this.getServletContext();
		String realPath = context.getRealPath("/WEB-INF/classes/db.properties");
		// 获得该文件的磁盘绝对路径.
		System.out.println(realPath);
		InputStream is = new FileInputStream(realPath);
		
		Properties properties = new Properties();
		properties.load(is);
		
		String driverClass = properties.getProperty("driverClass");
		String url = properties.getProperty("url");
		String username = properties.getProperty("username");
		String password = properties.getProperty("password");
		
		System.out.println(driverClass);
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}
类加载器读取文件:(扩展)
	public static void readFile() throws IOException{
		// 使用类的加载器来读取文件.
		// 类的加载器用来加载class文件,将class文件加载到内存.
		InputStream is = ReadFileUtils.class.getClassLoader().getResourceAsStream("db.properties");
		Properties properties = new Properties();
		properties.load(is);
		
		String driverClass = properties.getProperty("driverClass");
		String url = properties.getProperty("url");
		String username = properties.getProperty("username");
		String password = properties.getProperty("password");
		
		System.out.println(driverClass);
		System.out.println(url);
		System.out.println(username);
		System.out.println(password);
	}

Response的概述】

 Response:代表响应的对象.从服务器向浏览器输出内容.

Response的常用的API

Ø 响应行:


* 设置状态码.

Ø 响应头:


* 针对一个key对应多个value的头信息.


* 针对一个key对应一个value的头信息.

Ø 响应体



【文件下载的方式】

Ø 一种:超链接下载.直接将文件的路径写到超链接的href.---前提:文件类型,浏览器不支持.

Ø 二种:手动编写代码的方式完成文件的下载.

* 设置两个头和一个流:

    * Content-Type:文件的MIME的类型.

    * Content-Disposition:以下载的形式打开文件.

    * InputStream:文件的输入流.

案例:登录成功后,完成文件的下载.

 需求:

在登录成功后,页面跳转到文件下载的列表的页面,点击列表中的某些链接,下载文件.

  步骤一:将之前的登录功能准备好
  步骤二:在文件下载列表页面上添加文件下载的链接:

 步骤三:完成文件下载的代码的实现:

public class DownloadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1.接收参数
		String filename = request.getParameter("filename");
		// 2.完成文件下载:
		// 2.1设置Content-Type头
		String type = this.getServletContext().getMimeType(filename);
		response.setHeader("Content-Type", type);
		// 2.2设置Content-Disposition头
		response.setHeader("Content-Disposition", "attachment;filename="+filename);
		// 2.3设置文件的InputStream.
		String realPath = this.getServletContext().getRealPath("/download/"+filename);
		InputStream is = new FileInputStream(realPath);
		// 获得response的输出流:
		OutputStream os = response.getOutputStream();
		int len = 0;
		byte[] b = new byte[1024];
		while((len = is.read(b))!= -1){
			os.write(b, 0, len);
		}
		is.close();
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}
中文文件的下载:
IE浏览器下载中文文件的时候采用的URL的编码.
Firefox浏览器下载中文文件的时候采用的是Base64的编码.
/**
 * 文件下载的Servlet
 */
public class DownloadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1.接收参数
		String filename = new String(request.getParameter("filename").getBytes("ISO-8859-1"),"UTF-8");
		System.out.println(filename);
		// 2.完成文件下载:
		// 2.1设置Content-Ty 
		String type = this.getServletContext().getMimeType(filename);
		response.setHeader("Content-Type", type);
		// 2.3设置文件的InputStream.
		String realPath = this.getServletContext().getRealPath("/download/"+filename);
		
		// 根据浏览器的类型处理中文文件的乱码问题:
		String agent = request.getHeader("User-Agent");
		System.out.println(agent);
		if(agent.contains("Firefox")){
			filename = base64EncodeFileName(filename);
		}else{
			filename = URLEncoder.encode(filename,"UTF-8");
		}
		
		// 2.2设置Content-Disposition头
		response.setHeader("Content-Disposition", "attachment;filename="+filename);
		
		InputStream is = new FileInputStream(realPath);
		// 获得response的输出流:
		OutputStream os = response.getOutputStream();
		int len = 0;
		byte[] b = new byte[1024];
		while((len = is.read(b))!= -1){
			os.write(b, 0, len);
		}
		is.close();
	}
	
	public static String base64EncodeFileName(String fileName) {
		BASE64Encoder base64Encoder = new BASE64Encoder();
		try {
			return "=?UTF-8?B?"
					+ new String(base64Encoder.encode(fileName
							.getBytes("UTF-8"))) + "?=";
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

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

}
respo

 response输出响应内容的方法:

向页面响应的方法:

* getOutputStream();

* getWriter();

工程的根路径

* 这两个方法是互斥的.

    * 做出响应的时候只能使用其中的一种流响应.

 

* 输出中文乱码的处理:

    * 字节流:

        * 设置浏览器默认打开的编码:

            * resposne.setHeader(Content-Type,text/html;charset=UTF-8);

        * 设置中文字节取出的时候编码.

            * 中文.getBytes(UTF-8);

    * 字符流:

        * 设置浏览器打开的时候的编码

            * resposne.setHeader(Content-Type,text/html;charset=UTF-8);

        * 设置response的缓冲区的编码

            * response.setCharacterEncoding(UTF-8);

 

        ***** 简化的写法:response.setContentType(text/html;charset=UTF-8);

让我们的内容和浏览器的编码一致.


Request的概述】

Ø Request代表用户的请求.

RequestAPI

功能一:获得客户机相关的信息

Ø 获得请求方式:


Ø 获得请求的路径:


Ø 获得客户机相关的信息:

Ø 获得工程名:


功能二:获得从页面中提交的参数:


功能三:作为域对象存取数据:



【演示request获得客户机的信息】
public class RequestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 获得请求方式:
		String method = request.getMethod();
		System.out.println("请求方式:"+method);
		// 获得客户机的IP地址:
		String ip = request.getRemoteAddr();
		System.out.println("IP地址:"+ip);
		// 获得用户的请求的路径:
		String url = request.getRequestURL().toString();
		String uri = request.getRequestURI();
		System.out.println("获得请求的URL:"+url);
		System.out.println("获得请求的URI:"+uri);
		// 获得发布的工程名:
		String contextPath = request.getContextPath();
		System.out.println("工程名:"+contextPath);
		
	}

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

}

1.1.1.1 处理request接收参数的中文乱码的问题:

现在无论是GET还是POST提交中文的时候,都会出现乱码的问题.

解决:

Ø POST的解决方案:

* POST的参数在请求体中,直接到达后台的Servlet.数据封装到Servlet中的request.request也有一个缓冲区.request的缓冲区也是ISO-8859-1编码.

* 设置request的缓冲区的编码:

    * request.setCharacterEncoding(UTF-8);  --- 一定要在接收参数之前设置编码就OK.

Ø GET的解决方案:

* 1.修改tomcat的字符集的编码.(不推荐)

* 2.使用URLEncoderURLDecoder进行编码和解码的操作.

* 3.使用String的构造方法:


Request作为域对象存取数据:

使用request对象存取数据:

* setAttribute(String name,String value);

* Object getAttribute(String name);

 

request的作用范围:

* 作用范围就是一次请求的范围.

* 创建和销毁:

    * 创建:客户端向服务器发送了一次请求以后,服务器就会创建一个request的对象.

    * 销毁:当服务器对这次请求作出了响应之后.

 

重定向和转发的区别:(redirectforward的区别)

* 1.重定向的地址栏会发生变化,转发的地址栏不变.

* 2.重定向两次请求两次响应,转发一次请求一次响应.

* 3.重定向路径需要加工程名,转发的路径不需要加工程名.

* 4.重定向可以跳转到任意网站,转发只能在服务器内部进行转发.


-----------------------------------------------------------------------------

01_响应对象的概述&向客户端发送数据
WEB服务器会针对每一个客户端发出的HTTP请求,分别的创建一个请求对象和一个响应对象
如果需要获取客户端提交的数据,需要使用请求对象
如果需要向客户端发送一些数据,需要使用响应对象

响应 : 响应行 响应头 响应正文
  
  1XX:浏览器发送的请求信息不完善,需要浏览器进一步补充资料
  2XX:响应正常完成
  3XX:本次请求已经完成,但是需要浏览器进行进一步操作  302
  4XX:请求的资源错误
  5XX:服务器端错误

注意:
这两个流互相排斥,在一个Servlet中只能使用其中的一个,如果有字符输出流则不能有字节输出流,否则会出现异常


02_字节流向客户端发送中文的乱码处理
编码:
二进制   A 65  a 97   汉字
ASCII 美国标准信息码(128字符)
ISO-8859-1 -16 一共有15编码 13
//GB2312 2个字节表示一个字符 6700+
GBK   2个字节表示一个字符  18000+ 国家强制标准 
Unicode 万国码   2个字节表示一个字符
UTF-8 用1-6个字节来表示一个字符
ANSI 本地平台默认
     中文版window GBK
英文版的window UTF-8


原因:
乱码的出现是因为前后编码不一致,发送数据的编码,接收数据的编码

服务器发送数据:ISO-8859-1
浏览器接收数据:GBK

解决方法一:
将服务器发送数据格式改为GBK
OutputStream os = response.getOutputStream();
os.write("定个小目标".getBytes());//默认GBK

解决方法二
//设置响应头,告诉浏览器你应该使用什么编码
response.setHeader("Content-type", "text/html;charset=UTF-8");
os.write("定个小目标".getBytes("UTF-8"))

03_字符流向客户端发送中文的乱码处理

原因
服务器发送数据:ISO-8859-1 -> GBK
浏览器接收数据:GBK

解决方法一:
response.setCharacterEncoding("GBK");//设置编码的格式,也就是设置服务器发送数据的格式

如果服务器发送的是UTF-8
response.setCharacterEncoding("UTF-8");//服务器
response.setContentType("text/html;charset=UTF-8");//告诉浏览器采用什么方式进行解码

推荐方案
response.setContentType("text/html;charset=UTF-8");//告诉浏览器采用什么方式进行解码

04_响应头Refresh
定时自动刷新
response.setHeader("Refresh", "3");

定时自动跳转
response.setHeader("Refresh", "3;URL=http://baidu.com");    //跳转外部资源
response.setHeader("Refresh", "3;URL=/myResponse/ResponseDemo");//跳转内部资源

转发和跳转的区别
转发:共享请求和响应对象,跳转:不共享
转发:只能是内部地址,跳转:内部地址和外部地址都可以
转发:地址栏不会发生变化,跳转:地址栏会发生变化


05_请求重定向
概念:一个WEB资源接收到客户端的请求之后,通知这个客户端去访问(请求)另外的一个WEB资源

重定向和转发的区别
请求次数
重定向发出两次请求
转发只发出一次请求,共享请求对象和响应对象
访问的路径
重定向可以访问内部的路径,也可以访问外部的路径
转发只能访问内部的路径
地址栏
重定向的地址栏发生变化
转发地址栏不会变化

原理:设置location响应头,同时还需要设置一个响应码(状态码),302/307
  response.setHeader("Location", "http://baidu.com");
  response.setStatus(307);  //立即重定向


06_文件下载案例


步骤
//设置响应头
response.setHeader("Content-disposition", "attachment;filename=pic01.jpg");
//获取字节输出流对象
OutputStream os = response.getOutputStream();
//创建字节输入流对象
String path = getServletContext().getRealPath("/WEB-INF/pic01.jpg");
FileInputStream fis = new FileInputStream(path);
//循环读取并向客户端发送数据
int len = 0;
byte[] bys = new byte[1024];

while((len = fis.read(bys)) != -1) {
//向客户端发送数据
os.write(bys,0,len);
}

//释放资源
fis.close();


07_文件下载的细节
注意:
响应头里不能有中文,中文被认为是不安全的字符
更改如下:
String s = URLEncoder.encode("定个大目标.jpg", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + s);


08_请求对象的概述&获取请求行
HttpServletRequest
请求对象封装了HTTP协议的请求行,请求头,请求体,我们可以通过请求对象的方法来获取这些信息


获取请求行
StringBuffer getRequestURL() //完整的URL 
String getRequestURI()  //请求行中的资源路径
String getMethod()  //请求方式
String getContextPath() //当前项目的路径
String getQueryString() //请求行中资源路径后面的参数



注意:
getRequestURL()返回的是一个可变字符串,不能直接使用String来接收
getQueryString()获取的是资源路径后面的参数,请求体里的数据无法获取

09_获取请求头
String getHeader(String name) //通过name来获取请求头value
Enumeration getHeaderNames()  //获取所有的请求头name

Enumeration迭代遍历
Enumeration<String> e = request.getHeaderNames();
while(e.hasMoreElements()) {
String name = e.nextElement();
System.out.println(name);
}

10_获取表单提交的数据
String getParameter(String name) :根据表单项的name来获取表单项的value

注意:
有表单项提交过来,但是没有值, 打印的是空字符串
表单项根本没有提交过来,打印的就是null,就不能调用字符串的方法,否则会报空指针异常


11_获取表单提交的数据2
String[] getParameterValues(String name) 根据表单项的name获取表单项value的数组

应用场景: name是重复的,比如密码确认密码 复选框


12_获取表单提交的数据3
Map getParameterMap(): 获取表单提交来的所有数据,并封装成一个map返回,一些框架(工具类)会使用这个方法 
Enumeration getParameterNames()  获取提交过来表单项所有的name

返回值使用泛型时应该是Map<String,String[]>形式,
因为有时像checkbox这样的组件会有一个name对应对个value的时候,
所以该Map中键值对是<String-->String[]>的实现。


注意:
注册按钮提交过来没有意义,所以注册按钮千万不要写个name属性  

14_获取表单提交的数据乱码的处理
原因:
编码前后不一致
表单提交数据用的是UTF-8
请求对象接收数据转换成字符串 用的是默认的ISO-8859-1

对于post请求
request.setCharacterEncoding("UTF-8");//只能处理请求体,这里设置请求对象创建字符串所使用的编码是UTF-8

对于get请求
浏览器
按照表单页面的编码(UTF-8)进行转码,转成字节数组,拼接在请求资源的后面
接下来把字节数组做一个转义(url编码)在发送
服务器
服务器首先拿到这个数据做一个url解码,(正确的)
然后把解码之后的数据按照ISO-8859-1拼成字符串(错误)

做法:
//把字符串打回原形
byte[] bys = request.getParameter("username").getBytes("ISO-8859-1");
//把字节数组按照正确的编码转换字符串
String username = new String(bys,"UTF-8");


15_转发和包含
用ServletContext实现转发和包含,路径必须以正斜杠开头
RequestDispatcher rd = getServletContext().getRequestDispatcher("/register.html");
rd.forward(request, response);
rd.include(request, response);

用request对象实现转发和包含,路径可以不用正斜杠开头
RequestDispatcher rd = request.getRequestDispatcher("register.html");
rd.forward(request, response);
rd.include(request, response);


16_使用请求对象实现数据共享


ServletContext 上下文对象 范围是当前的web应用   
时间范围  tomcat 一加载项目 tomcat关闭
空间范围  整个web应用
request 请求对象 范围是当前的请求 需要同一个请求才能实现数据的共享
时间范围 一个请求开始,请求结束
空间范围  当前这个请求里面

//设置数据
request.setAttribute("username", "zhangsan");

//获取数据
Object obj = request.getAttribute("username");
System.out.println(obj);

//删除数据
request.removeAttribute("username");

//转发
RequestDispatcher rd = request.getRequestDispatcher("/RequestDemo9");
rd.forward(request, response);

访问网站访问量







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值