Resonse9_Response对象2
1. 功能:设置响应消息
a. 设置响应行
* 格式:HTTP/1.1 200 ok
* 设置状态码:void setStatus(int sc)
b. 设置响应头
* void setHeader(String name, String value)
c. 设置响应体:
使用步骤:
1、获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream()
2、使用输出流,将数据输出到客户端浏览器
2. 重定向
a、重定向:资源跳转的方式
b、实现方法:
方法一:
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/day09/responseDemo2");
方法二:
//简单的重定向方法
response.sendRedirect("/day09/responseDemo2");
代码实现:
一:header重定向
package cn.itcast.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 重定向
*/
@WebServlet("/responseDemo1")
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo1.....");
//访问/responseDemo1,会自动跳转到/responseDemo2资源
//1. 设置状态码为302
response.setStatus(302);
//2. 设置响应头location
response.setHeader("location","/day09/responseDemo2");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
package cn.itcast.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 重定向
*/
@WebServlet("/responseDemo2")
public class ResponseDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo2.....");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
浏览器访问http://localhost/day09/responseDemo1,检查输出:
二:简单的重定向
package cn.itcast.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 重定向
*/
@WebServlet("/responseDemo1")
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo1.....");
//简单的重定向方法
response.sendRedirect("/day09/responseDemo2");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
浏览器访问http://localhost/day09/responseDemo1,检查输出同实现一
c、重定向的特点:redirect
1、地址栏发生变化
2、重定向可以访问其他站点(服务器)的资源
3、重定向是两次请求。不能使用request对象来共享数据
d、转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据
e、forward和redirect 区别:见c和d
f、路径写法:路径分类
1、相对路径:通过相对路径不可以确定唯一资源。不推荐。
* 如:./index.html
* 不以/开头,以.开头路径
* 规则:找到当前资源和目标资源之间的相对位置关系
* ./:当前目录
* ../:后退一级目录
2、绝对路径:通过绝对路径可以确定唯一资源。推荐
* 如:http://localhost/day09/responseDemo2 /day09/responseDemo2
* 以/开头的路径
* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径application context)
* 建议虚拟目录动态获取:request.getContextPath()
* <a>,<form>,重定向都是给客户端浏览器使用,所以需要加虚拟目录
* 给服务器使用:不需要加虚拟目录
* (request.getRequestDispatcher("/requestDemo9").forward(request,response);)转发路径是给服务器用的,不需要加虚拟目录
3、代码实现
三、相对路径1
web包中新建location.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>找到当前资源和目标资源之间的相对位置关系</h1> <P> 当前资源:location.html http://localhost/day09/location.html </P> <P> 目标资源:responseDemo2 http://localhost/day09/responseDemo2 </P> <a href="./responseDemo2"> responseDemo2 </a> </body> </html>
浏览器访问http://localhost/day09/location.html,点击responseDemo2链接,检查输出:
四、相对路径2
web包中新建Directory:htmls,把location.html粘过来改名location2.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>找到当前资源和目标资源之间的相对位置关系</h1> <P> 当前资源:location2.html http://localhost/day09/htmls/location2.html </P> <P> 目标资源:responseDemo2 http://localhost/day09/responseDemo2 </P> <a href="../responseDemo2"> responseDemo2 </a> </body> </html>
浏览器访问http://localhost/day09/htmls/location2.html,点击responseDemo2链接,检查输出同四中结果
五、绝对路径:给客户端用的
更改location.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>相对路径</h1> <h1>找到当前资源和目标资源之间的相对位置关系</h1> <P> 当前资源:location.html http://localhost/day09/location.html </P> <P> 目标资源:responseDemo2 http://localhost/day09/responseDemo2 </P> <a href="./responseDemo2"> responseDemo2 </a> <a href="responseDemo2"> responseDemo2 </a> <br> <hr> <h1>绝对路径</h1> <!-- 从客户端发出,从浏览器发出请求服务器的资源,给客户端用的 --> <a href="/day09/responseDemo2"> responseDemo2 </a> </body> </html>
浏览器访问http://localhost/day09/location.html,点击绝对路径下的“responseDemo2”,检查输出:
六、绝对路径:对服务器端用的
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/responseDemo3") public class ResponseDemo3 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo3....."); //转发 request.getRequestDispatcher("/responseDemo2").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
浏览器访问浏览器访问http://localhost/day09/reponseDemo3,会自动访问reponseDemo2,检查输出:
七、绝对路径:动态获取虚拟路径
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 重定向 */ @WebServlet("/responseDemo1") public class ResponseDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo11....."); request.setAttribute("msg","response"); //动态获取虚拟目录 String contextPath = request.getContextPath(); //简单的重定向方法 response.sendRedirect(contextPath+"/responseDemo2"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
重启tomcat服务器,浏览器访问http://localhost/day09/responseDemo1,检查输出:
使用这种方式,更换项目路径时,不需要更改重定向中的路径。
3. 服务器输出字符数据到浏览器
a. 步骤:
1、获取字符输出流:PrintWriter pw = response.getWriter();
2、输出数据:pw.write("<h1>hello response</h1>");
b. 注意:中文会出现乱码问题。
乱码原因:编解码使用的字符集不一致。浏览器字符集默认为GBK(gb2312),而PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1,是tomcat返回的编码。
解决办法:获取流对象之前设置该流的默认编码并告诉浏览器响应体使用的编码
* response.setCharacterEncoding("GBK");
设置流的默认编码为GBK,如果设为utf-8浏览器解析中文就会出问题
* response.setHeader("content-type","text/html;charset=utf-8");
告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
* response.setContentType("text/html;charset=utf-8");
简单的形式,在获取流之前设置编码并告诉浏览器使用该编码进行解码。推荐!
c. 代码实现:
一:输出数据到浏览器
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/responseDemo4") public class ResponseDemo4 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1、获取字符输出流 PrintWriter pw = response.getWriter(); //2、输出数据 pw.write("<h1>hello response</h1>"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
浏览器访问http://localhost/day09/responseDemo4,检查浏览器展示,可以看到会把标签解析了。
二:解决GBK中文乱码
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/responseDemo4") public class ResponseDemo4 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取流对象之前,设置流的默认编码:ISO-8859-1 设置为:GBK response.setCharacterEncoding("GBK"); //1、获取字符输出流 PrintWriter pw = response.getWriter(); //2、输出数据 pw.write("你好 response"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
浏览器访问http://localhost/day09/responseDemo4,检查浏览器输出:你好 response
二、彻底解决乱码问题
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/responseDemo4") public class ResponseDemo4 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取流对象之前,设置流的默认编码:ISO-8859-1 设置为:utf-8 response.setCharacterEncoding("utf-8"); //告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码 response.setHeader("content-type","text/html;charset=utf-8"); //1、获取字符输出流 PrintWriter pw = response.getWriter(); //2、输出数据 pw.write("你好 response"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
浏览器访问http://localhost/day09/responseDemo4,浏览器会按照从服务器端接收到的utf-8进行解码,输出:你好 response;
可以不写setCharacterEncoding直接用response.setHeader()的方式进行解决中文乱码问题
三、简单的形式
response.setHeader("content-type","text/html;charset=utf-8");的简化写法:
response.setContentType("text/html;charset=utf-8");
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/responseDemo4") public class ResponseDemo4 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//简单的形式,设置编码 response.setContentType("text/html;charset=utf-8"); //1、获取字符输出流 PrintWriter pw = response.getWriter(); //2、输出数据 pw.write("你好 response"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
4. 服务器输出字节数据到浏览器
字节流一般输出的是图片等数据
a. 步骤:
1、获取字节输出流:ServletOutputStream os = response.getOutputStream();
2、输出数据:os.write("hello你好".getBytes());
中文编码问题同字符流解决办法。
b. 代码实现:
一:输出数据到浏览器
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/responseDemo5") public class ResponseDemo5 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1、获取字节输出流 ServletOutputStream os = response.getOutputStream(); //2、输出数据 os.write("hello".getBytes()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
浏览器访问http://localhost/day09/responseDemo5,检查浏览器输出:hello
getBytes()使用的是GBK编码,所以即使是中文也不会有乱码。
二:
package cn.itcast.web.servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/responseDemo5") public class ResponseDemo5 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1、获取字节输出流 ServletOutputStream os = response.getOutputStream(); //2、输出数据 os.write("你好".getBytes("utf-8")); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
浏览器访问http://localhost/day09/responseDemo5,检查浏览器输出乱码,解决办法:获取字节输出流之前使用response.setContentType("text/html;charset=utf-8");
5. 验证码
题外话:验证码也是一张图片,只不过这个图片在内存中,我们可以使用内存里的二进制数据把它写到页面上去。
ServletContext对象,使用response输出本地的图片到客户端浏览器。
a. 本质:图片
b. 目的:防止恶意表单注册
不需要重点练习,开发过程中要写验证码不会写这么丑陋的,都会上网去找一些美观的线程的验证码代码改改。这些代码能看懂就行。
c. 生成验证码:
package cn.itcast.web.servlet; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //import java.awt.*; import java.awt.Graphics; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; @WebServlet("/checkCodeServlet") public class CheckCodeServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int width = 100; int height = 50; //1. 创建一个对象,在内存中图片(代表验证码图片对象) BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//在浏览器输出一张宽100高50的黑色背景的图片 //2. 美化图片 //2.1 填充背景色 Graphics g = image.getGraphics();//获取画笔对象 g.setColor(Color.PINK);//设置画笔颜色 g.fillRect(0,0,width,height); //2.2 画边框 g.setColor(Color.BLUE); g.drawRect(0,0,width-1,height-1); String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; //生成随机角标 Random ran = new Random(); for (int i = 1; i <= 4; i++) { int index = ran.nextInt(str.length()); //获取字符 char ch = str.charAt(index);//随机字符 //2.3 写验证码 g.drawString(ch+"",width/5*i,height/2); } //2.4 画干扰线 g.setColor(Color.GREEN); //随机生成坐标点 for (int i = 0; i < 10; i++) { int x1 = ran.nextInt(width); int x2 = ran.nextInt(width); int y1 = ran.nextInt(height); int y2 = ran.nextInt(height); g.drawLine(x1,y1,x2,y2); } //3. 将图片输出到页面展示 ImageIO.write(image,"jpg",response.getOutputStream()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
浏览器访问http://localhost/day09/checkCodeServlet,检查浏览器展示,每次刷新图片都不一样
d. 点击切换验证码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script> /* 分析: 点击超链接或者图片,需要换一张 1. 给超链接和图片绑定单击事件 2. 重新设置图片的src属性值 */ window.onload = function () { //1. 获取图片对象 var img = document.getElementById("checkCode") //2. 绑定单击事件 img.onclick = function(){ //加时间戳 var date = new Date().getTime(); img.src="/day09/checkCodeServlet?time="+date; // 不加?之后的值会有缓存,点击一直访问的缓存图片 } } </script> </head> <body> <img id="checkCode" src="/day09/checkCodeServlet" /> <a id="change" href="">看不清换一张?</a> </body> </html>
浏览器访问http://localhost/day09/register.html,每次点击验证码图片,验证码都会变化。