JavaWeb.docx
- 文档编号:28729633
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:24
- 大小:154.67KB
JavaWeb.docx
《JavaWeb.docx》由会员分享,可在线阅读,更多相关《JavaWeb.docx(24页珍藏版)》请在冰豆网上搜索。
JavaWeb
【JavaWeb-6】HttpServletResponse的字符字节输出流、编码、文件下载、Captcha图片与HttpServletRequest获取request数据表单非表单数据、重定向与转发
1、HttpServletResponse。
——我们要输出东西,也就是设置响应的response,在下面我们利用字符输出流来向浏览器输出东西。
这里利用了response的getWriter方法,这个getWriter的返回值是一个PrintWriter对象。
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
//得到一个字符输出流
PrintWriterout=response.getWriter();
out.print("你好Hello!
");
}
——但是,上面的结果在浏览器里是部分显示“?
”,即中文部分。
原因是服务器默认的字符编码是“ISO-8859-1”,它是不支持中文的。
?
?
Hello!
1
——所以,我们在输出东西之前把服务器的编码设置一下:
response.setCharacterEncoding("UTF-8");
//得到一个字符输出流
PrintWriterout=response.getWriter();
out.print("你好Hello!
");
——结果如下。
原因是虽然我们服务器知道用UTF-8去编码,但是生成的文件送到浏览器的时候,浏览器不知道用什么编码来解析文档,所以一般情况下我们的浏览器都是GBK的编码,结果当然就是出现乱码了。
浣犲ソHello!
1
——解决办法,就是通过上面的语句告诉服务器用什么编码之后,再告诉浏览器用什么编码来解析文档。
response.setCharacterEncoding("UTF-8");
response.setHeader("content-type","text/html;charset=UTF-8");
PrintWriterout=response.getWriter();
out.print("你好Hello!
");
——这样,一切输出就正常了。
但是我们有一种简便的写法,就是只用一句代码就能代替上面的两行代码分别设置服务器和告诉浏览器的编码。
response.setContentType("text/html;charset=UTF-8");
PrintWriterout=response.getWriter();
out.print("你好Hello!
");
2、字节流输出。
——write方法的参数是字节数组,所以需要对字符串进行转换。
——这一次在浏览器中输出结果是正常的。
原因在getBytes()方法,这个方法是将字符串以平台默认的编码进行字节转换。
我们电脑一般都是GBK编码(中文的),浏览器默认也是GBK的,所以当然没问题。
getBytes()可以接受参数比如“UTF-8”,如果这样的话,浏览器是不知道的会出现乱码,这个时候,我们在前面设置个response.setContentType("text/html;charset=UTF-8")可以解决乱码问题。
//字节流输出
ServletOutputStreamsos=response.getOutputStream();
sos.write("你好Hello!
".getBytes());
3、文件的下载。
——我们新建了一个Servlet,把一张图片放在了WEB-INF/images/下面,这个图片名称里面有中文。
然后我们写了下面的代码,意思是先获取这个图片的路径、用这个路径生成一个文件输入流(FileInputStream)、利用response生成一个字节输出流、最后利用一个while循环把这个字节流的图片输出出去。
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
Stringpath=this.getServletContext().getRealPath("/images/img_头像.jpg");
//获取输入流
FileInputStreamfis=newFileInputStream(path);
//输出流
ServletOutputStreamsos=response.getOutputStream();
//输出
intlen=1;
byte[]b=newbyte[1024];
while((len=fis.read(b))!
=-1){
sos.write(b,0,len);
}
}
——我们输入“http:
//localhost:
8080/Day01_RequestResponse/servlet/HttpServletResponseDemo2”成功在浏览器上输出了图片。
成功个毛啊?
不是说好是下载图片的么?
——那我们就设置一下response的头文件,content-disposition和content-type两个属性。
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
Stringpath=this.getServletContext().getRealPath("/images/img_头像.jpg");
//获取输入流
FileInputStreamfis=newFileInputStream(path);
//输出流
ServletOutputStreamsos=response.getOutputStream();
//告诉浏览器是一个图片,并且以附件形式下载
Stringfilename=path.substring(path.lastIndexOf("\\")+1);
response.setHeader("content-disposition","attachment;filename="+filename);
response.setHeader("content-type","image/jpeg");
//输出
intlen=1;
byte[]b=newbyte[1024];
while((len=fis.read(b))!
=-1){
sos.write(b,0,len);
}
}
——这下,一打开网址,文件自动下载(win10,chrome)。
但是文件名是img_.jpg。
我们发现文件名原来是img_头像.jpg,中文变成2个空格,这是因为文件名出问题了。
文件名中出现中文的时候需要进行URLEncoder编码。
继续配置,其实就是一行代码,把我们的filename编码一下再使用。
filename=URLEncoder.encode(filename,"UTF-8");
1
——然后,就真的下载了一个叫做img_头像.jpg的图片。
这里补充一下,之前获取filename的时候index位置弄错了,写成下面这个样子,少往后移1位,所以文件名里面有自带了一个“/”,这斜杠如果不经过URLEncoder编码的话也不会正常显示,它显示-,而经过编码之后显示的是%5c,所以如果你看到文件名里有这个,说明文件名获取有问题。
filename=path.substring(path.lastIndexOf("\\"));
1
4、小技巧:
——MyEclipse里的代码提示功能:
Alt+/。
——选择DebugServer启动服务器,这样我们修改了一点代码之后就不需要重新部署重启服务器了,直接刷新浏览器就能够看到变化了。
5、Captcha,也就是实验一下图像相关的对象。
——创建一个Servlet,在里面写如下代码,每一步的意义都写在代码里了。
无非就是先获取一个宽高指定图片对象、获取画笔、设置颜色、画线画框填充背景画文字、利用ImageIO的write方法把这个图片以字节流的方式输出到浏览器中。
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
intwidth=115;
intheight=24;
//获取一个图片对象,默认是黑色的
BufferedImagebi=newBufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphicsg=bi.getGraphics();
//设置图片背景颜色,第一步设置颜色,第二部设置填充
g.setColor(Color.PINK);
g.fillRect(1,1,width-2,height-2);
//设置边框,也是两个步骤
g.setColor(Color.DARK_GRAY);
g.drawRect(0,0,width-1,height-1);
//设置一些线条
Randomrand=newRandom();
g.setColor(Color.RED);
for(inti=0;i<6;i++){
g.drawLine(rand.nextInt(width),rand.nextInt(height),rand.nextInt(width),rand.nextInt(height));
}
//写一些文字
g.setColor(Color.BLACK);
g.setFont(newFont("宋体",Font.BOLD|Font.ITALIC,15));
intposition=20;
for(inti=0;i<4;i++){
g.drawString(String.valueOf(rand.nextInt(10)),position*(i+1),16);
}
//将图片以流的方式输出到浏览器上
ImageIO.write(bi,"jpg",response.getOutputStream());
}
——我们创建一个login.html文件,把这个验证码图片集成到登录表单中。
我们直接访问“http:
//localhost:
8080/Day01_RequestResponse/login.html”即可,关于直接访问静态资源的url是被defaultservlet处理了,这个问题我在JavaWeb能够直接访问html文件的原理是什么?
里问过,记得其原理。
——直接刷新浏览器,相当于新的请求,验证码图片会变。
但是我们点击图片或者换一张的时候,如果请求依然是“/Day01_RequestResponse/servlet/Captcha”的话,我们会发现图片不会变化,因为浏览器的缓存原因。
也就是说浏览器发现你这个请求的url路径没变,所以把上一次在缓存中的东西拿出来,导致我们根本没有去服务器请求新的图片。
所以我们在请求路径后面增加一个日期变量。
DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http:
//www.w3.org/TR/html4/loose.dtd">
functioncaptchaRefresh(){
varimg=document.getElementsByTagName("img")[0];
img.src="/Day01_RequestResponse/servlet/Captcha?
time="+newDate().getTime();
}
captchaRefresh()">看不清换一张 ——我们利用前人的轮子来写Captcha就不需要自己手动写那么多代码了。 我们先把自己写的代码抽取方法到test1里面去。 然后引入一个用来生成Captcha的jar(ValidateCode.jar)放入WebRoot/WEB-INF/lib/下,最后在doGet里面写2行代码即可,只要2行,即创建、输出。 注意: 引入新的jar包需要重启服务器。 publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ ValidateCodevc=newValidateCode(115,24,4,6); vc.write(response.getOutputStream()); } ——我们在浏览器中刷新网址的时候,验证码图片是变化的,但有时候浏览器缓存搞鬼的话,我们可以禁止缓存,可以达到同样的目的: publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ //以下3种方式是针对不同浏览器的禁止缓存的方法 response.setHeader("pragma","no-cache"); response.setHeader("cache-control","no-cache"); //以下3行代码是同一个效果,都是通过设置缓存过期时间来达到不缓存的目的 response.setHeader("expires","0"); response.setIntHeader("expires",0); response.setDateHeader("expires",0); ValidateCodevc=newValidateCode(115,24,4,6); vc.write(response.getOutputStream()); } 6、自动刷新和自动跳转的例子。 ——我们创建了一个RefreshDemo1的Servlet类,在里面写了如下代码。 我们打开“http: //localhost: 8080/Day01_RequestResponse/servlet/RefreshDemo1”,这个页面就会每2秒钟刷新一下,你就会看到不同的随机数。 publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ //设置刷新,下面两行代码是等价的设置 //response.setHeader("refresh","2"); response.setIntHeader("refresh",2); //测试刷新 Randomrand=newRandom(); response.getWriter().write(String.valueOf(rand.nextInt(100))); } ——常用的例子,就是过几秒钟跳转。 也就是说刷新可以和页面跳转联系在一起。 本质上,这里说的页面跳转,其实也是发一个url路径去一个新的Servlet而已。 我们在RefreshDemo1的Servlet中写: publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ //不加这一句代码,页面上的中文都是问号? response.setContentType("text/html;charset=UTF-8"); //输出一句提醒 response.getWriter().write("注册成功! 3秒后自动跳转至主页! "); //核心代码,也就是在刷新秒数后面加了一个url response.setHeader("refresh","3;url=/Day01_RequestResponse/servlet/RefreshDemo2"); } ——然后在RefreshDemo2的Servlet中写: publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ //不加这一句代码,页面上的中文都是问号? response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("我是主页! "); } ——接下来我们访问“http: //localhost: 8080/Day01_RequestResponse/servlet/RefreshDemo1”就出现提示信息,然后过3秒就跳转了。 7、下面是请求方面的内容了,先来一个重定向。 ——重定向需要注意的就是和请求转发的区别。 重定向的意思就是,我发一个请求给A,A说我不处理但我告诉你去找B吧(注意此时A把响应返回回来了,也就是说我们在访问B之前,是完成的接受了A的响应的,而不是立即去B那里),然后我从A那得到B的地址,我自己再访问B。 也就是我自己访问了2次。 而转发的意思是,我请求A,A处理不了但它自动帮我转发给B处理去了,然后B处理的结果给A,A再把结果给我,我只访问了1次。 这就是区别。 下面看例子: ——我们创建一个Servlet类,叫RedirectDemo01,里面的代码主要的意思就是,我们得在响应里面告诉浏览器,这是一个重定向(302),然后再告诉浏览器重定向的地址(url)。 publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ System.out.println("RedirectDemo01: 我这里没有你要的东西,我告诉你去哪里找吧! "); response.setStatus(302); response.setHeader("location","/Day01_RequestResponse/servlet/RedirectDemo02"); System.out.println("RedirectDemo01: 302和地址都设置好了! "); } ——我们创建一个Servlet类,叫RedirectDemo02,里面简单一个输出,用来看看我们重定向的请求走向的。 publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ System.out.println("RedirectDemo02: 我有,你拿去吧! "); } ——我们在浏览器上输入“http: //localhost: 8080/Day01_RequestResponse/servlet/RedirectDemo01”后,发现浏览器的url地址变成了“http: //localhost: 8080/Day01_RequestResponse/servlet/RedirectDemo02”。 然后我们看我们Console中有如下输出信息。 可见我们在RedirectDemo01里面是完整的执行完了所有程序,之后在去重新请求RedirectDemo02的。 如果是转发的话,遇到转发的那行代码它就跑去其他Servlet类了,执行完再返回本Servlet类来继续向下执行,这就是区别。 RedirectDemo01: 我这里没有你要的东西,我告诉你去哪里找吧! RedirectDemo01: 302和地址都设置好了! RedirectDemo02: 我有,你拿去吧! ——当然,这个重定向是可以优化的。 上面的两行核心代码,一个设置302状态码一个设置url,可以合并成一句代码。 response.sendRedirect("/Day01_RestResponse/servlet/RedirectDemo02"); 8、插播一些小知识。 ——在同一个Servlet里面不能同时写getOutputStream和getWriter,这两个方法是冲突的,只能写一个,否则报错。 ——我们在service里面(可以看做是在doGet等方法里面)创建的输入输出流,不用我们自己关闭,服务器在执行完这个方法后会检查是否有未关闭的,如果有,服务器会帮我们关闭。 9、与请求消息行有关的方法,就是获取消息行里的信息的。 我们在一个Servlet里写: publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ System.out.println(request.getRequestURL()); System.out.println(request.getReque
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JavaWeb