学好的关键:理解HTTP协议
l setStatus(int sc) 设置响应状态码
l ***** sendRedirect(String location) 请求重定向
l setHeader(String name, String value) 设置响应头信息
l
//告知浏览器使用什么码表
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刷新
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【验证码】
Captcha:Completely 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服务器
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
(1) Request和Response打印出来到底是什么?
结果
答:Tomcat创建的request和response的实现类
(2)请求行相关方法
结果
方法:getMethod ==> GET
getRequestURL ==> 完整地址(带参) http://localhost:8080/day...../servletdemo1
getRequestURI ==> 部分地址(不带参) /day...../servletdemo1
getContextPath ==> 当前应用名字 /day..... 常用
getQueryString ==> 参数部分
如:http://localhost:8080/day...../servletdemo1?username=tom
则得到 username=tom
* 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) 方法
结果:获得相同消息头的值
<input type="text" name="username" />
*** getParameter(name) 根据表单中name属性的名,获取value属性的值方法
*** getParameterValues(String name)专业为复选框选取的值提供的方法
getParameterNames() 得到表单提交的所有name的方法
*** getParameterMap 到表单提交的所有值的方法 //做框架用,非常实用
getInputStream 以字节流的方式得到所有表单数据
第一步:创建表单 register.html
效果:
注意:
其中action后面的值 / 代表URL中8080后面的东西
第二步:编写servlet文件代码,获取表单数据:
根据表单中name属性的名,获取value属性的值方法
第三步:访问html文件,输入信息
后台服务器获得信息
(1)乱码问题
由结果可知 性别和爱好 2个参数的值出现乱码
解决办法:
和response部分一样,开头第一句写上:
request.setCharacterEncoding("UTF-8"); //只能解决post方式的乱码
//告诉服务器客户端什么编码,只能处理post请求方式
最后结果:
显示正常
(2)getParameterNames方法
其中for循环中,当name 为userName等单值name时 String[1];
当name 为hobby等多值name时 String[];
结果:
【实际开发中,应将这些数据封装为实体类】
在实体类中的字段(相当于成员变量)与表单中的name名一致!!!
如下图:
User.java
还有其他参数的get与set方法
(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: 首先找到beanutils和logging jar包,再复制到web-inf/lib下
B: 再编写代码: 使用Apache的BeanUtils
BeanUtils.populate()方法中 第一个参数要求object对象,第二个要求Map对象
*** 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中请求包含demo6,demo5会执行demo6的代码
相当于5+6合并为1个新的demo5,浏览器地址栏不会变
//解决post方式编码
*****request.setCharacterEncoding("UTF-8"); //告诉服务器客户端什么编码,只能处理post请求方式
//解决get方式编码
String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);
Demo3中 method方法改成get,demo3文件内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,间接会回头) 对客户端有利
原文:http://www.cnblogs.com/xydy1024/p/6705641.html