【原创102】reques&response笔记

学好的关键:理解HTTP协议

一、HttpServletResponse

1、响应行  HTTP/1.1  200 OK

l setStatus(int sc) 设置响应状态码

2、响应头

l ***** sendRedirect(String location) 请求重定向

l setHeader(String name, String value) 设置响应头信息

//告知浏览器使用什么码表

response.setHeader("content-type", "text/html;charset=UTF-8");

 

//告知客户端不缓存

response.setHeader("pragma", "no-cache");

response.setHeader("cache-control", "no-cache");

response.setDateHeader("expires", 0);

 

Referesh刷新

3、响应正文(主体)

l *** getWriter(); 字符输出流

l getOutputStream(); 字节输出流

l setCharacterEncoding(String charset) 告知服务器使用什么编码

l *****setContentType(String type)

01【响应编码问题】

效果:(浏览器显示)

浏览器中 abc?因为查不到码表

【服务器中默认的编码为ISO-8859-1,它不支持中文,tomcat规定的】

  

所以,应该告知服务器使用什么编码 setCharacterEncoding(String charset)

不是对应的中文,因为浏览器编码与设置的服务器编码不一致!

 

【告诉客户端要使用什么编码】==>setHeader方法

相当于下面的

简洁的方法  setContentType(String type) 同时设置了服务器浏览器的编码

 

response.setContentType("text/html; charset=UTF-8");

响应编码字节输出流(二)

或者

 

注意:【doXXX方法里第一行代码:response.setContentType("text/html;charset=UTF-8");

02【文件下载】

代码:

                //通过路径得到一个输入流
		String path = this.getServletContext().getRealPath("/WEB-INF/classes/美女.jpg");
		FileInputStream fis = new FileInputStream(path);
		//创建字节输出流
		ServletOutputStream sos = response.getOutputStream();
		
		//得到要下载的文件名
		String filename = path.substring(path.lastIndexOf("\\")+1);
		
		//设置文件名的编码
		filename = URLEncoder.encode(filename, "UTF-8");//将不安全的文件名改为UTF-8格式
		
		//告知客户端要下载文件
		response.setHeader("content-disposition", "attachment;filename="+filename);
		response.setHeader("content-type", "image/jpeg");
		
		//执行输出操作
		int len = 1;
		byte[] b = new byte[1024];
		while((len=fis.read(b))!=-1){
			sos.write(b,0,len);
		}
		
		sos.close();
		fis.close();        

  

03【验证码】

CaptchaCompletely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)==>验证码

 

/告知客户端不缓存 ==>每次回车URL图片都不一样

 

               response.setHeader("pragma", "no-cache");
		response.setHeader("cache-control", "no-cache");
		response.setDateHeader("expires", 0);             

 

/刷新

实际应用中:

04【请求重定向】

Servlet7全部执行完后再执行servlet8

 

 

/*//告诉客户端要重新定向新的资源
		response.setStatus(302);
		//告诉浏览器要去访问哪个URL
		response.setHeader("location", "/day09_00_HttpServletResponse/servlet/demo8");*/

//等于

//请求重定向
		response.sendRedirect("/day09_00_HttpServletResponse/servlet/demo8");

 

Servlet引擎 == tomcat服务器

 

 

二、HttpServletRequest

 

1、请求行  

 

Get  http://localhost:8080/day09/servlet/req1?username=zs  http/1.1

 

getMethod(); 获得请求方式

 

  GET, POST, or PUT

 

 

 

***getRequestURL();返回客户端发出请求时的完整URL

 

 获得 http://localhost:8080/day09/servlet/req1?username=zs

 

 

 

***getRequestURI(); 返回请求行中的资源名部分

 

 day09/servlet/req1

 

 

 

*****getContextPath(); 当前应用的虚拟目录

 

  /day09_01_request 当前应用名字

 

 

 

getQueryString() ; 返回请求行中的参数部分

 

 ?username=zs

 

 1RequestResponse打印出来到底是什么?

结果

答:Tomcat创建的requestresponse的实现类

 

 

(2)请求行相关方法

结果

方法:getMethod ==> GET

      getRequestURL ==> 完整地址(带参) http://localhost:8080/day...../servletdemo1

      getRequestURI ==> 部分地址(不带参) /day...../servletdemo1

      getContextPath ==> 当前应用名字 /day..... 常用

      getQueryString ==> 参数部分

      如:http://localhost:8080/day...../servletdemo1?username=tom

      则得到 username=tom

 

2、请求消息头

 * String   getHeader(String name)  根据头名称得到头信息值

 Enumeration   getHeaderNames()  得到所有头信息name

 Enumeration   getHeaders(String name)  根据头名称得到相同名称头信息值

 

 

(1)String getHeader(String name) 方法

 

 

User-Agent:浏览器信息(知道是啥浏览器)

结果: MSIE==>IE浏览器

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)

【补充】request.getHeader,简单的说就是获取请求的头部信息,根据http协议,它能获取到用户访问链接的信息,以下是我们常用的:

 

request.getHeader("referer"),它主要是用于获取链接的上一个引用。比如,从a.jsp跳转到b.jsp,那在b.jsp中获取到的引用就是a.jsp,如果手动刷新,b.jsp,获取到的引用仍然是a.jsp,刷新的时候,会检查服务端是否会有更新,没有的话,则使用本机的缓存,也就是说,你刷新时得到的响应依然是前一次得到的服务端的内容,因为你的jsp文件没有变化。当你在地址栏输入一个地址时,它的引用是null.相当于你第一次打开浏览器一样。

 

request.getHeader("host")获取请求服务器的主机,如你的http://localhost;8080/bbs/index.jsp..获取到的就是localhost:8080

 

 

(2)Enumeration   getHeaderNames() 方法

结果:获得所有请求消息头及对应的值 (根据名字 循环输出对应值)

(3)Enumeration   getHeaders(String name) 方法

结果:获得相同消息头的值

 

3、请求正文(重要)

与获取表单数据相关的方法

<input type="text" name="username" />

*** getParameter(name) 根据表单中name属性的名,获取value属性的值方法

*** getParameterValuesString name)专业为复选框选取的值提供的方法

                getParameterNames() 得到表单提交的所有name的方法

*** getParameterMap 到表单提交的所有值的方法   //做框架用,非常实用

  getInputStream  以字节流的方式得到所有表单数据

 

 

第一步:创建表单 register.html

效果:

注意:

其中action后面的值 / 代表URL8080后面的东西

 

第二步:编写servlet文件代码,获取表单数据:

根据表单中name属性的名,获取value属性的值方法

 

第三步:访问html文件,输入信息

后台服务器获得信息

(1)乱码问题

 由结果可知 性别和爱好 2个参数的值出现乱码

解决办法:

response部分一样,开头第一句写上:

 request.setCharacterEncoding("UTF-8");            //只能解决post方式的乱码

 

//告诉服务器客户端什么编码,只能处理post请求方式

最后结果:

显示正常

 

(2)getParameterNames方法

其中for循环中,当name userName等单值nameString[1];

               name hobby等多值nameString[];

结果:

 

【实际开发中,应将这些数据封装为实体类

     在实体类中的字段(相当于成员变量)与表单中的name一致!!!

如下图:

User.java

还有其他参数的getset方法

 

 

(3)getParameterMap(重要,框架实用)

 

 

 

未使用框架:

 

 Map<String,String[]> map = request.getParameterMap();

 

<String,String[]>相当于

 

try {
			User u = new User();
			System.out.println("封装数据前:"+u);
			//获取表单数据
			Map<String,String[]> map = request.getParameterMap();
			
			for (Map.Entry<String, String[]> m : map.entrySet()) {
				String name = m.getKey();
				String[] value = m.getValue();
				
				//创建一属性描述器 让name与user中的对应字段映射
				PropertyDescriptor pd = new PropertyDescriptor(name, User.class);
				//得到setter属性 获取user类中的setXXX方法 writer==set reader==get
				Method setter = pd.getWriteMethod();
				
				if(value.length==1){
					setter.invoke(u, value[0]);//给一个值的变量赋值
				}else{
					setter.invoke(u, (Object)value);//相当于给复选框赋值
				}
			}
			
			System.out.println("封装数据后:"+u);
		} catch (Exception e) {
			e.printStackTrace();
		}

 

改进:

 

在框架中使用getParameterMap

A: 首先找到beanutilslogging jar包,再复制到web-inf/lib

B: 再编写代码: 使用ApacheBeanUtils

BeanUtils.populate()方法中 第一个参数要求object对象,第二个要求Map对象

 

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

*** void setAttribute(String name, Object value);

*** Object getAttribute(String name); 先得有setAttribute

Void removeAttribute(String name); 先得有setAttribute

 

 

与请求转发相关的方法

//得到请求转发或请求包含的协助对象

RequestDispatcher getRequestDispatcher(String path)

*** forward(ServletRequest request, ServletResponse response) //转发的方法

include(ServletRequest request, ServletResponse response) //请求包含

(1)转发

转发图解:

Demo5

Demo6

Syso“这个事我能办”

(2)获得非表单数据 void setAttribute(String name, Object value)

Demo5

       将非表单的数据添加到request的域中 request.setAttribute();

Demo6

结果:

 

(3)请求包含 include(ServletRequest request, ServletResponse response)

Demo5中请求包含demo6demo5会执行demo6的代码

           相当于5+6合并为1个新的demo5,浏览器地址栏不会变

 

 

与请求编码相关的方法:

 

//解决post方式编码

 

*****request.setCharacterEncoding("UTF-8"); //告诉服务器客户端什么编码,只能处理post请求方式 

//解决get方式编码

String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);

 

Demo3method方法改成getdemo3文件内setCharacterEncoding方法只适用于post类型

 

结果:乱码!

所以:

对单个属性使用

          String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);

不方便,但一般也不会使用get类型,表单常用post!!!记住下面的即可

                  request.setCharacterEncoding("UTF-8"); 

 

请求转发与重定向的区别:

1.浏览器发请求:

             转发(只发一次请求,浏览器地址栏不变)

             重定向(发2次请求,浏览器地址栏会变)

2.传递数据:

             转发(可传递数据)

             重定向(不能传递)

  

3.跳转执行者:

           转发(服务器内部执行)

           重定向(浏览器客户端执行)

 

4.跳转其他应用是否可行?

如:请求转发能否跳到百度

   第一个参数http://www.baidu.com”    “/http://www.baidu.com/表示当前应用下

不加/时 结果:

/时,依然不行,只是错误提示会变成 /day09-01……/http:/......

所有,请求转发不能跳转到百度!

4.1请求转发不能跳转其他应用

重定向能否跳到百度

 

结果:

     浏览器地址栏 “……/demo5”变成 “http://www.baidu.com”

相当于手动在浏览器地址栏输入百度地址!

4.2重定向能跳转其他应用!

总结:

请求转发(request,一次不回头)  对服务器有利,

重定向  response,间接会回头) 对客户端有利

 

 

posted @ 2017-04-13 19:37  夕阳独影  阅读(338)  评论(4编辑  收藏  举报